@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,292 @@
1
+ /**
2
+ * @openelement/adapter-vite - CLI: Client Island Build
3
+ *
4
+ * Client build for Island components.
5
+ * Produces dist/client/islands/*.js + manifest for SSG post-processing.
6
+ *
7
+ * ADR 0011: This module exports buildClient() only - it is called from
8
+ * closeBundle() in open:build plugin. No longer a standalone CLI entry.
9
+ * ctx parameter is required (no globalThis fallback).
10
+ *
11
+ * Usage:
12
+ * deno task build (unified entry - runs all 3 phases)
13
+ */ import { build as viteBuild } from 'vite';
14
+ import { existsSync, readFileSync } from 'node:fs';
15
+ import { join, resolve } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+ import process from 'node:process';
18
+ import { generateClientEntry } from '@openelement/ssg';
19
+ import { createOpenJsrPackageResolverPlugin } from '../ssg-package-resolver.js';
20
+ import { formatError } from '@openelement/core/errors';
21
+ import { createLogger } from '@openelement/core/logger';
22
+ const log = createLogger('ssg');
23
+ const VIRTUAL_CLIENT_ENTRY_ID = 'virtual:open-client-entry';
24
+ const RESOLVED_CLIENT_ENTRY_ID = '\0' + VIRTUAL_CLIENT_ENTRY_ID;
25
+ const FALLBACK_openElement_VERSION = '0.23.0';
26
+ /** Workspace root derived from this module's location (packages/adapter-vite/src/cli/).
27
+ * Only valid in local workspace (file:// import.meta.url). In JSR consumers, returns null. */ const WORKSPACE_ROOT = (()=>{
28
+ if (!import.meta.url.startsWith('file:')) return null;
29
+ try {
30
+ return fileURLToPath(new URL('../../../..', import.meta.url)).replace(/\\/g, '/');
31
+ } catch {
32
+ return null;
33
+ }
34
+ })();
35
+ function getJsrPackageVersion(metaUrl) {
36
+ const match = metaUrl.match(/\/@openelement\/adapter-vite\/([^/]+)\//);
37
+ return match?.[1] ?? FALLBACK_openElement_VERSION;
38
+ }
39
+ /**
40
+ * Look up a bare specifier in a deno.json import map.
41
+ * Walks up directory tree to find workspace-level deno.json as fallback.
42
+ * Returns { target, denoJsonDir } so relative paths can be resolved correctly.
43
+ */ function lookupInDenoJson(id, root) {
44
+ const denoJsonDirs = new Set();
45
+ let dir = resolve(root);
46
+ // Walk up from consumer root
47
+ while(!denoJsonDirs.has(dir)){
48
+ denoJsonDirs.add(dir);
49
+ const found = tryDenoJsonDir(id, dir);
50
+ if (found) return found;
51
+ const parent = resolve(dir, '..');
52
+ if (parent === dir) break;
53
+ dir = parent;
54
+ }
55
+ // Also try workspace root (module-relative, for monorepo dev / testing)
56
+ if (WORKSPACE_ROOT && !denoJsonDirs.has(WORKSPACE_ROOT)) {
57
+ const found = tryDenoJsonDir(id, WORKSPACE_ROOT);
58
+ if (found) return found;
59
+ }
60
+ return null;
61
+ }
62
+ /** Check a single directory for a deno.json with the given import. */ function tryDenoJsonDir(id, dir) {
63
+ const denoJsonPath = join(dir, 'deno.json');
64
+ if (!existsSync(denoJsonPath)) return null;
65
+ const raw = readFileSync(denoJsonPath, 'utf-8');
66
+ // Strip JSONC comments:
67
+ // - Line comments: // at start of line (after optional whitespace)
68
+ // - Block comments: /* ... */
69
+ // - Trailing commas (Deno JSONC allows them, JSON.parse does not)
70
+ const json = raw.replace(/^\s*\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '').replace(/,\s*([}\]])/g, '$1');
71
+ let denoJson;
72
+ try {
73
+ denoJson = JSON.parse(json);
74
+ } catch {
75
+ return null; // Invalid JSON — skip this deno.json
76
+ }
77
+ const imports = denoJson.imports;
78
+ if (!imports) return null;
79
+ // Exact match
80
+ if (imports[id]) return {
81
+ target: imports[id],
82
+ denoJsonDir: dir
83
+ };
84
+ // Prefix/subpath matching (trailing slash)
85
+ for (const [key, value] of Object.entries(imports)){
86
+ if (key.endsWith('/') && id.startsWith(key)) {
87
+ return {
88
+ target: value + id.slice(key.length),
89
+ denoJsonDir: dir
90
+ };
91
+ }
92
+ }
93
+ return null;
94
+ }
95
+ /**
96
+ * Convert a Deno import map target to a resolvable Vite path.
97
+ * - file:// URLs → absolute filesystem path
98
+ * - Relative paths (./) → resolved relative to denoJsonDir
99
+ * - npm:, jsr: → null (handled by node_modules)
100
+ */ function convertImportMapTarget(target, denoJsonDir) {
101
+ if (target.startsWith('file://')) {
102
+ try {
103
+ return fileURLToPath(target).replace(/\\/g, '/');
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+ // Relative path — resolve relative to the deno.json directory
109
+ if (target.startsWith('./') || target.startsWith('../')) {
110
+ return resolve(denoJsonDir, target).replace(/\\/g, '/');
111
+ }
112
+ // npm:, jsr: — let Vite/Rolldown handle these normally
113
+ return null;
114
+ }
115
+ async function buildClient(ctx) {
116
+ const root = ctx.phase3.root || process.cwd();
117
+ const outDir = ctx.phase3.outDir || 'dist';
118
+ const islandsDir = ctx.phase3.islandsDir || 'app/islands';
119
+ const localIslands = ctx.phase1.islandTagNames || [];
120
+ const localIslandFiles = ctx.phase1.islandFiles || [];
121
+ const packageIslandDecls = ctx.phase1.packageIslandDecls || [];
122
+ // Aliases pre-generated by createOpenPlugin() and stored in ctx
123
+ const resolveAlias = ctx.phase1.userResolveAlias;
124
+ const serializedAlias = resolveAlias ? Array.isArray(resolveAlias) ? resolveAlias.filter((a)=>typeof a.find === 'string').map((a)=>({
125
+ find: a.find,
126
+ replacement: a.replacement
127
+ })) : Object.entries(resolveAlias).map(([find, replacement])=>({
128
+ find,
129
+ replacement
130
+ })) : [];
131
+ // Always resolve @openelement/core/style-sheet from workspace (core re-exports it)
132
+ if (WORKSPACE_ROOT) {
133
+ serializedAlias.push({
134
+ find: '@openelement/core/style-sheet',
135
+ replacement: join(WORKSPACE_ROOT, 'packages', 'core', 'src', 'style-sheet.ts')
136
+ });
137
+ serializedAlias.push({
138
+ find: /^@openelement\/router/,
139
+ replacement: join(WORKSPACE_ROOT, 'packages', 'router', 'src')
140
+ });
141
+ }
142
+ serializedAlias.sort((a, b)=>{
143
+ const findA = typeof a.find === 'string' ? a.find.length : 0;
144
+ const findB = typeof b.find === 'string' ? b.find.length : 0;
145
+ return findB - findA;
146
+ });
147
+ if (localIslands.length === 0 && packageIslandDecls.length === 0) {
148
+ log.info('No islands found - zero client JS output');
149
+ return;
150
+ }
151
+ const totalIslands = localIslands.length + packageIslandDecls.length;
152
+ log.info(`Building client bundle for ${totalIslands} island(s)...`);
153
+ // Generate client entry code
154
+ const islandEntries = [
155
+ ...localIslands.map((tagName, i)=>({
156
+ tagName,
157
+ modulePath: resolve(root, localIslandFiles[i] ? `${islandsDir}/${localIslandFiles[i]}` : `${islandsDir}/${tagName}.ts`).replace(/\\/g, '/'),
158
+ isPackage: false,
159
+ strategy: ctx.phase1.islandMeta[tagName]?.hydrate || ctx.phase3.upgradeStrategy || 'idle',
160
+ ssr: ctx.phase1.islandMeta[tagName]?.hydrate === 'only' ? false : ctx.phase1.islandMeta[tagName]?.ssr,
161
+ dsd: ctx.phase1.islandMeta[tagName]?.hydrate === 'only' ? false : ctx.phase1.islandMeta[tagName]?.dsd,
162
+ reason: ctx.phase1.islandMeta[tagName]?.reason
163
+ })),
164
+ ...packageIslandDecls.map((island)=>({
165
+ tagName: island.tagName,
166
+ modulePath: island.modulePath,
167
+ isPackage: true,
168
+ strategy: island.hydrate || ctx.phase3.upgradeStrategy || 'idle',
169
+ ssr: island.hydrate === 'only' ? false : island.ssr,
170
+ dsd: island.hydrate === 'only' ? false : island.dsd,
171
+ reason: island.reason
172
+ }))
173
+ ];
174
+ const clientEntryCode = generateClientEntry(islandEntries);
175
+ // Restore RegExp from serialized noExternal patterns
176
+ const noExternalPatterns = (ctx.phase3.ssrNoExternal || []).map((item)=>{
177
+ if (typeof item === 'string') return item;
178
+ if (item && typeof item === 'object' && item.__type === 'RegExp') {
179
+ return new RegExp(item.source, item.flags);
180
+ }
181
+ return item;
182
+ });
183
+ const clientOutDir = resolve(root, outDir, 'client');
184
+ const clientBase = ctx.phase3.base || '/';
185
+ const clientConfig = {
186
+ configFile: false,
187
+ root,
188
+ base: `${clientBase}client/`,
189
+ logLevel: 'warn',
190
+ // ADR-0057: JSX automatic runtime must be configured in the internal
191
+ // viteBuild() call — configFile:false means user's vite.config.ts is
192
+ // NOT read. Without this, esbuild defaults to classic React.createElement
193
+ // transform, producing {type, props, $$typeof} objects that DsdElement
194
+ // does not recognize (causes [object Object] rendering).
195
+ esbuild: {
196
+ jsx: 'automatic',
197
+ jsxImportSource: '@openelement/core'
198
+ },
199
+ build: {
200
+ outDir: clientOutDir,
201
+ emptyOutDir: true,
202
+ chunkSizeWarningLimit: 1500,
203
+ minify: 'oxc',
204
+ manifest: true,
205
+ rollupOptions: {
206
+ input: {
207
+ client: VIRTUAL_CLIENT_ENTRY_ID
208
+ },
209
+ output: {
210
+ format: 'esm',
211
+ entryFileNames: 'islands/[name].js',
212
+ chunkFileNames: 'islands/[name]-[hash].js',
213
+ manualChunks (id) {
214
+ if (id.includes(`/${islandsDir}/`)) {
215
+ const match = id.match(/\/([^/]+)\.(ts|js)$/);
216
+ if (match) return `island-${match[1]}`;
217
+ }
218
+ for (const island of packageIslandDecls){
219
+ if (id.includes(island.modulePath)) return `island-${island.tagName}`;
220
+ }
221
+ }
222
+ }
223
+ }
224
+ },
225
+ resolve: {
226
+ ...serializedAlias.length > 0 ? {
227
+ alias: serializedAlias
228
+ } : {},
229
+ extensions: [
230
+ '.ts',
231
+ '.tsx',
232
+ '.js',
233
+ '.jsx',
234
+ '.json'
235
+ ]
236
+ },
237
+ ssr: {
238
+ noExternal: noExternalPatterns.length > 0 ? noExternalPatterns : undefined
239
+ },
240
+ plugins: [
241
+ createOpenJsrPackageResolverPlugin({
242
+ workspaceRoot: WORKSPACE_ROOT,
243
+ version: getJsrPackageVersion(import.meta.url)
244
+ }),
245
+ {
246
+ name: 'open:virtual-client-entry',
247
+ resolveId (id) {
248
+ if (id === VIRTUAL_CLIENT_ENTRY_ID) return RESOLVED_CLIENT_ENTRY_ID;
249
+ },
250
+ load (id) {
251
+ if (id === RESOLVED_CLIENT_ENTRY_ID) return clientEntryCode;
252
+ }
253
+ },
254
+ {
255
+ name: 'open:deno-import-map-resolve',
256
+ enforce: 'pre',
257
+ async resolveId (id, importer) {
258
+ // Only handle bare specifiers (no relative imports, no absolute paths)
259
+ if (id.startsWith('.') || id.startsWith('/') || id.startsWith('file:')) {
260
+ return null;
261
+ }
262
+ // Try deno.json import map — walks up from root to find
263
+ // workspace-level deno.json as fallback for monorepo dev.
264
+ const result = lookupInDenoJson(id, root);
265
+ if (!result) return null;
266
+ // Only handle file:// and relative targets (workspace-local dev mappings).
267
+ // npm:, jsr: → return null, let node_modules handle them.
268
+ const resolved = convertImportMapTarget(result.target, result.denoJsonDir);
269
+ if (!resolved) return null;
270
+ return await this.resolve(resolved, importer, {
271
+ skipSelf: true
272
+ });
273
+ }
274
+ }
275
+ ]
276
+ };
277
+ try {
278
+ await viteBuild(clientConfig);
279
+ log.info('Client bundle built -> ' + clientOutDir);
280
+ const { printBuildManifest } = await import('../build-manifest.js');
281
+ printBuildManifest({
282
+ root,
283
+ outDir,
284
+ phase: 2
285
+ });
286
+ } catch (error) {
287
+ log.error(`Client build failed: ${formatError(error)}`);
288
+ throw error;
289
+ }
290
+ }
291
+ export { buildClient };
292
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2NsaS9idWlsZC1jbGllbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAb3BlbmVsZW1lbnQvYWRhcHRlci12aXRlIC0gQ0xJOiBDbGllbnQgSXNsYW5kIEJ1aWxkXG4gKlxuICogQ2xpZW50IGJ1aWxkIGZvciBJc2xhbmQgY29tcG9uZW50cy5cbiAqIFByb2R1Y2VzIGRpc3QvY2xpZW50L2lzbGFuZHMvKi5qcyArIG1hbmlmZXN0IGZvciBTU0cgcG9zdC1wcm9jZXNzaW5nLlxuICpcbiAqIEFEUiAwMDExOiBUaGlzIG1vZHVsZSBleHBvcnRzIGJ1aWxkQ2xpZW50KCkgb25seSAtIGl0IGlzIGNhbGxlZCBmcm9tXG4gKiBjbG9zZUJ1bmRsZSgpIGluIG9wZW46YnVpbGQgcGx1Z2luLiBObyBsb25nZXIgYSBzdGFuZGFsb25lIENMSSBlbnRyeS5cbiAqIGN0eCBwYXJhbWV0ZXIgaXMgcmVxdWlyZWQgKG5vIGdsb2JhbFRoaXMgZmFsbGJhY2spLlxuICpcbiAqIFVzYWdlOlxuICogICBkZW5vIHRhc2sgYnVpbGQgICh1bmlmaWVkIGVudHJ5IC0gcnVucyBhbGwgMyBwaGFzZXMpXG4gKi9cblxuaW1wb3J0IHsgYnVpbGQgYXMgdml0ZUJ1aWxkLCB0eXBlIElubGluZUNvbmZpZyB9IGZyb20gJ3ZpdGUnO1xuaW1wb3J0IHsgZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luLCByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5pbXBvcnQgcHJvY2VzcyBmcm9tICdub2RlOnByb2Nlc3MnO1xuaW1wb3J0IHsgZ2VuZXJhdGVDbGllbnRFbnRyeSB9IGZyb20gJ0BvcGVuZWxlbWVudC9zc2cnO1xuaW1wb3J0IHR5cGUgeyBDbGllbnRJc2xhbmRFbnRyeSB9IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9zc2cnO1xuaW1wb3J0IHR5cGUgeyBPcGVuRWxlbWVudEJ1aWxkQ29udGV4dCB9IGZyb20gJy4uL2J1aWxkLWNvbnRleHQuanMnO1xuaW1wb3J0IHsgY3JlYXRlT3BlbkpzclBhY2thZ2VSZXNvbHZlclBsdWdpbiB9IGZyb20gJy4uL3NzZy1wYWNrYWdlLXJlc29sdmVyLmpzJztcbmltcG9ydCB7IGZvcm1hdEVycm9yIH0gZnJvbSAnQG9wZW5lbGVtZW50L2NvcmUvZXJyb3JzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJ0BvcGVuZWxlbWVudC9jb3JlL2xvZ2dlcic7XG5cbmNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcignc3NnJyk7XG5cbmNvbnN0IFZJUlRVQUxfQ0xJRU5UX0VOVFJZX0lEID0gJ3ZpcnR1YWw6b3Blbi1jbGllbnQtZW50cnknO1xuY29uc3QgUkVTT0xWRURfQ0xJRU5UX0VOVFJZX0lEID0gJ1xcMCcgKyBWSVJUVUFMX0NMSUVOVF9FTlRSWV9JRDtcbmNvbnN0IEZBTExCQUNLX29wZW5FbGVtZW50X1ZFUlNJT04gPSAnMC4yMy4wJztcblxudHlwZSBWaXRlQnVpbGRPcHRpb25zV2l0aE1hbmlmZXN0ID0gTm9uTnVsbGFibGU8SW5saW5lQ29uZmlnWydidWlsZCddPiAmIHtcbiAgbWFuaWZlc3Q/OiBib29sZWFuO1xufTtcblxudHlwZSBWaXRlSW5saW5lQ29uZmlnV2l0aE1hbmlmZXN0ID0gT21pdDxJbmxpbmVDb25maWcsICdidWlsZCc+ICYge1xuICBidWlsZD86IFZpdGVCdWlsZE9wdGlvbnNXaXRoTWFuaWZlc3Q7XG59O1xuXG4vKiogV29ya3NwYWNlIHJvb3QgZGVyaXZlZCBmcm9tIHRoaXMgbW9kdWxlJ3MgbG9jYXRpb24gKHBhY2thZ2VzL2FkYXB0ZXItdml0ZS9zcmMvY2xpLykuXG4gKiBPbmx5IHZhbGlkIGluIGxvY2FsIHdvcmtzcGFjZSAoZmlsZTovLyBpbXBvcnQubWV0YS51cmwpLiBJbiBKU1IgY29uc3VtZXJzLCByZXR1cm5zIG51bGwuICovXG5jb25zdCBXT1JLU1BBQ0VfUk9PVDogc3RyaW5nIHwgbnVsbCA9ICgoKSA9PiB7XG4gIGlmICghaW1wb3J0Lm1ldGEudXJsLnN0YXJ0c1dpdGgoJ2ZpbGU6JykpIHJldHVybiBudWxsO1xuICB0cnkge1xuICAgIHJldHVybiBmaWxlVVJMVG9QYXRoKG5ldyBVUkwoJy4uLy4uLy4uLy4uJywgaW1wb3J0Lm1ldGEudXJsKSkucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufSkoKTtcblxuZnVuY3Rpb24gZ2V0SnNyUGFja2FnZVZlcnNpb24obWV0YVVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbWF0Y2ggPSBtZXRhVXJsLm1hdGNoKC9cXC9Ab3BlbmVsZW1lbnRcXC9hZGFwdGVyLXZpdGVcXC8oW14vXSspXFwvLyk7XG4gIHJldHVybiBtYXRjaD8uWzFdID8/IEZBTExCQUNLX29wZW5FbGVtZW50X1ZFUlNJT047XG59XG5cbi8qKlxuICogTG9vayB1cCBhIGJhcmUgc3BlY2lmaWVyIGluIGEgZGVuby5qc29uIGltcG9ydCBtYXAuXG4gKiBXYWxrcyB1cCBkaXJlY3RvcnkgdHJlZSB0byBmaW5kIHdvcmtzcGFjZS1sZXZlbCBkZW5vLmpzb24gYXMgZmFsbGJhY2suXG4gKiBSZXR1cm5zIHsgdGFyZ2V0LCBkZW5vSnNvbkRpciB9IHNvIHJlbGF0aXZlIHBhdGhzIGNhbiBiZSByZXNvbHZlZCBjb3JyZWN0bHkuXG4gKi9cbmZ1bmN0aW9uIGxvb2t1cEluRGVub0pzb24oXG4gIGlkOiBzdHJpbmcsXG4gIHJvb3Q6IHN0cmluZyxcbik6IHsgdGFyZ2V0OiBzdHJpbmc7IGRlbm9Kc29uRGlyOiBzdHJpbmcgfSB8IG51bGwge1xuICBjb25zdCBkZW5vSnNvbkRpcnMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgbGV0IGRpciA9IHJlc29sdmUocm9vdCk7XG5cbiAgLy8gV2FsayB1cCBmcm9tIGNvbnN1bWVyIHJvb3RcbiAgd2hpbGUgKCFkZW5vSnNvbkRpcnMuaGFzKGRpcikpIHtcbiAgICBkZW5vSnNvbkRpcnMuYWRkKGRpcik7XG4gICAgY29uc3QgZm91bmQgPSB0cnlEZW5vSnNvbkRpcihpZCwgZGlyKTtcbiAgICBpZiAoZm91bmQpIHJldHVybiBmb3VuZDtcbiAgICBjb25zdCBwYXJlbnQgPSByZXNvbHZlKGRpciwgJy4uJyk7XG4gICAgaWYgKHBhcmVudCA9PT0gZGlyKSBicmVhaztcbiAgICBkaXIgPSBwYXJlbnQ7XG4gIH1cblxuICAvLyBBbHNvIHRyeSB3b3Jrc3BhY2Ugcm9vdCAobW9kdWxlLXJlbGF0aXZlLCBmb3IgbW9ub3JlcG8gZGV2IC8gdGVzdGluZylcbiAgaWYgKFdPUktTUEFDRV9ST09UICYmICFkZW5vSnNvbkRpcnMuaGFzKFdPUktTUEFDRV9ST09UKSkge1xuICAgIGNvbnN0IGZvdW5kID0gdHJ5RGVub0pzb25EaXIoaWQsIFdPUktTUEFDRV9ST09UKTtcbiAgICBpZiAoZm91bmQpIHJldHVybiBmb3VuZDtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKiogQ2hlY2sgYSBzaW5nbGUgZGlyZWN0b3J5IGZvciBhIGRlbm8uanNvbiB3aXRoIHRoZSBnaXZlbiBpbXBvcnQuICovXG5mdW5jdGlvbiB0cnlEZW5vSnNvbkRpcihcbiAgaWQ6IHN0cmluZyxcbiAgZGlyOiBzdHJpbmcsXG4pOiB7IHRhcmdldDogc3RyaW5nOyBkZW5vSnNvbkRpcjogc3RyaW5nIH0gfCBudWxsIHtcbiAgY29uc3QgZGVub0pzb25QYXRoID0gam9pbihkaXIsICdkZW5vLmpzb24nKTtcbiAgaWYgKCFleGlzdHNTeW5jKGRlbm9Kc29uUGF0aCkpIHJldHVybiBudWxsO1xuICBjb25zdCByYXcgPSByZWFkRmlsZVN5bmMoZGVub0pzb25QYXRoLCAndXRmLTgnKTtcbiAgLy8gU3RyaXAgSlNPTkMgY29tbWVudHM6XG4gIC8vIC0gTGluZSBjb21tZW50czogLy8gYXQgc3RhcnQgb2YgbGluZSAoYWZ0ZXIgb3B0aW9uYWwgd2hpdGVzcGFjZSlcbiAgLy8gLSBCbG9jayBjb21tZW50czogLyogLi4uICovXG4gIC8vIC0gVHJhaWxpbmcgY29tbWFzIChEZW5vIEpTT05DIGFsbG93cyB0aGVtLCBKU09OLnBhcnNlIGRvZXMgbm90KVxuICBjb25zdCBqc29uID0gcmF3XG4gICAgLnJlcGxhY2UoL15cXHMqXFwvXFwvLiokL2dtLCAnJylcbiAgICAucmVwbGFjZSgvXFwvXFwqW1xcc1xcU10qP1xcKlxcLy9nLCAnJylcbiAgICAucmVwbGFjZSgvLFxccyooW31cXF1dKS9nLCAnJDEnKTtcbiAgbGV0IGRlbm9Kc29uOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgdHJ5IHtcbiAgICBkZW5vSnNvbiA9IEpTT04ucGFyc2UoanNvbik7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBudWxsOyAvLyBJbnZhbGlkIEpTT04g4oCUIHNraXAgdGhpcyBkZW5vLmpzb25cbiAgfVxuICBjb25zdCBpbXBvcnRzID0gZGVub0pzb24uaW1wb3J0cyBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgdW5kZWZpbmVkO1xuICBpZiAoIWltcG9ydHMpIHJldHVybiBudWxsO1xuICAvLyBFeGFjdCBtYXRjaFxuICBpZiAoaW1wb3J0c1tpZF0pIHJldHVybiB7IHRhcmdldDogaW1wb3J0c1tpZF0sIGRlbm9Kc29uRGlyOiBkaXIgfTtcbiAgLy8gUHJlZml4L3N1YnBhdGggbWF0Y2hpbmcgKHRyYWlsaW5nIHNsYXNoKVxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhpbXBvcnRzKSkge1xuICAgIGlmIChrZXkuZW5kc1dpdGgoJy8nKSAmJiBpZC5zdGFydHNXaXRoKGtleSkpIHtcbiAgICAgIHJldHVybiB7IHRhcmdldDogdmFsdWUgKyBpZC5zbGljZShrZXkubGVuZ3RoKSwgZGVub0pzb25EaXI6IGRpciB9O1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgRGVubyBpbXBvcnQgbWFwIHRhcmdldCB0byBhIHJlc29sdmFibGUgVml0ZSBwYXRoLlxuICogLSBmaWxlOi8vIFVSTHMg4oaSIGFic29sdXRlIGZpbGVzeXN0ZW0gcGF0aFxuICogLSBSZWxhdGl2ZSBwYXRocyAoLi8pIOKGkiByZXNvbHZlZCByZWxhdGl2ZSB0byBkZW5vSnNvbkRpclxuICogLSBucG06LCBqc3I6IOKGkiBudWxsIChoYW5kbGVkIGJ5IG5vZGVfbW9kdWxlcylcbiAqL1xuZnVuY3Rpb24gY29udmVydEltcG9ydE1hcFRhcmdldCh0YXJnZXQ6IHN0cmluZywgZGVub0pzb25EaXI6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBpZiAodGFyZ2V0LnN0YXJ0c1dpdGgoJ2ZpbGU6Ly8nKSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZmlsZVVSTFRvUGF0aCh0YXJnZXQpLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICAvLyBSZWxhdGl2ZSBwYXRoIOKAlCByZXNvbHZlIHJlbGF0aXZlIHRvIHRoZSBkZW5vLmpzb24gZGlyZWN0b3J5XG4gIGlmICh0YXJnZXQuc3RhcnRzV2l0aCgnLi8nKSB8fCB0YXJnZXQuc3RhcnRzV2l0aCgnLi4vJykpIHtcbiAgICByZXR1cm4gcmVzb2x2ZShkZW5vSnNvbkRpciwgdGFyZ2V0KS5yZXBsYWNlKC9cXFxcL2csICcvJyk7XG4gIH1cbiAgLy8gbnBtOiwganNyOiDigJQgbGV0IFZpdGUvUm9sbGRvd24gaGFuZGxlIHRoZXNlIG5vcm1hbGx5XG4gIHJldHVybiBudWxsO1xufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZENsaWVudChjdHg6IE9wZW5FbGVtZW50QnVpbGRDb250ZXh0KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJvb3QgPSBjdHgucGhhc2UzLnJvb3QgfHwgcHJvY2Vzcy5jd2QoKTtcbiAgY29uc3Qgb3V0RGlyID0gY3R4LnBoYXNlMy5vdXREaXIgfHwgJ2Rpc3QnO1xuICBjb25zdCBpc2xhbmRzRGlyID0gY3R4LnBoYXNlMy5pc2xhbmRzRGlyIHx8ICdhcHAvaXNsYW5kcyc7XG4gIGNvbnN0IGxvY2FsSXNsYW5kcyA9IGN0eC5waGFzZTEuaXNsYW5kVGFnTmFtZXMgfHwgW107XG4gIGNvbnN0IGxvY2FsSXNsYW5kRmlsZXMgPSBjdHgucGhhc2UxLmlzbGFuZEZpbGVzIHx8IFtdO1xuICBjb25zdCBwYWNrYWdlSXNsYW5kRGVjbHMgPSBjdHgucGhhc2UxLnBhY2thZ2VJc2xhbmREZWNscyB8fCBbXTtcblxuICAvLyBBbGlhc2VzIHByZS1nZW5lcmF0ZWQgYnkgY3JlYXRlT3BlblBsdWdpbigpIGFuZCBzdG9yZWQgaW4gY3R4XG4gIGNvbnN0IHJlc29sdmVBbGlhcyA9IGN0eC5waGFzZTEudXNlclJlc29sdmVBbGlhcztcbiAgY29uc3Qgc2VyaWFsaXplZEFsaWFzID0gcmVzb2x2ZUFsaWFzXG4gICAgPyAoQXJyYXkuaXNBcnJheShyZXNvbHZlQWxpYXMpXG4gICAgICA/IHJlc29sdmVBbGlhcy5maWx0ZXIoKGEpID0+IHR5cGVvZiBhLmZpbmQgPT09ICdzdHJpbmcnKS5tYXAoKGEpID0+ICh7XG4gICAgICAgIGZpbmQ6IGEuZmluZCBhcyBzdHJpbmcsXG4gICAgICAgIHJlcGxhY2VtZW50OiBhLnJlcGxhY2VtZW50LFxuICAgICAgfSkpXG4gICAgICA6IE9iamVjdC5lbnRyaWVzKHJlc29sdmVBbGlhcykubWFwKChbZmluZCwgcmVwbGFjZW1lbnRdKSA9PiAoeyBmaW5kLCByZXBsYWNlbWVudCB9KSkpXG4gICAgOiBbXTtcblxuICAvLyBBbHdheXMgcmVzb2x2ZSBAb3BlbmVsZW1lbnQvY29yZS9zdHlsZS1zaGVldCBmcm9tIHdvcmtzcGFjZSAoY29yZSByZS1leHBvcnRzIGl0KVxuICBpZiAoV09SS1NQQUNFX1JPT1QpIHtcbiAgICBzZXJpYWxpemVkQWxpYXMucHVzaCh7XG4gICAgICBmaW5kOiAnQG9wZW5lbGVtZW50L2NvcmUvc3R5bGUtc2hlZXQnLFxuICAgICAgcmVwbGFjZW1lbnQ6IGpvaW4oV09SS1NQQUNFX1JPT1QsICdwYWNrYWdlcycsICdjb3JlJywgJ3NyYycsICdzdHlsZS1zaGVldC50cycpLFxuICAgIH0pO1xuICAgIChzZXJpYWxpemVkQWxpYXMgYXMgQXJyYXk8eyBmaW5kOiBzdHJpbmcgfCBSZWdFeHA7IHJlcGxhY2VtZW50OiBzdHJpbmcgfT4pLnB1c2goe1xuICAgICAgZmluZDogL15Ab3BlbmVsZW1lbnRcXC9yb3V0ZXIvLFxuICAgICAgcmVwbGFjZW1lbnQ6IGpvaW4oV09SS1NQQUNFX1JPT1QsICdwYWNrYWdlcycsICdyb3V0ZXInLCAnc3JjJyksXG4gICAgfSk7XG4gIH1cbiAgc2VyaWFsaXplZEFsaWFzLnNvcnQoKGEsIGIpID0+IHtcbiAgICBjb25zdCBmaW5kQSA9IHR5cGVvZiBhLmZpbmQgPT09ICdzdHJpbmcnID8gYS5maW5kLmxlbmd0aCA6IDA7XG4gICAgY29uc3QgZmluZEIgPSB0eXBlb2YgYi5maW5kID09PSAnc3RyaW5nJyA/IGIuZmluZC5sZW5ndGggOiAwO1xuICAgIHJldHVybiBmaW5kQiAtIGZpbmRBO1xuICB9KTtcblxuICBpZiAobG9jYWxJc2xhbmRzLmxlbmd0aCA9PT0gMCAmJiBwYWNrYWdlSXNsYW5kRGVjbHMubGVuZ3RoID09PSAwKSB7XG4gICAgbG9nLmluZm8oJ05vIGlzbGFuZHMgZm91bmQgLSB6ZXJvIGNsaWVudCBKUyBvdXRwdXQnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB0b3RhbElzbGFuZHMgPSBsb2NhbElzbGFuZHMubGVuZ3RoICsgcGFja2FnZUlzbGFuZERlY2xzLmxlbmd0aDtcbiAgbG9nLmluZm8oYEJ1aWxkaW5nIGNsaWVudCBidW5kbGUgZm9yICR7dG90YWxJc2xhbmRzfSBpc2xhbmQocykuLi5gKTtcblxuICAvLyBHZW5lcmF0ZSBjbGllbnQgZW50cnkgY29kZVxuICBjb25zdCBpc2xhbmRFbnRyaWVzOiBDbGllbnRJc2xhbmRFbnRyeVtdID0gW1xuICAgIC4uLmxvY2FsSXNsYW5kcy5tYXAoKHRhZ05hbWU6IHN0cmluZywgaTogbnVtYmVyKSA9PiAoe1xuICAgICAgdGFnTmFtZSxcbiAgICAgIG1vZHVsZVBhdGg6IHJlc29sdmUoXG4gICAgICAgIHJvb3QsXG4gICAgICAgIGxvY2FsSXNsYW5kRmlsZXNbaV1cbiAgICAgICAgICA/IGAke2lzbGFuZHNEaXJ9LyR7bG9jYWxJc2xhbmRGaWxlc1tpXX1gXG4gICAgICAgICAgOiBgJHtpc2xhbmRzRGlyfS8ke3RhZ05hbWV9LnRzYCxcbiAgICAgICkucmVwbGFjZSgvXFxcXC9nLCAnLycpLFxuICAgICAgaXNQYWNrYWdlOiBmYWxzZSxcbiAgICAgIHN0cmF0ZWd5OiBjdHgucGhhc2UxLmlzbGFuZE1ldGFbdGFnTmFtZV0/Lmh5ZHJhdGUgfHwgY3R4LnBoYXNlMy51cGdyYWRlU3RyYXRlZ3kgfHwgJ2lkbGUnLFxuICAgICAgc3NyOiBjdHgucGhhc2UxLmlzbGFuZE1ldGFbdGFnTmFtZV0/Lmh5ZHJhdGUgPT09ICdvbmx5J1xuICAgICAgICA/IGZhbHNlXG4gICAgICAgIDogY3R4LnBoYXNlMS5pc2xhbmRNZXRhW3RhZ05hbWVdPy5zc3IsXG4gICAgICBkc2Q6IGN0eC5waGFzZTEuaXNsYW5kTWV0YVt0YWdOYW1lXT8uaHlkcmF0ZSA9PT0gJ29ubHknXG4gICAgICAgID8gZmFsc2VcbiAgICAgICAgOiBjdHgucGhhc2UxLmlzbGFuZE1ldGFbdGFnTmFtZV0/LmRzZCxcbiAgICAgIHJlYXNvbjogY3R4LnBoYXNlMS5pc2xhbmRNZXRhW3RhZ05hbWVdPy5yZWFzb24sXG4gICAgfSkpLFxuICAgIC4uLnBhY2thZ2VJc2xhbmREZWNscy5tYXAoXG4gICAgICAoaXNsYW5kKSA9PiAoe1xuICAgICAgICB0YWdOYW1lOiBpc2xhbmQudGFnTmFtZSxcbiAgICAgICAgbW9kdWxlUGF0aDogaXNsYW5kLm1vZHVsZVBhdGgsXG4gICAgICAgIGlzUGFja2FnZTogdHJ1ZSxcbiAgICAgICAgc3RyYXRlZ3k6IGlzbGFuZC5oeWRyYXRlIHx8IGN0eC5waGFzZTMudXBncmFkZVN0cmF0ZWd5IHx8ICdpZGxlJyxcbiAgICAgICAgc3NyOiBpc2xhbmQuaHlkcmF0ZSA9PT0gJ29ubHknID8gZmFsc2UgOiBpc2xhbmQuc3NyLFxuICAgICAgICBkc2Q6IGlzbGFuZC5oeWRyYXRlID09PSAnb25seScgPyBmYWxzZSA6IGlzbGFuZC5kc2QsXG4gICAgICAgIHJlYXNvbjogaXNsYW5kLnJlYXNvbixcbiAgICAgIH0pLFxuICAgICksXG4gIF07XG5cbiAgY29uc3QgY2xpZW50RW50cnlDb2RlID0gZ2VuZXJhdGVDbGllbnRFbnRyeShpc2xhbmRFbnRyaWVzKTtcblxuICAvLyBSZXN0b3JlIFJlZ0V4cCBmcm9tIHNlcmlhbGl6ZWQgbm9FeHRlcm5hbCBwYXR0ZXJuc1xuICBjb25zdCBub0V4dGVybmFsUGF0dGVybnMgPSAoY3R4LnBoYXNlMy5zc3JOb0V4dGVybmFsIHx8IFtdKS5tYXAoKGl0ZW0pID0+IHtcbiAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSByZXR1cm4gaXRlbTtcbiAgICBpZiAoaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcgJiYgKGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLl9fdHlwZSA9PT0gJ1JlZ0V4cCcpIHtcbiAgICAgIHJldHVybiBuZXcgUmVnRXhwKFxuICAgICAgICAoaXRlbSBhcyB7IHNvdXJjZTogc3RyaW5nOyBmbGFnczogc3RyaW5nIH0pLnNvdXJjZSxcbiAgICAgICAgKGl0ZW0gYXMgeyBzb3VyY2U6IHN0cmluZzsgZmxhZ3M6IHN0cmluZyB9KS5mbGFncyxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtO1xuICB9KTtcblxuICBjb25zdCBjbGllbnRPdXREaXIgPSByZXNvbHZlKHJvb3QsIG91dERpciwgJ2NsaWVudCcpO1xuICBjb25zdCBjbGllbnRCYXNlID0gY3R4LnBoYXNlMy5iYXNlIHx8ICcvJztcbiAgY29uc3QgY2xpZW50Q29uZmlnOiBWaXRlSW5saW5lQ29uZmlnV2l0aE1hbmlmZXN0ID0ge1xuICAgIGNvbmZpZ0ZpbGU6IGZhbHNlLFxuICAgIHJvb3QsXG4gICAgYmFzZTogYCR7Y2xpZW50QmFzZX1jbGllbnQvYCxcbiAgICBsb2dMZXZlbDogJ3dhcm4nLFxuICAgIC8vIEFEUi0wMDU3OiBKU1ggYXV0b21hdGljIHJ1bnRpbWUgbXVzdCBiZSBjb25maWd1cmVkIGluIHRoZSBpbnRlcm5hbFxuICAgIC8vIHZpdGVCdWlsZCgpIGNhbGwg4oCUIGNvbmZpZ0ZpbGU6ZmFsc2UgbWVhbnMgdXNlcidzIHZpdGUuY29uZmlnLnRzIGlzXG4gICAgLy8gTk9UIHJlYWQuIFdpdGhvdXQgdGhpcywgZXNidWlsZCBkZWZhdWx0cyB0byBjbGFzc2ljIFJlYWN0LmNyZWF0ZUVsZW1lbnRcbiAgICAvLyB0cmFuc2Zvcm0sIHByb2R1Y2luZyB7dHlwZSwgcHJvcHMsICQkdHlwZW9mfSBvYmplY3RzIHRoYXQgRHNkRWxlbWVudFxuICAgIC8vIGRvZXMgbm90IHJlY29nbml6ZSAoY2F1c2VzIFtvYmplY3QgT2JqZWN0XSByZW5kZXJpbmcpLlxuICAgIGVzYnVpbGQ6IHtcbiAgICAgIGpzeDogJ2F1dG9tYXRpYycsXG4gICAgICBqc3hJbXBvcnRTb3VyY2U6ICdAb3BlbmVsZW1lbnQvY29yZScsXG4gICAgfSxcbiAgICBidWlsZDoge1xuICAgICAgb3V0RGlyOiBjbGllbnRPdXREaXIsXG4gICAgICBlbXB0eU91dERpcjogdHJ1ZSxcbiAgICAgIGNodW5rU2l6ZVdhcm5pbmdMaW1pdDogMTUwMCxcbiAgICAgIG1pbmlmeTogJ294YycsXG4gICAgICBtYW5pZmVzdDogdHJ1ZSxcbiAgICAgIHJvbGx1cE9wdGlvbnM6IHtcbiAgICAgICAgaW5wdXQ6IHsgY2xpZW50OiBWSVJUVUFMX0NMSUVOVF9FTlRSWV9JRCB9LFxuICAgICAgICBvdXRwdXQ6IHtcbiAgICAgICAgICBmb3JtYXQ6ICdlc20nLFxuICAgICAgICAgIGVudHJ5RmlsZU5hbWVzOiAnaXNsYW5kcy9bbmFtZV0uanMnLFxuICAgICAgICAgIGNodW5rRmlsZU5hbWVzOiAnaXNsYW5kcy9bbmFtZV0tW2hhc2hdLmpzJyxcbiAgICAgICAgICBtYW51YWxDaHVua3MoaWQ6IHN0cmluZykge1xuICAgICAgICAgICAgaWYgKGlkLmluY2x1ZGVzKGAvJHtpc2xhbmRzRGlyfS9gKSkge1xuICAgICAgICAgICAgICBjb25zdCBtYXRjaCA9IGlkLm1hdGNoKC9cXC8oW14vXSspXFwuKHRzfGpzKSQvKTtcbiAgICAgICAgICAgICAgaWYgKG1hdGNoKSByZXR1cm4gYGlzbGFuZC0ke21hdGNoWzFdfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGlzbGFuZCBvZiBwYWNrYWdlSXNsYW5kRGVjbHMpIHtcbiAgICAgICAgICAgICAgaWYgKGlkLmluY2x1ZGVzKGlzbGFuZC5tb2R1bGVQYXRoKSkgcmV0dXJuIGBpc2xhbmQtJHtpc2xhbmQudGFnTmFtZX1gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAgcmVzb2x2ZToge1xuICAgICAgLi4uKHNlcmlhbGl6ZWRBbGlhcy5sZW5ndGggPiAwID8geyBhbGlhczogc2VyaWFsaXplZEFsaWFzIH0gOiB7fSksXG4gICAgICBleHRlbnNpb25zOiBbJy50cycsICcudHN4JywgJy5qcycsICcuanN4JywgJy5qc29uJ10sXG4gICAgfSxcbiAgICBzc3I6IHtcbiAgICAgIG5vRXh0ZXJuYWw6IChub0V4dGVybmFsUGF0dGVybnMubGVuZ3RoID4gMCA/IG5vRXh0ZXJuYWxQYXR0ZXJucyA6IHVuZGVmaW5lZCkgYXNcbiAgICAgICAgfCAoc3RyaW5nIHwgUmVnRXhwKVtdXG4gICAgICAgIHwgdW5kZWZpbmVkLFxuICAgIH0sXG4gICAgcGx1Z2luczogW1xuICAgICAgY3JlYXRlT3BlbkpzclBhY2thZ2VSZXNvbHZlclBsdWdpbih7XG4gICAgICAgIHdvcmtzcGFjZVJvb3Q6IFdPUktTUEFDRV9ST09ULFxuICAgICAgICB2ZXJzaW9uOiBnZXRKc3JQYWNrYWdlVmVyc2lvbihpbXBvcnQubWV0YS51cmwpLFxuICAgICAgfSksXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICdvcGVuOnZpcnR1YWwtY2xpZW50LWVudHJ5JyxcbiAgICAgICAgcmVzb2x2ZUlkKGlkKSB7XG4gICAgICAgICAgaWYgKGlkID09PSBWSVJUVUFMX0NMSUVOVF9FTlRSWV9JRCkgcmV0dXJuIFJFU09MVkVEX0NMSUVOVF9FTlRSWV9JRDtcbiAgICAgICAgfSxcbiAgICAgICAgbG9hZChpZCkge1xuICAgICAgICAgIGlmIChpZCA9PT0gUkVTT0xWRURfQ0xJRU5UX0VOVFJZX0lEKSByZXR1cm4gY2xpZW50RW50cnlDb2RlO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ29wZW46ZGVuby1pbXBvcnQtbWFwLXJlc29sdmUnLFxuICAgICAgICBlbmZvcmNlOiAncHJlJyxcbiAgICAgICAgYXN5bmMgcmVzb2x2ZUlkKGlkLCBpbXBvcnRlcikge1xuICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIGJhcmUgc3BlY2lmaWVycyAobm8gcmVsYXRpdmUgaW1wb3J0cywgbm8gYWJzb2x1dGUgcGF0aHMpXG4gICAgICAgICAgaWYgKGlkLnN0YXJ0c1dpdGgoJy4nKSB8fCBpZC5zdGFydHNXaXRoKCcvJykgfHwgaWQuc3RhcnRzV2l0aCgnZmlsZTonKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gVHJ5IGRlbm8uanNvbiBpbXBvcnQgbWFwIOKAlCB3YWxrcyB1cCBmcm9tIHJvb3QgdG8gZmluZFxuICAgICAgICAgIC8vIHdvcmtzcGFjZS1sZXZlbCBkZW5vLmpzb24gYXMgZmFsbGJhY2sgZm9yIG1vbm9yZXBvIGRldi5cbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBsb29rdXBJbkRlbm9Kc29uKGlkLCByb290KTtcbiAgICAgICAgICBpZiAoIXJlc3VsdCkgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgICAvLyBPbmx5IGhhbmRsZSBmaWxlOi8vIGFuZCByZWxhdGl2ZSB0YXJnZXRzICh3b3Jrc3BhY2UtbG9jYWwgZGV2IG1hcHBpbmdzKS5cbiAgICAgICAgICAvLyBucG06LCBqc3I6IOKGkiByZXR1cm4gbnVsbCwgbGV0IG5vZGVfbW9kdWxlcyBoYW5kbGUgdGhlbS5cbiAgICAgICAgICBjb25zdCByZXNvbHZlZCA9IGNvbnZlcnRJbXBvcnRNYXBUYXJnZXQocmVzdWx0LnRhcmdldCwgcmVzdWx0LmRlbm9Kc29uRGlyKTtcbiAgICAgICAgICBpZiAoIXJlc29sdmVkKSByZXR1cm4gbnVsbDtcblxuICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJlc29sdmUocmVzb2x2ZWQsIGltcG9ydGVyLCB7IHNraXBTZWxmOiB0cnVlIH0pO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICBdLFxuICB9O1xuXG4gIHRyeSB7XG4gICAgYXdhaXQgdml0ZUJ1aWxkKGNsaWVudENvbmZpZyk7XG4gICAgbG9nLmluZm8oJ0NsaWVudCBidW5kbGUgYnVpbHQgLT4gJyArIGNsaWVudE91dERpcik7XG5cbiAgICBjb25zdCB7IHByaW50QnVpbGRNYW5pZmVzdCB9ID0gYXdhaXQgaW1wb3J0KCcuLi9idWlsZC1tYW5pZmVzdC5qcycpO1xuICAgIHByaW50QnVpbGRNYW5pZmVzdCh7IHJvb3QsIG91dERpciwgcGhhc2U6IDIgfSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nLmVycm9yKGBDbGllbnQgYnVpbGQgZmFpbGVkOiAke2Zvcm1hdEVycm9yKGVycm9yKX1gKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBidWlsZENsaWVudCB9O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Q0FZQyxHQUVELFNBQVMs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
@@ -0,0 +1,40 @@
1
+ import type { FrameworkOptions, HydrationStrategy } from '@openelement/protocol/framework';
2
+ import type { OpenElementPackageManifest } from '@openelement/protocol/manifest';
3
+ import type { OpenElementBuildContext } from "../build-context.js";
4
+ interface BuildSSGOptions {
5
+ root?: string;
6
+ outDir?: string;
7
+ routesDir?: string;
8
+ islandsDir?: string;
9
+ middleware?: FrameworkOptions['middleware'];
10
+ ssr?: FrameworkOptions['ssr'];
11
+ islandTagNames?: string[];
12
+ islandMeta?: Record<string, Partial<import('@openelement/protocol/ssg').IslandDecl>>;
13
+ packageManifests?: OpenElementPackageManifest[];
14
+ /** @security Injected as raw HTML without sanitization */ headExtras?: string;
15
+ allowHeadExtrasScripts?: boolean;
16
+ html?: {
17
+ lang?: string;
18
+ title?: string;
19
+ };
20
+ appShell?: FrameworkOptions['appShell'];
21
+ layouts?: FrameworkOptions['layouts'];
22
+ upgradeStrategy?: HydrationStrategy;
23
+ resolveAlias?: Record<string, string> | import('vite').Alias[];
24
+ base?: string;
25
+ /**
26
+ * View Transitions API configuration.
27
+ * When true (default), injects <meta name="view-transition" content="same-origin">
28
+ * into all HTML files for smooth cross-page animations in MPA navigation.
29
+ * Set to false to disable.
30
+ * @default true
31
+ */ viewTransition?: boolean;
32
+ /**
33
+ * Speculation Rules API configuration.
34
+ * Enables browser prefetch/prerender of pages before the user navigates.
35
+ * Can be a boolean (true = auto-generate from routes) or explicit rules.
36
+ */ speculation?: boolean | import('@openelement/protocol/ssg').SpeculationRulesOptions;
37
+ /** ADR-0047: Skip Deno pre-resolution, use regex fallback for external deps. */ skipPreResolution?: boolean;
38
+ }
39
+ declare function buildSSG(options: BuildSSGOptions | undefined, ctx: OpenElementBuildContext): Promise<void>;
40
+ export { buildSSG };