@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.
@@ -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/IGVyciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyKSk7XG4gICAgdGhyb3cgbmV3IFNzclJlbmRlckVycm9yKCdTU0cgcGlwZWxpbmUnLCBjYXVzZSk7XG4gIH1cbn1cblxuZXhwb3J0IHsgYnVpbGRTU0cgfTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUFTLElBQUksUUFBUSxrQkFBa0I7QUFDdkM7Ozs7Ozs7Ozs7Ozs7O0NBY0MsR0FFRCxTQUFTLElBQUksRUFBRSxPQUFPLFFBQVEsWUFBWTtBQUMxQyxTQUFTLGFBQWEsUUFBUSxXQUFXO0FBQ3pDLFNBQVMsYUFBYSxRQUFRLE9BQU87QUFDckMsT0FBTyxhQUFhLGVBQWU7QUFDbkMsU0FBUyxVQUFVLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxhQUFhLFFBQVEsVUFBVTtBQUk3RSxTQUFTLFNBQVMsUUFBUSxtQkFBbUI7QUFDN0MsU0FBUyxjQUFjLFFBQVEsMkJBQTJCO0FBQzFELFNBQVMsWUFBWSxRQUFRLDJCQUEyQjtBQUN4RCxTQUFTLHVCQUF1QixRQUFRLGtCQUFrQjtBQUMxRCxTQUFTLGlDQUFpQyxRQUFRLGdDQUFnQztBQUNsRixTQUFTLGtDQUFrQyxRQUFRLDZCQUE2QjtBQUNoRixTQUFTLHlCQUF5QixFQUFFLHVCQUF1QixRQUFRLG1CQUFtQjtBQUN0RixTQUFTLDBCQUEwQixRQUFRLGVBQWU7QUFDMUQsU0FBUyxvQkFBb0IsUUFBUSxv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
File without changes
@@ -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;