import { encryptString, generateCspDigest } from "../../../core/encryption.js";
import { markHTMLString } from "../escape.js";
import { renderChild } from "./any.js";
import { createThinHead } from "./astro/head-and-content.js";
import { createRenderInstruction } from "./instruction.js";
import { renderSlotToString } from "./slot.js";
const internalProps = /* @__PURE__ */ new Set([
"server:component-path",
"server:component-export",
"server:component-directive",
"server:defer"
]);
function containsServerDirective(props) {
return "server:component-directive" in props;
}
const SCRIPT_RE = /<\/script/giu;
const COMMENT_RE = /");
for (const name in this.slots) {
if (name === "fallback") {
await renderChild(destination, this.slots.fallback(this.result));
}
}
destination.write(
``
);
}
getComponentPath() {
if (this.componentPath) {
return this.componentPath;
}
const componentPath = this.props["server:component-path"];
if (!componentPath) {
throw new Error(`Could not find server component path`);
}
this.componentPath = componentPath;
return componentPath;
}
getComponentExport() {
if (this.componentExport) {
return this.componentExport;
}
const componentExport = this.props["server:component-export"];
if (!componentExport) {
throw new Error(`Could not find server component export`);
}
this.componentExport = componentExport;
return componentExport;
}
async getHostId() {
if (!this.hostId) {
this.hostId = await crypto.randomUUID();
}
return this.hostId;
}
async getIslandContent() {
if (this.islandContent) {
return this.islandContent;
}
const componentPath = this.getComponentPath();
const componentExport = this.getComponentExport();
const componentId = this.result.serverIslandNameMap.get(componentPath);
if (!componentId) {
throw new Error(`Could not find server component name`);
}
for (const key2 of Object.keys(this.props)) {
if (internalProps.has(key2)) {
delete this.props[key2];
}
}
const renderedSlots = {};
for (const name in this.slots) {
if (name !== "fallback") {
const content = await renderSlotToString(this.result, this.slots[name]);
renderedSlots[name] = content.toString();
}
}
const key = await this.result.key;
const propsEncrypted = Object.keys(this.props).length === 0 ? "" : await encryptString(key, JSON.stringify(this.props));
const hostId = await this.getHostId();
const slash = this.result.base.endsWith("/") ? "" : "/";
let serverIslandUrl = `${this.result.base}${slash}_server-islands/${componentId}${this.result.trailingSlash === "always" ? "/" : ""}`;
const potentialSearchParams = createSearchParams(
componentExport,
propsEncrypted,
safeJsonStringify(renderedSlots)
);
const useGETRequest = isWithinURLLimit(serverIslandUrl, potentialSearchParams);
if (useGETRequest) {
serverIslandUrl += "?" + potentialSearchParams.toString();
this.result._metadata.extraHead.push(
markHTMLString(
``
)
);
}
const method = useGETRequest ? (
// GET request
`let response = await fetch('${serverIslandUrl}');`
) : (
// POST request
`let data = {
componentExport: ${safeJsonStringify(componentExport)},
encryptedProps: ${safeJsonStringify(propsEncrypted)},
slots: ${safeJsonStringify(renderedSlots)},
};
let response = await fetch('${serverIslandUrl}', {
method: 'POST',
body: JSON.stringify(data),
});`
);
this.islandContent = `${method}replaceServerIsland('${hostId}', response);`;
return this.islandContent;
}
}
const renderServerIslandRuntime = () => {
return ``;
};
const SERVER_ISLAND_REPLACER = markHTMLString(
`async function replaceServerIsland(id, r) {
let s = document.querySelector(\`script[data-island-id="\${id}"]\`);
// If there's no matching script, or the request fails then return
if (!s || r.status !== 200 || r.headers.get('content-type')?.split(';')[0].trim() !== 'text/html') return;
// Load the HTML before modifying the DOM in case of errors
let html = await r.text();
// Remove any placeholder content before the island script
while (s.previousSibling && s.previousSibling.nodeType !== 8 && s.previousSibling.data !== '[if astro]>server-island-start line.trim()).filter((line) => line && !line.startsWith("//")).join(" ")
);
export {
ServerIslandComponent,
containsServerDirective,
renderServerIslandRuntime
};