@web-widget/web-widget
Version:
Web front-end application container
200 lines (199 loc) • 6.84 kB
JavaScript
import {
getClientModuleId,
getDisplayModuleId,
unsafePropsToAttrs
} from "./chunk-L7YKSBOA.js";
import {
__forAwait,
__objRest,
__privateAdd,
__privateGet,
__privateSet,
__spreadProps,
__spreadValues
} from "./chunk-PFFVE7GG.js";
// src/server.ts
import { mergeMeta, rebaseMeta, renderMetaToString } from "@web-widget/helpers";
import {
renderLifecycleCacheLayer,
callSyncCacheProvider
} from "@web-widget/lifecycle-cache/server";
var __FEATURE_INJECTING_STYLES__ = false;
var showWebContainerWarning = true;
async function readableStreamToString(readableStream) {
let result = "";
const textDecoder = new TextDecoder();
try {
for (var iter = __forAwait(readableStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
const chunk = temp.value;
result += textDecoder.decode(chunk, { stream: true });
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && await temp.call(iter);
} finally {
if (error)
throw error[0];
}
}
return result;
}
var getType = (obj) => Object.prototype.toString.call(obj).slice(8, -1);
function unsafeAttrsToHtml(attrs) {
return Object.entries(attrs).map(
([attrName, attrValue]) => `${attrName}${attrValue === "" ? "" : '="' + attrValue + '"'}`
).join(" ");
}
var _children, _clientImport, _loader, _options, _renderStage;
var ServerWebWidgetRenderer = class {
constructor(loader, _a) {
__privateAdd(this, _children);
__privateAdd(this, _clientImport);
__privateAdd(this, _loader);
__privateAdd(this, _options);
__privateAdd(this, _renderStage);
this.localName = "web-widget";
var _b = _a, { children = "", renderStage } = _b, options = __objRest(_b, ["children", "renderStage"]);
if (children && options.renderTarget !== "shadow") {
throw new Error(
`Rendering content in a slot requires "options.renderTarget = 'shadow'".`
);
}
__privateSet(this, _children, children);
__privateSet(this, _clientImport, getClientModuleId(loader, options));
__privateSet(this, _loader, loader);
__privateSet(this, _options, options);
__privateSet(this, _renderStage, renderStage);
}
get attributes() {
const clientImport = __privateGet(this, _clientImport);
const _a = __privateGet(this, _options), { data: contextdata, meta: contextmeta } = _a, options = __objRest(_a, ["data", "meta"]);
const renderStage = __privateGet(this, _renderStage);
if (renderStage === "server") {
return unsafePropsToAttrs({
name: options.name
});
}
const attrs = unsafePropsToAttrs(__spreadProps(__spreadValues({}, options), {
// base: options.base?.startsWith("file://") ? undefined : options.base,
contextdata: JSON.stringify(contextdata),
contextmeta: JSON.stringify(contextmeta),
import: clientImport,
recovering: renderStage !== "client"
}));
if (attrs.contextdata === "{}") {
delete attrs.contextdata;
}
if (attrs.contextmeta === "{}") {
delete attrs.contextmeta;
}
return attrs;
}
async renderInnerHTMLToString() {
var _a, _b, _c, _d;
const children = __privateGet(this, _children);
const clientImport = __privateGet(this, _clientImport);
const loader = __privateGet(this, _loader);
const options = __privateGet(this, _options);
const renderStage = __privateGet(this, _renderStage);
let result = "";
if (renderStage === "client") {
return result;
}
const module = await loader();
if (typeof module.render !== "function") {
throw new TypeError(
`The module does not export a "render" method: ${getDisplayModuleId(
loader,
options
)}`
);
}
const meta = rebaseMeta(
mergeMeta((_a = module.meta) != null ? _a : {}, (_b = options.meta) != null ? _b : {}),
clientImport
);
if ((_c = meta.script) == null ? void 0 : _c.length) {
console.warn(`Script tags in meta will be ignored.`);
}
const styleLinks = meta.link ? meta.link.filter(({ rel }) => rel === "stylesheet") : [];
const styles = meta.style || [];
const hasStyle = styleLinks.length || styles.length;
const context = {
children: options.renderTarget === "light" ? children : void 0,
data: options.data,
meta,
module
};
const rawResult = await callSyncCacheProvider(
() => module.render(context)
);
if (getType(rawResult) === "ReadableStream") {
result = await readableStreamToString(rawResult);
} else if (typeof rawResult === "string") {
result = rawResult;
} else {
throw new TypeError(
`Render results in an unknown format: ${getDisplayModuleId(
loader,
options
)}`
);
}
if (hasStyle && __FEATURE_INJECTING_STYLES__) {
result += renderMetaToString({
link: styleLinks,
style: styles
});
result += `<web-widget.body>${result}</web-widget.body>`;
}
if (options.renderTarget === "shadow") {
const shimCode = `(${(a, c = document.currentScript, p = c && c.parentElement, _ = c && c.remove()) => a && p && a(p)})(window.attachShadowRoots)`.replace(/\s/g, "");
result += `<template shadowrootmode="open">${result}</template>`;
result += `<script>${shimCode}</script>`;
result += children;
}
try {
result += renderLifecycleCacheLayer();
} catch (error) {
if ((_d = error == null ? void 0 : error.message) == null ? void 0 : _d.includes("Context is not available")) {
if (isWebContainer()) {
if (showWebContainerWarning) {
console.warn(
`WARN: LifecycleCache cannot be serialized.
WARN: This may be because the WebContainer environment does not support AsyncLocalStorage.
WARN: Please see https://github.com/stackblitz/webcontainer-core/issues/1169`
);
showWebContainerWarning = false;
}
} else {
}
} else {
throw error;
}
}
return result;
}
async renderOuterHTMLToString() {
const tag = this.localName;
const attributes = this.attributes;
const children = await this.renderInnerHTMLToString();
return `<${tag} ${unsafeAttrsToHtml(attributes)}>${children}</${tag}>`;
}
};
_children = new WeakMap();
_clientImport = new WeakMap();
_loader = new WeakMap();
_options = new WeakMap();
_renderStage = new WeakMap();
function isWebContainer() {
var _a, _b;
return typeof ((_b = (_a = Reflect.get(globalThis, "process")) == null ? void 0 : _a.versions) == null ? void 0 : _b.webcontainer) === "string";
}
var WebWidgetRenderer = ServerWebWidgetRenderer;
export {
WebWidgetRenderer
};
//# sourceMappingURL=web-widget.server.js.map