@openelement/adapter-vite 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.
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/package.json +87 -0
- package/src/alias-utils.js +39 -0
- package/src/build-context.d.ts +111 -0
- package/src/build-context.js +184 -0
- package/src/build-manifest.d.ts +38 -0
- package/src/build-manifest.js +198 -0
- package/src/build.js +97 -0
- package/src/cli/build-client.d.ts +3 -0
- package/src/cli/build-client.js +292 -0
- package/src/cli/build-ssg.d.ts +40 -0
- package/src/cli/build-ssg.js +377 -0
- package/src/cli/build.d.ts +0 -0
- package/src/cli/build.js +27 -0
- package/src/cli/ssg-render.js +32 -0
- package/src/generated-data-resolver.d.ts +12 -0
- package/src/generated-data-resolver.js +52 -0
- package/src/head-injection.d.ts +31 -0
- package/src/head-injection.js +248 -0
- package/src/index.d.ts +58 -0
- package/src/index.js +52 -0
- package/src/island-transform.js +27 -0
- package/src/nitro-mount.d.ts +24 -0
- package/src/nitro-mount.js +27 -0
- package/src/plugin-mdx.d.ts +7 -0
- package/src/plugin-mdx.js +15 -0
- package/src/plugin.d.ts +22 -0
- package/src/plugin.js +264 -0
- package/src/ssg-package-resolver.js +256 -0
- package/src/subpath-resolver.d.ts +26 -0
- package/src/subpath-resolver.js +153 -0
- package/src/workspace-alias.js +113 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { Deno } from "@deno/shim-deno";
|
|
2
|
+
/**
|
|
3
|
+
* @openelement/adapter-vite - CLI: SSG Build
|
|
4
|
+
*
|
|
5
|
+
* SSG rendering + post-processing.
|
|
6
|
+
* Builds a self-contained SSR bundle via viteBuild(ssr:true, noExternal),
|
|
7
|
+
* then imports it to render all pages to static HTML, and post-processes
|
|
8
|
+
* island paths.
|
|
9
|
+
*
|
|
10
|
+
* ADR 0011: This module exports buildSSG() only - it is called from
|
|
11
|
+
* closeBundle() in open:build plugin. No longer a standalone CLI entry.
|
|
12
|
+
* ctx parameter is required (no globalThis fallback).
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* deno task build (unified entry - runs all 3 phases)
|
|
16
|
+
*/ import { join, resolve } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
import { normalizePath } from 'vite';
|
|
19
|
+
import process from 'node:process';
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { ssgRender } from '@openelement/ssg';
|
|
22
|
+
import { SsrRenderError } from '@openelement/core/errors';
|
|
23
|
+
import { createLogger } from '@openelement/core/logger';
|
|
24
|
+
import { createSsgRenderEvidence } from './ssg-render.js';
|
|
25
|
+
import { createGeneratedDataResolverPlugin } from '../generated-data-resolver.js';
|
|
26
|
+
import { createOpenJsrPackageResolverPlugin } from '../ssg-package-resolver.js';
|
|
27
|
+
import { generateSsrPolyfillBanner, resolveExternalManifest } from '@openelement/ssg';
|
|
28
|
+
import { optionalPackageStubsPlugin } from '../plugin.js';
|
|
29
|
+
import { normalizeViteAliases } from '../alias-utils.js';
|
|
30
|
+
/** Fallback package version when adapter-vite cannot read its own deno.json. */ const DEFAULT_ADAPTER_VERSION_FALLBACK = '0.35.1';
|
|
31
|
+
/** Chunk size warning limit (kB) for the SSR bundle build. */ const SSR_CHUNK_SIZE_WARNING_LIMIT_KB = 1500;
|
|
32
|
+
/** Rollup/Vite output paths mapping for known externals. */ const SSR_EXTERNAL_PATHS = {
|
|
33
|
+
'sanitize-html': 'npm:sanitize-html@^2.17.4'
|
|
34
|
+
};
|
|
35
|
+
const log = createLogger('ssg');
|
|
36
|
+
const VIRTUAL_SSG_ENTRY_ID = 'virtual:open-ssg-entry';
|
|
37
|
+
const RESOLVED_SSG_ENTRY_ID = '\0' + VIRTUAL_SSG_ENTRY_ID;
|
|
38
|
+
function getJsrPackageVersion(metaUrl) {
|
|
39
|
+
const match = metaUrl.match(/\/@openelement\/adapter-vite\/([^/]+)\//);
|
|
40
|
+
if (match) return match[1];
|
|
41
|
+
// Read from own deno.json
|
|
42
|
+
try {
|
|
43
|
+
const denoJson = JSON.parse(typeof Deno !== 'undefined' ? Deno.readTextFileSync(new URL('../deno.json', import.meta.url)) : readFileSync(new URL('../deno.json', import.meta.url), 'utf-8'));
|
|
44
|
+
return denoJson.version || DEFAULT_ADAPTER_VERSION_FALLBACK;
|
|
45
|
+
} catch {
|
|
46
|
+
return DEFAULT_ADAPTER_VERSION_FALLBACK;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function getLocalOpenElementPackageRoot(metaUrl) {
|
|
50
|
+
if (!metaUrl.startsWith('file:')) return null;
|
|
51
|
+
try {
|
|
52
|
+
const root = resolve(fileURLToPath(new URL('.', metaUrl)), '..', '..', '..', '..');
|
|
53
|
+
return existsSync(resolve(root, 'packages', 'core', 'deno.json')) ? root : null;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function buildSSG(options = {}, ctx) {
|
|
59
|
+
const root = options.root || ctx.phase3.root || process.cwd();
|
|
60
|
+
const outDir = options.outDir || ctx.phase3.outDir || 'dist';
|
|
61
|
+
const routesDir = options.routesDir || ctx.phase3.routesDir || 'app/routes';
|
|
62
|
+
const islandsDir = options.islandsDir || ctx.phase3.islandsDir || 'app/islands';
|
|
63
|
+
const appShell = options.appShell ?? ctx.phase3.appShell;
|
|
64
|
+
const layouts = options.layouts ?? ctx.phase3.layouts;
|
|
65
|
+
// SOP-v0.21.6: Detect if we're running from a Deno workspace.
|
|
66
|
+
// In workspace mode, @deno/vite-plugin resolves bare specifiers.
|
|
67
|
+
// In JSR mode, we need the open:ssg-core-resolve plugin.
|
|
68
|
+
const workspaceRoot = (()=>{
|
|
69
|
+
try {
|
|
70
|
+
for(let d = resolve(root); d !== resolve(d, '..'); d = resolve(d, '..')){
|
|
71
|
+
const cfg = JSON.parse(readFileSync(resolve(d, 'deno.json'), 'utf-8'));
|
|
72
|
+
if (cfg.workspace && Array.isArray(cfg.workspace)) return d;
|
|
73
|
+
}
|
|
74
|
+
} catch {}
|
|
75
|
+
return null;
|
|
76
|
+
})();
|
|
77
|
+
// Read island metadata from ctx (ADR 0010: no .openElement/ fallback)
|
|
78
|
+
const islandTagNames = options.islandTagNames || ctx.phase1.islandTagNames || [];
|
|
79
|
+
const islandMeta = options.islandMeta || ctx.phase1.islandMeta || {};
|
|
80
|
+
const packageManifests = options.packageManifests || ctx.phase1.packageManifests || [];
|
|
81
|
+
const metadataResolveAlias = options.resolveAlias || ctx.phase1.userResolveAlias;
|
|
82
|
+
// Read options from ctx
|
|
83
|
+
if (!options.headExtras) options.headExtras = ctx.phase3.headExtras || undefined;
|
|
84
|
+
if (options.allowHeadExtrasScripts === undefined) {
|
|
85
|
+
options.allowHeadExtrasScripts = ctx.phase3.allowHeadExtrasScripts;
|
|
86
|
+
}
|
|
87
|
+
if (!options.html) options.html = ctx.phase3.html || undefined;
|
|
88
|
+
if (!options.middleware) options.middleware = ctx.phase3.middleware || undefined;
|
|
89
|
+
if (!options.upgradeStrategy) options.upgradeStrategy = ctx.phase3.upgradeStrategy;
|
|
90
|
+
if (!options.base) options.base = ctx.phase3.base;
|
|
91
|
+
if (options.viewTransition === undefined) options.viewTransition = ctx.phase3.viewTransition;
|
|
92
|
+
if (!options.speculation) options.speculation = ctx.phase3.speculation || undefined;
|
|
93
|
+
// Generate SSG entry code
|
|
94
|
+
const { scanRoutes, scanIslands, scanIslandMeta, fileToTagName } = await import('@openelement/ssg');
|
|
95
|
+
const { generateHonoEntryCode } = await import('@openelement/ssg');
|
|
96
|
+
const routes = await scanRoutes(routesDir);
|
|
97
|
+
// v0.25.0: Generate type-safe route parameter declarations for `virtual:open-routes`
|
|
98
|
+
const { generateRouteTypes } = await import('@openelement/ssg');
|
|
99
|
+
const routeTypeDts = generateRouteTypes(routes);
|
|
100
|
+
const dotOpenElementDir = join(root, '.openElement');
|
|
101
|
+
mkdirSync(dotOpenElementDir, {
|
|
102
|
+
recursive: true
|
|
103
|
+
});
|
|
104
|
+
writeFileSync(join(dotOpenElementDir, 'routes.d.ts'), routeTypeDts, 'utf-8');
|
|
105
|
+
log.info(`Route types generated -> .openElement/routes.d.ts`);
|
|
106
|
+
const islandsRoot = join(root, islandsDir);
|
|
107
|
+
const ssgIslandFiles = await scanIslands(islandsRoot);
|
|
108
|
+
const ssgIslandTagNames = islandTagNames.length > 0 ? islandTagNames : ssgIslandFiles.map((f)=>fileToTagName(f));
|
|
109
|
+
const ssgIslandMeta = Object.keys(islandMeta).length > 0 ? islandMeta : await scanIslandMeta(islandsRoot, ssgIslandFiles);
|
|
110
|
+
const { buildEntryDescriptor } = await import('@openelement/ssg');
|
|
111
|
+
ctx.phase1.ssrAdmissionPlan = buildEntryDescriptor(routes, {
|
|
112
|
+
routesDir,
|
|
113
|
+
islandsDir,
|
|
114
|
+
ssg: true,
|
|
115
|
+
islandTagNames: ssgIslandTagNames,
|
|
116
|
+
islandFiles: ssgIslandFiles,
|
|
117
|
+
islandMeta: ssgIslandMeta,
|
|
118
|
+
packageManifests,
|
|
119
|
+
clientOnlyTags: [],
|
|
120
|
+
appShell,
|
|
121
|
+
layouts
|
|
122
|
+
}).ssrAdmissionPlan;
|
|
123
|
+
const rawSsgEntryCode = generateSsrPolyfillBanner() + '\n' + generateHonoEntryCode(routes, {
|
|
124
|
+
routesDir,
|
|
125
|
+
islandsDir,
|
|
126
|
+
middleware: options.middleware,
|
|
127
|
+
ssg: true,
|
|
128
|
+
islandTagNames: ssgIslandTagNames,
|
|
129
|
+
islandFiles: ssgIslandFiles,
|
|
130
|
+
islandMeta: ssgIslandMeta,
|
|
131
|
+
packageManifests,
|
|
132
|
+
headExtras: options.headExtras,
|
|
133
|
+
allowHeadExtrasScripts: options.allowHeadExtrasScripts,
|
|
134
|
+
html: options.html,
|
|
135
|
+
upgradeStrategy: options.upgradeStrategy || 'idle',
|
|
136
|
+
clientOnlyTags: [],
|
|
137
|
+
appShell,
|
|
138
|
+
layouts
|
|
139
|
+
});
|
|
140
|
+
// Deno import map resolution handles bare specifiers (e.g. @openelement/ui/open-callout)
|
|
141
|
+
// via the createDenoImportMapPlugin added to the Phase 3 viteBuild plugins below.
|
|
142
|
+
const ssgEntryCode = rawSsgEntryCode;
|
|
143
|
+
try {
|
|
144
|
+
const { build: viteBuild } = await import('vite');
|
|
145
|
+
// SSR noExternal: packages that MUST be inlined into the SSR bundle.
|
|
146
|
+
// Without these, the SSR bundle contains bare specifier imports that cannot
|
|
147
|
+
// be resolved in non-workspace environments (e.g. CF Pages), causing
|
|
148
|
+
// import(entry.js) to fail and the entire SSG pipeline to produce empty HTML.
|
|
149
|
+
const defaultNoExternal = [
|
|
150
|
+
/^@openelement\//
|
|
151
|
+
];
|
|
152
|
+
// ADR-0047: External packages are externalized, not bundled.
|
|
153
|
+
// ADR-0054: AST-based exports resolution covers ALL subpath exports
|
|
154
|
+
// so Rolldown externalizes them correctly via manifest.specifiers.
|
|
155
|
+
// Consumer template deno.json declares these packages so Deno can
|
|
156
|
+
// resolve them at runtime when buildSSG() executes import(entry.js).
|
|
157
|
+
// Hono stays external unless the user explicitly requests adapter-specific
|
|
158
|
+
// bundling through options.ssr.noExternal.
|
|
159
|
+
const ssrExternalDefaults = [
|
|
160
|
+
'hono'
|
|
161
|
+
];
|
|
162
|
+
// Step 0: Deno pre-resolution + AST subpath discovery (ADR-0047 + ADR-0054)
|
|
163
|
+
const manifest = await resolveExternalManifest(ssrExternalDefaults, root, options.skipPreResolution || ctx.phase3?.skipPreResolution);
|
|
164
|
+
const userNoExternal = options.ssr?.noExternal || [];
|
|
165
|
+
const allNoExternal = [
|
|
166
|
+
...defaultNoExternal,
|
|
167
|
+
...userNoExternal
|
|
168
|
+
];
|
|
169
|
+
// Handle alias - prefer CLI options, then ctx from Phase 1
|
|
170
|
+
const alias = metadataResolveAlias;
|
|
171
|
+
const viteResolveAlias = normalizeViteAliases(alias, root);
|
|
172
|
+
if (alias) {
|
|
173
|
+
if (Array.isArray(alias)) {
|
|
174
|
+
for (const a of alias){
|
|
175
|
+
if (a.find === '@openelement/ui') {
|
|
176
|
+
// v0.14.6: Check if replacement is already covered by defaultNoExternal
|
|
177
|
+
const isAlreadyCovered = defaultNoExternal.some((pattern)=>pattern instanceof RegExp && pattern.test(a.replacement));
|
|
178
|
+
if (!isAlreadyCovered) {
|
|
179
|
+
allNoExternal.push(a.replacement);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} else if ('@openelement/ui' in alias) {
|
|
184
|
+
const isAlreadyCovered = defaultNoExternal.some((pattern)=>pattern instanceof RegExp && pattern.test(alias['@openelement/ui']));
|
|
185
|
+
if (!isAlreadyCovered) {
|
|
186
|
+
allNoExternal.push(alias['@openelement/ui']);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Build the self-contained SSR bundle (ADR 0008 Phase C)
|
|
191
|
+
// Replaces createServer() + ssrLoadModule() with viteBuild + import().
|
|
192
|
+
// noExternal ensures all dependencies are inlined into a single bundle,
|
|
193
|
+
// so module-level variables (Phase B) are shared across the entire graph.
|
|
194
|
+
const ssrOutDir = join(root, outDir, 'server');
|
|
195
|
+
log.info(`Building SSR bundle -> ${ssrOutDir}`);
|
|
196
|
+
const clientOnlyIslandIds = new Set(Object.entries(ssgIslandMeta).filter(([, meta])=>meta.ssr === false).map(([tag])=>{
|
|
197
|
+
const file = ssgIslandFiles[ssgIslandTagNames.indexOf(tag)];
|
|
198
|
+
return file ? normalizePath(resolve(root, islandsDir, file)) : '';
|
|
199
|
+
}).filter(Boolean));
|
|
200
|
+
// v0.21: Build filePath -> tagName map for client-only placeholder generation.
|
|
201
|
+
const clientOnlyTagMap = new Map();
|
|
202
|
+
for (const [tag, meta] of Object.entries(ssgIslandMeta)){
|
|
203
|
+
if (meta.ssr !== false) continue;
|
|
204
|
+
const file = ssgIslandFiles[ssgIslandTagNames.indexOf(tag)];
|
|
205
|
+
if (file) clientOnlyTagMap.set(normalizePath(resolve(root, islandsDir, file)), tag);
|
|
206
|
+
}
|
|
207
|
+
// v0.21 SOP-004: Conflict detection: same tag must not be both SSR and client:only.
|
|
208
|
+
const ssrTags = new Set(Object.entries(ssgIslandMeta).filter(([, meta])=>meta.ssr !== false).map(([tag])=>tag));
|
|
209
|
+
const conflictTags = [
|
|
210
|
+
...clientOnlyTagMap.values()
|
|
211
|
+
].filter((t)=>ssrTags.has(t));
|
|
212
|
+
if (conflictTags.length > 0) {
|
|
213
|
+
throw new Error(`[openElement] SSR+client:only conflict detected for tags: ${conflictTags.join(', ')}. ` + 'A tag cannot be both SSR-capable and client:only on the same page.');
|
|
214
|
+
}
|
|
215
|
+
await viteBuild({
|
|
216
|
+
configFile: false,
|
|
217
|
+
root,
|
|
218
|
+
logLevel: 'error',
|
|
219
|
+
build: {
|
|
220
|
+
ssr: true,
|
|
221
|
+
outDir: ssrOutDir,
|
|
222
|
+
chunkSizeWarningLimit: SSR_CHUNK_SIZE_WARNING_LIMIT_KB,
|
|
223
|
+
rollupOptions: {
|
|
224
|
+
input: {
|
|
225
|
+
entry: VIRTUAL_SSG_ENTRY_ID
|
|
226
|
+
},
|
|
227
|
+
// v0.21: Suppress IMPORT_IS_UNDEFINED for revalidate; the generated
|
|
228
|
+
// code uses typeof check which correctly handles undefined exports.
|
|
229
|
+
onwarn (warning, warn) {
|
|
230
|
+
if (warning.code === 'IMPORT_IS_UNDEFINED') return;
|
|
231
|
+
warn(warning);
|
|
232
|
+
},
|
|
233
|
+
output: {
|
|
234
|
+
format: 'esm',
|
|
235
|
+
// Workspace sources may use explicit npm: specifiers that Rolldown
|
|
236
|
+
// rewrites to bare imports while bundling. Re-emit known externals
|
|
237
|
+
// as Deno-resolvable npm: imports for fresh JSR consumers.
|
|
238
|
+
paths: SSR_EXTERNAL_PATHS,
|
|
239
|
+
// ADR-0044: customElements polyfill must run before ESM imports.
|
|
240
|
+
// Uses Map-backed define()/get(); renderDsdByName() looks up
|
|
241
|
+
// components via customElements.get(tagName) during SSG rendering.
|
|
242
|
+
// SOP-016: HTMLElement stub is self-contained in @openelement/core/dsd-element.ts.
|
|
243
|
+
banner: `\
|
|
244
|
+
if (typeof globalThis.customElements === 'undefined') {
|
|
245
|
+
const __openCeRegistry = new Map();
|
|
246
|
+
globalThis.customElements = {
|
|
247
|
+
define(name, ctor, _opts) { __openCeRegistry.set(name, ctor); },
|
|
248
|
+
get(name) { return __openCeRegistry.get(name); },
|
|
249
|
+
whenDefined(name) { return Promise.resolve(__openCeRegistry.get(name)); },
|
|
250
|
+
upgrade(_root) {},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
`
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
ssr: {
|
|
258
|
+
noExternal: allNoExternal,
|
|
259
|
+
external: manifest.specifiers
|
|
260
|
+
},
|
|
261
|
+
// ADR 0008 Phase A: Inject headExtras via define instead of .openElement/head-extras.html
|
|
262
|
+
// The generated entry code uses __HEAD_EXTRAS__ which gets replaced
|
|
263
|
+
// at build time. This avoids the Vite SSR AsyncFunction syntax errors
|
|
264
|
+
// that large inline strings (with backticks/${}) cause.
|
|
265
|
+
define: options.headExtras ? {
|
|
266
|
+
__HEAD_EXTRAS__: JSON.stringify(options.headExtras)
|
|
267
|
+
} : {
|
|
268
|
+
__HEAD_EXTRAS__: '""'
|
|
269
|
+
},
|
|
270
|
+
esbuild: {
|
|
271
|
+
// ADR-0057: JSX automatic runtime, same reason as build-client.ts.
|
|
272
|
+
// SSG build also processes .tsx island files for SSR rendering.
|
|
273
|
+
jsx: 'automatic',
|
|
274
|
+
jsxImportSource: '@openelement/core',
|
|
275
|
+
tsconfigRaw: {
|
|
276
|
+
compilerOptions: {
|
|
277
|
+
useDefineForClassFields: false
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
plugins: [
|
|
282
|
+
// ADR 0010: Virtual SSG entry module
|
|
283
|
+
// Replaces .openElement/.openElement-ssg-entry.ts file write
|
|
284
|
+
{
|
|
285
|
+
name: 'open:virtual-ssg-entry',
|
|
286
|
+
resolveId (id) {
|
|
287
|
+
if (id === VIRTUAL_SSG_ENTRY_ID) return RESOLVED_SSG_ENTRY_ID;
|
|
288
|
+
},
|
|
289
|
+
load (id) {
|
|
290
|
+
if (id === RESOLVED_SSG_ENTRY_ID) return ssgEntryCode;
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
// ADR 0008 Phase C: Provide stubs for retained optional packages.
|
|
294
|
+
// The generated entry code can import @openelement/content and
|
|
295
|
+
// @openelement/i18n, but these may not be installed.
|
|
296
|
+
// This plugin resolves them to empty stubs when missing, so the
|
|
297
|
+
// viteBuild() succeeds regardless of which packages are available.
|
|
298
|
+
optionalPackageStubsPlugin(),
|
|
299
|
+
createGeneratedDataResolverPlugin({
|
|
300
|
+
root,
|
|
301
|
+
name: 'open:ssg-generated-data'
|
|
302
|
+
}),
|
|
303
|
+
createOpenJsrPackageResolverPlugin({
|
|
304
|
+
workspaceRoot,
|
|
305
|
+
version: getJsrPackageVersion(import.meta.url),
|
|
306
|
+
localPackageRoot: getLocalOpenElementPackageRoot(import.meta.url),
|
|
307
|
+
userAliases: metadataResolveAlias
|
|
308
|
+
}),
|
|
309
|
+
{
|
|
310
|
+
name: 'open:ssg-client-only-island-stubs',
|
|
311
|
+
enforce: 'pre',
|
|
312
|
+
load (id) {
|
|
313
|
+
const normalized = normalizePath(id.split('?')[0]);
|
|
314
|
+
if (!clientOnlyIslandIds.has(normalized)) return;
|
|
315
|
+
const tagName = clientOnlyTagMap.get(normalized) || 'open-client-only-stub';
|
|
316
|
+
// Client-only stub marker uses an unbranded attribute.
|
|
317
|
+
// SSR outputs <tag-name data-client-only="true"></tag-name>
|
|
318
|
+
// Client runtime imports the real module and upgrades the element.
|
|
319
|
+
return [
|
|
320
|
+
`import { defineIslandConfig } from '@openelement/app';`,
|
|
321
|
+
`export const tagName = ${JSON.stringify(tagName)};`,
|
|
322
|
+
'export const openElement = defineIslandConfig({ ssr: false });',
|
|
323
|
+
`export default class OpenClientOnlyStub extends HTMLElement {
|
|
324
|
+
connectedCallback() {
|
|
325
|
+
if (!this.hasAttribute('data-client-only')) {
|
|
326
|
+
this.setAttribute('data-client-only', 'true');
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}`
|
|
330
|
+
].join('\n');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
],
|
|
334
|
+
resolve: {
|
|
335
|
+
preserveSymlinks: true,
|
|
336
|
+
extensions: [
|
|
337
|
+
'.ts',
|
|
338
|
+
'.tsx',
|
|
339
|
+
'.js',
|
|
340
|
+
'.jsx',
|
|
341
|
+
'.json'
|
|
342
|
+
],
|
|
343
|
+
...viteResolveAlias ? {
|
|
344
|
+
alias: viteResolveAlias
|
|
345
|
+
} : {}
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
log.info('SSR bundle built successfully');
|
|
349
|
+
// Load the SSR bundle and run SSG rendering pipeline
|
|
350
|
+
const ssrBundlePath = resolve(ssrOutDir, 'entry.js');
|
|
351
|
+
// M-18 fix: Use process.platform instead of Deno.build.os for Node.js compat
|
|
352
|
+
const isWindows = typeof process !== 'undefined' && process.platform === 'win32';
|
|
353
|
+
const ssrBundleUrl = isWindows ? 'file:///' + ssrBundlePath.replace(/\\/g, '/') : 'file://' + ssrBundlePath;
|
|
354
|
+
const module = await import(ssrBundleUrl);
|
|
355
|
+
if (!module.default) {
|
|
356
|
+
throw new SsrRenderError('virtual:open-ssg-entry', new Error('Failed to load Hono app'));
|
|
357
|
+
}
|
|
358
|
+
// Delegate to shared ssgRender() - zero Vite dependency from this point
|
|
359
|
+
await ssgRender(module, {
|
|
360
|
+
root,
|
|
361
|
+
outDir,
|
|
362
|
+
base: options.base || '/',
|
|
363
|
+
headExtras: options.headExtras,
|
|
364
|
+
html: options.html,
|
|
365
|
+
middleware: options.middleware,
|
|
366
|
+
islandTagNames: ssgIslandTagNames,
|
|
367
|
+
viewTransition: options.viewTransition,
|
|
368
|
+
speculation: options.speculation
|
|
369
|
+
}, createSsgRenderEvidence(ctx));
|
|
370
|
+
log.info('Static site generated -> ' + join(root, outDir));
|
|
371
|
+
} catch (err) {
|
|
372
|
+
const cause = err instanceof Error ? err : new Error(String(err));
|
|
373
|
+
throw new SsrRenderError('SSG pipeline', cause);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
export { buildSSG };
|
|
377
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2NsaS9idWlsZC1zc2cudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVubyB9IGZyb20gXCJAZGVuby9zaGltLWRlbm9cIjtcbi8qKlxuICogQG9wZW5lbGVtZW50L2FkYXB0ZXItdml0ZSAtIENMSTogU1NHIEJ1aWxkXG4gKlxuICogU1NHIHJlbmRlcmluZyArIHBvc3QtcHJvY2Vzc2luZy5cbiAqIEJ1aWxkcyBhIHNlbGYtY29udGFpbmVkIFNTUiBidW5kbGUgdmlhIHZpdGVCdWlsZChzc3I6dHJ1ZSwgbm9FeHRlcm5hbCksXG4gKiB0aGVuIGltcG9ydHMgaXQgdG8gcmVuZGVyIGFsbCBwYWdlcyB0byBzdGF0aWMgSFRNTCwgYW5kIHBvc3QtcHJvY2Vzc2VzXG4gKiBpc2xhbmQgcGF0aHMuXG4gKlxuICogQURSIDAwMTE6IFRoaXMgbW9kdWxlIGV4cG9ydHMgYnVpbGRTU0coKSBvbmx5IC0gaXQgaXMgY2FsbGVkIGZyb21cbiAqIGNsb3NlQnVuZGxlKCkgaW4gb3BlbjpidWlsZCBwbHVnaW4uIE5vIGxvbmdlciBhIHN0YW5kYWxvbmUgQ0xJIGVudHJ5LlxuICogY3R4IHBhcmFtZXRlciBpcyByZXF1aXJlZCAobm8gZ2xvYmFsVGhpcyBmYWxsYmFjaykuXG4gKlxuICogVXNhZ2U6XG4gKiAgIGRlbm8gdGFzayBidWlsZCAgKHVuaWZpZWQgZW50cnkgLSBydW5zIGFsbCAzIHBoYXNlcylcbiAqL1xuXG5pbXBvcnQgeyBqb2luLCByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5pbXBvcnQgeyBub3JtYWxpemVQYXRoIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuaW1wb3J0IHsgZXhpc3RzU3luYywgbWtkaXJTeW5jLCByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB0eXBlIHsgRnJhbWV3b3JrT3B0aW9ucywgSHlkcmF0aW9uU3RyYXRlZ3kgfSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvZnJhbWV3b3JrJztcbmltcG9ydCB0eXBlIHsgT3BlbkVsZW1lbnRQYWNrYWdlTWFuaWZlc3QgfSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvbWFuaWZlc3QnO1xuaW1wb3J0IHR5cGUgeyBPcGVuRWxlbWVudEJ1aWxkQ29udGV4dCB9IGZyb20gJy4uL2J1aWxkLWNvbnRleHQuanMnO1xuaW1wb3J0IHsgc3NnUmVuZGVyIH0gZnJvbSAnQG9wZW5lbGVtZW50L3NzZyc7XG5pbXBvcnQgeyBTc3JSZW5kZXJFcnJvciB9IGZyb20gJ0BvcGVuZWxlbWVudC9jb3JlL2Vycm9ycyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICdAb3BlbmVsZW1lbnQvY29yZS9sb2dnZXInO1xuaW1wb3J0IHsgY3JlYXRlU3NnUmVuZGVyRXZpZGVuY2UgfSBmcm9tICcuL3NzZy1yZW5kZXIuanMnO1xuaW1wb3J0IHsgY3JlYXRlR2VuZXJhdGVkRGF0YVJlc29sdmVyUGx1Z2luIH0gZnJvbSAnLi4vZ2VuZXJhdGVkLWRhdGEtcmVzb2x2ZXIuanMnO1xuaW1wb3J0IHsgY3JlYXRlT3BlbkpzclBhY2thZ2VSZXNvbHZlclBsdWdpbiB9IGZyb20gJy4uL3NzZy1wYWNrYWdlLXJlc29sdmVyLmpzJztcbmltcG9ydCB7IGdlbmVyYXRlU3NyUG9seWZpbGxCYW5uZXIsIHJlc29sdmVFeHRlcm5hbE1hbmlmZXN0IH0gZnJvbSAnQG9wZW5lbGVtZW50L3NzZyc7XG5pbXBvcnQgeyBvcHRpb25hbFBhY2thZ2VTdHVic1BsdWdpbiB9IGZyb20gJy4uL3BsdWdpbi5qcyc7XG5pbXBvcnQgeyBub3JtYWxpemVWaXRlQWxpYXNlcyB9IGZyb20gJy4uL2FsaWFzLXV0aWxzLmpzJztcblxuLyoqIEZhbGxiYWNrIHBhY2thZ2UgdmVyc2lvbiB3aGVuIGFkYXB0ZXItdml0ZSBjYW5ub3QgcmVhZCBpdHMgb3duIGRlbm8uanNvbi4gKi9cbmNvbnN0IERFRkFVTFRfQURBUFRFUl9WRVJTSU9OX0ZBTExCQUNLID0gJzAuMzUuMSc7XG5cbi8qKiBDaHVuayBzaXplIHdhcm5pbmcgbGltaXQgKGtCKSBmb3IgdGhlIFNTUiBidW5kbGUgYnVpbGQuICovXG5jb25zdCBTU1JfQ0hVTktfU0laRV9XQVJOSU5HX0xJTUlUX0tCID0gMTUwMDtcblxuLyoqIFJvbGx1cC9WaXRlIG91dHB1dCBwYXRocyBtYXBwaW5nIGZvciBrbm93biBleHRlcm5hbHMuICovXG5jb25zdCBTU1JfRVhURVJOQUxfUEFUSFM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICdzYW5pdGl6ZS1odG1sJzogJ25wbTpzYW5pdGl6ZS1odG1sQF4yLjE3LjQnLFxufTtcblxuY29uc3QgbG9nID0gY3JlYXRlTG9nZ2VyKCdzc2cnKTtcblxuY29uc3QgVklSVFVBTF9TU0dfRU5UUllfSUQgPSAndmlydHVhbDpvcGVuLXNzZy1lbnRyeSc7XG5jb25zdCBSRVNPTFZFRF9TU0dfRU5UUllfSUQgPSAnXFwwJyArIFZJUlRVQUxfU1NHX0VOVFJZX0lEO1xuZnVuY3Rpb24gZ2V0SnNyUGFja2FnZVZlcnNpb24obWV0YVVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbWF0Y2ggPSBtZXRhVXJsLm1hdGNoKC9cXC9Ab3BlbmVsZW1lbnRcXC9hZGFwdGVyLXZpdGVcXC8oW14vXSspXFwvLyk7XG4gIGlmIChtYXRjaCkgcmV0dXJuIG1hdGNoWzFdO1xuICAvLyBSZWFkIGZyb20gb3duIGRlbm8uanNvblxuICB0cnkge1xuICAgIGNvbnN0IGRlbm9Kc29uID0gSlNPTi5wYXJzZShcbiAgICAgIHR5cGVvZiBEZW5vICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICA/IERlbm8ucmVhZFRleHRGaWxlU3luYyhuZXcgVVJMKCcuLi9kZW5vLmpzb24nLCBpbXBvcnQubWV0YS51cmwpKVxuICAgICAgICA6IHJlYWRGaWxlU3luYyhuZXcgVVJMKCcuLi9kZW5vLmpzb24nLCBpbXBvcnQubWV0YS51cmwpLCAndXRmLTgnKSxcbiAgICApO1xuICAgIHJldHVybiBkZW5vSnNvbi52ZXJzaW9uIHx8IERFRkFVTFRfQURBUFRFUl9WRVJTSU9OX0ZBTExCQUNLO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gREVGQVVMVF9BREFQVEVSX1ZFUlNJT05fRkFMTEJBQ0s7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0TG9jYWxPcGVuRWxlbWVudFBhY2thZ2VSb290KG1ldGFVcmw6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBpZiAoIW1ldGFVcmwuc3RhcnRzV2l0aCgnZmlsZTonKSkgcmV0dXJuIG51bGw7XG4gIHRyeSB7XG4gICAgY29uc3Qgcm9vdCA9IHJlc29sdmUoZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuJywgbWV0YVVybCkpLCAnLi4nLCAnLi4nLCAnLi4nLCAnLi4nKTtcbiAgICByZXR1cm4gZXhpc3RzU3luYyhyZXNvbHZlKHJvb3QsICdwYWNrYWdlcycsICdjb3JlJywgJ2Rlbm8uanNvbicpKSA/IHJvb3QgOiBudWxsO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgQnVpbGRTU0dPcHRpb25zIHtcbiAgcm9vdD86IHN0cmluZztcbiAgb3V0RGlyPzogc3RyaW5nO1xuICByb3V0ZXNEaXI/OiBzdHJpbmc7XG4gIGlzbGFuZHNEaXI/OiBzdHJpbmc7XG4gIG1pZGRsZXdhcmU/OiBGcmFtZXdvcmtPcHRpb25zWydtaWRkbGV3YXJlJ107XG4gIHNzcj86IEZyYW1ld29ya09wdGlvbnNbJ3NzciddO1xuICBpc2xhbmRUYWdOYW1lcz86IHN0cmluZ1tdO1xuICBpc2xhbmRNZXRhPzogUmVjb3JkPHN0cmluZywgUGFydGlhbDxpbXBvcnQoJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9zc2cnKS5Jc2xhbmREZWNsPj47XG4gIHBhY2thZ2VNYW5pZmVzdHM/OiBPcGVuRWxlbWVudFBhY2thZ2VNYW5pZmVzdFtdO1xuICAvKiogQHNlY3VyaXR5IEluamVjdGVkIGFzIHJhdyBIVE1MIHdpdGhvdXQgc2FuaXRpemF0aW9uICovXG4gIGhlYWRFeHRyYXM/OiBzdHJpbmc7XG4gIGFsbG93SGVhZEV4dHJhc1NjcmlwdHM/OiBib29sZWFuO1xuICBodG1sPzogeyBsYW5nPzogc3RyaW5nOyB0aXRsZT86IHN0cmluZyB9O1xuICBhcHBTaGVsbD86IEZyYW1ld29ya09wdGlvbnNbJ2FwcFNoZWxsJ107XG4gIGxheW91dHM/OiBGcmFtZXdvcmtPcHRpb25zWydsYXlvdXRzJ107XG4gIHVwZ3JhZGVTdHJhdGVneT86IEh5ZHJhdGlvblN0cmF0ZWd5O1xuICByZXNvbHZlQWxpYXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgaW1wb3J0KCd2aXRlJykuQWxpYXNbXTtcbiAgYmFzZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFZpZXcgVHJhbnNpdGlvbnMgQVBJIGNvbmZpZ3VyYXRpb24uXG4gICAqIFdoZW4gdHJ1ZSAoZGVmYXVsdCksIGluamVjdHMgPG1ldGEgbmFtZT1cInZpZXctdHJhbnNpdGlvblwiIGNvbnRlbnQ9XCJzYW1lLW9yaWdpblwiPlxuICAgKiBpbnRvIGFsbCBIVE1MIGZpbGVzIGZvciBzbW9vdGggY3Jvc3MtcGFnZSBhbmltYXRpb25zIGluIE1QQSBuYXZpZ2F0aW9uLlxuICAgKiBTZXQgdG8gZmFsc2UgdG8gZGlzYWJsZS5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgdmlld1RyYW5zaXRpb24/OiBib29sZWFuO1xuICAvKipcbiAgICogU3BlY3VsYXRpb24gUnVsZXMgQVBJIGNvbmZpZ3VyYXRpb24uXG4gICAqIEVuYWJsZXMgYnJvd3NlciBwcmVmZXRjaC9wcmVyZW5kZXIgb2YgcGFnZXMgYmVmb3JlIHRoZSB1c2VyIG5hdmlnYXRlcy5cbiAgICogQ2FuIGJlIGEgYm9vbGVhbiAodHJ1ZSA9IGF1dG8tZ2VuZXJhdGUgZnJvbSByb3V0ZXMpIG9yIGV4cGxpY2l0IHJ1bGVzLlxuICAgKi9cbiAgc3BlY3VsYXRpb24/OiBib29sZWFuIHwgaW1wb3J0KCdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvc3NnJykuU3BlY3VsYXRpb25SdWxlc09wdGlvbnM7XG4gIC8qKiBBRFItMDA0NzogU2tpcCBEZW5vIHByZS1yZXNvbHV0aW9uLCB1c2UgcmVnZXggZmFsbGJhY2sgZm9yIGV4dGVybmFsIGRlcHMuICovXG4gIHNraXBQcmVSZXNvbHV0aW9uPzogYm9vbGVhbjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRTU0coXG4gIG9wdGlvbnM6IEJ1aWxkU1NHT3B0aW9ucyA9IHt9LFxuICBjdHg6IE9wZW5FbGVtZW50QnVpbGRDb250ZXh0LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJvb3QgPSBvcHRpb25zLnJvb3QgfHwgY3R4LnBoYXNlMy5yb290IHx8IHByb2Nlc3MuY3dkKCk7XG4gIGNvbnN0IG91dERpciA9IG9wdGlvbnMub3V0RGlyIHx8IGN0eC5waGFzZTMub3V0RGlyIHx8ICdkaXN0JztcbiAgY29uc3Qgcm91dGVzRGlyID0gb3B0aW9ucy5yb3V0ZXNEaXIgfHwgY3R4LnBoYXNlMy5yb3V0ZXNEaXIgfHwgJ2FwcC9yb3V0ZXMnO1xuICBjb25zdCBpc2xhbmRzRGlyID0gb3B0aW9ucy5pc2xhbmRzRGlyIHx8IGN0eC5waGFzZTMuaXNsYW5kc0RpciB8fCAnYXBwL2lzbGFuZHMnO1xuICBjb25zdCBhcHBTaGVsbCA9IG9wdGlvbnMuYXBwU2hlbGwgPz8gY3R4LnBoYXNlMy5hcHBTaGVsbDtcbiAgY29uc3QgbGF5b3V0cyA9IG9wdGlvbnMubGF5b3V0cyA/PyBjdHgucGhhc2UzLmxheW91dHM7XG5cbiAgLy8gU09QLXYwLjIxLjY6IERldGVjdCBpZiB3ZSdyZSBydW5uaW5nIGZyb20gYSBEZW5vIHdvcmtzcGFjZS5cbiAgLy8gSW4gd29ya3NwYWNlIG1vZGUsIEBkZW5vL3ZpdGUtcGx1Z2luIHJlc29sdmVzIGJhcmUgc3BlY2lmaWVycy5cbiAgLy8gSW4gSlNSIG1vZGUsIHdlIG5lZWQgdGhlIG9wZW46c3NnLWNvcmUtcmVzb2x2ZSBwbHVnaW4uXG4gIGNvbnN0IHdvcmtzcGFjZVJvb3QgPSAoKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBmb3IgKGxldCBkID0gcmVzb2x2ZShyb290KTsgZCAhPT0gcmVzb2x2ZShkLCAnLi4nKTsgZCA9IHJlc29sdmUoZCwgJy4uJykpIHtcbiAgICAgICAgY29uc3QgY2ZnID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMocmVzb2x2ZShkLCAnZGVuby5qc29uJyksICd1dGYtOCcpKTtcbiAgICAgICAgaWYgKGNmZy53b3Jrc3BhY2UgJiYgQXJyYXkuaXNBcnJheShjZmcud29ya3NwYWNlKSkgcmV0dXJuIGQ7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7IC8qIGRlbm8uanNvbiBub3QgZm91bmQsIGtlZXAgd2Fsa2luZyB1cCAqLyB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH0pKCk7XG5cbiAgLy8gUmVhZCBpc2xhbmQgbWV0YWRhdGEgZnJvbSBjdHggKEFEUiAwMDEwOiBubyAub3BlbkVsZW1lbnQvIGZhbGxiYWNrKVxuICBjb25zdCBpc2xhbmRUYWdOYW1lcyA9IG9wdGlvbnMuaXNsYW5kVGFnTmFtZXMgfHwgY3R4LnBoYXNlMS5pc2xhbmRUYWdOYW1lcyB8fCBbXTtcbiAgY29uc3QgaXNsYW5kTWV0YSA9IG9wdGlvbnMuaXNsYW5kTWV0YSB8fCBjdHgucGhhc2UxLmlzbGFuZE1ldGEgfHwge307XG4gIGNvbnN0IHBhY2thZ2VNYW5pZmVzdHMgPSBvcHRpb25zLnBhY2thZ2VNYW5pZmVzdHMgfHwgY3R4LnBoYXNlMS5wYWNrYWdlTWFuaWZlc3RzIHx8IFtdO1xuICBjb25zdCBtZXRhZGF0YVJlc29sdmVBbGlhcyA9IG9wdGlvbnMucmVzb2x2ZUFsaWFzIHx8XG4gICAgKGN0eC5waGFzZTEudXNlclJlc29sdmVBbGlhcyBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgaW1wb3J0KCd2aXRlJykuQWxpYXNbXSB8IHVuZGVmaW5lZCk7XG5cbiAgLy8gUmVhZCBvcHRpb25zIGZyb20gY3R4XG4gIGlmICghb3B0aW9ucy5oZWFkRXh0cmFzKSBvcHRpb25zLmhlYWRFeHRyYXMgPSBjdHgucGhhc2UzLmhlYWRFeHRyYXMgfHwgdW5kZWZpbmVkO1xuICBpZiAob3B0aW9ucy5hbGxvd0hlYWRFeHRyYXNTY3JpcHRzID09PSB1bmRlZmluZWQpIHtcbiAgICBvcHRpb25zLmFsbG93SGVhZEV4dHJhc1NjcmlwdHMgPSBjdHgucGhhc2UzLmFsbG93SGVhZEV4dHJhc1NjcmlwdHM7XG4gIH1cbiAgaWYgKCFvcHRpb25zLmh0bWwpIG9wdGlvbnMuaHRtbCA9IGN0eC5waGFzZTMuaHRtbCB8fCB1bmRlZmluZWQ7XG4gIGlmICghb3B0aW9ucy5taWRkbGV3YXJlKSBvcHRpb25zLm1pZGRsZXdhcmUgPSBjdHgucGhhc2UzLm1pZGRsZXdhcmUgfHwgdW5kZWZpbmVkO1xuICBpZiAoIW9wdGlvbnMudXBncmFkZVN0cmF0ZWd5KSBvcHRpb25zLnVwZ3JhZGVTdHJhdGVneSA9IGN0eC5waGFzZTMudXBncmFkZVN0cmF0ZWd5O1xuICBpZiAoIW9wdGlvbnMuYmFzZSkgb3B0aW9ucy5iYXNlID0gY3R4LnBoYXNlMy5iYXNlO1xuICBpZiAob3B0aW9ucy52aWV3VHJhbnNpdGlvbiA9PT0gdW5kZWZpbmVkKSBvcHRpb25zLnZpZXdUcmFuc2l0aW9uID0gY3R4LnBoYXNlMy52aWV3VHJhbnNpdGlvbjtcbiAgaWYgKCFvcHRpb25zLnNwZWN1bGF0aW9uKSBvcHRpb25zLnNwZWN1bGF0aW9uID0gY3R4LnBoYXNlMy5zcGVjdWxhdGlvbiB8fCB1bmRlZmluZWQ7XG5cbiAgLy8gR2VuZXJhdGUgU1NHIGVudHJ5IGNvZGVcbiAgY29uc3QgeyBzY2FuUm91dGVzLCBzY2FuSXNsYW5kcywgc2NhbklzbGFuZE1ldGEsIGZpbGVUb1RhZ05hbWUgfSA9IGF3YWl0IGltcG9ydChcbiAgICAnQG9wZW5lbGVtZW50L3NzZydcbiAgKTtcbiAgY29uc3QgeyBnZW5lcmF0ZUhvbm9FbnRyeUNvZGUgfSA9IGF3YWl0IGltcG9ydCgnQG9wZW5lbGVtZW50L3NzZycpO1xuXG4gIGNvbnN0IHJvdXRlcyA9IGF3YWl0IHNjYW5Sb3V0ZXMocm91dGVzRGlyKTtcblxuICAvLyB2MC4yNS4wOiBHZW5lcmF0ZSB0eXBlLXNhZmUgcm91dGUgcGFyYW1ldGVyIGRlY2xhcmF0aW9ucyBmb3IgYHZpcnR1YWw6b3Blbi1yb3V0ZXNgXG4gIGNvbnN0IHsgZ2VuZXJhdGVSb3V0ZVR5cGVzIH0gPSBhd2FpdCBpbXBvcnQoJ0BvcGVuZWxlbWVudC9zc2cnKTtcbiAgY29uc3Qgcm91dGVUeXBlRHRzID0gZ2VuZXJhdGVSb3V0ZVR5cGVzKHJvdXRlcyk7XG4gIGNvbnN0IGRvdE9wZW5FbGVtZW50RGlyID0gam9pbihyb290LCAnLm9wZW5FbGVtZW50Jyk7XG4gIG1rZGlyU3luYyhkb3RPcGVuRWxlbWVudERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIHdyaXRlRmlsZVN5bmMoam9pbihkb3RPcGVuRWxlbWVudERpciwgJ3JvdXRlcy5kLnRzJyksIHJvdXRlVHlwZUR0cywgJ3V0Zi04Jyk7XG4gIGxvZy5pbmZvKGBSb3V0ZSB0eXBlcyBnZW5lcmF0ZWQgLT4gLm9wZW5FbGVtZW50L3JvdXRlcy5kLnRzYCk7XG5cbiAgY29uc3QgaXNsYW5kc1Jvb3QgPSBqb2luKHJvb3QsIGlzbGFuZHNEaXIpO1xuICBjb25zdCBzc2dJc2xhbmRGaWxlcyA9IGF3YWl0IHNjYW5Jc2xhbmRzKGlzbGFuZHNSb290KTtcbiAgY29uc3Qgc3NnSXNsYW5kVGFnTmFtZXMgPSBpc2xhbmRUYWdOYW1lcy5sZW5ndGggPiAwXG4gICAgPyBpc2xhbmRUYWdOYW1lc1xuICAgIDogc3NnSXNsYW5kRmlsZXMubWFwKChmKSA9PiBmaWxlVG9UYWdOYW1lKGYpKTtcbiAgY29uc3Qgc3NnSXNsYW5kTWV0YSA9IE9iamVjdC5rZXlzKGlzbGFuZE1ldGEpLmxlbmd0aCA+IDBcbiAgICA/IGlzbGFuZE1ldGFcbiAgICA6IGF3YWl0IHNjYW5Jc2xhbmRNZXRhKGlzbGFuZHNSb290LCBzc2dJc2xhbmRGaWxlcyk7XG4gIGNvbnN0IHsgYnVpbGRFbnRyeURlc2NyaXB0b3IgfSA9IGF3YWl0IGltcG9ydCgnQG9wZW5lbGVtZW50L3NzZycpO1xuXG4gIGN0eC5waGFzZTEuc3NyQWRtaXNzaW9uUGxhbiA9IGJ1aWxkRW50cnlEZXNjcmlwdG9yKHJvdXRlcywge1xuICAgIHJvdXRlc0RpcixcbiAgICBpc2xhbmRzRGlyLFxuICAgIHNzZzogdHJ1ZSxcbiAgICBpc2xhbmRUYWdOYW1lczogc3NnSXNsYW5kVGFnTmFtZXMsXG4gICAgaXNsYW5kRmlsZXM6IHNzZ0lzbGFuZEZpbGVzLFxuICAgIGlzbGFuZE1ldGE6IHNzZ0lzbGFuZE1ldGEsXG4gICAgcGFja2FnZU1hbmlmZXN0cyxcbiAgICBjbGllbnRPbmx5VGFnczogW10sXG4gICAgYXBwU2hlbGwsXG4gICAgbGF5b3V0cyxcbiAgfSkuc3NyQWRtaXNzaW9uUGxhbjtcblxuICBjb25zdCByYXdTc2dFbnRyeUNvZGUgPSBnZW5lcmF0ZVNzclBvbHlmaWxsQmFubmVyKCkgKyAnXFxuJyArIGdlbmVyYXRlSG9ub0VudHJ5Q29kZShyb3V0ZXMsIHtcbiAgICByb3V0ZXNEaXIsXG4gICAgaXNsYW5kc0RpcixcbiAgICBtaWRkbGV3YXJlOiBvcHRpb25zLm1pZGRsZXdhcmUsXG4gICAgc3NnOiB0cnVlLFxuICAgIGlzbGFuZFRhZ05hbWVzOiBzc2dJc2xhbmRUYWdOYW1lcyxcbiAgICBpc2xhbmRGaWxlczogc3NnSXNsYW5kRmlsZXMsXG4gICAgaXNsYW5kTWV0YTogc3NnSXNsYW5kTWV0YSxcbiAgICBwYWNrYWdlTWFuaWZlc3RzLFxuICAgIGhlYWRFeHRyYXM6IG9wdGlvbnMuaGVhZEV4dHJhcyxcbiAgICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiBvcHRpb25zLmFsbG93SGVhZEV4dHJhc1NjcmlwdHMsXG4gICAgaHRtbDogb3B0aW9ucy5odG1sLFxuICAgIHVwZ3JhZGVTdHJhdGVneTogb3B0aW9ucy51cGdyYWRlU3RyYXRlZ3kgfHwgJ2lkbGUnLFxuICAgIGNsaWVudE9ubHlUYWdzOiBbXSxcbiAgICBhcHBTaGVsbCxcbiAgICBsYXlvdXRzLFxuICB9KTtcbiAgLy8gRGVubyBpbXBvcnQgbWFwIHJlc29sdXRpb24gaGFuZGxlcyBiYXJlIHNwZWNpZmllcnMgKGUuZy4gQG9wZW5lbGVtZW50L3VpL29wZW4tY2FsbG91dClcbiAgLy8gdmlhIHRoZSBjcmVhdGVEZW5vSW1wb3J0TWFwUGx1Z2luIGFkZGVkIHRvIHRoZSBQaGFzZSAzIHZpdGVCdWlsZCBwbHVnaW5zIGJlbG93LlxuICBjb25zdCBzc2dFbnRyeUNvZGUgPSByYXdTc2dFbnRyeUNvZGU7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCB7IGJ1aWxkOiB2aXRlQnVpbGQgfSA9IGF3YWl0IGltcG9ydCgndml0ZScpO1xuXG4gICAgLy8gU1NSIG5vRXh0ZXJuYWw6IHBhY2thZ2VzIHRoYXQgTVVTVCBiZSBpbmxpbmVkIGludG8gdGhlIFNTUiBidW5kbGUuXG4gICAgLy8gV2l0aG91dCB0aGVzZSwgdGhlIFNTUiBidW5kbGUgY29udGFpbnMgYmFyZSBzcGVjaWZpZXIgaW1wb3J0cyB0aGF0IGNhbm5vdFxuICAgIC8vIGJlIHJlc29sdmVkIGluIG5vbi13b3Jrc3BhY2UgZW52aXJvbm1lbnRzIChlLmcuIENGIFBhZ2VzKSwgY2F1c2luZ1xuICAgIC8vIGltcG9ydChlbnRyeS5qcykgdG8gZmFpbCBhbmQgdGhlIGVudGlyZSBTU0cgcGlwZWxpbmUgdG8gcHJvZHVjZSBlbXB0eSBIVE1MLlxuICAgIGNvbnN0IGRlZmF1bHROb0V4dGVybmFsID0gW1xuICAgICAgL15Ab3BlbmVsZW1lbnRcXC8vLFxuICAgIF07XG4gICAgLy8gQURSLTAwNDc6IEV4dGVybmFsIHBhY2thZ2VzIGFyZSBleHRlcm5hbGl6ZWQsIG5vdCBidW5kbGVkLlxuICAgIC8vIEFEUi0wMDU0OiBBU1QtYmFzZWQgZXhwb3J0cyByZXNvbHV0aW9uIGNvdmVycyBBTEwgc3VicGF0aCBleHBvcnRzXG4gICAgLy8gc28gUm9sbGRvd24gZXh0ZXJuYWxpemVzIHRoZW0gY29ycmVjdGx5IHZpYSBtYW5pZmVzdC5zcGVjaWZpZXJzLlxuICAgIC8vIENvbnN1bWVyIHRlbXBsYXRlIGRlbm8uanNvbiBkZWNsYXJlcyB0aGVzZSBwYWNrYWdlcyBzbyBEZW5vIGNhblxuICAgIC8vIHJlc29sdmUgdGhlbSBhdCBydW50aW1lIHdoZW4gYnVpbGRTU0coKSBleGVjdXRlcyBpbXBvcnQoZW50cnkuanMpLlxuICAgIC8vIEhvbm8gc3RheXMgZXh0ZXJuYWwgdW5sZXNzIHRoZSB1c2VyIGV4cGxpY2l0bHkgcmVxdWVzdHMgYWRhcHRlci1zcGVjaWZpY1xuICAgIC8vIGJ1bmRsaW5nIHRocm91Z2ggb3B0aW9ucy5zc3Iubm9FeHRlcm5hbC5cbiAgICBjb25zdCBzc3JFeHRlcm5hbERlZmF1bHRzID0gW1xuICAgICAgJ2hvbm8nLFxuICAgIF07XG5cbiAgICAvLyBTdGVwIDA6IERlbm8gcHJlLXJlc29sdXRpb24gKyBBU1Qgc3VicGF0aCBkaXNjb3ZlcnkgKEFEUi0wMDQ3ICsgQURSLTAwNTQpXG4gICAgY29uc3QgbWFuaWZlc3QgPSBhd2FpdCByZXNvbHZlRXh0ZXJuYWxNYW5pZmVzdChcbiAgICAgIHNzckV4dGVybmFsRGVmYXVsdHMsXG4gICAgICByb290LFxuICAgICAgb3B0aW9ucy5za2lwUHJlUmVzb2x1dGlvbiB8fCBjdHgucGhhc2UzPy5za2lwUHJlUmVzb2x1dGlvbixcbiAgICApO1xuXG4gICAgY29uc3QgdXNlck5vRXh0ZXJuYWwgPSBvcHRpb25zLnNzcj8ubm9FeHRlcm5hbCB8fCBbXTtcbiAgICBjb25zdCBhbGxOb0V4dGVybmFsID0gWy4uLmRlZmF1bHROb0V4dGVybmFsLCAuLi51c2VyTm9FeHRlcm5hbF07XG5cbiAgICAvLyBIYW5kbGUgYWxpYXMgLSBwcmVmZXIgQ0xJIG9wdGlvbnMsIHRoZW4gY3R4IGZyb20gUGhhc2UgMVxuICAgIGNvbnN0IGFsaWFzID0gbWV0YWRhdGFSZXNvbHZlQWxpYXM7XG4gICAgY29uc3Qgdml0ZVJlc29sdmVBbGlhcyA9IG5vcm1hbGl6ZVZpdGVBbGlhc2VzKGFsaWFzLCByb290KTtcbiAgICBpZiAoYWxpYXMpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGFsaWFzKSkge1xuICAgICAgICBmb3IgKGNvbnN0IGEgb2YgYWxpYXMpIHtcbiAgICAgICAgICBpZiAoYS5maW5kID09PSAnQG9wZW5lbGVtZW50L3VpJykge1xuICAgICAgICAgICAgLy8gdjAuMTQuNjogQ2hlY2sgaWYgcmVwbGFjZW1lbnQgaXMgYWxyZWFkeSBjb3ZlcmVkIGJ5IGRlZmF1bHROb0V4dGVybmFsXG4gICAgICAgICAgICBjb25zdCBpc0FscmVhZHlDb3ZlcmVkID0gZGVmYXVsdE5vRXh0ZXJuYWwuc29tZShcbiAgICAgICAgICAgICAgKHBhdHRlcm46IHN0cmluZyB8IFJlZ0V4cCkgPT5cbiAgICAgICAgICAgICAgICBwYXR0ZXJuIGluc3RhbmNlb2YgUmVnRXhwICYmIHBhdHRlcm4udGVzdChhLnJlcGxhY2VtZW50KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoIWlzQWxyZWFkeUNvdmVyZWQpIHtcbiAgICAgICAgICAgICAgYWxsTm9FeHRlcm5hbC5wdXNoKGEucmVwbGFjZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICgnQG9wZW5lbGVtZW50L3VpJyBpbiBhbGlhcykge1xuICAgICAgICBjb25zdCBpc0FscmVhZHlDb3ZlcmVkID0gZGVmYXVsdE5vRXh0ZXJuYWwuc29tZShcbiAgICAgICAgICAocGF0dGVybjogc3RyaW5nIHwgUmVnRXhwKSA9PlxuICAgICAgICAgICAgcGF0dGVybiBpbnN0YW5jZW9mIFJlZ0V4cCAmJiBwYXR0ZXJuLnRlc3QoYWxpYXNbJ0BvcGVuZWxlbWVudC91aSddKSxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFpc0FscmVhZHlDb3ZlcmVkKSB7XG4gICAgICAgICAgYWxsTm9FeHRlcm5hbC5wdXNoKGFsaWFzWydAb3BlbmVsZW1lbnQvdWknXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBCdWlsZCB0aGUgc2VsZi1jb250YWluZWQgU1NSIGJ1bmRsZSAoQURSIDAwMDggUGhhc2UgQylcbiAgICAvLyBSZXBsYWNlcyBjcmVhdGVTZXJ2ZXIoKSArIHNzckxvYWRNb2R1bGUoKSB3aXRoIHZpdGVCdWlsZCArIGltcG9ydCgpLlxuICAgIC8vIG5vRXh0ZXJuYWwgZW5zdXJlcyBhbGwgZGVwZW5kZW5jaWVzIGFyZSBpbmxpbmVkIGludG8gYSBzaW5nbGUgYnVuZGxlLFxuICAgIC8vIHNvIG1vZHVsZS1sZXZlbCB2YXJpYWJsZXMgKFBoYXNlIEIpIGFyZSBzaGFyZWQgYWNyb3NzIHRoZSBlbnRpcmUgZ3JhcGguXG4gICAgY29uc3Qgc3NyT3V0RGlyID0gam9pbihyb290LCBvdXREaXIsICdzZXJ2ZXInKTtcbiAgICBsb2cuaW5mbyhgQnVpbGRpbmcgU1NSIGJ1bmRsZSAtPiAke3Nzck91dERpcn1gKTtcbiAgICBjb25zdCBjbGllbnRPbmx5SXNsYW5kSWRzID0gbmV3IFNldChcbiAgICAgIE9iamVjdC5lbnRyaWVzKHNzZ0lzbGFuZE1ldGEpXG4gICAgICAgIC5maWx0ZXIoKFssIG1ldGFdKSA9PiBtZXRhLnNzciA9PT0gZmFsc2UpXG4gICAgICAgIC5tYXAoKFt0YWddKSA9PiB7XG4gICAgICAgICAgY29uc3QgZmlsZSA9IHNzZ0lzbGFuZEZpbGVzW3NzZ0lzbGFuZFRhZ05hbWVzLmluZGV4T2YodGFnKV07XG4gICAgICAgICAgcmV0dXJuIGZpbGUgPyBub3JtYWxpemVQYXRoKHJlc29sdmUocm9vdCwgaXNsYW5kc0RpciwgZmlsZSkpIDogJyc7XG4gICAgICAgIH0pXG4gICAgICAgIC5maWx0ZXIoQm9vbGVhbiksXG4gICAgKTtcbiAgICAvLyB2MC4yMTogQnVpbGQgZmlsZVBhdGggLT4gdGFnTmFtZSBtYXAgZm9yIGNsaWVudC1vbmx5IHBsYWNlaG9sZGVyIGdlbmVyYXRpb24uXG4gICAgY29uc3QgY2xpZW50T25seVRhZ01hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCBbdGFnLCBtZXRhXSBvZiBPYmplY3QuZW50cmllcyhzc2dJc2xhbmRNZXRhKSkge1xuICAgICAgaWYgKG1ldGEuc3NyICE9PSBmYWxzZSkgY29udGludWU7XG4gICAgICBjb25zdCBmaWxlID0gc3NnSXNsYW5kRmlsZXNbc3NnSXNsYW5kVGFnTmFtZXMuaW5kZXhPZih0YWcpXTtcbiAgICAgIGlmIChmaWxlKSBjbGllbnRPbmx5VGFnTWFwLnNldChub3JtYWxpemVQYXRoKHJlc29sdmUocm9vdCwgaXNsYW5kc0RpciwgZmlsZSkpLCB0YWcpO1xuICAgIH1cblxuICAgIC8vIHYwLjIxIFNPUC0wMDQ6IENvbmZsaWN0IGRldGVjdGlvbjogc2FtZSB0YWcgbXVzdCBub3QgYmUgYm90aCBTU1IgYW5kIGNsaWVudDpvbmx5LlxuICAgIGNvbnN0IHNzclRhZ3MgPSBuZXcgU2V0KFxuICAgICAgT2JqZWN0LmVudHJpZXMoc3NnSXNsYW5kTWV0YSlcbiAgICAgICAgLmZpbHRlcigoWywgbWV0YV0pID0+IG1ldGEuc3NyICE9PSBmYWxzZSlcbiAgICAgICAgLm1hcCgoW3RhZ10pID0+IHRhZyksXG4gICAgKTtcbiAgICBjb25zdCBjb25mbGljdFRhZ3MgPSBbLi4uY2xpZW50T25seVRhZ01hcC52YWx1ZXMoKV0uZmlsdGVyKCh0KSA9PiBzc3JUYWdzLmhhcyh0KSk7XG4gICAgaWYgKGNvbmZsaWN0VGFncy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBbb3BlbkVsZW1lbnRdIFNTUitjbGllbnQ6b25seSBjb25mbGljdCBkZXRlY3RlZCBmb3IgdGFnczogJHtjb25mbGljdFRhZ3Muam9pbignLCAnKX0uIGAgK1xuICAgICAgICAgICdBIHRhZyBjYW5ub3QgYmUgYm90aCBTU1ItY2FwYWJsZSBhbmQgY2xpZW50Om9ubHkgb24gdGhlIHNhbWUgcGFnZS4nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBhd2FpdCB2aXRlQnVpbGQoe1xuICAgICAgY29uZmlnRmlsZTogZmFsc2UsXG4gICAgICByb290LFxuICAgICAgbG9nTGV2ZWw6ICdlcnJvcicsXG4gICAgICBidWlsZDoge1xuICAgICAgICBzc3I6IHRydWUsXG4gICAgICAgIG91dERpcjogc3NyT3V0RGlyLFxuICAgICAgICBjaHVua1NpemVXYXJuaW5nTGltaXQ6IFNTUl9DSFVOS19TSVpFX1dBUk5JTkdfTElNSVRfS0IsXG4gICAgICAgIHJvbGx1cE9wdGlvbnM6IHtcbiAgICAgICAgICBpbnB1dDogeyBlbnRyeTogVklSVFVBTF9TU0dfRU5UUllfSUQgfSxcbiAgICAgICAgICAvLyB2MC4yMTogU3VwcHJlc3MgSU1QT1JUX0lTX1VOREVGSU5FRCBmb3IgcmV2YWxpZGF0ZTsgdGhlIGdlbmVyYXRlZFxuICAgICAgICAgIC8vIGNvZGUgdXNlcyB0eXBlb2YgY2hlY2sgd2hpY2ggY29ycmVjdGx5IGhhbmRsZXMgdW5kZWZpbmVkIGV4cG9ydHMuXG4gICAgICAgICAgb253YXJuKHdhcm5pbmcsIHdhcm4pIHtcbiAgICAgICAgICAgIGlmICh3YXJuaW5nLmNvZGUgPT09ICdJTVBPUlRfSVNfVU5ERUZJTkVEJykgcmV0dXJuO1xuICAgICAgICAgICAgd2Fybih3YXJuaW5nKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIG91dHB1dDoge1xuICAgICAgICAgICAgZm9ybWF0OiAnZXNtJyxcbiAgICAgICAgICAgIC8vIFdvcmtzcGFjZSBzb3VyY2VzIG1heSB1c2UgZXhwbGljaXQgbnBtOiBzcGVjaWZpZXJzIHRoYXQgUm9sbGRvd25cbiAgICAgICAgICAgIC8vIHJld3JpdGVzIHRvIGJhcmUgaW1wb3J0cyB3aGlsZSBidW5kbGluZy4gUmUtZW1pdCBrbm93biBleHRlcm5hbHNcbiAgICAgICAgICAgIC8vIGFzIERlbm8tcmVzb2x2YWJsZSBucG06IGltcG9ydHMgZm9yIGZyZXNoIEpTUiBjb25zdW1lcnMuXG4gICAgICAgICAgICBwYXRoczogU1NSX0VYVEVSTkFMX1BBVEhTLFxuICAgICAgICAgICAgLy8gQURSLTAwNDQ6IGN1c3RvbUVsZW1lbnRzIHBvbHlmaWxsIG11c3QgcnVuIGJlZm9yZSBFU00gaW1wb3J0cy5cbiAgICAgICAgICAgIC8vIFVzZXMgTWFwLWJhY2tlZCBkZWZpbmUoKS9nZXQoKTsgcmVuZGVyRHNkQnlOYW1lKCkgbG9va3MgdXBcbiAgICAgICAgICAgIC8vIGNvbXBvbmVudHMgdmlhIGN1c3RvbUVsZW1lbnRzLmdldCh0YWdOYW1lKSBkdXJpbmcgU1NHIHJlbmRlcmluZy5cbiAgICAgICAgICAgIC8vIFNPUC0wMTY6IEhUTUxFbGVtZW50IHN0dWIgaXMgc2VsZi1jb250YWluZWQgaW4gQG9wZW5lbGVtZW50L2NvcmUvZHNkLWVsZW1lbnQudHMuXG4gICAgICAgICAgICBiYW5uZXI6IGBcXFxuaWYgKHR5cGVvZiBnbG9iYWxUaGlzLmN1c3RvbUVsZW1lbnRzID09PSAndW5kZWZpbmVkJykge1xuICBjb25zdCBfX29wZW5DZVJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICBnbG9iYWxUaGlzLmN1c3RvbUVsZW1lbnRzID0ge1xuICAgIGRlZmluZShuYW1lLCBjdG9yLCBfb3B0cykgeyBfX29wZW5DZVJlZ2lzdHJ5LnNldChuYW1lLCBjdG9yKTsgfSxcbiAgICBnZXQobmFtZSkgeyByZXR1cm4gX19vcGVuQ2VSZWdpc3RyeS5nZXQobmFtZSk7IH0sXG4gICAgd2hlbkRlZmluZWQobmFtZSkgeyByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKF9fb3BlbkNlUmVnaXN0cnkuZ2V0KG5hbWUpKTsgfSxcbiAgICB1cGdyYWRlKF9yb290KSB7fSxcbiAgfTtcbn1cbmAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBzc3I6IHsgbm9FeHRlcm5hbDogYWxsTm9FeHRlcm5hbCwgZXh0ZXJuYWw6IG1hbmlmZXN0LnNwZWNpZmllcnMgfSxcbiAgICAgIC8vIEFEUiAwMDA4IFBoYXNlIEE6IEluamVjdCBoZWFkRXh0cmFzIHZpYSBkZWZpbmUgaW5zdGVhZCBvZiAub3BlbkVsZW1lbnQvaGVhZC1leHRyYXMuaHRtbFxuICAgICAgLy8gVGhlIGdlbmVyYXRlZCBlbnRyeSBjb2RlIHVzZXMgX19IRUFEX0VYVFJBU19fIHdoaWNoIGdldHMgcmVwbGFjZWRcbiAgICAgIC8vIGF0IGJ1aWxkIHRpbWUuIFRoaXMgYXZvaWRzIHRoZSBWaXRlIFNTUiBBc3luY0Z1bmN0aW9uIHN5bnRheCBlcnJvcnNcbiAgICAgIC8vIHRoYXQgbGFyZ2UgaW5saW5lIHN0cmluZ3MgKHdpdGggYmFja3RpY2tzLyR7fSkgY2F1c2UuXG4gICAgICBkZWZpbmU6IG9wdGlvbnMuaGVhZEV4dHJhc1xuICAgICAgICA/IHsgX19IRUFEX0VYVFJBU19fOiBKU09OLnN0cmluZ2lmeShvcHRpb25zLmhlYWRFeHRyYXMpIH1cbiAgICAgICAgOiB7IF9fSEVBRF9FWFRSQVNfXzogJ1wiXCInIH0sXG4gICAgICBlc2J1aWxkOiB7XG4gICAgICAgIC8vIEFEUi0wMDU3OiBKU1ggYXV0b21hdGljIHJ1bnRpbWUsIHNhbWUgcmVhc29uIGFzIGJ1aWxkLWNsaWVudC50cy5cbiAgICAgICAgLy8gU1NHIGJ1aWxkIGFsc28gcHJvY2Vzc2VzIC50c3ggaXNsYW5kIGZpbGVzIGZvciBTU1IgcmVuZGVyaW5nLlxuICAgICAgICBqc3g6ICdhdXRvbWF0aWMnLFxuICAgICAgICBqc3hJbXBvcnRTb3VyY2U6ICdAb3BlbmVsZW1lbnQvY29yZScsXG4gICAgICAgIHRzY29uZmlnUmF3OiB7XG4gICAgICAgICAgY29tcGlsZXJPcHRpb25zOiB7XG4gICAgICAgICAgICB1c2VEZWZpbmVGb3JDbGFzc0ZpZWxkczogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEFEUiAwMDEwOiBWaXJ0dWFsIFNTRyBlbnRyeSBtb2R1bGVcbiAgICAgICAgLy8gUmVwbGFjZXMgLm9wZW5FbGVtZW50Ly5vcGVuRWxlbWVudC1zc2ctZW50cnkudHMgZmlsZSB3cml0ZVxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ29wZW46dmlydHVhbC1zc2ctZW50cnknLFxuICAgICAgICAgIHJlc29sdmVJZChpZCkge1xuICAgICAgICAgICAgaWYgKGlkID09PSBWSVJUVUFMX1NTR19FTlRSWV9JRCkgcmV0dXJuIFJFU09MVkVEX1NTR19FTlRSWV9JRDtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxvYWQoaWQpIHtcbiAgICAgICAgICAgIGlmIChpZCA9PT0gUkVTT0xWRURfU1NHX0VOVFJZX0lEKSByZXR1cm4gc3NnRW50cnlDb2RlO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIC8vIEFEUiAwMDA4IFBoYXNlIEM6IFByb3ZpZGUgc3R1YnMgZm9yIHJldGFpbmVkIG9wdGlvbmFsIHBhY2thZ2VzLlxuICAgICAgICAvLyBUaGUgZ2VuZXJhdGVkIGVudHJ5IGNvZGUgY2FuIGltcG9ydCBAb3BlbmVsZW1lbnQvY29udGVudCBhbmRcbiAgICAgICAgLy8gQG9wZW5lbGVtZW50L2kxOG4sIGJ1dCB0aGVzZSBtYXkgbm90IGJlIGluc3RhbGxlZC5cbiAgICAgICAgLy8gVGhpcyBwbHVnaW4gcmVzb2x2ZXMgdGhlbSB0byBlbXB0eSBzdHVicyB3aGVuIG1pc3NpbmcsIHNvIHRoZVxuICAgICAgICAvLyB2aXRlQnVpbGQoKSBzdWNjZWVkcyByZWdhcmRsZXNzIG9mIHdoaWNoIHBhY2thZ2VzIGFyZSBhdmFpbGFibGUuXG4gICAgICAgIG9wdGlvbmFsUGFja2FnZVN0dWJzUGx1Z2luKCksXG4gICAgICAgIGNyZWF0ZUdlbmVyYXRlZERhdGFSZXNvbHZlclBsdWdpbih7XG4gICAgICAgICAgcm9vdCxcbiAgICAgICAgICBuYW1lOiAnb3Blbjpzc2ctZ2VuZXJhdGVkLWRhdGEnLFxuICAgICAgICB9KSxcbiAgICAgICAgY3JlYXRlT3BlbkpzclBhY2thZ2VSZXNvbHZlclBsdWdpbih7XG4gICAgICAgICAgd29ya3NwYWNlUm9vdCxcbiAgICAgICAgICB2ZXJzaW9uOiBnZXRKc3JQYWNrYWdlVmVyc2lvbihpbXBvcnQubWV0YS51cmwpLFxuICAgICAgICAgIGxvY2FsUGFja2FnZVJvb3Q6IGdldExvY2FsT3BlbkVsZW1lbnRQYWNrYWdlUm9vdChpbXBvcnQubWV0YS51cmwpLFxuICAgICAgICAgIHVzZXJBbGlhc2VzOiBtZXRhZGF0YVJlc29sdmVBbGlhcyxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnb3Blbjpzc2ctY2xpZW50LW9ubHktaXNsYW5kLXN0dWJzJyxcbiAgICAgICAgICBlbmZvcmNlOiAncHJlJyxcbiAgICAgICAgICBsb2FkKGlkKSB7XG4gICAgICAgICAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplUGF0aChpZC5zcGxpdCgnPycpWzBdKTtcbiAgICAgICAgICAgIGlmICghY2xpZW50T25seUlzbGFuZElkcy5oYXMobm9ybWFsaXplZCkpIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IHRhZ05hbWUgPSBjbGllbnRPbmx5VGFnTWFwLmdldChub3JtYWxpemVkKSB8fCAnb3Blbi1jbGllbnQtb25seS1zdHViJztcbiAgICAgICAgICAgIC8vIENsaWVudC1vbmx5IHN0dWIgbWFya2VyIHVzZXMgYW4gdW5icmFuZGVkIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIC8vIFNTUiBvdXRwdXRzIDx0YWctbmFtZSBkYXRhLWNsaWVudC1vbmx5PVwidHJ1ZVwiPjwvdGFnLW5hbWU+XG4gICAgICAgICAgICAvLyBDbGllbnQgcnVudGltZSBpbXBvcnRzIHRoZSByZWFsIG1vZHVsZSBhbmQgdXBncmFkZXMgdGhlIGVsZW1lbnQuXG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICBgaW1wb3J0IHsgZGVmaW5lSXNsYW5kQ29uZmlnIH0gZnJvbSAnQG9wZW5lbGVtZW50L2FwcCc7YCxcbiAgICAgICAgICAgICAgYGV4cG9ydCBjb25zdCB0YWdOYW1lID0gJHtKU09OLnN0cmluZ2lmeSh0YWdOYW1lKX07YCxcbiAgICAgICAgICAgICAgJ2V4cG9ydCBjb25zdCBvcGVuRWxlbWVudCA9IGRlZmluZUlzbGFuZENvbmZpZyh7IHNzcjogZmFsc2UgfSk7JyxcbiAgICAgICAgICAgICAgYGV4cG9ydCBkZWZhdWx0IGNsYXNzIE9wZW5DbGllbnRPbmx5U3R1YiBleHRlbmRzIEhUTUxFbGVtZW50IHtcbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKCF0aGlzLmhhc0F0dHJpYnV0ZSgnZGF0YS1jbGllbnQtb25seScpKSB7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnZGF0YS1jbGllbnQtb25seScsICd0cnVlJyk7XG4gICAgfVxuICB9XG59YCxcbiAgICAgICAgICAgIF0uam9pbignXFxuJyk7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICByZXNvbHZlOiB7XG4gICAgICAgIHByZXNlcnZlU3ltbGlua3M6IHRydWUsXG4gICAgICAgIGV4dGVuc2lvbnM6IFsnLnRzJywgJy50c3gnLCAnLmpzJywgJy5qc3gnLCAnLmpzb24nXSxcbiAgICAgICAgLi4uKHZpdGVSZXNvbHZlQWxpYXMgPyB7IGFsaWFzOiB2aXRlUmVzb2x2ZUFsaWFzIH0gOiB7fSksXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGxvZy5pbmZvKCdTU1IgYnVuZGxlIGJ1aWx0IHN1Y2Nlc3NmdWxseScpO1xuXG4gICAgLy8gTG9hZCB0aGUgU1NSIGJ1bmRsZSBhbmQgcnVuIFNTRyByZW5kZXJpbmcgcGlwZWxpbmVcbiAgICBjb25zdCBzc3JCdW5kbGVQYXRoID0gcmVzb2x2ZShzc3JPdXREaXIsICdlbnRyeS5qcycpO1xuICAgIC8vIE0tMTggZml4OiBVc2UgcHJvY2Vzcy5wbGF0Zm9ybSBpbnN0ZWFkIG9mIERlbm8uYnVpbGQub3MgZm9yIE5vZGUuanMgY29tcGF0XG4gICAgY29uc3QgaXNXaW5kb3dzID0gdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMic7XG4gICAgY29uc3Qgc3NyQnVuZGxlVXJsID0gaXNXaW5kb3dzXG4gICAgICA/ICdmaWxlOi8vLycgKyBzc3JCdW5kbGVQYXRoLnJlcGxhY2UoL1xcXFwvZywgJy8nKVxuICAgICAgOiAnZmlsZTovLycgKyBzc3JCdW5kbGVQYXRoO1xuICAgIGNvbnN0IG1vZHVsZSA9IGF3YWl0IGltcG9ydChzc3JCdW5kbGVVcmwpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgaWYgKCFtb2R1bGUuZGVmYXVsdCkge1xuICAgICAgdGhyb3cgbmV3IFNzclJlbmRlckVycm9yKCd2aXJ0dWFsOm9wZW4tc3NnLWVudHJ5JywgbmV3IEVycm9yKCdGYWlsZWQgdG8gbG9hZCBIb25vIGFwcCcpKTtcbiAgICB9XG5cbiAgICAvLyBEZWxlZ2F0ZSB0byBzaGFyZWQgc3NnUmVuZGVyKCkgLSB6ZXJvIFZpdGUgZGVwZW5kZW5jeSBmcm9tIHRoaXMgcG9pbnRcbiAgICBhd2FpdCBzc2dSZW5kZXIoXG4gICAgICBtb2R1bGUgYXMgUGFyYW1ldGVyczx0eXBlb2Ygc3NnUmVuZGVyPlswXSxcbiAgICAgIHtcbiAgICAgICAgcm9vdCxcbiAgICAgICAgb3V0RGlyLFxuICAgICAgICBiYXNlOiBvcHRpb25zLmJhc2UgfHwgJy8nLFxuICAgICAgICBoZWFkRXh0cmFzOiBvcHRpb25zLmhlYWRFeHRyYXMsXG4gICAgICAgIGh0bWw6IG9wdGlvbnMuaHRtbCxcbiAgICAgICAgbWlkZGxld2FyZTogb3B0aW9ucy5taWRkbGV3YXJlLFxuICAgICAgICBpc2xhbmRUYWdOYW1lczogc3NnSXNsYW5kVGFnTmFtZXMsXG4gICAgICAgIHZpZXdUcmFuc2l0aW9uOiBvcHRpb25zLnZpZXdUcmFuc2l0aW9uLFxuICAgICAgICBzcGVjdWxhdGlvbjogb3B0aW9ucy5zcGVjdWxhdGlvbiBhcyBib29sZWFuIHwgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAgY3JlYXRlU3NnUmVuZGVyRXZpZGVuY2UoY3R4KSxcbiAgICApO1xuXG4gICAgbG9nLmluZm8oJ1N0YXRpYyBzaXRlIGdlbmVyYXRlZCAtPiAnICsgam9pbihyb290LCBvdXREaXIpKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc3QgY2F1c2UgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyKSk7XG4gICAgdGhyb3cgbmV3IFNzclJlbmRlckVycm9yKCdTU0cgcGlwZWxpbmUnLCBjYXVzZSk7XG4gIH1cbn1cblxuZXhwb3J0IHsgYnVpbGRTU0cgfTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUFTLElBQUksUUFBUSxrQkFBa0I7QUFDdkM7Ozs7Ozs7Ozs7Ozs7O0NBY0MsR0FFRCxTQUFTLElBQUksRUFBRSxPQUFPLFFBQVEsWUFBWTtBQUMxQyxTQUFTLGFBQWEsUUFBUSxXQUFXO0FBQ3pDLFNBQVMsYUFBYSxRQUFRLE9BQU87QUFDckMsT0FBTyxhQUFhLGVBQWU7QUFDbkMsU0FBUyxVQUFVLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxhQUFhLFFBQVEsVUFBVTtBQUk3RSxTQUFTLFNBQVMsUUFBUSxtQkFBbUI7QUFDN0MsU0FBUyxjQUFjLFFBQVEsMkJBQTJCO0FBQzFELFNBQVMsWUFBWSxRQUFRLDJCQUEyQjtBQUN4RCxTQUFTLHVCQUF1QixRQUFRLGtCQUFrQjtBQUMxRCxTQUFTLGlDQUFpQyxRQUFRLGdDQUFnQztBQUNsRixTQUFTLGtDQUFrQyxRQUFRLDZCQUE2QjtBQUNoRixTQUFTLHlCQUF5QixFQUFFLHVCQUF1QixRQUFRLG1CQUFtQjtBQUN0RixTQUFTLDBCQUEwQixRQUFRLGVBQWU7QUFDMUQsU0FBUyxvQkFBb0IsUUFBUSxvQkFBb0I7QUFFekQsOEVBQThFLEdBQzlFLE1BQU0sbUNBQW1DO0FBRXpDLDREQUE0RCxHQUM1RCxNQUFNLGtDQUFrQztBQUV4QywwREFBMEQsR0FDMUQsTUFBTSxxQkFBNkM7RUFDakQsaUJBQWlCO0FBQ25CO0FBRUEsTUFBTSxNQUFNLGFBQWE7QUFFekIsTUFBTSx1QkFBdUI7QUFDN0IsTUFBTSx3QkFBd0IsT0FBTztBQUNyQyxTQUFTLHFCQUFxQixPQUFlO0VBQzNDLE1BQU0sUUFBUSxRQUFRLEtBQUssQ0FBQztFQUM1QixJQUFJLE9BQU8sT0FBTyxLQUFLLENBQUMsRUFBRTtFQUMxQiwwQkFBMEI7RUFDMUIsSUFBSTtJQUNGLE1BQU0sV0FBVyxLQUFLLEtBQUssQ0FDekIsT0FBTyxTQUFTLGNBQ1osS0FBSyxnQkFBZ0IsQ0FBQyxJQUFJLElBQUksZ0JBQWdCLFlBQVksR0FBRyxLQUM3RCxhQUFhLElBQUksSUFBSSxnQkFBZ0IsWUFBWSxHQUFHLEdBQUc7SUFFN0QsT0FBTyxTQUFTLE9BQU8sSUFBSTtFQUM3QixFQUFFLE9BQU07SUFDTixPQUFPO0VBQ1Q7QUFDRjtBQUVBLFNBQVMsK0JBQStCLE9BQWU7RUFDckQsSUFBSSxDQUFDLFFBQVEsVUFBVSxDQUFDLFVBQVUsT0FBTztFQUN6QyxJQUFJO0lBQ0YsTUFBTSxPQUFPLFFBQVEsY0FBYyxJQUFJLElBQUksS0FBSyxXQUFXLE1BQU0sTUFBTSxNQUFNO0lBQzdFLE9BQU8sV0FBVyxRQUFRLE1BQU0sWUFBWSxRQUFRLGdCQUFnQixPQUFPO0VBQzdFLEVBQUUsT0FBTTtJQUNOLE9BQU87RUFDVDtBQUNGO0FBdUNBLGVBQWUsU0FDYixVQUEyQixDQUFDLENBQUMsRUFDN0IsR0FBNEI7RUFFNUIsTUFBTSxPQUFPLFFBQVEsSUFBSSxJQUFJLElBQUksTUFBTSxDQUFDLElBQUksSUFBSSxRQUFRLEdBQUc7RUFDM0QsTUFBTSxTQUFTLFFBQVEsTUFBTSxJQUFJLElBQUksTUFBTSxDQUFDLE1BQU0sSUFBSTtFQUN0RCxNQUFNLFlBQVksUUFBUSxTQUFTLElBQUksSUFBSSxNQUFNLENBQUMsU0FBUyxJQUFJO0VBQy9ELE1BQU0sYUFBYSxRQUFRLFVBQVUsSUFBSSxJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUk7RUFDbEUsTUFBTSxXQUFXLFFBQVEsUUFBUSxJQUFJLElBQUksTUFBTSxDQUFDLFFBQVE7RUFDeEQsTUFBTSxVQUFVLFFBQVEsT0FBTyxJQUFJLElBQUksTUFBTSxDQUFDLE9BQU87RUFFckQsOERBQThEO0VBQzlELGlFQUFpRTtFQUNqRSx5REFBeUQ7RUFDekQsTUFBTSxnQkFBZ0IsQ0FBQztJQUNyQixJQUFJO01BQ0YsSUFBSyxJQUFJLElBQUksUUFBUSxPQUFPLE1BQU0sUUFBUSxHQUFHLE9BQU8sSUFBSSxRQUFRLEdBQUcsTUFBTztRQUN4RSxNQUFNLE1BQU0sS0FBSyxLQUFLLENBQUMsYUFBYSxRQUFRLEdBQUcsY0FBYztRQUM3RCxJQUFJLElBQUksU0FBUyxJQUFJLE1BQU0sT0FBTyxDQUFDLElBQUksU0FBUyxHQUFHLE9BQU87TUFDNUQ7SUFDRixFQUFFLE9BQU0sQ0FBNkM7SUFDckQsT0FBTztFQUNULENBQUM7RUFFRCxzRUFBc0U7RUFDdEUsTUFBTSxpQkFBaUIsUUFBUSxjQUFjLElBQUksSUFBSSxNQUFNLENBQUMsY0FBYyxJQUFJLEVBQUU7RUFDaEYsTUFBTSxhQUFhLFFBQVEsVUFBVSxJQUFJLElBQUksTUFBTSxDQUFDLFVBQVUsSUFBSSxDQUFDO0VBQ25FLE1BQU0sbUJBQW1CLFFBQVEsZ0JBQWdCLElBQUksSUFBSSxNQUFNLENBQUMsZ0JBQWdCLElBQUksRUFBRTtFQUN0RixNQUFNLHVCQUF1QixRQUFRLFlBQVksSUFDOUMsSUFBSSxNQUFNLENBQUMsZ0JBQWdCO0VBRTlCLHdCQUF3QjtFQUN4QixJQUFJLENBQUMsUUFBUSxVQUFVLEVBQUUsUUFBUSxVQUFVLEdBQUcsSUFBSSxNQUFNLENBQUMsVUFBVSxJQUFJO0VBQ3ZFLElBQUksUUFBUSxzQkFBc0IsS0FBSyxXQUFXO0lBQ2hELFFBQVEsc0JBQXNCLEdBQUcsSUFBSSxNQUFNLENBQUMsc0JBQXNCO0VBQ3BFO0VBQ0EsSUFBSSxDQUFDLFFBQVEsSUFBSSxFQUFFLFFBQVEsSUFBSSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksSUFBSTtFQUNyRCxJQUFJLENBQUMsUUFBUSxVQUFVLEVBQUUsUUFBUSxVQUFVLEdBQUcsSUFBSSxNQUFNLENBQUMsVUFBVSxJQUFJO0VBQ3ZFLElBQUksQ0FBQyxRQUFRLGVBQWUsRUFBRSxRQUFRLGVBQWUsR0FBRyxJQUFJLE1BQU0sQ0FBQyxlQUFlO0VBQ2xGLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxRQUFRLElBQUksR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJO0VBQ2pELElBQUksUUFBUSxjQUFjLEtBQUssV0FBVyxRQUFRLGNBQWMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxjQUFjO0VBQzVGLElBQUksQ0FBQyxRQUFRLFdBQVcsRUFBRSxRQUFRLFdBQVcsR0FBRyxJQUFJLE1BQU0sQ0FBQyxXQUFXLElBQUk7RUFFMUUsMEJBQTBCO0VBQzFCLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FDN0U7RUFFRixNQUFNLEVBQUUscUJBQXFCLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQztFQUUvQyxNQUFNLFNBQVMsTUFBTSxXQUFXO0VBRWhDLHFGQUFxRjtFQUNyRixNQUFNLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQztFQUM1QyxNQUFNLGVBQWUsbUJBQW1CO0VBQ3hDLE1BQU0sb0JBQW9CLEtBQUssTUFBTTtFQUNyQyxVQUFVLG1CQUFtQjtJQUFFLFdBQVc7RUFBSztFQUMvQyxjQUFjLEtBQUssbUJBQW1CLGdCQUFnQixjQUFjO0VBQ3BFLElBQUksSUFBSSxDQUFDLENBQUMsaURBQWlELENBQUM7RUFFNUQsTUFBTSxjQUFjLEtBQUssTUFBTTtFQUMvQixNQUFNLGlCQUFpQixNQUFNLFlBQVk7RUFDekMsTUFBTSxvQkFBb0IsZUFBZSxNQUFNLEdBQUcsSUFDOUMsaUJBQ0EsZUFBZSxHQUFHLENBQUMsQ0FBQyxJQUFNLGNBQWM7RUFDNUMsTUFBTSxnQkFBZ0IsT0FBTyxJQUFJLENBQUMsWUFBWSxNQUFNLEdBQUcsSUFDbkQsYUFDQSxNQUFNLGVBQWUsYUFBYTtFQUN0QyxNQUFNLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQztFQUU5QyxJQUFJLE1BQU0sQ0FBQyxnQkFBZ0IsR0FBRyxxQkFBcUIsUUFBUTtJQUN6RDtJQUNBO0lBQ0EsS0FBSztJQUNMLGdCQUFnQjtJQUNoQixhQUFhO0lBQ2IsWUFBWTtJQUNaO0lBQ0EsZ0JBQWdCLEVBQUU7SUFDbEI7SUFDQTtFQUNGLEdBQUcsZ0JBQWdCO0VBRW5CLE1BQU0sa0JBQWtCLDhCQUE4QixPQUFPLHNCQUFzQixRQUFRO0lBQ3pGO0lBQ0E7SUFDQSxZQUFZLFFBQVEsVUFBVTtJQUM5QixLQUFLO0lBQ0wsZ0JBQWdCO0lBQ2hCLGFBQWE7SUFDYixZQUFZO0lBQ1o7SUFDQSxZQUFZLFFBQVEsVUFBVTtJQUM5Qix3QkFBd0IsUUFBUSxzQkFBc0I7SUFDdEQsTUFBTSxRQUFRLElBQUk7SUFDbEIsaUJBQWlCLFFBQVEsZUFBZSxJQUFJO0lBQzVDLGdCQUFnQixFQUFFO0lBQ2xCO0lBQ0E7RUFDRjtFQUNBLHlGQUF5RjtFQUN6RixrRkFBa0Y7RUFDbEYsTUFBTSxlQUFlO0VBRXJCLElBQUk7SUFDRixNQUFNLEVBQUUsT0FBTyxTQUFTLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQztJQUUxQyxxRUFBcUU7SUFDckUsNEVBQTRFO0lBQzVFLHFFQUFxRTtJQUNyRSw4RUFBOEU7SUFDOUUsTUFBTSxvQkFBb0I7TUFDeEI7S0FDRDtJQUNELDZEQUE2RDtJQUM3RCxvRUFBb0U7SUFDcEUsbUVBQW1FO0lBQ25FLGtFQUFrRTtJQUNsRSxxRUFBcUU7SUFDckUsMkVBQTJFO0lBQzNFLDJDQUEyQztJQUMzQyxNQUFNLHNCQUFzQjtNQUMxQjtLQUNEO0lBRUQsNEVBQTRFO0lBQzVFLE1BQU0sV0FBVyxNQUFNLHdCQUNyQixxQkFDQSxNQUNBLFFBQVEsaUJBQWlCLElBQUksSUFBSSxNQUFNLEVBQUU7SUFHM0MsTUFBTSxpQkFBaUIsUUFBUSxHQUFHLEVBQUUsY0FBYyxFQUFFO0lBQ3BELE1BQU0sZ0JBQWdCO1NBQUk7U0FBc0I7S0FBZTtJQUUvRCwyREFBMkQ7SUFDM0QsTUFBTSxRQUFRO0lBQ2QsTUFBTSxtQkFBbUIscUJBQXFCLE9BQU87SUFDckQsSUFBSSxPQUFPO01BQ1QsSUFBSSxNQUFNLE9BQU8sQ0FBQyxRQUFRO1FBQ3hCLEtBQUssTUFBTSxLQUFLLE1BQU87VUFDckIsSUFBSSxFQUFFLElBQUksS0FBSyxtQkFBbUI7WUFDaEMsd0VBQXdFO1lBQ3hFLE1BQU0sbUJBQW1CLGtCQUFrQixJQUFJLENBQzdDLENBQUMsVUFDQyxtQkFBbUIsVUFBVSxRQUFRLElBQUksQ0FBQyxFQUFFLFdBQVc7WUFFM0QsSUFBSSxDQUFDLGtCQUFrQjtjQUNyQixjQUFjLElBQUksQ0FBQyxFQUFFLFdBQVc7WUFDbEM7VUFDRjtRQUNGO01BQ0YsT0FBTyxJQUFJLHFCQUFxQixPQUFPO1FBQ3JDLE1BQU0sbUJBQW1CLGtCQUFrQixJQUFJLENBQzdDLENBQUMsVUFDQyxtQkFBbUIsVUFBVSxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQWtCO1FBRXRFLElBQUksQ0FBQyxrQkFBa0I7VUFDckIsY0FBYyxJQUFJLENBQUMsS0FBSyxDQUFDLGtCQUFrQjtRQUM3QztNQUNGO0lBQ0Y7SUFFQSx5REFBeUQ7SUFDekQsdUVBQXVFO0lBQ3ZFLHdFQUF3RTtJQUN4RSwwRUFBMEU7SUFDMUUsTUFBTSxZQUFZLEtBQUssTUFBTSxRQUFRO0lBQ3JDLElBQUksSUFBSSxDQUFDLENBQUMsdUJBQXVCLEVBQUUsV0FBVztJQUM5QyxNQUFNLHNCQUFzQixJQUFJLElBQzlCLE9BQU8sT0FBTyxDQUFDLGVBQ1osTUFBTSxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUssS0FBSyxHQUFHLEtBQUssT0FDbEMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJO01BQ1QsTUFBTSxPQUFPLGNBQWMsQ0FBQyxrQkFBa0IsT0FBTyxDQUFDLEtBQUs7TUFDM0QsT0FBTyxPQUFPLGNBQWMsUUFBUSxNQUFNLFlBQVksU0FBUztJQUNqRSxHQUNDLE1BQU0sQ0FBQztJQUVaLCtFQUErRTtJQUMvRSxNQUFNLG1CQUFtQixJQUFJO0lBQzdCLEtBQUssTUFBTSxDQUFDLEtBQUssS0FBSyxJQUFJLE9BQU8sT0FBTyxDQUFDLGVBQWdCO01BQ3ZELElBQUksS0FBSyxHQUFHLEtBQUssT0FBTztNQUN4QixNQUFNLE9BQU8sY0FBYyxDQUFDLGtCQUFrQixPQUFPLENBQUMsS0FBSztNQUMzRCxJQUFJLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxjQUFjLFFBQVEsTUFBTSxZQUFZLFFBQVE7SUFDakY7SUFFQSxvRkFBb0Y7SUFDcEYsTUFBTSxVQUFVLElBQUksSUFDbEIsT0FBTyxPQUFPLENBQUMsZUFDWixNQUFNLENBQUMsQ0FBQyxHQUFHLEtBQUssR0FBSyxLQUFLLEdBQUcsS0FBSyxPQUNsQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBSztJQUVwQixNQUFNLGVBQWU7U0FBSSxpQkFBaUIsTUFBTTtLQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBTSxRQUFRLEdBQUcsQ0FBQztJQUM5RSxJQUFJLGFBQWEsTUFBTSxHQUFHLEdBQUc7TUFDM0IsTUFBTSxJQUFJLE1BQ1IsQ0FBQywwREFBMEQsRUFBRSxhQUFhLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUN0RjtJQUVOO0lBRUEsTUFBTSxVQUFVO01BQ2QsWUFBWTtNQUNaO01BQ0EsVUFBVTtNQUNWLE9BQU87UUFDTCxLQUFLO1FBQ0wsUUFBUTtRQUNSLHVCQUF1QjtRQUN2QixlQUFlO1VBQ2IsT0FBTztZQUFFLE9BQU87VUFBcUI7VUFDckMsb0VBQW9FO1VBQ3BFLG9FQUFvRTtVQUNwRSxRQUFPLE9BQU8sRUFBRSxJQUFJO1lBQ2xCLElBQUksUUFBUSxJQUFJLEtBQUssdUJBQXVCO1lBQzVDLEtBQUs7VUFDUDtVQUNBLFFBQVE7WUFDTixRQUFRO1lBQ1IsbUVBQW1FO1lBQ25FLG1FQUFtRTtZQUNuRSwyREFBMkQ7WUFDM0QsT0FBTztZQUNQLGlFQUFpRTtZQUNqRSw2REFBNkQ7WUFDN0QsbUVBQW1FO1lBQ25FLG1GQUFtRjtZQUNuRixRQUFRLENBQUM7Ozs7Ozs7Ozs7QUFVckIsQ0FBQztVQUNTO1FBQ0Y7TUFDRjtNQUNBLEtBQUs7UUFBRSxZQUFZO1FBQWUsVUFBVSxTQUFTLFVBQVU7TUFBQztNQUNoRSwwRkFBMEY7TUFDMUYsb0VBQW9FO01BQ3BFLHNFQUFzRTtNQUN0RSx3REFBd0Q7TUFDeEQsUUFBUSxRQUFRLFVBQVUsR0FDdEI7UUFBRSxpQkFBaUIsS0FBSyxTQUFTLENBQUMsUUFBUSxVQUFVO01BQUUsSUFDdEQ7UUFBRSxpQkFBaUI7TUFBSztNQUM1QixTQUFTO1FBQ1AsbUVBQW1FO1FBQ25FLGdFQUFnRTtRQUNoRSxLQUFLO1FBQ0wsaUJBQWlCO1FBQ2pCLGFBQWE7VUFDWCxpQkFBaUI7WUFDZix5QkFBeUI7VUFDM0I7UUFDRjtNQUNGO01BQ0EsU0FBUztRQUNQLHFDQUFxQztRQUNyQyw2REFBNkQ7UUFDN0Q7VUFDRSxNQUFNO1VBQ04sV0FBVSxFQUFFO1lBQ1YsSUFBSSxPQUFPLHNCQUFzQixPQUFPO1VBQzFDO1VBQ0EsTUFBSyxFQUFFO1lBQ0wsSUFBSSxPQUFPLHVCQUF1QixPQUFPO1VBQzNDO1FBQ0Y7UUFDQSxrRUFBa0U7UUFDbEUsK0RBQStEO1FBQy9ELHFEQUFxRDtRQUNyRCxnRUFBZ0U7UUFDaEUsbUVBQW1FO1FBQ25FO1FBQ0Esa0NBQWtDO1VBQ2hDO1VBQ0EsTUFBTTtRQUNSO1FBQ0EsbUNBQW1DO1VBQ2pDO1VBQ0EsU0FBUyxxQkFBcUIsWUFBWSxHQUFHO1VBQzdDLGtCQUFrQiwrQkFBK0IsWUFBWSxHQUFHO1VBQ2hFLGFBQWE7UUFDZjtRQUNBO1VBQ0UsTUFBTTtVQUNOLFNBQVM7VUFDVCxNQUFLLEVBQUU7WUFDTCxNQUFNLGFBQWEsY0FBYyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNqRCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsQ0FBQyxhQUFhO1lBQzFDLE1BQU0sVUFBVSxpQkFBaUIsR0FBRyxDQUFDLGVBQWU7WUFDcEQsdURBQXVEO1lBQ3ZELDREQUE0RDtZQUM1RCxtRUFBbUU7WUFDbkUsT0FBTztjQUNMLENBQUMsc0RBQXNELENBQUM7Y0FDeEQsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztjQUNwRDtjQUNBLENBQUM7Ozs7OztDQU1kLENBQUM7YUFDVyxDQUFDLElBQUksQ0FBQztVQUNUO1FBQ0Y7T0FDRDtNQUNELFNBQVM7UUFDUCxrQkFBa0I7UUFDbEIsWUFBWTtVQUFDO1VBQU87VUFBUTtVQUFPO1VBQVE7U0FBUTtRQUNuRCxHQUFJLG1CQUFtQjtVQUFFLE9BQU87UUFBaUIsSUFBSSxDQUFDLENBQUM7TUFDekQ7SUFDRjtJQUNBLElBQUksSUFBSSxDQUFDO0lBRVQscURBQXFEO0lBQ3JELE1BQU0sZ0JBQWdCLFFBQVEsV0FBVztJQUN6Qyw2RUFBNkU7SUFDN0UsTUFBTSxZQUFZLE9BQU8sWUFBWSxlQUFlLFFBQVEsUUFBUSxLQUFLO0lBQ3pFLE1BQU0sZUFBZSxZQUNqQixhQUFhLGNBQWMsT0FBTyxDQUFDLE9BQU8sT0FDMUMsWUFBWTtJQUNoQixNQUFNLFNBQVMsTUFBTSxNQUFNLENBQUM7SUFFNUIsSUFBSSxDQUFDLE9BQU8sT0FBTyxFQUFFO01BQ25CLE1BQU0sSUFBSSxlQUFlLDBCQUEwQixJQUFJLE1BQU07SUFDL0Q7SUFFQSx3RUFBd0U7SUFDeEUsTUFBTSxVQUNKLFFBQ0E7TUFDRTtNQUNBO01BQ0EsTUFBTSxRQUFRLElBQUksSUFBSTtNQUN0QixZQUFZLFFBQVEsVUFBVTtNQUM5QixNQUFNLFFBQVEsSUFBSTtNQUNsQixZQUFZLFFBQVEsVUFBVTtNQUM5QixnQkFBZ0I7TUFDaEIsZ0JBQWdCLFFBQVEsY0FBYztNQUN0QyxhQUFhLFFBQVEsV0FBVztJQUNsQyxHQUNBLHdCQUF3QjtJQUcxQixJQUFJLElBQUksQ0FBQyw4QkFBOEIsS0FBSyxNQUFNO0VBQ3BELEVBQUUsT0FBTyxLQUFLO0lBQ1osTUFBTSxRQUFRLGVBQWUsUUFBUSxNQUFNLElBQUksTUFBTSxPQUFPO0lBQzVELE1BQU0sSUFBSSxlQUFlLGdCQUFnQjtFQUMzQztBQUNGO0FBRUEsU0FBUyxRQUFRLEdBQUcifQ==
|
|
File without changes
|
package/src/cli/build.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/adapter-vite - CLI: Full Static Build
|
|
3
|
+
*
|
|
4
|
+
* ADR 0011: One-command build entry. viteBuild() triggers Phase 1,
|
|
5
|
+
* and closeBundle() in open:build plugin automatically runs Phase 2/3.
|
|
6
|
+
* No orchestrator needed - all three phases run in a single viteBuild() call.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* deno run -A npm:@openelement/adapter-vite/cli/build
|
|
10
|
+
* deno task build
|
|
11
|
+
*/ import { build as viteBuild } from 'vite';
|
|
12
|
+
import process from 'node:process';
|
|
13
|
+
import { formatError } from '@openelement/core/errors';
|
|
14
|
+
import { createLogger } from '@openelement/core/logger';
|
|
15
|
+
if (import.meta.main) {
|
|
16
|
+
try {
|
|
17
|
+
await viteBuild({
|
|
18
|
+
configLoader: 'native'
|
|
19
|
+
});
|
|
20
|
+
process.exit(0);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
const log = createLogger('adapter-vite');
|
|
23
|
+
log.error(`Build failed: ${formatError(error)}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2NsaS9idWlsZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBvcGVuZWxlbWVudC9hZGFwdGVyLXZpdGUgLSBDTEk6IEZ1bGwgU3RhdGljIEJ1aWxkXG4gKlxuICogQURSIDAwMTE6IE9uZS1jb21tYW5kIGJ1aWxkIGVudHJ5LiB2aXRlQnVpbGQoKSB0cmlnZ2VycyBQaGFzZSAxLFxuICogYW5kIGNsb3NlQnVuZGxlKCkgaW4gb3BlbjpidWlsZCBwbHVnaW4gYXV0b21hdGljYWxseSBydW5zIFBoYXNlIDIvMy5cbiAqIE5vIG9yY2hlc3RyYXRvciBuZWVkZWQgLSBhbGwgdGhyZWUgcGhhc2VzIHJ1biBpbiBhIHNpbmdsZSB2aXRlQnVpbGQoKSBjYWxsLlxuICpcbiAqIFVzYWdlOlxuICogICBkZW5vIHJ1biAtQSBucG06QG9wZW5lbGVtZW50L2FkYXB0ZXItdml0ZS9jbGkvYnVpbGRcbiAqICAgZGVubyB0YXNrIGJ1aWxkXG4gKi9cblxuaW1wb3J0IHsgYnVpbGQgYXMgdml0ZUJ1aWxkIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuaW1wb3J0IHsgZm9ybWF0RXJyb3IgfSBmcm9tICdAb3BlbmVsZW1lbnQvY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnQG9wZW5lbGVtZW50L2NvcmUvbG9nZ2VyJztcblxuaWYgKGltcG9ydC5tZXRhLm1haW4pIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCB2aXRlQnVpbGQoeyBjb25maWdMb2FkZXI6ICduYXRpdmUnIH0pO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zdCBsb2cgPSBjcmVhdGVMb2dnZXIoJ2FkYXB0ZXItdml0ZScpO1xuICAgIGxvZy5lcnJvcihgQnVpbGQgZmFpbGVkOiAke2Zvcm1hdEVycm9yKGVycm9yKX1gKTtcbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7OztDQVVDLEdBRUQsU0FBUyxTQUFTLFNBQVMsUUFBUSxPQUFPO0FBQzFDLE9BQU8sYUFBYSxlQUFlO0FBQ25DLFNBQVMsV0FBVyxRQUFRLDJCQUEyQjtBQUN2RCxTQUFTLFlBQVksUUFBUSwyQkFBMkI7QUFFeEQsSUFBSSxZQUFZLElBQUksRUFBRTtFQUNwQixJQUFJO0lBQ0YsTUFBTSxVQUFVO01BQUUsY0FBYztJQUFTO0lBQ3pDLFFBQVEsSUFBSSxDQUFDO0VBQ2YsRUFBRSxPQUFPLE9BQU87SUFDZCxNQUFNLE1BQU0sYUFBYTtJQUN6QixJQUFJLEtBQUssQ0FBQyxDQUFDLGNBQWMsRUFBRSxZQUFZLFFBQVE7SUFDL0MsUUFBUSxJQUFJLENBQUM7RUFDZjtBQUNGIn0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility wrapper for the SSG render pipeline.
|
|
3
|
+
*
|
|
4
|
+
* The implementation is internal to adapter-vite in v0.40.x.
|
|
5
|
+
* adapter-vite keeps this module so existing imports continue to work while
|
|
6
|
+
* build orchestration uses the local SSG helpers.
|
|
7
|
+
*/ import { resolveDynamicRoutePath, ssgRender as ssgRenderCore } from '@openelement/ssg';
|
|
8
|
+
import { printBuildManifest } from '../build-manifest.js';
|
|
9
|
+
export { resolveDynamicRoutePath };
|
|
10
|
+
export async function ssgRender(module, options, ctx) {
|
|
11
|
+
return await ssgRenderCore(module, options, createSsgRenderEvidence(ctx));
|
|
12
|
+
}
|
|
13
|
+
export function createSsgRenderEvidence(ctx) {
|
|
14
|
+
if (!ctx) return {};
|
|
15
|
+
return {
|
|
16
|
+
i18nOptions: ctx.plugins.i18nOptions,
|
|
17
|
+
localIslandMeta: ctx.phase1.islandMeta,
|
|
18
|
+
packageIslandDecls: ctx.phase1.packageIslandDecls,
|
|
19
|
+
packageManifests: ctx.phase1.packageManifests,
|
|
20
|
+
admissionDecisions: ctx.phase1.ssrAdmissionPlan?.decisions || [],
|
|
21
|
+
cemClassifications: ctx.phase1.cemClassifications,
|
|
22
|
+
onPrintBuildManifest: (input)=>{
|
|
23
|
+
printBuildManifest(input);
|
|
24
|
+
},
|
|
25
|
+
onGenerateSitemap: async (outputDir)=>{
|
|
26
|
+
if (!ctx.plugins.sitemapOptions) return;
|
|
27
|
+
const { generateSitemap } = await import('@openelement/content/sitemap');
|
|
28
|
+
generateSitemap(outputDir, ctx.plugins.sitemapOptions);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2NsaS9zc2ctcmVuZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29tcGF0aWJpbGl0eSB3cmFwcGVyIGZvciB0aGUgU1NHIHJlbmRlciBwaXBlbGluZS5cbiAqXG4gKiBUaGUgaW1wbGVtZW50YXRpb24gaXMgaW50ZXJuYWwgdG8gYWRhcHRlci12aXRlIGluIHYwLjQwLnguXG4gKiBhZGFwdGVyLXZpdGUga2VlcHMgdGhpcyBtb2R1bGUgc28gZXhpc3RpbmcgaW1wb3J0cyBjb250aW51ZSB0byB3b3JrIHdoaWxlXG4gKiBidWlsZCBvcmNoZXN0cmF0aW9uIHVzZXMgdGhlIGxvY2FsIFNTRyBoZWxwZXJzLlxuICovXG5cbmltcG9ydCB7IHJlc29sdmVEeW5hbWljUm91dGVQYXRoLCBzc2dSZW5kZXIgYXMgc3NnUmVuZGVyQ29yZSB9IGZyb20gJ0BvcGVuZWxlbWVudC9zc2cnO1xuaW1wb3J0IHR5cGUgeyBTc2dSZW5kZXJFdmlkZW5jZSwgU3NnUmVuZGVyT3B0aW9ucywgU3NyQnVuZGxlIH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL3NzZyc7XG5pbXBvcnQgeyBwcmludEJ1aWxkTWFuaWZlc3QgfSBmcm9tICcuLi9idWlsZC1tYW5pZmVzdC5qcyc7XG5pbXBvcnQgdHlwZSB7IE9wZW5FbGVtZW50QnVpbGRDb250ZXh0IH0gZnJvbSAnLi4vYnVpbGQtY29udGV4dC5qcyc7XG5cbmV4cG9ydCB7IHJlc29sdmVEeW5hbWljUm91dGVQYXRoIH07XG5leHBvcnQgdHlwZSB7XG4gIFNzZ1BhZ2VPdXRwdXQsXG4gIFNzZ1JlbmRlckV2aWRlbmNlLFxuICBTc2dSZW5kZXJPcHRpb25zLFxuICBTc3JCdW5kbGUsXG59IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9zc2cnO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3NnUmVuZGVyKFxuICBtb2R1bGU6IFNzckJ1bmRsZSxcbiAgb3B0aW9uczogU3NnUmVuZGVyT3B0aW9ucyxcbiAgY3R4PzogT3BlbkVsZW1lbnRCdWlsZENvbnRleHQsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIGF3YWl0IHNzZ1JlbmRlckNvcmUobW9kdWxlLCBvcHRpb25zLCBjcmVhdGVTc2dSZW5kZXJFdmlkZW5jZShjdHgpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNzZ1JlbmRlckV2aWRlbmNlKFxuICBjdHg/OiBPcGVuRWxlbWVudEJ1aWxkQ29udGV4dCxcbik6IFNzZ1JlbmRlckV2aWRlbmNlIHtcbiAgaWYgKCFjdHgpIHJldHVybiB7fTtcblxuICByZXR1cm4ge1xuICAgIGkxOG5PcHRpb25zOiBjdHgucGx1Z2lucy5pMThuT3B0aW9ucyxcbiAgICBsb2NhbElzbGFuZE1ldGE6IGN0eC5waGFzZTEuaXNsYW5kTWV0YSxcbiAgICBwYWNrYWdlSXNsYW5kRGVjbHM6IGN0eC5waGFzZTEucGFja2FnZUlzbGFuZERlY2xzLFxuICAgIHBhY2thZ2VNYW5pZmVzdHM6IGN0eC5waGFzZTEucGFja2FnZU1hbmlmZXN0cyxcbiAgICBhZG1pc3Npb25EZWNpc2lvbnM6IGN0eC5waGFzZTEuc3NyQWRtaXNzaW9uUGxhbj8uZGVjaXNpb25zIHx8IFtdLFxuICAgIGNlbUNsYXNzaWZpY2F0aW9uczogY3R4LnBoYXNlMS5jZW1DbGFzc2lmaWNhdGlvbnMsXG4gICAgb25QcmludEJ1aWxkTWFuaWZlc3Q6IChpbnB1dCkgPT4ge1xuICAgICAgcHJpbnRCdWlsZE1hbmlmZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG9uR2VuZXJhdGVTaXRlbWFwOiBhc3luYyAob3V0cHV0RGlyKSA9PiB7XG4gICAgICBpZiAoIWN0eC5wbHVnaW5zLnNpdGVtYXBPcHRpb25zKSByZXR1cm47XG4gICAgICBjb25zdCB7IGdlbmVyYXRlU2l0ZW1hcCB9ID0gYXdhaXQgaW1wb3J0KCdAb3BlbmVsZW1lbnQvY29udGVudC9zaXRlbWFwJykgYXMge1xuICAgICAgICBnZW5lcmF0ZVNpdGVtYXA6IChkaXI6IHN0cmluZywgb3B0czogdW5rbm93bikgPT4gc3RyaW5nW107XG4gICAgICB9O1xuICAgICAgZ2VuZXJhdGVTaXRlbWFwKG91dHB1dERpciwgY3R4LnBsdWdpbnMuc2l0ZW1hcE9wdGlvbnMpO1xuICAgIH0sXG4gIH07XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztDQU1DLEdBRUQsU0FBUyx1QkFBdUIsRUFBRSxhQUFhLGFBQWEsUUFBUSxtQkFBbUI7QUFFdkYsU0FBUyxrQkFBa0IsUUFBUSx1QkFBdUI7QUFHMUQsU0FBUyx1QkFBdUIsR0FBRztBQVFuQyxPQUFPLGVBQWUsVUFDcEIsTUFBaUIsRUFDakIsT0FBeUIsRUFDekIsR0FBNkI7RUFFN0IsT0FBTyxNQUFNLGNBQWMsUUFBUSxTQUFTLHdCQUF3QjtBQUN0RTtBQUVBLE9BQU8sU0FBUyx3QkFDZCxHQUE2QjtFQUU3QixJQUFJLENBQUMsS0FBSyxPQUFPLENBQUM7RUFFbEIsT0FBTztJQUNMLGFBQWEsSUFBSSxPQUFPLENBQUMsV0FBVztJQUNwQyxpQkFBaUIsSUFBSSxNQUFNLENBQUMsVUFBVTtJQUN0QyxvQkFBb0IsSUFBSSxNQUFNLENBQUMsa0JBQWtCO0lBQ2pELGtCQUFrQixJQUFJLE1BQU0sQ0FBQyxnQkFBZ0I7SUFDN0Msb0JBQW9CLElBQUksTUFBTSxDQUFDLGdCQUFnQixFQUFFLGFBQWEsRUFBRTtJQUNoRSxvQkFBb0IsSUFBSSxNQUFNLENBQUMsa0JBQWtCO0lBQ2pELHNCQUFzQixDQUFDO01BQ3JCLG1CQUFtQjtJQUNyQjtJQUNBLG1CQUFtQixPQUFPO01BQ3hCLElBQUksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxjQUFjLEVBQUU7TUFDakMsTUFBTSxFQUFFLGVBQWUsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDO01BR3pDLGdCQUFnQixXQUFXLElBQUksT0FBTyxDQUFDLGNBQWM7SUFDdkQ7RUFDRjtBQUNGIn0=
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
export declare const GENERATED_NAV_ID: '@openelement/generated/nav';
|
|
3
|
+
export declare const GENERATED_BLOG_DATA_ID: '@openelement/generated/blog-data';
|
|
4
|
+
export declare const GENERATED_I18N_ID: '@openelement/generated/i18n';
|
|
5
|
+
export type GeneratedDataResolverOptions = {
|
|
6
|
+
root: string;
|
|
7
|
+
dataDir?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
allowFallback?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function generatedDataPath(root: string, id: string, dataDir?: string): string | null;
|
|
12
|
+
export declare function createGeneratedDataResolverPlugin(options: GeneratedDataResolverOptions): Plugin;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
export const GENERATED_NAV_ID = '@openelement/generated/nav';
|
|
4
|
+
export const GENERATED_BLOG_DATA_ID = '@openelement/generated/blog-data';
|
|
5
|
+
export const GENERATED_I18N_ID = '@openelement/generated/i18n';
|
|
6
|
+
const GENERATED_DATA_FILES = {
|
|
7
|
+
[GENERATED_NAV_ID]: '_generated-nav.ts',
|
|
8
|
+
[GENERATED_BLOG_DATA_ID]: '_generated-blog-data.ts',
|
|
9
|
+
[GENERATED_I18N_ID]: '_generated-i18n-data.ts'
|
|
10
|
+
};
|
|
11
|
+
const GENERATED_DATA_FALLBACKS = {
|
|
12
|
+
[GENERATED_NAV_ID]: 'export const headerNav = [];\nexport const navSections = [];',
|
|
13
|
+
[GENERATED_BLOG_DATA_ID]: [
|
|
14
|
+
'export const posts = [];',
|
|
15
|
+
'export function getPostBySlug() { return undefined; }',
|
|
16
|
+
'export function getBlogOptions() { return {}; }'
|
|
17
|
+
].join('\n'),
|
|
18
|
+
[GENERATED_I18N_ID]: [
|
|
19
|
+
'export const locales = [];',
|
|
20
|
+
'export function getDefaultLocale() { return "en"; }',
|
|
21
|
+
'export function getI18nOptions() { return null; }'
|
|
22
|
+
].join('\n')
|
|
23
|
+
};
|
|
24
|
+
export function generatedDataPath(root, id, dataDir = 'app/data') {
|
|
25
|
+
const fileName = GENERATED_DATA_FILES[id];
|
|
26
|
+
if (!fileName) return null;
|
|
27
|
+
return resolve(root, dataDir, fileName);
|
|
28
|
+
}
|
|
29
|
+
export function createGeneratedDataResolverPlugin(options) {
|
|
30
|
+
const dataDir = options.dataDir ?? 'app/data';
|
|
31
|
+
const allowFallback = options.allowFallback ?? true;
|
|
32
|
+
return {
|
|
33
|
+
name: options.name ?? 'open:generated-data',
|
|
34
|
+
enforce: 'pre',
|
|
35
|
+
resolveId (id) {
|
|
36
|
+
if (!GENERATED_DATA_FILES[id]) return null;
|
|
37
|
+
const path = generatedDataPath(options.root, id, dataDir);
|
|
38
|
+
if (path && existsSync(path)) return path;
|
|
39
|
+
return '\0open:generated-data:' + id;
|
|
40
|
+
},
|
|
41
|
+
load (id) {
|
|
42
|
+
const prefix = '\0open:generated-data:';
|
|
43
|
+
if (!id.startsWith(prefix)) return null;
|
|
44
|
+
const sourceId = id.slice(prefix.length);
|
|
45
|
+
const path = generatedDataPath(options.root, sourceId, dataDir);
|
|
46
|
+
if (path && existsSync(path)) return readFileSync(path, 'utf-8');
|
|
47
|
+
if (allowFallback) return GENERATED_DATA_FALLBACKS[sourceId] ?? null;
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2dlbmVyYXRlZC1kYXRhLXJlc29sdmVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgUGx1Z2luIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMgfSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuXG5leHBvcnQgY29uc3QgR0VORVJBVEVEX05BVl9JRCA9ICdAb3BlbmVsZW1lbnQvZ2VuZXJhdGVkL25hdic7XG5leHBvcnQgY29uc3QgR0VORVJBVEVEX0JMT0dfREFUQV9JRCA9ICdAb3BlbmVsZW1lbnQvZ2VuZXJhdGVkL2Jsb2ctZGF0YSc7XG5leHBvcnQgY29uc3QgR0VORVJBVEVEX0kxOE5fSUQgPSAnQG9wZW5lbGVtZW50L2dlbmVyYXRlZC9pMThuJztcblxuY29uc3QgR0VORVJBVEVEX0RBVEFfRklMRVM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gIFtHRU5FUkFURURfTkFWX0lEXTogJ19nZW5lcmF0ZWQtbmF2LnRzJyxcbiAgW0dFTkVSQVRFRF9CTE9HX0RBVEFfSURdOiAnX2dlbmVyYXRlZC1ibG9nLWRhdGEudHMnLFxuICBbR0VORVJBVEVEX0kxOE5fSURdOiAnX2dlbmVyYXRlZC1pMThuLWRhdGEudHMnLFxufTtcblxuY29uc3QgR0VORVJBVEVEX0RBVEFfRkFMTEJBQ0tTOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBbR0VORVJBVEVEX05BVl9JRF06ICdleHBvcnQgY29uc3QgaGVhZGVyTmF2ID0gW107XFxuZXhwb3J0IGNvbnN0IG5hdlNlY3Rpb25zID0gW107JyxcbiAgW0dFTkVSQVRFRF9CTE9HX0RBVEFfSURdOiBbXG4gICAgJ2V4cG9ydCBjb25zdCBwb3N0cyA9IFtdOycsXG4gICAgJ2V4cG9ydCBmdW5jdGlvbiBnZXRQb3N0QnlTbHVnKCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9JyxcbiAgICAnZXhwb3J0IGZ1bmN0aW9uIGdldEJsb2dPcHRpb25zKCkgeyByZXR1cm4ge307IH0nLFxuICBdLmpvaW4oJ1xcbicpLFxuICBbR0VORVJBVEVEX0kxOE5fSURdOiBbXG4gICAgJ2V4cG9ydCBjb25zdCBsb2NhbGVzID0gW107JyxcbiAgICAnZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRMb2NhbGUoKSB7IHJldHVybiBcImVuXCI7IH0nLFxuICAgICdleHBvcnQgZnVuY3Rpb24gZ2V0STE4bk9wdGlvbnMoKSB7IHJldHVybiBudWxsOyB9JyxcbiAgXS5qb2luKCdcXG4nKSxcbn07XG5cbmV4cG9ydCB0eXBlIEdlbmVyYXRlZERhdGFSZXNvbHZlck9wdGlvbnMgPSB7XG4gIHJvb3Q6IHN0cmluZztcbiAgZGF0YURpcj86IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbiAgYWxsb3dGYWxsYmFjaz86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVkRGF0YVBhdGgoXG4gIHJvb3Q6IHN0cmluZyxcbiAgaWQ6IHN0cmluZyxcbiAgZGF0YURpciA9ICdhcHAvZGF0YScsXG4pOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgZmlsZU5hbWUgPSBHRU5FUkFURURfREFUQV9GSUxFU1tpZF07XG4gIGlmICghZmlsZU5hbWUpIHJldHVybiBudWxsO1xuICByZXR1cm4gcmVzb2x2ZShyb290LCBkYXRhRGlyLCBmaWxlTmFtZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVHZW5lcmF0ZWREYXRhUmVzb2x2ZXJQbHVnaW4oXG4gIG9wdGlvbnM6IEdlbmVyYXRlZERhdGFSZXNvbHZlck9wdGlvbnMsXG4pOiBQbHVnaW4ge1xuICBjb25zdCBkYXRhRGlyID0gb3B0aW9ucy5kYXRhRGlyID8/ICdhcHAvZGF0YSc7XG4gIGNvbnN0IGFsbG93RmFsbGJhY2sgPSBvcHRpb25zLmFsbG93RmFsbGJhY2sgPz8gdHJ1ZTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6IG9wdGlvbnMubmFtZSA/PyAnb3BlbjpnZW5lcmF0ZWQtZGF0YScsXG4gICAgZW5mb3JjZTogJ3ByZScsXG5cbiAgICByZXNvbHZlSWQoaWQpIHtcbiAgICAgIGlmICghR0VORVJBVEVEX0RBVEFfRklMRVNbaWRdKSByZXR1cm4gbnVsbDtcbiAgICAgIGNvbnN0IHBhdGggPSBnZW5lcmF0ZWREYXRhUGF0aChvcHRpb25zLnJvb3QsIGlkLCBkYXRhRGlyKTtcbiAgICAgIGlmIChwYXRoICYmIGV4aXN0c1N5bmMocGF0aCkpIHJldHVybiBwYXRoO1xuICAgICAgcmV0dXJuICdcXDBvcGVuOmdlbmVyYXRlZC1kYXRhOicgKyBpZDtcbiAgICB9LFxuXG4gICAgbG9hZChpZCkge1xuICAgICAgY29uc3QgcHJlZml4ID0gJ1xcMG9wZW46Z2VuZXJhdGVkLWRhdGE6JztcbiAgICAgIGlmICghaWQuc3RhcnRzV2l0aChwcmVmaXgpKSByZXR1cm4gbnVsbDtcblxuICAgICAgY29uc3Qgc291cmNlSWQgPSBpZC5zbGljZShwcmVmaXgubGVuZ3RoKTtcbiAgICAgIGNvbnN0IHBhdGggPSBnZW5lcmF0ZWREYXRhUGF0aChvcHRpb25zLnJvb3QsIHNvdXJjZUlkLCBkYXRhRGlyKTtcbiAgICAgIGlmIChwYXRoICYmIGV4aXN0c1N5bmMocGF0aCkpIHJldHVybiByZWFkRmlsZVN5bmMocGF0aCwgJ3V0Zi04Jyk7XG5cbiAgICAgIGlmIChhbGxvd0ZhbGxiYWNrKSByZXR1cm4gR0VORVJBVEVEX0RBVEFfRkFMTEJBQ0tTW3NvdXJjZUlkXSA/PyBudWxsO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSxcbiAgfTtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxTQUFTLFVBQVUsRUFBRSxZQUFZLFFBQVEsVUFBVTtBQUNuRCxTQUFTLE9BQU8sUUFBUSxZQUFZO0FBRXBDLE9BQU8sTUFBTSxtQkFBbUIsNkJBQTZCO0FBQzdELE9BQU8sTUFBTSx5QkFBeUIsbUNBQW1DO0FBQ3pFLE9BQU8sTUFBTSxvQkFBb0IsOEJBQThCO0FBRS9ELE1BQU0sdUJBQStDO0VBQ25ELENBQUMsaUJBQWlCLEVBQUU7RUFDcEIsQ0FBQyx1QkFBdUIsRUFBRTtFQUMxQixDQUFDLGtCQUFrQixFQUFFO0FBQ3ZCO0FBRUEsTUFBTSwyQkFBbUQ7RUFDdkQsQ0FBQyxpQkFBaUIsRUFBRTtFQUNwQixDQUFDLHVCQUF1QixFQUFFO0lBQ3hCO0lBQ0E7SUFDQTtHQUNELENBQUMsSUFBSSxDQUFDO0VBQ1AsQ0FBQyxrQkFBa0IsRUFBRTtJQUNuQjtJQUNBO0lBQ0E7R0FDRCxDQUFDLElBQUksQ0FBQztBQUNUO0FBU0EsT0FBTyxTQUFTLGtCQUNkLElBQVksRUFDWixFQUFVLEVBQ1YsVUFBVSxVQUFVO0VBRXBCLE1BQU0sV0FBVyxvQkFBb0IsQ0FBQyxHQUFHO0VBQ3pDLElBQUksQ0FBQyxVQUFVLE9BQU87RUFDdEIsT0FBTyxRQUFRLE1BQU0sU0FBUztBQUNoQztBQUVBLE9BQU8sU0FBUyxrQ0FDZCxPQUFxQztFQUVyQyxNQUFNLFVBQVUsUUFBUSxPQUFPLElBQUk7RUFDbkMsTUFBTSxnQkFBZ0IsUUFBUSxhQUFhLElBQUk7RUFFL0MsT0FBTztJQUNMLE1BQU0sUUFBUSxJQUFJLElBQUk7SUFDdEIsU0FBUztJQUVULFdBQVUsRUFBRTtNQUNWLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsT0FBTztNQUN0QyxNQUFNLE9BQU8sa0JBQWtCLFFBQVEsSUFBSSxFQUFFLElBQUk7TUFDakQsSUFBSSxRQUFRLFdBQVcsT0FBTyxPQUFPO01BQ3JDLE9BQU8sMkJBQTJCO0lBQ3BDO0lBRUEsTUFBSyxFQUFFO01BQ0wsTUFBTSxTQUFTO01BQ2YsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDLFNBQVMsT0FBTztNQUVuQyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsT0FBTyxNQUFNO01BQ3ZDLE1BQU0sT0FBTyxrQkFBa0IsUUFBUSxJQUFJLEVBQUUsVUFBVTtNQUN2RCxJQUFJLFFBQVEsV0FBVyxPQUFPLE9BQU8sYUFBYSxNQUFNO01BRXhELElBQUksZUFBZSxPQUFPLHdCQUF3QixDQUFDLFNBQVMsSUFBSTtNQUNoRSxPQUFPO0lBQ1Q7RUFDRjtBQUNGIn0=
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/adapter-vite — Head injection validation & serialization.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from index.ts in v0.22 (SOP-004: adapter-vite decomposition).
|
|
5
|
+
*
|
|
6
|
+
* Provides:
|
|
7
|
+
* - assertNoScriptTags() — script tag safety check for head fragments
|
|
8
|
+
* - validateSafeUrl() — URL protocol validation against XSS vectors
|
|
9
|
+
* - buildHeadExtras() — serialize headFragments, stylesheets, and scripts
|
|
10
|
+
* into a single headExtras string
|
|
11
|
+
*/ import type { FrameworkOptions } from '@openelement/protocol/framework';
|
|
12
|
+
/**
|
|
13
|
+
* Assert that HTML content does NOT contain <script> tags.
|
|
14
|
+
* Scripts must go through inject.scripts for URL validation.
|
|
15
|
+
*/ export declare function assertNoScriptTags(html: string, context: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Validate a URL string for known XSS vectors (javascript:, data:, etc.).
|
|
18
|
+
* Also validates percent-encoding is not malformed.
|
|
19
|
+
* Returns the normalized URL string.
|
|
20
|
+
*/ export declare function validateSafeUrl(url: string, context: string): string;
|
|
21
|
+
/** Result of building head extras from FrameworkOptions. */ export interface HeadExtrasResult {
|
|
22
|
+
headExtras: string | undefined;
|
|
23
|
+
allowHeadExtrasScripts: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build the headExtras string from FrameworkOptions.inject.
|
|
27
|
+
*
|
|
28
|
+
* Serializes headFragments, stylesheets, and scripts into a single
|
|
29
|
+
* HTML string to inject into <head>. Validates all URLs and ensures
|
|
30
|
+
* no raw <script> tags bypass the structured injection APIs.
|
|
31
|
+
*/ export declare function buildHeadExtras(options: FrameworkOptions): HeadExtrasResult;
|