@openelement/ssg 0.41.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,169 @@
1
+ /**
2
+ * @openelement/ssg - SSG entry code generation
3
+ *
4
+ * Generates the SSG-specific sections of the virtual Hono entry module,
5
+ * including SSG utility re-exports, routeInfo, renderRoute, getStaticPaths,
6
+ * and supporting helper functions.
7
+ */ import { routeRevalidateExpr, routeTagNameExpr } from './entry-render-helpers.js';
8
+ /**
9
+ * Render the SSG-specific section of the entry code.
10
+ *
11
+ * This includes SSG utility re-exports, route metadata, renderRoute,
12
+ * getStaticPaths, and supporting helper functions.
13
+ *
14
+ * Returns an empty string when SSG mode is disabled.
15
+ */ export function renderSsgSection(desc) {
16
+ if (!desc.isSSG) return '';
17
+ const lines = [];
18
+ lines.push('');
19
+ lines.push('// - SSG Utility Re-exports (ADR 0008 Phase C) -');
20
+ lines.push('// Used by build-ssg.ts after importing the SSR bundle.');
21
+ lines.push('// Shared module scope ensures adapter/data state is consistent.');
22
+ lines.push('');
23
+ lines.push('export { renderDsd, renderDsdTree, wrapInDocument } from "@openelement/core"');
24
+ lines.push('export { posts, getPostBySlug, getBlogOptions } from "@openelement/generated/blog-data"');
25
+ lines.push('export { generateSitemap } from "@openelement/content/sitemap"');
26
+ lines.push('export { locales, getDefaultLocale, getI18nOptions } from "@openelement/generated/i18n"');
27
+ lines.push('');
28
+ lines.push('// - ADR 0014: DSD-first rendering API -');
29
+ lines.push('// build-ssg.ts calls these - never touches customElements directly.');
30
+ lines.push('');
31
+ // --- routeInfo: structured route metadata ---
32
+ lines.push('export const routeInfo = [');
33
+ for (const r of desc.pageRoutes){
34
+ const tagNameExpr = routeTagNameExpr(r.varName, r.tagName);
35
+ lines.push(` { path: '${r.path}', filePath: ${JSON.stringify(r.filePath)}, tagName: ${tagNameExpr}, module: ${r.varName}, isDynamic: ${!!r.isDynamic}, paramNames: ${JSON.stringify(r.paramNames || [])}, revalidate: ${routeRevalidateExpr(r.varName)}, rendering: (__pageDefinition(${r.varName}).renderIntent?.mode || "auto"), streaming: (__pageDefinition(${r.varName}).renderIntent?.streaming || "auto") },`);
36
+ }
37
+ lines.push('];');
38
+ lines.push('');
39
+ lines.push('function __pageDefinition(module) {');
40
+ lines.push(' return module?.default?.openElementPage || {};');
41
+ lines.push('}');
42
+ lines.push('');
43
+ lines.push('function __routeMeta(module) {');
44
+ lines.push(' const page = __pageDefinition(module);');
45
+ lines.push(' return {');
46
+ lines.push(' ...(page.route !== undefined ? { route: page.route } : {}),');
47
+ lines.push(' ...(page.head?.title !== undefined ? { title: page.head.title } : {}),');
48
+ lines.push(' ...(page.head?.description !== undefined ? { description: page.head.description } : {}),');
49
+ lines.push(' };');
50
+ lines.push('}');
51
+ lines.push('');
52
+ lines.push('function __rendererContext(routePath, params) {');
53
+ lines.push(' return {');
54
+ lines.push(' req: {');
55
+ lines.push(' path: routePath,');
56
+ lines.push(' param: (name) => name ? params[name] : params,');
57
+ lines.push(' },');
58
+ lines.push(' get: () => undefined,');
59
+ lines.push(' set: () => undefined,');
60
+ lines.push(' };');
61
+ lines.push('}');
62
+ lines.push('');
63
+ lines.push('function __matchingRenderers(routePath) {');
64
+ lines.push(' const renderers = [];');
65
+ for (const renderer of desc.renderers){
66
+ if (renderer.scope === '/') {
67
+ lines.push(` renderers.push(${renderer.varName}.default);`);
68
+ } else {
69
+ lines.push(` if (routePath.toLowerCase() === '${renderer.scope.toLowerCase()}' || routePath.toLowerCase().startsWith('${renderer.scope.toLowerCase()}/')) renderers.push(${renderer.varName}.default);`);
70
+ }
71
+ }
72
+ lines.push(' return renderers;');
73
+ lines.push('}');
74
+ lines.push('');
75
+ // --- renderRoute ---
76
+ lines.push('/**');
77
+ lines.push(' * Render a route to structured output with diagnostics (ADR 0014, v0.15.3).');
78
+ lines.push(' * Returns { html, errors, hydrationHints, componentCount, renderTimeMs }.');
79
+ lines.push(' * Caller can inspect errors/hints for observability or use .html for output.');
80
+ lines.push(' */');
81
+ lines.push('export async function renderRoute(routePath, options = {}) {');
82
+ lines.push(' const info = routeInfo.find(r => r.path === routePath);');
83
+ lines.push(" if (!info) throw new Error('[openElement] renderRoute: route not found: ' + routePath);");
84
+ lines.push(' const { params = {}, locale, title, lang, headExtras } = options;');
85
+ lines.push(' const page = __pageDefinition(info.module);');
86
+ lines.push(' const routeMeta = __routeMeta(info.module);');
87
+ lines.push(' const loadContext = {');
88
+ lines.push(' params,');
89
+ lines.push(' request: options.request,');
90
+ lines.push(' env: options.env || {},');
91
+ lines.push(' platform: options.platform,');
92
+ lines.push(' route: { path: routePath, filePath: info.filePath },');
93
+ lines.push(' };');
94
+ lines.push(' let data;');
95
+ lines.push(' try {');
96
+ lines.push(' data = typeof info.module.loader === "function" ? await info.module.loader(loadContext) : undefined;');
97
+ lines.push(' } catch (error) {');
98
+ lines.push(' if (__isOpenElementRedirect(error)) {');
99
+ lines.push(' const html = wrapInDocument(__statusHtml("Redirect", "Redirecting to " + error.location), {');
100
+ lines.push(' title: "Redirect",');
101
+ lines.push(' lang: lang || locale || "en",');
102
+ lines.push(' headExtras: headExtras !== undefined ? headExtras : (typeof __headExtras !== "undefined" ? __headExtras : ""),');
103
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(desc.document.allowHeadExtrasScripts)},`);
104
+ lines.push(' });');
105
+ lines.push(' return { html, status: error.status, redirect: { location: error.location, status: error.status }, errors: [], hydrationHints: [], componentCount: 0, renderTimeMs: 0 };');
106
+ lines.push(' }');
107
+ lines.push(' if (__isOpenElementNotFound(error)) {');
108
+ lines.push(' const html = wrapInDocument(__statusHtml("404 Not Found", error.message || "Not Found"), {');
109
+ lines.push(' title: "404 Not Found",');
110
+ lines.push(' lang: lang || locale || "en",');
111
+ lines.push(' headExtras: headExtras !== undefined ? headExtras : (typeof __headExtras !== "undefined" ? __headExtras : ""),');
112
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(desc.document.allowHeadExtrasScripts)},`);
113
+ lines.push(' });');
114
+ lines.push(' return { html, status: 404, notFound: true, errors: [], hydrationHints: [], componentCount: 0, renderTimeMs: 0 };');
115
+ lines.push(' }');
116
+ lines.push(' throw error;');
117
+ lines.push(' }');
118
+ lines.push(' const props = { ...params, data, __openElementActionData: undefined, __openElementParams: params, __openElementRequest: options.request, __openElementRoute: loadContext.route, __openElementMeta: routeMeta };');
119
+ lines.push(' if (locale) props.locale = locale;');
120
+ lines.push(' const startTime = typeof performance !== "undefined" ? performance.now() : 0;');
121
+ lines.push(' let node = jsx(info.tagName, props);');
122
+ lines.push(' for (const renderer of __matchingRenderers(routePath)) {');
123
+ lines.push(' node = await renderer.wrap(node, __rendererContext(routePath, params));');
124
+ lines.push(' }');
125
+ lines.push(' const content = await __renderAppShell(node, routePath, { locale, routeMeta });');
126
+ lines.push(' const renderTimeMs = typeof performance !== "undefined" ? performance.now() - startTime : 0;');
127
+ lines.push(' const componentCount = (content.match(/<template shadowrootmode="open"/g) || []).length;');
128
+ lines.push(' const fullHtml = wrapInDocument(content, {');
129
+ lines.push(' title: title || page.head?.title || "openElement",');
130
+ lines.push(' lang: lang || locale || "en",');
131
+ lines.push(' meta: { description: page.head?.description, tags: page.head?.meta },');
132
+ lines.push(' headExtras: headExtras !== undefined ? headExtras : (typeof __headExtras !== "undefined" ? __headExtras : ""),');
133
+ lines.push(' dangerouslyHeadFragments: page.head?.dangerouslyHeadFragments || [],');
134
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(desc.document.allowHeadExtrasScripts)},`);
135
+ lines.push(' });');
136
+ lines.push(' return {');
137
+ lines.push(' html: fullHtml,');
138
+ lines.push(' errors: [],');
139
+ lines.push(' hydrationHints: [],');
140
+ lines.push(' componentCount,');
141
+ lines.push(' renderTimeMs,');
142
+ lines.push(' };');
143
+ lines.push('}');
144
+ lines.push('');
145
+ // --- getStaticPaths ---
146
+ lines.push('/**');
147
+ lines.push(' * Get static paths for a dynamic route (ADR 0014).');
148
+ lines.push(' * Returns [] for non-dynamic routes.');
149
+ lines.push(' */');
150
+ lines.push('export async function getStaticPaths(routePath) {');
151
+ lines.push(' const info = routeInfo.find(r => r.path === routePath);');
152
+ lines.push(' if (!info || !info.isDynamic) return [];');
153
+ const dynamicRoutes = desc.pageRoutes.filter((r)=>r.isDynamic);
154
+ if (dynamicRoutes.length > 0) {
155
+ lines.push(" // Dispatch to the route module's getStaticPaths()");
156
+ for (const r of dynamicRoutes){
157
+ lines.push(` if (routePath === '${r.path.replace(/'/g, "\\'")}') {`);
158
+ lines.push(` if (typeof ${r.varName}.getStaticPaths === 'function') {`);
159
+ lines.push(` return await ${r.varName}.getStaticPaths();`);
160
+ lines.push(` }`);
161
+ lines.push(` return [];`);
162
+ lines.push(` }`);
163
+ }
164
+ }
165
+ lines.push(' return [];');
166
+ lines.push('}');
167
+ return lines.join('\n');
168
+ }
169
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9zc2cvc3JjL2VudHJ5LXJlbmRlci1zc2cudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAb3BlbmVsZW1lbnQvc3NnIC0gU1NHIGVudHJ5IGNvZGUgZ2VuZXJhdGlvblxuICpcbiAqIEdlbmVyYXRlcyB0aGUgU1NHLXNwZWNpZmljIHNlY3Rpb25zIG9mIHRoZSB2aXJ0dWFsIEhvbm8gZW50cnkgbW9kdWxlLFxuICogaW5jbHVkaW5nIFNTRyB1dGlsaXR5IHJlLWV4cG9ydHMsIHJvdXRlSW5mbywgcmVuZGVyUm91dGUsIGdldFN0YXRpY1BhdGhzLFxuICogYW5kIHN1cHBvcnRpbmcgaGVscGVyIGZ1bmN0aW9ucy5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEVudHJ5RGVzY3JpcHRvciB9IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9zc2cnO1xuaW1wb3J0IHsgcm91dGVSZXZhbGlkYXRlRXhwciwgcm91dGVUYWdOYW1lRXhwciB9IGZyb20gJy4vZW50cnktcmVuZGVyLWhlbHBlcnMuanMnO1xuXG4vKipcbiAqIFJlbmRlciB0aGUgU1NHLXNwZWNpZmljIHNlY3Rpb24gb2YgdGhlIGVudHJ5IGNvZGUuXG4gKlxuICogVGhpcyBpbmNsdWRlcyBTU0cgdXRpbGl0eSByZS1leHBvcnRzLCByb3V0ZSBtZXRhZGF0YSwgcmVuZGVyUm91dGUsXG4gKiBnZXRTdGF0aWNQYXRocywgYW5kIHN1cHBvcnRpbmcgaGVscGVyIGZ1bmN0aW9ucy5cbiAqXG4gKiBSZXR1cm5zIGFuIGVtcHR5IHN0cmluZyB3aGVuIFNTRyBtb2RlIGlzIGRpc2FibGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyU3NnU2VjdGlvbihkZXNjOiBFbnRyeURlc2NyaXB0b3IpOiBzdHJpbmcge1xuICBpZiAoIWRlc2MuaXNTU0cpIHJldHVybiAnJztcblxuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcblxuICBsaW5lcy5wdXNoKCcnKTtcbiAgbGluZXMucHVzaChcbiAgICAnLy8gLSBTU0cgVXRpbGl0eSBSZS1leHBvcnRzIChBRFIgMDAwOCBQaGFzZSBDKSAtJyxcbiAgKTtcbiAgbGluZXMucHVzaCgnLy8gVXNlZCBieSBidWlsZC1zc2cudHMgYWZ0ZXIgaW1wb3J0aW5nIHRoZSBTU1IgYnVuZGxlLicpO1xuICBsaW5lcy5wdXNoKFxuICAgICcvLyBTaGFyZWQgbW9kdWxlIHNjb3BlIGVuc3VyZXMgYWRhcHRlci9kYXRhIHN0YXRlIGlzIGNvbnNpc3RlbnQuJyxcbiAgKTtcbiAgbGluZXMucHVzaCgnJyk7XG4gIGxpbmVzLnB1c2goXG4gICAgJ2V4cG9ydCB7IHJlbmRlckRzZCwgcmVuZGVyRHNkVHJlZSwgd3JhcEluRG9jdW1lbnQgfSBmcm9tIFwiQG9wZW5lbGVtZW50L2NvcmVcIicsXG4gICk7XG4gIGxpbmVzLnB1c2goXG4gICAgJ2V4cG9ydCB7IHBvc3RzLCBnZXRQb3N0QnlTbHVnLCBnZXRCbG9nT3B0aW9ucyB9IGZyb20gXCJAb3BlbmVsZW1lbnQvZ2VuZXJhdGVkL2Jsb2ctZGF0YVwiJyxcbiAgKTtcbiAgbGluZXMucHVzaCgnZXhwb3J0IHsgZ2VuZXJhdGVTaXRlbWFwIH0gZnJvbSBcIkBvcGVuZWxlbWVudC9jb250ZW50L3NpdGVtYXBcIicpO1xuICBsaW5lcy5wdXNoKFxuICAgICdleHBvcnQgeyBsb2NhbGVzLCBnZXREZWZhdWx0TG9jYWxlLCBnZXRJMThuT3B0aW9ucyB9IGZyb20gXCJAb3BlbmVsZW1lbnQvZ2VuZXJhdGVkL2kxOG5cIicsXG4gICk7XG4gIGxpbmVzLnB1c2goJycpO1xuICBsaW5lcy5wdXNoKFxuICAgICcvLyAtIEFEUiAwMDE0OiBEU0QtZmlyc3QgcmVuZGVyaW5nIEFQSSAtJyxcbiAgKTtcbiAgbGluZXMucHVzaChcbiAgICAnLy8gYnVpbGQtc3NnLnRzIGNhbGxzIHRoZXNlIC0gbmV2ZXIgdG91Y2hlcyBjdXN0b21FbGVtZW50cyBkaXJlY3RseS4nLFxuICApO1xuICBsaW5lcy5wdXNoKCcnKTtcblxuICAvLyAtLS0gcm91dGVJbmZvOiBzdHJ1Y3R1cmVkIHJvdXRlIG1ldGFkYXRhIC0tLVxuICBsaW5lcy5wdXNoKCdleHBvcnQgY29uc3Qgcm91dGVJbmZvID0gWycpO1xuICBmb3IgKGNvbnN0IHIgb2YgZGVzYy5wYWdlUm91dGVzKSB7XG4gICAgY29uc3QgdGFnTmFtZUV4cHIgPSByb3V0ZVRhZ05hbWVFeHByKHIudmFyTmFtZSwgci50YWdOYW1lKTtcbiAgICBsaW5lcy5wdXNoKFxuICAgICAgYCAgeyBwYXRoOiAnJHtyLnBhdGh9JywgZmlsZVBhdGg6ICR7XG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHIuZmlsZVBhdGgpXG4gICAgICB9LCB0YWdOYW1lOiAke3RhZ05hbWVFeHByfSwgbW9kdWxlOiAke3IudmFyTmFtZX0sIGlzRHluYW1pYzogJHshIXJcbiAgICAgICAgLmlzRHluYW1pY30sIHBhcmFtTmFtZXM6ICR7SlNPTi5zdHJpbmdpZnkoci5wYXJhbU5hbWVzIHx8IFtdKX0sIHJldmFsaWRhdGU6ICR7XG4gICAgICAgIHJvdXRlUmV2YWxpZGF0ZUV4cHIoci52YXJOYW1lKVxuICAgICAgfSwgcmVuZGVyaW5nOiAoX19wYWdlRGVmaW5pdGlvbigke3IudmFyTmFtZX0pLnJlbmRlckludGVudD8ubW9kZSB8fCBcImF1dG9cIiksIHN0cmVhbWluZzogKF9fcGFnZURlZmluaXRpb24oJHtyLnZhck5hbWV9KS5yZW5kZXJJbnRlbnQ/LnN0cmVhbWluZyB8fCBcImF1dG9cIikgfSxgLFxuICAgICk7XG4gIH1cbiAgbGluZXMucHVzaCgnXTsnKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgbGluZXMucHVzaCgnZnVuY3Rpb24gX19wYWdlRGVmaW5pdGlvbihtb2R1bGUpIHsnKTtcbiAgbGluZXMucHVzaCgnICByZXR1cm4gbW9kdWxlPy5kZWZhdWx0Py5vcGVuRWxlbWVudFBhZ2UgfHwge307Jyk7XG4gIGxpbmVzLnB1c2goJ30nKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgbGluZXMucHVzaCgnZnVuY3Rpb24gX19yb3V0ZU1ldGEobW9kdWxlKSB7Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgcGFnZSA9IF9fcGFnZURlZmluaXRpb24obW9kdWxlKTsnKTtcbiAgbGluZXMucHVzaCgnICByZXR1cm4geycpO1xuICBsaW5lcy5wdXNoKCcgICAgLi4uKHBhZ2Uucm91dGUgIT09IHVuZGVmaW5lZCA/IHsgcm91dGU6IHBhZ2Uucm91dGUgfSA6IHt9KSwnKTtcbiAgbGluZXMucHVzaCgnICAgIC4uLihwYWdlLmhlYWQ/LnRpdGxlICE9PSB1bmRlZmluZWQgPyB7IHRpdGxlOiBwYWdlLmhlYWQudGl0bGUgfSA6IHt9KSwnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgIC4uLihwYWdlLmhlYWQ/LmRlc2NyaXB0aW9uICE9PSB1bmRlZmluZWQgPyB7IGRlc2NyaXB0aW9uOiBwYWdlLmhlYWQuZGVzY3JpcHRpb24gfSA6IHt9KSwnLFxuICApO1xuICBsaW5lcy5wdXNoKCcgIH07Jyk7XG4gIGxpbmVzLnB1c2goJ30nKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgbGluZXMucHVzaCgnZnVuY3Rpb24gX19yZW5kZXJlckNvbnRleHQocm91dGVQYXRoLCBwYXJhbXMpIHsnKTtcbiAgbGluZXMucHVzaCgnICByZXR1cm4geycpO1xuICBsaW5lcy5wdXNoKCcgICAgcmVxOiB7Jyk7XG4gIGxpbmVzLnB1c2goJyAgICAgIHBhdGg6IHJvdXRlUGF0aCwnKTtcbiAgbGluZXMucHVzaCgnICAgICAgcGFyYW06IChuYW1lKSA9PiBuYW1lID8gcGFyYW1zW25hbWVdIDogcGFyYW1zLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgfSwnKTtcbiAgbGluZXMucHVzaCgnICAgIGdldDogKCkgPT4gdW5kZWZpbmVkLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgc2V0OiAoKSA9PiB1bmRlZmluZWQsJyk7XG4gIGxpbmVzLnB1c2goJyAgfTsnKTtcbiAgbGluZXMucHVzaCgnfScpO1xuICBsaW5lcy5wdXNoKCcnKTtcblxuICBsaW5lcy5wdXNoKCdmdW5jdGlvbiBfX21hdGNoaW5nUmVuZGVyZXJzKHJvdXRlUGF0aCkgeycpO1xuICBsaW5lcy5wdXNoKCcgIGNvbnN0IHJlbmRlcmVycyA9IFtdOycpO1xuICBmb3IgKGNvbnN0IHJlbmRlcmVyIG9mIGRlc2MucmVuZGVyZXJzKSB7XG4gICAgaWYgKHJlbmRlcmVyLnNjb3BlID09PSAnLycpIHtcbiAgICAgIGxpbmVzLnB1c2goYCAgcmVuZGVyZXJzLnB1c2goJHtyZW5kZXJlci52YXJOYW1lfS5kZWZhdWx0KTtgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGluZXMucHVzaChcbiAgICAgICAgYCAgaWYgKHJvdXRlUGF0aC50b0xvd2VyQ2FzZSgpID09PSAnJHtyZW5kZXJlci5zY29wZS50b0xvd2VyQ2FzZSgpfScgfHwgcm91dGVQYXRoLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aCgnJHtyZW5kZXJlci5zY29wZS50b0xvd2VyQ2FzZSgpfS8nKSkgcmVuZGVyZXJzLnB1c2goJHtyZW5kZXJlci52YXJOYW1lfS5kZWZhdWx0KTtgLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgbGluZXMucHVzaCgnICByZXR1cm4gcmVuZGVyZXJzOycpO1xuICBsaW5lcy5wdXNoKCd9Jyk7XG4gIGxpbmVzLnB1c2goJycpO1xuXG4gIC8vIC0tLSByZW5kZXJSb3V0ZSAtLS1cbiAgbGluZXMucHVzaCgnLyoqJyk7XG4gIGxpbmVzLnB1c2goJyAqIFJlbmRlciBhIHJvdXRlIHRvIHN0cnVjdHVyZWQgb3V0cHV0IHdpdGggZGlhZ25vc3RpY3MgKEFEUiAwMDE0LCB2MC4xNS4zKS4nKTtcbiAgbGluZXMucHVzaChcbiAgICAnICogUmV0dXJucyB7IGh0bWwsIGVycm9ycywgaHlkcmF0aW9uSGludHMsIGNvbXBvbmVudENvdW50LCByZW5kZXJUaW1lTXMgfS4nLFxuICApO1xuICBsaW5lcy5wdXNoKFxuICAgICcgKiBDYWxsZXIgY2FuIGluc3BlY3QgZXJyb3JzL2hpbnRzIGZvciBvYnNlcnZhYmlsaXR5IG9yIHVzZSAuaHRtbCBmb3Igb3V0cHV0LicsXG4gICk7XG4gIGxpbmVzLnB1c2goJyAqLycpO1xuICBsaW5lcy5wdXNoKCdleHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVuZGVyUm91dGUocm91dGVQYXRoLCBvcHRpb25zID0ge30pIHsnKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBpbmZvID0gcm91dGVJbmZvLmZpbmQociA9PiByLnBhdGggPT09IHJvdXRlUGF0aCk7Jyk7XG4gIGxpbmVzLnB1c2goXG4gICAgXCIgIGlmICghaW5mbykgdGhyb3cgbmV3IEVycm9yKCdbb3BlbkVsZW1lbnRdIHJlbmRlclJvdXRlOiByb3V0ZSBub3QgZm91bmQ6ICcgKyByb3V0ZVBhdGgpO1wiLFxuICApO1xuICBsaW5lcy5wdXNoKFxuICAgICcgIGNvbnN0IHsgcGFyYW1zID0ge30sIGxvY2FsZSwgdGl0bGUsIGxhbmcsIGhlYWRFeHRyYXMgfSA9IG9wdGlvbnM7JyxcbiAgKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBwYWdlID0gX19wYWdlRGVmaW5pdGlvbihpbmZvLm1vZHVsZSk7Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3Qgcm91dGVNZXRhID0gX19yb3V0ZU1ldGEoaW5mby5tb2R1bGUpOycpO1xuICBsaW5lcy5wdXNoKCcgIGNvbnN0IGxvYWRDb250ZXh0ID0geycpO1xuICBsaW5lcy5wdXNoKCcgICAgcGFyYW1zLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgcmVxdWVzdDogb3B0aW9ucy5yZXF1ZXN0LCcpO1xuICBsaW5lcy5wdXNoKCcgICAgZW52OiBvcHRpb25zLmVudiB8fCB7fSwnKTtcbiAgbGluZXMucHVzaCgnICAgIHBsYXRmb3JtOiBvcHRpb25zLnBsYXRmb3JtLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgcm91dGU6IHsgcGF0aDogcm91dGVQYXRoLCBmaWxlUGF0aDogaW5mby5maWxlUGF0aCB9LCcpO1xuICBsaW5lcy5wdXNoKCcgIH07Jyk7XG4gIGxpbmVzLnB1c2goJyAgbGV0IGRhdGE7Jyk7XG4gIGxpbmVzLnB1c2goJyAgdHJ5IHsnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgIGRhdGEgPSB0eXBlb2YgaW5mby5tb2R1bGUubG9hZGVyID09PSBcImZ1bmN0aW9uXCIgPyBhd2FpdCBpbmZvLm1vZHVsZS5sb2FkZXIobG9hZENvbnRleHQpIDogdW5kZWZpbmVkOycsXG4gICk7XG4gIGxpbmVzLnB1c2goJyAgfSBjYXRjaCAoZXJyb3IpIHsnKTtcbiAgbGluZXMucHVzaCgnICAgIGlmIChfX2lzT3BlbkVsZW1lbnRSZWRpcmVjdChlcnJvcikpIHsnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgICAgY29uc3QgaHRtbCA9IHdyYXBJbkRvY3VtZW50KF9fc3RhdHVzSHRtbChcIlJlZGlyZWN0XCIsIFwiUmVkaXJlY3RpbmcgdG8gXCIgKyBlcnJvci5sb2NhdGlvbiksIHsnLFxuICApO1xuICBsaW5lcy5wdXNoKCcgICAgICAgIHRpdGxlOiBcIlJlZGlyZWN0XCIsJyk7XG4gIGxpbmVzLnB1c2goJyAgICAgICAgbGFuZzogbGFuZyB8fCBsb2NhbGUgfHwgXCJlblwiLCcpO1xuICBsaW5lcy5wdXNoKFxuICAgICcgICAgICAgIGhlYWRFeHRyYXM6IGhlYWRFeHRyYXMgIT09IHVuZGVmaW5lZCA/IGhlYWRFeHRyYXMgOiAodHlwZW9mIF9faGVhZEV4dHJhcyAhPT0gXCJ1bmRlZmluZWRcIiA/IF9faGVhZEV4dHJhcyA6IFwiXCIpLCcsXG4gICk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgICAgYWxsb3dIZWFkRXh0cmFzU2NyaXB0czogJHtKU09OLnN0cmluZ2lmeShkZXNjLmRvY3VtZW50LmFsbG93SGVhZEV4dHJhc1NjcmlwdHMpfSxgLFxuICApO1xuICBsaW5lcy5wdXNoKCcgICAgICB9KTsnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgICAgcmV0dXJuIHsgaHRtbCwgc3RhdHVzOiBlcnJvci5zdGF0dXMsIHJlZGlyZWN0OiB7IGxvY2F0aW9uOiBlcnJvci5sb2NhdGlvbiwgc3RhdHVzOiBlcnJvci5zdGF0dXMgfSwgZXJyb3JzOiBbXSwgaHlkcmF0aW9uSGludHM6IFtdLCBjb21wb25lbnRDb3VudDogMCwgcmVuZGVyVGltZU1zOiAwIH07JyxcbiAgKTtcbiAgbGluZXMucHVzaCgnICAgIH0nKTtcbiAgbGluZXMucHVzaCgnICAgIGlmIChfX2lzT3BlbkVsZW1lbnROb3RGb3VuZChlcnJvcikpIHsnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgICAgY29uc3QgaHRtbCA9IHdyYXBJbkRvY3VtZW50KF9fc3RhdHVzSHRtbChcIjQwNCBOb3QgRm91bmRcIiwgZXJyb3IubWVzc2FnZSB8fCBcIk5vdCBGb3VuZFwiKSwgeycsXG4gICk7XG4gIGxpbmVzLnB1c2goJyAgICAgICAgdGl0bGU6IFwiNDA0IE5vdCBGb3VuZFwiLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgICAgIGxhbmc6IGxhbmcgfHwgbG9jYWxlIHx8IFwiZW5cIiwnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgICAgICBoZWFkRXh0cmFzOiBoZWFkRXh0cmFzICE9PSB1bmRlZmluZWQgPyBoZWFkRXh0cmFzIDogKHR5cGVvZiBfX2hlYWRFeHRyYXMgIT09IFwidW5kZWZpbmVkXCIgPyBfX2hlYWRFeHRyYXMgOiBcIlwiKSwnLFxuICApO1xuICBsaW5lcy5wdXNoKFxuICAgIGAgICAgICAgIGFsbG93SGVhZEV4dHJhc1NjcmlwdHM6ICR7SlNPTi5zdHJpbmdpZnkoZGVzYy5kb2N1bWVudC5hbGxvd0hlYWRFeHRyYXNTY3JpcHRzKX0sYCxcbiAgKTtcbiAgbGluZXMucHVzaCgnICAgICAgfSk7Jyk7XG4gIGxpbmVzLnB1c2goXG4gICAgJyAgICAgIHJldHVybiB7IGh0bWwsIHN0YXR1czogNDA0LCBub3RGb3VuZDogdHJ1ZSwgZXJyb3JzOiBbXSwgaHlkcmF0aW9uSGludHM6IFtdLCBjb21wb25lbnRDb3VudDogMCwgcmVuZGVyVGltZU1zOiAwIH07JyxcbiAgKTtcbiAgbGluZXMucHVzaCgnICAgIH0nKTtcbiAgbGluZXMucHVzaCgnICAgIHRocm93IGVycm9yOycpO1xuICBsaW5lcy5wdXNoKCcgIH0nKTtcbiAgbGluZXMucHVzaChcbiAgICAnICBjb25zdCBwcm9wcyA9IHsgLi4ucGFyYW1zLCBkYXRhLCBfX29wZW5FbGVtZW50QWN0aW9uRGF0YTogdW5kZWZpbmVkLCBfX29wZW5FbGVtZW50UGFyYW1zOiBwYXJhbXMsIF9fb3BlbkVsZW1lbnRSZXF1ZXN0OiBvcHRpb25zLnJlcXVlc3QsIF9fb3BlbkVsZW1lbnRSb3V0ZTogbG9hZENvbnRleHQucm91dGUsIF9fb3BlbkVsZW1lbnRNZXRhOiByb3V0ZU1ldGEgfTsnLFxuICApO1xuICBsaW5lcy5wdXNoKCcgIGlmIChsb2NhbGUpIHByb3BzLmxvY2FsZSA9IGxvY2FsZTsnKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBzdGFydFRpbWUgPSB0eXBlb2YgcGVyZm9ybWFuY2UgIT09IFwidW5kZWZpbmVkXCIgPyBwZXJmb3JtYW5jZS5ub3coKSA6IDA7Jyk7XG4gIGxpbmVzLnB1c2goJyAgbGV0IG5vZGUgPSBqc3goaW5mby50YWdOYW1lLCBwcm9wcyk7Jyk7XG4gIGxpbmVzLnB1c2goJyAgZm9yIChjb25zdCByZW5kZXJlciBvZiBfX21hdGNoaW5nUmVuZGVyZXJzKHJvdXRlUGF0aCkpIHsnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgIG5vZGUgPSBhd2FpdCByZW5kZXJlci53cmFwKG5vZGUsIF9fcmVuZGVyZXJDb250ZXh0KHJvdXRlUGF0aCwgcGFyYW1zKSk7JyxcbiAgKTtcbiAgbGluZXMucHVzaCgnICB9Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgY29udGVudCA9IGF3YWl0IF9fcmVuZGVyQXBwU2hlbGwobm9kZSwgcm91dGVQYXRoLCB7IGxvY2FsZSwgcm91dGVNZXRhIH0pOycpO1xuICBsaW5lcy5wdXNoKFxuICAgICcgIGNvbnN0IHJlbmRlclRpbWVNcyA9IHR5cGVvZiBwZXJmb3JtYW5jZSAhPT0gXCJ1bmRlZmluZWRcIiA/IHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRUaW1lIDogMDsnLFxuICApO1xuICBsaW5lcy5wdXNoKFxuICAgICcgIGNvbnN0IGNvbXBvbmVudENvdW50ID0gKGNvbnRlbnQubWF0Y2goLzx0ZW1wbGF0ZSBzaGFkb3dyb290bW9kZT1cIm9wZW5cIi9nKSB8fCBbXSkubGVuZ3RoOycsXG4gICk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgZnVsbEh0bWwgPSB3cmFwSW5Eb2N1bWVudChjb250ZW50LCB7Jyk7XG4gIGxpbmVzLnB1c2goJyAgICB0aXRsZTogdGl0bGUgfHwgcGFnZS5oZWFkPy50aXRsZSB8fCBcIm9wZW5FbGVtZW50XCIsJyk7XG4gIGxpbmVzLnB1c2goJyAgICBsYW5nOiBsYW5nIHx8IGxvY2FsZSB8fCBcImVuXCIsJyk7XG4gIGxpbmVzLnB1c2goJyAgICBtZXRhOiB7IGRlc2NyaXB0aW9uOiBwYWdlLmhlYWQ/LmRlc2NyaXB0aW9uLCB0YWdzOiBwYWdlLmhlYWQ/Lm1ldGEgfSwnKTtcbiAgbGluZXMucHVzaChcbiAgICAnICAgIGhlYWRFeHRyYXM6IGhlYWRFeHRyYXMgIT09IHVuZGVmaW5lZCA/IGhlYWRFeHRyYXMgOiAodHlwZW9mIF9faGVhZEV4dHJhcyAhPT0gXCJ1bmRlZmluZWRcIiA/IF9faGVhZEV4dHJhcyA6IFwiXCIpLCcsXG4gICk7XG4gIGxpbmVzLnB1c2goJyAgICBkYW5nZXJvdXNseUhlYWRGcmFnbWVudHM6IHBhZ2UuaGVhZD8uZGFuZ2Vyb3VzbHlIZWFkRnJhZ21lbnRzIHx8IFtdLCcpO1xuICBsaW5lcy5wdXNoKFxuICAgIGAgICAgYWxsb3dIZWFkRXh0cmFzU2NyaXB0czogJHtKU09OLnN0cmluZ2lmeShkZXNjLmRvY3VtZW50LmFsbG93SGVhZEV4dHJhc1NjcmlwdHMpfSxgLFxuICApO1xuICBsaW5lcy5wdXNoKCcgIH0pOycpO1xuICBsaW5lcy5wdXNoKCcgIHJldHVybiB7Jyk7XG4gIGxpbmVzLnB1c2goJyAgICBodG1sOiBmdWxsSHRtbCwnKTtcbiAgbGluZXMucHVzaCgnICAgIGVycm9yczogW10sJyk7XG4gIGxpbmVzLnB1c2goJyAgICBoeWRyYXRpb25IaW50czogW10sJyk7XG4gIGxpbmVzLnB1c2goJyAgICBjb21wb25lbnRDb3VudCwnKTtcbiAgbGluZXMucHVzaCgnICAgIHJlbmRlclRpbWVNcywnKTtcbiAgbGluZXMucHVzaCgnICB9OycpO1xuICBsaW5lcy5wdXNoKCd9Jyk7XG4gIGxpbmVzLnB1c2goJycpO1xuXG4gIC8vIC0tLSBnZXRTdGF0aWNQYXRocyAtLS1cbiAgbGluZXMucHVzaCgnLyoqJyk7XG4gIGxpbmVzLnB1c2goJyAqIEdldCBzdGF0aWMgcGF0aHMgZm9yIGEgZHluYW1pYyByb3V0ZSAoQURSIDAwMTQpLicpO1xuICBsaW5lcy5wdXNoKCcgKiBSZXR1cm5zIFtdIGZvciBub24tZHluYW1pYyByb3V0ZXMuJyk7XG4gIGxpbmVzLnB1c2goJyAqLycpO1xuICBsaW5lcy5wdXNoKCdleHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0U3RhdGljUGF0aHMocm91dGVQYXRoKSB7Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgaW5mbyA9IHJvdXRlSW5mby5maW5kKHIgPT4gci5wYXRoID09PSByb3V0ZVBhdGgpOycpO1xuICBsaW5lcy5wdXNoKCcgIGlmICghaW5mbyB8fCAhaW5mby5pc0R5bmFtaWMpIHJldHVybiBbXTsnKTtcbiAgY29uc3QgZHluYW1pY1JvdXRlcyA9IGRlc2MucGFnZVJvdXRlcy5maWx0ZXIoKHIpID0+IHIuaXNEeW5hbWljKTtcbiAgaWYgKGR5bmFtaWNSb3V0ZXMubGVuZ3RoID4gMCkge1xuICAgIGxpbmVzLnB1c2goXCIgIC8vIERpc3BhdGNoIHRvIHRoZSByb3V0ZSBtb2R1bGUncyBnZXRTdGF0aWNQYXRocygpXCIpO1xuICAgIGZvciAoY29uc3QgciBvZiBkeW5hbWljUm91dGVzKSB7XG4gICAgICBsaW5lcy5wdXNoKGAgIGlmIChyb3V0ZVBhdGggPT09ICcke3IucGF0aC5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIil9Jykge2ApO1xuICAgICAgbGluZXMucHVzaChcbiAgICAgICAgYCAgICBpZiAodHlwZW9mICR7ci52YXJOYW1lfS5nZXRTdGF0aWNQYXRocyA9PT0gJ2Z1bmN0aW9uJykge2AsXG4gICAgICApO1xuICAgICAgbGluZXMucHVzaChgICAgICAgcmV0dXJuIGF3YWl0ICR7ci52YXJOYW1lfS5nZXRTdGF0aWNQYXRocygpO2ApO1xuICAgICAgbGluZXMucHVzaChgICAgIH1gKTtcbiAgICAgIGxpbmVzLnB1c2goYCAgICByZXR1cm4gW107YCk7XG4gICAgICBsaW5lcy5wdXNoKGAgIH1gKTtcbiAgICB9XG4gIH1cbiAgbGluZXMucHVzaCgnICByZXR1cm4gW107Jyk7XG4gIGxpbmVzLnB1c2goJ30nKTtcblxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztDQU1DLEdBR0QsU0FBUyxtQkFBbUIsRUFBRSxnQkFBZ0IsUUFBUSw0QkFBNEI7QUFFbEY7Ozs7Ozs7Q0FPQyxHQUNELE9BQU8sU0FBUyxpQkFBaUIsSUFBcUI7RUFDcEQsSUFBSSxDQUFDLEtBQUssS0FBSyxFQUFFLE9BQU87RUFFeEIsTUFBTSxRQUFrQixFQUFFO0VBRTFCLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1I7RUFFRixNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1I7RUFFRixNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBRVgsK0NBQStDO0VBQy9DLE1BQU0sSUFBSSxDQUFDO0VBQ1gsS0FBSyxNQUFN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QUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1I7RUFFRixNQUFNLElBQUksQ0FDUixDQUFDLGdDQUFnQyxFQUFFLEtBQUssU0FBUyxDQUFDLEtBQUssUUFBUSxDQUFDLHNCQUFzQixFQUFFLENBQUMsQ0FBQztFQUU1RixNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQ1IsQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLLFNBQVMsQ0FBQyxLQUFLLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLENBQUM7RUFFNUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1IsQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLFNBQVMsQ0FBQyxLQUFLLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLENBQUM7RUFFeEYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFFWCx5QkFBeUI7RUFDekIsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLGdCQUFnQixLQUFLLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFNLEVBQUUsU0FBUztFQUMvRCxJQUFJLGNBQWMsTUFBTSxHQUFHLEdBQUc7SUFDNUIsTUFBTSxJQUFJLENBQUM7SUFDWCxLQUFLLE1BQU0sS0FBSyxjQUFlO01BQzdCLE1BQU0sSUFBSSxDQUFDLENBQUMscUJBQXFCLEVBQUUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sT0FBTyxJQUFJLENBQUM7TUFDcEUsTUFBTSxJQUFJLENBQ1IsQ0FBQyxlQUFlLEVBQUUsRUFBRSxPQUFPLENBQUMsaUNBQWlDLENBQUM7TUFFaEUsTUFBTSxJQUFJLENBQUMsQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztNQUM5RCxNQUFNLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQztNQUNsQixNQUFNLElBQUksQ0FBQyxDQUFDLGNBQWMsQ0FBQztNQUMzQixNQUFNLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUNsQjtFQUNGO0VBQ0EsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUVYLE9BQU8sTUFBTSxJQUFJLENBQUM7QUFDcEIifQ==
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @openelement/core - Entry Renderer
3
+ *
4
+ * Pure function: routes + options -> Hono entry virtual module code.
5
+ *
6
+ * openElement Architecture (v0.5.0):
7
+ * - API routes use Hono standard app.route() (not app.all + fetch transform)
8
+ * - Island upgrade is handled by the client entry (built by Vite in Phase 2).
9
+ * No inline script in SSG HTML; the client entry is a Vite-built module
10
+ * referenced via <script type="module" src="..."> and imports island modules
11
+ * for side-effect custom element registration.
12
+ * - HTML document wrapping delegates to wrapInDocument from html-escape.ts
13
+ * (imported at runtime - single source of truth, no duplicate HTML logic)
14
+ * - DSD output must remain plain HTML, without Lit SSR marker comments.
15
+ *
16
+ * H-16 KNOWN ISSUE: Circular dependency between adapter-vite <-> content
17
+ * adapter-vite generates code that imports @openelement/content/sitemap
18
+ * content package imports @openelement/adapter-vite/build-context
19
+ * Shared contracts now live in @openelement/core, @openelement/ssg, @openelement/router,
20
+ * and @openelement/signal. Generated optional package imports are still emitted explicitly
21
+ * so consumer import maps can be checked.
22
+ *
23
+ * Thin orchestrator: delegates code generation to focused sub-modules:
24
+ * - entry-render-helpers.ts — individual code fragment generators
25
+ * - entry-render-runtime.ts — runtime helper function code generation
26
+ * - entry-render-ssg.ts — SSG re-export & routeInfo/renderRoute/getStaticPaths
27
+ *
28
+ * v0.41.0-alpha.1: The intermediate EntryDescriptor data model was collapsed
29
+ * into this file. `generateHonoEntryCode()` builds descriptor-shaped data and
30
+ * passes it directly to `renderEntry()` without a separate public descriptor
31
+ * builder or file.
32
+ */ import type { EntryDescriptor, IslandDecl, SsrAdmissionPlan } from '@openelement/protocol/ssg';
33
+ import type { CompatibilityClassification, FrameworkOptions, HydrationStrategy, RouteEntry } from '@openelement/protocol/framework';
34
+ import type { OpenElementPackageManifest } from '@openelement/protocol/manifest';
35
+ /**
36
+ * Render an EntryDescriptor into a complete virtual module string.
37
+ *
38
+ * Pure function - deterministic, testable, side-effect-free.
39
+ */ export declare function renderEntry(desc: EntryDescriptor): string;
40
+ export declare function buildEntryDescriptor(routes: RouteEntry[], options?: {
41
+ routesDir?: string;
42
+ islandsDir?: string;
43
+ middleware?: FrameworkOptions['middleware'];
44
+ ssg?: boolean;
45
+ islandTagNames?: string[];
46
+ /** Relative file paths for local islands (preserves subdirectory structure) */ islandFiles?: string[];
47
+ /** Local island metadata indexed by tag name. */ islandMeta?: Record<string, Partial<IslandDecl>>;
48
+ /** Package manifests discovered from npm/JSR packages */ packageManifests?: OpenElementPackageManifest[];
49
+ /** CEM-derived compatibility classifications (from compatibility classifier) */ cemClassifications?: CompatibilityClassification[];
50
+ /** @security Injected as raw HTML without sanitization */ headExtras?: string;
51
+ allowHeadExtrasScripts?: boolean;
52
+ html?: {
53
+ lang?: string;
54
+ title?: string;
55
+ };
56
+ upgradeStrategy?: HydrationStrategy;
57
+ /** Additional client-only tag names from external registries (ADR-0035 A1) */ clientOnlyTags?: string[];
58
+ appShell?: FrameworkOptions['appShell'];
59
+ layouts?: FrameworkOptions['layouts'];
60
+ }): EntryDescriptor;
61
+ export declare function buildSsrAdmissionPlan(islands: IslandDecl[], cemClassifications?: CompatibilityClassification[], clientOnlyTags?: string[]): SsrAdmissionPlan;
62
+ /** Options for the Hono entry code generator */ export interface HonoEntryOptions {
63
+ routesDir?: string;
64
+ islandsDir?: string;
65
+ componentsDir?: string;
66
+ middleware?: FrameworkOptions['middleware'];
67
+ ssg?: boolean;
68
+ islandTagNames?: string[];
69
+ /** Relative file paths for local islands (preserves subdirectory structure) */ islandFiles?: string[];
70
+ islandMeta?: Record<string, Partial<IslandDecl>>;
71
+ packageManifests?: OpenElementPackageManifest[];
72
+ /** @security Injected as raw HTML without sanitization */ headExtras?: string;
73
+ allowHeadExtrasScripts?: boolean;
74
+ html?: {
75
+ lang?: string;
76
+ title?: string;
77
+ };
78
+ upgradeStrategy?: HydrationStrategy;
79
+ /** Additional client-only tag names from external registries (ADR-0035 A1) */ clientOnlyTags?: string[];
80
+ appShell?: FrameworkOptions['appShell'];
81
+ layouts?: FrameworkOptions['layouts'];
82
+ }
83
+ /**
84
+ * Generate the Hono entry module code from scanned routes.
85
+ *
86
+ * Internally builds a descriptor-shaped object and renders it directly.
87
+ */ export declare function generateHonoEntryCode(routes: RouteEntry[], options?: HonoEntryOptions): string;