@openelement/ssg 0.41.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,307 @@
1
+ /**
2
+ * @openelement/ssg - Entry renderer helper functions
3
+ *
4
+ * Shared code-generation helper functions used by entry-renderer.ts
5
+ * and its sub-modules (entry-render-runtime.ts, entry-render-ssg.ts).
6
+ *
7
+ * Each function generates a fragment of the virtual Hono entry module.
8
+ */ export function renderImport(imp) {
9
+ const names = imp.alias ? `${imp.names[0]} as ${imp.alias}` : imp.names.join(', ');
10
+ return `import { ${names} } from '${imp.from}'`;
11
+ }
12
+ export function routeTagNameExpr(varName, fallback) {
13
+ void varName;
14
+ return JSON.stringify(fallback);
15
+ }
16
+ export function pageDefinitionExpr(varName) {
17
+ return `(${varName}.default?.openElementPage || {})`;
18
+ }
19
+ export function routeMetaExpr(varName) {
20
+ const pageDef = pageDefinitionExpr(varName);
21
+ return `({ ...(${pageDef}.route !== undefined ? { route: ${pageDef}.route } : {}), ...(${pageDef}.head?.title !== undefined ? { title: ${pageDef}.head.title } : {}), ...(${pageDef}.head?.description !== undefined ? { description: ${pageDef}.head.description } : {}) })`;
22
+ }
23
+ export function routeRevalidateExpr(varName) {
24
+ const pageDef = pageDefinitionExpr(varName);
25
+ return `(${pageDef}.renderIntent?.revalidate ?? false)`;
26
+ }
27
+ /** Generate a POST handler for a page route (form action handling). */ export function renderActionRoute(lines, route, renderers, docConfig, isSSG) {
28
+ const matchingRenderers = renderers.filter((r)=>{
29
+ if (r.scope === '/') return true;
30
+ return route.path === r.scope || route.path.startsWith(r.scope + '/');
31
+ });
32
+ const pathStr = route.path.replace(/'/g, "\\'");
33
+ const tagNameExpr = routeTagNameExpr(route.varName, route.tagName);
34
+ const pageDefExpr = pageDefinitionExpr(route.varName);
35
+ const routeMeta = routeMetaExpr(route.varName);
36
+ const routeContext = `{ path: ${JSON.stringify(route.path)}, filePath: ${JSON.stringify(route.filePath)} }`;
37
+ const headExtrasExpr = isSSG ? '__headExtras' : JSON.stringify(docConfig.headExtras);
38
+ lines.push(`// Action POST: ${route.path} (${route.filePath})`);
39
+ lines.push(`app.post('${pathStr}', async (c) => {`);
40
+ lines.push(` let __tag = ${tagNameExpr}`);
41
+ lines.push(` let __page = ${pageDefExpr}`);
42
+ lines.push(` let __params = {}`);
43
+ lines.push(` let __routeMeta = ${routeMeta}`);
44
+ lines.push(` const __routeContext = ${routeContext}`);
45
+ lines.push(` try {`);
46
+ lines.push(` __params = c.req.param() || {}`);
47
+ lines.push(` const __loadContext = {`);
48
+ lines.push(` params: __params,`);
49
+ lines.push(` request: c.req.raw,`);
50
+ lines.push(` env: c.env || {},`);
51
+ lines.push(` platform: (() => { try { return c.executionCtx } catch { return undefined } })(),`);
52
+ lines.push(` route: __routeContext,`);
53
+ lines.push(` }`);
54
+ lines.push(` const __data = typeof ${route.varName}.loader === "function" ? await ${route.varName}.loader(__loadContext) : undefined`);
55
+ lines.push(` const __formData = await c.req.parseBody()`);
56
+ lines.push(` const __actionCtx = { ...__loadContext, formData: __formData }`);
57
+ lines.push(` const __actionData = typeof ${route.varName}.action === "function" ? await ${route.varName}.action(__actionCtx) : undefined`);
58
+ lines.push(` let node = jsx(__tag, { ...__params, data: __data, __openElementActionData: __actionData, __openElementParams: __params, __openElementRequest: c.req.raw, __openElementRoute: __routeContext, __openElementMeta: __routeMeta })`);
59
+ lines.push(``);
60
+ if (matchingRenderers.length > 0) {
61
+ lines.push(` // Renderer tree wrapping (outer -> inner)`);
62
+ for (const renderer of matchingRenderers){
63
+ lines.push(` node = await ${renderer.varName}.default.wrap(node, c)`);
64
+ }
65
+ }
66
+ lines.push(` const content = await __renderAppShell(node, c.req.path || ${JSON.stringify(route.path)}, { routeMeta: __routeMeta })`);
67
+ lines.push(` return c.html(wrapInDocument(content, {`);
68
+ lines.push(` title: __page.head?.title || ${JSON.stringify(docConfig.title)},`);
69
+ lines.push(` lang: ${JSON.stringify(docConfig.lang)},`);
70
+ lines.push(` meta: { description: __page.head?.description, tags: __page.head?.meta },`);
71
+ lines.push(` headExtras: ${headExtrasExpr},`);
72
+ lines.push(` dangerouslyHeadFragments: __page.head?.dangerouslyHeadFragments || [],`);
73
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(docConfig.allowHeadExtrasScripts)},`);
74
+ lines.push(` cspNonce: c.get('cspNonce'),`);
75
+ lines.push(` }))`);
76
+ lines.push(` } catch (err) {`);
77
+ lines.push(` if (__isOpenElementRedirect(err)) {`);
78
+ lines.push(` return c.redirect(err.location, err.status)`);
79
+ lines.push(` }`);
80
+ lines.push(` if (__isOpenElementNotFound(err)) {`);
81
+ lines.push(` return c.html(wrapInDocument(__statusHtml("404 Not Found", err.message || "Not Found"), {`);
82
+ lines.push(` title: "404 Not Found",`);
83
+ lines.push(` lang: ${JSON.stringify(docConfig.lang)},`);
84
+ lines.push(` headExtras: ${headExtrasExpr},`);
85
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(docConfig.allowHeadExtrasScripts)},`);
86
+ lines.push(` cspNonce: c.get('cspNonce'),`);
87
+ lines.push(` }), 404)`);
88
+ lines.push(` }`);
89
+ lines.push(` console.error('[openElement] Action POST failed for ${pathStr}:', err)`);
90
+ lines.push(` if (import.meta.env.PROD) {`);
91
+ lines.push(` return c.html('<h1>500 Internal Server Error</h1>', 500)`);
92
+ lines.push(` } else {`);
93
+ lines.push(` const safeErr = escapeHtml(String(err.stack || err))`);
94
+ lines.push(` return c.html('<h1>500</h1><pre>' + safeErr + '</pre>', 500)`);
95
+ lines.push(` }`);
96
+ lines.push(` }`);
97
+ lines.push(`})`);
98
+ lines.push('');
99
+ }
100
+ /** Generate the route-to-module map for /_data endpoint. */ export function renderDataRouteMap(lines, pageRoutes) {
101
+ lines.push('// Route-to-module map for /_data endpoint (SPA client navigation)');
102
+ lines.push('const __dataRouteMap = {');
103
+ for (const r of pageRoutes){
104
+ lines.push(` ${JSON.stringify(r.path)}: ${r.varName},`);
105
+ }
106
+ lines.push('};');
107
+ lines.push('');
108
+ }
109
+ /** Generate the /_data GET endpoint for SPA navigation data fetching. */ export function renderDataEndpoint(lines) {
110
+ lines.push('// /_data endpoint - returns JSON loader data for SPA navigation');
111
+ lines.push(`app.get('/_data', async (c) => {`);
112
+ lines.push(` const routePath = c.req.query('route');`);
113
+ lines.push(` if (!routePath) return c.json({ error: 'Missing route query' }, 400);`);
114
+ lines.push(` const mod = __dataRouteMap[routePath];`);
115
+ lines.push(` if (!mod) return c.json({ error: 'Route not found' }, 404);`);
116
+ lines.push(` if (typeof mod.loader !== 'function') return c.json({ data: null });`);
117
+ lines.push(` try {`);
118
+ lines.push(` const loadContext = {`);
119
+ lines.push(` params: {},`);
120
+ lines.push(` request: c.req.raw,`);
121
+ lines.push(` env: c.env || {},`);
122
+ lines.push(` platform: undefined,`);
123
+ lines.push(` route: { path: routePath, filePath: '' },`);
124
+ lines.push(` };`);
125
+ lines.push(` const data = await mod.loader(loadContext);`);
126
+ lines.push(` return c.json({ data });`);
127
+ lines.push(` } catch (err) {`);
128
+ lines.push(` return c.json({ error: String(err) }, 500);`);
129
+ lines.push(` }`);
130
+ lines.push(`})`);
131
+ lines.push('');
132
+ }
133
+ function renderCorsOrigin(origin) {
134
+ if (typeof origin === 'object' && !Array.isArray(origin)) return origin.body;
135
+ return JSON.stringify(origin);
136
+ }
137
+ const CORS_ALLOW = "allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], allowHeaders: ['Content-Type', 'Authorization'], credentials: true, maxAge: 86400";
138
+ export function renderMiddleware(lines, mw) {
139
+ if (mw.comment) {
140
+ lines.push(`// ${mw.comment}`);
141
+ }
142
+ switch(mw.kind){
143
+ case 'requestId':
144
+ lines.push("app.use('*', requestId())");
145
+ break;
146
+ case 'logger':
147
+ lines.push("app.use('*', honoLogger())");
148
+ break;
149
+ case 'cors':
150
+ {
151
+ const corsOrigin = mw.config?.corsOrigin;
152
+ if (corsOrigin === '*' || Array.isArray(corsOrigin) && corsOrigin.includes('*')) {
153
+ throw new Error('CORS misconfiguration: origin "*" with credentials: true is invalid. ' + 'Specify explicit origin(s) or set credentials: false.');
154
+ }
155
+ if (corsOrigin !== undefined) {
156
+ const originStr = renderCorsOrigin(corsOrigin);
157
+ lines.push(`app.use('*', cors({ origin: ${originStr}, ${CORS_ALLOW} }))`);
158
+ } else {
159
+ lines.push("app.use('*', cors({ origin: (origin) => {");
160
+ lines.push(' if (origin && /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/.test(origin)) return origin');
161
+ lines.push(' // In production, set middleware.corsOrigin explicitly');
162
+ lines.push(' return undefined');
163
+ lines.push(`}, ${CORS_ALLOW} }))`);
164
+ }
165
+ break;
166
+ }
167
+ case 'securityHeaders':
168
+ lines.push("app.use('*', secureHeaders())");
169
+ break;
170
+ case 'csp':
171
+ {
172
+ const cspConfig = mw.config?.csp;
173
+ if (cspConfig) {
174
+ const headerName = cspConfig.reportOnly ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy';
175
+ if (cspConfig.nonce) {
176
+ const basePolicy = cspConfig.policy || '';
177
+ const hasScriptSrc = /script-src/i.test(basePolicy);
178
+ const policyTemplate = hasScriptSrc ? basePolicy.replace(/script-src\s+([^;]*)/i, "script-src 'nonce-NONCE_PLACEHOLDER' $1") : basePolicy + "; script-src 'nonce-NONCE_PLACEHOLDER'";
179
+ lines.push(`// CSP with auto-nonce: generates a per-request nonce and adds it to script tags`);
180
+ lines.push(`app.use('*', async (c, next) => {`);
181
+ lines.push(` const nonce = crypto.randomUUID().replace(/-/g, '')`);
182
+ lines.push(` c.set('cspNonce', nonce)`);
183
+ lines.push(` const policy = ${JSON.stringify(policyTemplate)}.replace('NONCE_PLACEHOLDER', nonce)`);
184
+ lines.push(` await next()`);
185
+ lines.push(` c.header('${headerName}', policy)`);
186
+ lines.push(`})`);
187
+ } else {
188
+ lines.push(`app.use('*', async (c, next) => {`);
189
+ lines.push(` await next()`);
190
+ lines.push(` c.header('${headerName}', ${JSON.stringify(cspConfig.policy)})`);
191
+ lines.push(`})`);
192
+ }
193
+ }
194
+ break;
195
+ }
196
+ }
197
+ lines.push('');
198
+ }
199
+ /**
200
+ * Render an API route using Hono's standard app.route().
201
+ */ export function renderApiRoute(lines, route) {
202
+ lines.push(`// API: ${route.path} (${route.filePath})`);
203
+ lines.push(`if (${route.varName}.default && typeof ${route.varName}.default.fetch === 'function') {`);
204
+ lines.push(` app.route('${route.path}', ${route.varName}.default)`);
205
+ lines.push(`} else if (typeof ${route.varName}.default === 'function') {`);
206
+ lines.push(` app.all('${route.path}', async (c) => {`);
207
+ lines.push(` return await ${route.varName}.default({`);
208
+ lines.push(` request: c.req.raw,`);
209
+ lines.push(` params: c.req.param() || {},`);
210
+ lines.push(` env: c.env || {},`);
211
+ lines.push(` platform: c.executionCtx,`);
212
+ lines.push(` })`);
213
+ lines.push(` })`);
214
+ lines.push(`} else {`);
215
+ lines.push(` throw new Error('API route ${route.path} must default-export a Hono app or a function (ctx) => Response')`);
216
+ lines.push(`}`);
217
+ lines.push('');
218
+ }
219
+ export function renderPageRoute(lines, route, renderers, docConfig, isSSG) {
220
+ const matchingRenderers = renderers.filter((r)=>{
221
+ if (r.scope === '/') return true;
222
+ return route.path === r.scope || route.path.startsWith(r.scope + '/');
223
+ });
224
+ lines.push(`// Page: ${route.path} (${route.filePath})`);
225
+ const pathStr = route.path.replace(/'/g, "\\'");
226
+ const tagNameExpr = routeTagNameExpr(route.varName, route.tagName);
227
+ const pageDefExpr = pageDefinitionExpr(route.varName);
228
+ const routeMeta = routeMetaExpr(route.varName);
229
+ const routeContext = `{ path: ${JSON.stringify(route.path)}, filePath: ${JSON.stringify(route.filePath)} }`;
230
+ lines.push(`// GET handler - renders the page with loader data`);
231
+ lines.push(`app.get('${pathStr}', async (c) => {`);
232
+ lines.push(` let __tag = ${tagNameExpr}`);
233
+ lines.push(` let __page = ${pageDefExpr}`);
234
+ lines.push(` let __params = {}`);
235
+ lines.push(` let __routeMeta = ${routeMeta}`);
236
+ lines.push(` const __routeContext = ${routeContext}`);
237
+ lines.push(` try {`);
238
+ lines.push(` __params = c.req.param() || {}`);
239
+ lines.push(` const __loadContext = {`);
240
+ lines.push(` params: __params,`);
241
+ lines.push(` request: c.req.raw,`);
242
+ lines.push(` env: c.env || {},`);
243
+ lines.push(` platform: (() => { try { return c.executionCtx } catch { return undefined } })(),`);
244
+ lines.push(` route: __routeContext,`);
245
+ lines.push(` }`);
246
+ lines.push(` const __data = typeof ${route.varName}.loader === "function" ? await ${route.varName}.loader(__loadContext) : undefined`);
247
+ lines.push(` let node = jsx(__tag, { ...__params, data: __data, __openElementActionData: undefined, __openElementParams: __params, __openElementRequest: c.req.raw, __openElementRoute: __routeContext, __openElementMeta: __routeMeta })`);
248
+ lines.push('');
249
+ const headExtrasExpr = isSSG ? '__headExtras' : JSON.stringify(docConfig.headExtras);
250
+ if (matchingRenderers.length > 0) {
251
+ lines.push(` // Renderer tree wrapping (outer -> inner)`);
252
+ for (const renderer of matchingRenderers){
253
+ lines.push(` node = await ${renderer.varName}.default.wrap(node, c)`);
254
+ }
255
+ }
256
+ lines.push(` const content = await __renderAppShell(node, c.req.path || ${JSON.stringify(route.path)}, { routeMeta: __routeMeta })`);
257
+ lines.push(` return c.html(wrapInDocument(content, {`);
258
+ lines.push(` title: __page.head?.title || ${JSON.stringify(docConfig.title)},`);
259
+ lines.push(` lang: ${JSON.stringify(docConfig.lang)},`);
260
+ lines.push(` meta: { description: __page.head?.description, tags: __page.head?.meta },`);
261
+ lines.push(` headExtras: ${headExtrasExpr},`);
262
+ lines.push(` dangerouslyHeadFragments: __page.head?.dangerouslyHeadFragments || [],`);
263
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(docConfig.allowHeadExtrasScripts)},`);
264
+ lines.push(` cspNonce: c.get('cspNonce'),`);
265
+ lines.push(` }))`);
266
+ lines.push(` } catch (err) {`);
267
+ lines.push(` if (__isOpenElementRedirect(err)) {`);
268
+ lines.push(` return c.redirect(err.location, err.status)`);
269
+ lines.push(` }`);
270
+ lines.push(` if (__isOpenElementNotFound(err)) {`);
271
+ lines.push(` return c.html(wrapInDocument(__statusHtml("404 Not Found", err.message || "Not Found"), {`);
272
+ lines.push(` title: "404 Not Found",`);
273
+ lines.push(` lang: ${JSON.stringify(docConfig.lang)},`);
274
+ lines.push(` headExtras: ${headExtrasExpr},`);
275
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(docConfig.allowHeadExtrasScripts)},`);
276
+ lines.push(` cspNonce: c.get('cspNonce'),`);
277
+ lines.push(` }), 404)`);
278
+ lines.push(` }`);
279
+ lines.push(` if (typeof __page.error === "function") {`);
280
+ lines.push(` try {`);
281
+ lines.push(` const errorNode = jsx(__tag, { ...__params, __openElementParams: __params, __openElementError: err, __openElementRequest: c.req.raw, __openElementRoute: __routeContext, __openElementMeta: __routeMeta })`);
282
+ lines.push(` const errorContent = await __renderAppShell(errorNode, c.req.path || ${JSON.stringify(route.path)}, { routeMeta: __routeMeta })`);
283
+ lines.push(` return c.html(wrapInDocument(errorContent, {`);
284
+ lines.push(` title: __page.head?.title || ${JSON.stringify(docConfig.title)},`);
285
+ lines.push(` lang: ${JSON.stringify(docConfig.lang)},`);
286
+ lines.push(` meta: { description: __page.head?.description, tags: __page.head?.meta },`);
287
+ lines.push(` headExtras: ${headExtrasExpr},`);
288
+ lines.push(` dangerouslyHeadFragments: __page.head?.dangerouslyHeadFragments || [],`);
289
+ lines.push(` allowHeadExtrasScripts: ${JSON.stringify(docConfig.allowHeadExtrasScripts)},`);
290
+ lines.push(` cspNonce: c.get('cspNonce'),`);
291
+ lines.push(` }), 500)`);
292
+ lines.push(` } catch (errorRenderFailure) {`);
293
+ lines.push(` console.error('[openElement] Route error renderer failed for ${pathStr}:', errorRenderFailure)`);
294
+ lines.push(` }`);
295
+ lines.push(` }`);
296
+ lines.push(` console.error('[openElement] Route render failed for ${pathStr}:', err)`);
297
+ lines.push(` if (import.meta.env.PROD) {`);
298
+ lines.push(` return c.html('<h1>500 Internal Server Error</h1>', 500)`);
299
+ lines.push(` } else {`);
300
+ lines.push(` const safeErr = escapeHtml(String(err.stack || err))`);
301
+ lines.push(` return c.html('<h1>500</h1><pre>' + safeErr + '</pre>', 500)`);
302
+ lines.push(` }`);
303
+ lines.push(` }`);
304
+ lines.push(`})`);
305
+ lines.push('');
306
+ }
307
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9zc2cvc3JjL2VudHJ5LXJlbmRlci1oZWxwZXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG9wZW5lbGVtZW50L3NzZyAtIEVudHJ5IHJlbmRlcmVyIGhlbHBlciBmdW5jdGlvbnNcbiAqXG4gKiBTaGFyZWQgY29kZS1nZW5lcmF0aW9uIGhlbHBlciBmdW5jdGlvbnMgdXNlZCBieSBlbnRyeS1yZW5kZXJlci50c1xuICogYW5kIGl0cyBzdWItbW9kdWxlcyAoZW50cnktcmVuZGVyLXJ1bnRpbWUudHMsIGVudHJ5LXJlbmRlci1zc2cudHMpLlxuICpcbiAqIEVhY2ggZnVuY3Rpb24gZ2VuZXJhdGVzIGEgZnJhZ21lbnQgb2YgdGhlIHZpcnR1YWwgSG9ubyBlbnRyeSBtb2R1bGUuXG4gKi9cblxuaW1wb3J0IHR5cGUge1xuICBBcGlSb3V0ZURlY2wsXG4gIENvcnNPcmlnaW5Db25maWcsXG4gIEltcG9ydERlY2wsXG4gIE1pZGRsZXdhcmVEZWNsLFxuICBQYWdlUm91dGVEZWNsLFxuICBSZW5kZXJlckRlY2wsXG59IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9zc2cnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVySW1wb3J0KGltcDogSW1wb3J0RGVjbCk6IHN0cmluZyB7XG4gIGNvbnN0IG5hbWVzID0gaW1wLmFsaWFzID8gYCR7aW1wLm5hbWVzWzBdfSBhcyAke2ltcC5hbGlhc31gIDogaW1wLm5hbWVzLmpvaW4oJywgJyk7XG4gIHJldHVybiBgaW1wb3J0IHsgJHtuYW1lc30gfSBmcm9tICcke2ltcC5mcm9tfSdgO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcm91dGVUYWdOYW1lRXhwcih2YXJOYW1lOiBzdHJpbmcsIGZhbGxiYWNrOiBzdHJpbmcpOiBzdHJpbmcge1xuICB2b2lkIHZhck5hbWU7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShmYWxsYmFjayk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYWdlRGVmaW5pdGlvbkV4cHIodmFyTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAoJHt2YXJOYW1lfS5kZWZhdWx0Py5vcGVuRWxlbWVudFBhZ2UgfHwge30pYDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdXRlTWV0YUV4cHIodmFyTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFnZURlZiA9IHBhZ2VEZWZpbml0aW9uRXhwcih2YXJOYW1lKTtcbiAgcmV0dXJuIGAoeyAuLi4oJHtwYWdlRGVmfS5yb3V0ZSAhPT0gdW5kZWZpbmVkID8geyByb3V0ZTogJHtwYWdlRGVmfS5yb3V0ZSB9IDoge30pLCAuLi4oJHtwYWdlRGVmfS5oZWFkPy50aXRsZSAhPT0gdW5kZWZpbmVkID8geyB0aXRsZTogJHtwYWdlRGVmfS5oZWFkLnRpdGxlIH0gOiB7fSksIC4uLigke3BhZ2VEZWZ9LmhlYWQ/LmRlc2NyaXB0aW9uICE9PSB1bmRlZmluZWQgPyB7IGRlc2NyaXB0aW9uOiAke3BhZ2VEZWZ9LmhlYWQuZGVzY3JpcHRpb24gfSA6IHt9KSB9KWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByb3V0ZVJldmFsaWRhdGVFeHByKHZhck5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBhZ2VEZWYgPSBwYWdlRGVmaW5pdGlvbkV4cHIodmFyTmFtZSk7XG4gIHJldHVybiBgKCR7cGFnZURlZn0ucmVuZGVySW50ZW50Py5yZXZhbGlkYXRlID8/IGZhbHNlKWA7XG59XG5cbi8qKiBHZW5lcmF0ZSBhIFBPU1QgaGFuZGxlciBmb3IgYSBwYWdlIHJvdXRlIChmb3JtIGFjdGlvbiBoYW5kbGluZykuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyQWN0aW9uUm91dGUoXG4gIGxpbmVzOiBzdHJpbmdbXSxcbiAgcm91dGU6IFBhZ2VSb3V0ZURlY2wsXG4gIHJlbmRlcmVyczogUmVuZGVyZXJEZWNsW10sXG4gIGRvY0NvbmZpZzoge1xuICAgIHRpdGxlOiBzdHJpbmc7XG4gICAgbGFuZzogc3RyaW5nO1xuICAgIGhlYWRFeHRyYXM6IHN0cmluZztcbiAgICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiBib29sZWFuO1xuICB9LFxuICBpc1NTRzogYm9vbGVhbixcbik6IHZvaWQge1xuICBjb25zdCBtYXRjaGluZ1JlbmRlcmVycyA9IHJlbmRlcmVycy5maWx0ZXIoKHIpID0+IHtcbiAgICBpZiAoci5zY29wZSA9PT0gJy8nKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gcm91dGUucGF0aCA9PT0gci5zY29wZSB8fCByb3V0ZS5wYXRoLnN0YXJ0c1dpdGgoci5zY29wZSArICcvJyk7XG4gIH0pO1xuXG4gIGNvbnN0IHBhdGhTdHIgPSByb3V0ZS5wYXRoLnJlcGxhY2UoLycvZywgXCJcXFxcJ1wiKTtcbiAgY29uc3QgdGFnTmFtZUV4cHIgPSByb3V0ZVRhZ05hbWVFeHByKHJvdXRlLnZhck5hbWUsIHJvdXRlLnRhZ05hbWUpO1xuICBjb25zdCBwYWdlRGVmRXhwciA9IHBhZ2VEZWZpbml0aW9uRXhwcihyb3V0ZS52YXJOYW1lKTtcbiAgY29uc3Qgcm91dGVNZXRhID0gcm91dGVNZXRhRXhwcihyb3V0ZS52YXJOYW1lKTtcbiAgY29uc3Qgcm91dGVDb250ZXh0ID0gYHsgcGF0aDogJHtKU09OLnN0cmluZ2lmeShyb3V0ZS5wYXRoKX0sIGZpbGVQYXRoOiAke1xuICAgIEpTT04uc3RyaW5naWZ5KHJvdXRlLmZpbGVQYXRoKVxuICB9IH1gO1xuICBjb25zdCBoZWFkRXh0cmFzRXhwciA9IGlzU1NHID8gJ19faGVhZEV4dHJhcycgOiBKU09OLnN0cmluZ2lmeShkb2NDb25maWcuaGVhZEV4dHJhcyk7XG5cbiAgbGluZXMucHVzaChgLy8gQWN0aW9uIFBPU1Q6ICR7cm91dGUucGF0aH0gKCR7cm91dGUuZmlsZVBhdGh9KWApO1xuICBsaW5lcy5wdXNoKGBhcHAucG9zdCgnJHtwYXRoU3RyfScsIGFzeW5jIChjKSA9PiB7YCk7XG4gIGxpbmVzLnB1c2goYCAgbGV0IF9fdGFnID0gJHt0YWdOYW1lRXhwcn1gKTtcbiAgbGluZXMucHVzaChgICBsZXQgX19wYWdlID0gJHtwYWdlRGVmRXhwcn1gKTtcbiAgbGluZXMucHVzaChgICBsZXQgX19wYXJhbXMgPSB7fWApO1xuICBsaW5lcy5wdXNoKGAgIGxldCBfX3JvdXRlTWV0YSA9ICR7cm91dGVNZXRhfWApO1xuICBsaW5lcy5wdXNoKGAgIGNvbnN0IF9fcm91dGVDb250ZXh0ID0gJHtyb3V0ZUNvbnRleHR9YCk7XG4gIGxpbmVzLnB1c2goYCAgdHJ5IHtgKTtcbiAgbGluZXMucHVzaChgICAgIF9fcGFyYW1zID0gYy5yZXEucGFyYW0oKSB8fCB7fWApO1xuICBsaW5lcy5wdXNoKGAgICAgY29uc3QgX19sb2FkQ29udGV4dCA9IHtgKTtcbiAgbGluZXMucHVzaChgICAgICAgcGFyYW1zOiBfX3BhcmFtcyxgKTtcbiAgbGluZXMucHVzaChgICAgICAgcmVxdWVzdDogYy5yZXEucmF3LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICBlbnY6IGMuZW52IHx8IHt9LGApO1xuICBsaW5lcy5wdXNoKFxuICAgIGAgICAgICBwbGF0Zm9ybTogKCgpID0+IHsgdHJ5IHsgcmV0dXJuIGMuZXhlY3V0aW9uQ3R4IH0gY2F0Y2ggeyByZXR1cm4gdW5kZWZpbmVkIH0gfSkoKSxgLFxuICApO1xuICBsaW5lcy5wdXNoKGAgICAgICByb3V0ZTogX19yb3V0ZUNvbnRleHQsYCk7XG4gIGxpbmVzLnB1c2goYCAgICB9YCk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICBjb25zdCBfX2RhdGEgPSB0eXBlb2YgJHtyb3V0ZS52YXJOYW1lfS5sb2FkZXIgPT09IFwiZnVuY3Rpb25cIiA/IGF3YWl0ICR7cm91dGUudmFyTmFtZX0ubG9hZGVyKF9fbG9hZENvbnRleHQpIDogdW5kZWZpbmVkYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgIGNvbnN0IF9fZm9ybURhdGEgPSBhd2FpdCBjLnJlcS5wYXJzZUJvZHkoKWApO1xuICBsaW5lcy5wdXNoKGAgICAgY29uc3QgX19hY3Rpb25DdHggPSB7IC4uLl9fbG9hZENvbnRleHQsIGZvcm1EYXRhOiBfX2Zvcm1EYXRhIH1gKTtcbiAgbGluZXMucHVzaChcbiAgICBgICAgIGNvbnN0IF9fYWN0aW9uRGF0YSA9IHR5cGVvZiAke3JvdXRlLnZhck5hbWV9LmFjdGlvbiA9PT0gXCJmdW5jdGlvblwiID8gYXdhaXQgJHtyb3V0ZS52YXJOYW1lfS5hY3Rpb24oX19hY3Rpb25DdHgpIDogdW5kZWZpbmVkYCxcbiAgKTtcbiAgbGluZXMucHVzaChcbiAgICBgICAgIGxldCBub2RlID0ganN4KF9fdGFnLCB7IC4uLl9fcGFyYW1zLCBkYXRhOiBfX2RhdGEsIF9fb3BlbkVsZW1lbnRBY3Rpb25EYXRhOiBfX2FjdGlvbkRhdGEsIF9fb3BlbkVsZW1lbnRQYXJhbXM6IF9fcGFyYW1zLCBfX29wZW5FbGVtZW50UmVxdWVzdDogYy5yZXEucmF3LCBfX29wZW5FbGVtZW50Um91dGU6IF9fcm91dGVDb250ZXh0LCBfX29wZW5FbGVtZW50TWV0YTogX19yb3V0ZU1ldGEgfSlgLFxuICApO1xuICBsaW5lcy5wdXNoKGBgKTtcblxuICBpZiAobWF0Y2hpbmdSZW5kZXJlcnMubGVuZ3RoID4gMCkge1xuICAgIGxpbmVzLnB1c2goYCAgICAvLyBSZW5kZXJlciB0cmVlIHdyYXBwaW5nIChvdXRlciAtPiBpbm5lcilgKTtcbiAgICBmb3IgKGNvbnN0IHJlbmRlcmVyIG9mIG1hdGNoaW5nUmVuZGVyZXJzKSB7XG4gICAgICBsaW5lcy5wdXNoKGAgICAgbm9kZSA9IGF3YWl0ICR7cmVuZGVyZXIudmFyTmFtZX0uZGVmYXVsdC53cmFwKG5vZGUsIGMpYCk7XG4gICAgfVxuICB9XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgX19yZW5kZXJBcHBTaGVsbChub2RlLCBjLnJlcS5wYXRoIHx8ICR7XG4gICAgICBKU09OLnN0cmluZ2lmeShyb3V0ZS5wYXRoKVxuICAgIH0sIHsgcm91dGVNZXRhOiBfX3JvdXRlTWV0YSB9KWAsXG4gICk7XG4gIGxpbmVzLnB1c2goYCAgICByZXR1cm4gYy5odG1sKHdyYXBJbkRvY3VtZW50KGNvbnRlbnQsIHtgKTtcbiAgbGluZXMucHVzaChgICAgICAgdGl0bGU6IF9fcGFnZS5oZWFkPy50aXRsZSB8fCAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy50aXRsZSl9LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICBsYW5nOiAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy5sYW5nKX0sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIG1ldGE6IHsgZGVzY3JpcHRpb246IF9fcGFnZS5oZWFkPy5kZXNjcmlwdGlvbiwgdGFnczogX19wYWdlLmhlYWQ/Lm1ldGEgfSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgaGVhZEV4dHJhczogJHtoZWFkRXh0cmFzRXhwcn0sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIGRhbmdlcm91c2x5SGVhZEZyYWdtZW50czogX19wYWdlLmhlYWQ/LmRhbmdlcm91c2x5SGVhZEZyYWdtZW50cyB8fCBbXSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgYWxsb3dIZWFkRXh0cmFzU2NyaXB0czogJHtKU09OLnN0cmluZ2lmeShkb2NDb25maWcuYWxsb3dIZWFkRXh0cmFzU2NyaXB0cyl9LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICBjc3BOb25jZTogYy5nZXQoJ2NzcE5vbmNlJyksYCk7XG4gIGxpbmVzLnB1c2goYCAgICB9KSlgKTtcbiAgbGluZXMucHVzaChgICB9IGNhdGNoIChlcnIpIHtgKTtcbiAgbGluZXMucHVzaChgICAgIGlmIChfX2lzT3BlbkVsZW1lbnRSZWRpcmVjdChlcnIpKSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHJldHVybiBjLnJlZGlyZWN0KGVyci5sb2NhdGlvbiwgZXJyLnN0YXR1cylgKTtcbiAgbGluZXMucHVzaChgICAgIH1gKTtcbiAgbGluZXMucHVzaChgICAgIGlmIChfX2lzT3BlbkVsZW1lbnROb3RGb3VuZChlcnIpKSB7YCk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgIHJldHVybiBjLmh0bWwod3JhcEluRG9jdW1lbnQoX19zdGF0dXNIdG1sKFwiNDA0IE5vdCBGb3VuZFwiLCBlcnIubWVzc2FnZSB8fCBcIk5vdCBGb3VuZFwiKSwge2AsXG4gICk7XG4gIGxpbmVzLnB1c2goYCAgICAgICAgdGl0bGU6IFwiNDA0IE5vdCBGb3VuZFwiLGApO1xuICBsaW5lcy5wdXNoKGAgICAgICAgIGxhbmc6ICR7SlNPTi5zdHJpbmdpZnkoZG9jQ29uZmlnLmxhbmcpfSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgICBoZWFkRXh0cmFzOiAke2hlYWRFeHRyYXNFeHByfSxgKTtcbiAgbGluZXMucHVzaChcbiAgICBgICAgICAgICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy5hbGxvd0hlYWRFeHRyYXNTY3JpcHRzKX0sYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgICBjc3BOb25jZTogYy5nZXQoJ2NzcE5vbmNlJyksYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIH0pLCA0MDQpYCk7XG4gIGxpbmVzLnB1c2goYCAgICB9YCk7XG4gIGxpbmVzLnB1c2goYCAgICBjb25zb2xlLmVycm9yKCdbb3BlbkVsZW1lbnRdIEFjdGlvbiBQT1NUIGZhaWxlZCBmb3IgJHtwYXRoU3RyfTonLCBlcnIpYCk7XG4gIGxpbmVzLnB1c2goYCAgICBpZiAoaW1wb3J0Lm1ldGEuZW52LlBST0QpIHtgKTtcbiAgbGluZXMucHVzaChgICAgICAgcmV0dXJuIGMuaHRtbCgnPGgxPjUwMCBJbnRlcm5hbCBTZXJ2ZXIgRXJyb3I8L2gxPicsIDUwMClgKTtcbiAgbGluZXMucHVzaChgICAgIH0gZWxzZSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIGNvbnN0IHNhZmVFcnIgPSBlc2NhcGVIdG1sKFN0cmluZyhlcnIuc3RhY2sgfHwgZXJyKSlgKTtcbiAgbGluZXMucHVzaChgICAgICAgcmV0dXJuIGMuaHRtbCgnPGgxPjUwMDwvaDE+PHByZT4nICsgc2FmZUVyciArICc8L3ByZT4nLCA1MDApYCk7XG4gIGxpbmVzLnB1c2goYCAgICB9YCk7XG4gIGxpbmVzLnB1c2goYCAgfWApO1xuICBsaW5lcy5wdXNoKGB9KWApO1xuICBsaW5lcy5wdXNoKCcnKTtcbn1cblxuLyoqIEdlbmVyYXRlIHRoZSByb3V0ZS10by1tb2R1bGUgbWFwIGZvciAvX2RhdGEgZW5kcG9pbnQuICovXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyRGF0YVJvdXRlTWFwKFxuICBsaW5lczogc3RyaW5nW10sXG4gIHBhZ2VSb3V0ZXM6IFBhZ2VSb3V0ZURlY2xbXSxcbik6IHZvaWQge1xuICBsaW5lcy5wdXNoKCcvLyBSb3V0ZS10by1tb2R1bGUgbWFwIGZvciAvX2RhdGEgZW5kcG9pbnQgKFNQQSBjbGllbnQgbmF2aWdhdGlvbiknKTtcbiAgbGluZXMucHVzaCgnY29uc3QgX19kYXRhUm91dGVNYXAgPSB7Jyk7XG4gIGZvciAoY29uc3QgciBvZiBwYWdlUm91dGVzKSB7XG4gICAgbGluZXMucHVzaChgICAke0pTT04uc3RyaW5naWZ5KHIucGF0aCl9OiAke3IudmFyTmFtZX0sYCk7XG4gIH1cbiAgbGluZXMucHVzaCgnfTsnKTtcbiAgbGluZXMucHVzaCgnJyk7XG59XG5cbi8qKiBHZW5lcmF0ZSB0aGUgL19kYXRhIEdFVCBlbmRwb2ludCBmb3IgU1BBIG5hdmlnYXRpb24gZGF0YSBmZXRjaGluZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJEYXRhRW5kcG9pbnQobGluZXM6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGxpbmVzLnB1c2goJy8vIC9fZGF0YSBlbmRwb2ludCAtIHJldHVybnMgSlNPTiBsb2FkZXIgZGF0YSBmb3IgU1BBIG5hdmlnYXRpb24nKTtcbiAgbGluZXMucHVzaChgYXBwLmdldCgnL19kYXRhJywgYXN5bmMgKGMpID0+IHtgKTtcbiAgbGluZXMucHVzaChgICBjb25zdCByb3V0ZVBhdGggPSBjLnJlcS5xdWVyeSgncm91dGUnKTtgKTtcbiAgbGluZXMucHVzaChgICBpZiAoIXJvdXRlUGF0aCkgcmV0dXJuIGMuanNvbih7IGVycm9yOiAnTWlzc2luZyByb3V0ZSBxdWVyeScgfSwgNDAwKTtgKTtcbiAgbGluZXMucHVzaChgICBjb25zdCBtb2QgPSBfX2RhdGFSb3V0ZU1hcFtyb3V0ZVBhdGhdO2ApO1xuICBsaW5lcy5wdXNoKGAgIGlmICghbW9kKSByZXR1cm4gYy5qc29uKHsgZXJyb3I6ICdSb3V0ZSBub3QgZm91bmQnIH0sIDQwNCk7YCk7XG4gIGxpbmVzLnB1c2goYCAgaWYgKHR5cGVvZiBtb2QubG9hZGVyICE9PSAnZnVuY3Rpb24nKSByZXR1cm4gYy5qc29uKHsgZGF0YTogbnVsbCB9KTtgKTtcbiAgbGluZXMucHVzaChgICB0cnkge2ApO1xuICBsaW5lcy5wdXNoKGAgICAgY29uc3QgbG9hZENvbnRleHQgPSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHBhcmFtczoge30sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHJlcXVlc3Q6IGMucmVxLnJhdyxgKTtcbiAgbGluZXMucHVzaChgICAgICAgZW52OiBjLmVudiB8fCB7fSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgcGxhdGZvcm06IHVuZGVmaW5lZCxgKTtcbiAgbGluZXMucHVzaChgICAgICAgcm91dGU6IHsgcGF0aDogcm91dGVQYXRoLCBmaWxlUGF0aDogJycgfSxgKTtcbiAgbGluZXMucHVzaChgICAgIH07YCk7XG4gIGxpbmVzLnB1c2goYCAgICBjb25zdCBkYXRhID0gYXdhaXQgbW9kLmxvYWRlcihsb2FkQ29udGV4dCk7YCk7XG4gIGxpbmVzLnB1c2goYCAgICByZXR1cm4gYy5qc29uKHsgZGF0YSB9KTtgKTtcbiAgbGluZXMucHVzaChgICB9IGNhdGNoIChlcnIpIHtgKTtcbiAgbGluZXMucHVzaChgICAgIHJldHVybiBjLmpzb24oeyBlcnJvcjogU3RyaW5nKGVycikgfSwgNTAwKTtgKTtcbiAgbGluZXMucHVzaChgICB9YCk7XG4gIGxpbmVzLnB1c2goYH0pYCk7XG4gIGxpbmVzLnB1c2goJycpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJDb3JzT3JpZ2luKG9yaWdpbjogQ29yc09yaWdpbkNvbmZpZyk6IHN0cmluZyB7XG4gIGlmICh0eXBlb2Ygb3JpZ2luID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShvcmlnaW4pKSByZXR1cm4gb3JpZ2luLmJvZHk7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShvcmlnaW4pO1xufVxuXG5jb25zdCBDT1JTX0FMTE9XID1cbiAgXCJhbGxvd01ldGhvZHM6IFsnR0VUJywgJ1BPU1QnLCAnUFVUJywgJ0RFTEVURScsICdQQVRDSCddLCBhbGxvd0hlYWRlcnM6IFsnQ29udGVudC1UeXBlJywgJ0F1dGhvcml6YXRpb24nXSwgY3JlZGVudGlhbHM6IHRydWUsIG1heEFnZTogODY0MDBcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlck1pZGRsZXdhcmUobGluZXM6IHN0cmluZ1tdLCBtdzogTWlkZGxld2FyZURlY2wpOiB2b2lkIHtcbiAgaWYgKG13LmNvbW1lbnQpIHtcbiAgICBsaW5lcy5wdXNoKGAvLyAke213LmNvbW1lbnR9YCk7XG4gIH1cblxuICBzd2l0Y2ggKG13LmtpbmQpIHtcbiAgICBjYXNlICdyZXF1ZXN0SWQnOlxuICAgICAgbGluZXMucHVzaChcImFwcC51c2UoJyonLCByZXF1ZXN0SWQoKSlcIik7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2xvZ2dlcic6XG4gICAgICBsaW5lcy5wdXNoKFwiYXBwLnVzZSgnKicsIGhvbm9Mb2dnZXIoKSlcIik7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2NvcnMnOiB7XG4gICAgICBjb25zdCBjb3JzT3JpZ2luID0gbXcuY29uZmlnPy5jb3JzT3JpZ2luO1xuICAgICAgaWYgKGNvcnNPcmlnaW4gPT09ICcqJyB8fCAoQXJyYXkuaXNBcnJheShjb3JzT3JpZ2luKSAmJiBjb3JzT3JpZ2luLmluY2x1ZGVzKCcqJykpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnQ09SUyBtaXNjb25maWd1cmF0aW9uOiBvcmlnaW4gXCIqXCIgd2l0aCBjcmVkZW50aWFsczogdHJ1ZSBpcyBpbnZhbGlkLiAnICtcbiAgICAgICAgICAgICdTcGVjaWZ5IGV4cGxpY2l0IG9yaWdpbihzKSBvciBzZXQgY3JlZGVudGlhbHM6IGZhbHNlLicsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoY29yc09yaWdpbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IG9yaWdpblN0ciA9IHJlbmRlckNvcnNPcmlnaW4oY29yc09yaWdpbik7XG4gICAgICAgIGxpbmVzLnB1c2goXG4gICAgICAgICAgYGFwcC51c2UoJyonLCBjb3JzKHsgb3JpZ2luOiAke29yaWdpblN0cn0sICR7Q09SU19BTExPV30gfSkpYCxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxpbmVzLnB1c2goXCJhcHAudXNlKCcqJywgY29ycyh7IG9yaWdpbjogKG9yaWdpbikgPT4ge1wiKTtcbiAgICAgICAgbGluZXMucHVzaChcbiAgICAgICAgICAnICBpZiAob3JpZ2luICYmIC9eaHR0cHM/OlxcXFwvXFxcXC8obG9jYWxob3N0fDEyN1xcXFwuMFxcXFwuMFxcXFwuMSkoOlxcXFxkKyk/JC8udGVzdChvcmlnaW4pKSByZXR1cm4gb3JpZ2luJyxcbiAgICAgICAgKTtcbiAgICAgICAgbGluZXMucHVzaCgnICAvLyBJbiBwcm9kdWN0aW9uLCBzZXQgbWlkZGxld2FyZS5jb3JzT3JpZ2luIGV4cGxpY2l0bHknKTtcbiAgICAgICAgbGluZXMucHVzaCgnICByZXR1cm4gdW5kZWZpbmVkJyk7XG4gICAgICAgIGxpbmVzLnB1c2goYH0sICR7Q09SU19BTExPV30gfSkpYCk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBjYXNlICdzZWN1cml0eUhlYWRlcnMnOlxuICAgICAgbGluZXMucHVzaChcImFwcC51c2UoJyonLCBzZWN1cmVIZWFkZXJzKCkpXCIpO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdjc3AnOiB7XG4gICAgICBjb25zdCBjc3BDb25maWcgPSBtdy5jb25maWc/LmNzcDtcbiAgICAgIGlmIChjc3BDb25maWcpIHtcbiAgICAgICAgY29uc3QgaGVhZGVyTmFtZSA9IGNzcENvbmZpZy5yZXBvcnRPbmx5XG4gICAgICAgICAgPyAnQ29udGVudC1TZWN1cml0eS1Qb2xpY3ktUmVwb3J0LU9ubHknXG4gICAgICAgICAgOiAnQ29udGVudC1TZWN1cml0eS1Qb2xpY3knO1xuICAgICAgICBpZiAoY3NwQ29uZmlnLm5vbmNlKSB7XG4gICAgICAgICAgY29uc3QgYmFzZVBvbGljeTogc3RyaW5nID0gY3NwQ29uZmlnLnBvbGljeSB8fCAnJztcbiAgICAgICAgICBjb25zdCBoYXNTY3JpcHRTcmMgPSAvc2NyaXB0LXNyYy9pLnRlc3QoYmFzZVBvbGljeSk7XG4gICAgICAgICAgY29uc3QgcG9saWN5VGVtcGxhdGUgPSBoYXNTY3JpcHRTcmNcbiAgICAgICAgICAgID8gYmFzZVBvbGljeS5yZXBsYWNlKFxuICAgICAgICAgICAgICAvc2NyaXB0LXNyY1xccysoW147XSopL2ksXG4gICAgICAgICAgICAgIFwic2NyaXB0LXNyYyAnbm9uY2UtTk9OQ0VfUExBQ0VIT0xERVInICQxXCIsXG4gICAgICAgICAgICApXG4gICAgICAgICAgICA6IGJhc2VQb2xpY3kgKyBcIjsgc2NyaXB0LXNyYyAnbm9uY2UtTk9OQ0VfUExBQ0VIT0xERVInXCI7XG4gICAgICAgICAgbGluZXMucHVzaChcbiAgICAgICAgICAgIGAvLyBDU1Agd2l0aCBhdXRvLW5vbmNlOiBnZW5lcmF0ZXMgYSBwZXItcmVxdWVzdCBub25jZSBhbmQgYWRkcyBpdCB0byBzY3JpcHQgdGFnc2AsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBsaW5lcy5wdXNoKGBhcHAudXNlKCcqJywgYXN5bmMgKGMsIG5leHQpID0+IHtgKTtcbiAgICAgICAgICBsaW5lcy5wdXNoKGAgIGNvbnN0IG5vbmNlID0gY3J5cHRvLnJhbmRvbVVVSUQoKS5yZXBsYWNlKC8tL2csICcnKWApO1xuICAgICAgICAgIGxpbmVzLnB1c2goYCAgYy5zZXQoJ2NzcE5vbmNlJywgbm9uY2UpYCk7XG4gICAgICAgICAgbGluZXMucHVzaChcbiAgICAgICAgICAgIGAgIGNvbnN0IHBvbGljeSA9ICR7XG4gICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHBvbGljeVRlbXBsYXRlKVxuICAgICAgICAgICAgfS5yZXBsYWNlKCdOT05DRV9QTEFDRUhPTERFUicsIG5vbmNlKWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBsaW5lcy5wdXNoKGAgIGF3YWl0IG5leHQoKWApO1xuICAgICAgICAgIGxpbmVzLnB1c2goYCAgYy5oZWFkZXIoJyR7aGVhZGVyTmFtZX0nLCBwb2xpY3kpYCk7XG4gICAgICAgICAgbGluZXMucHVzaChgfSlgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsaW5lcy5wdXNoKGBhcHAudXNlKCcqJywgYXN5bmMgKGMsIG5leHQpID0+IHtgKTtcbiAgICAgICAgICBsaW5lcy5wdXNoKGAgIGF3YWl0IG5leHQoKWApO1xuICAgICAgICAgIGxpbmVzLnB1c2goXG4gICAgICAgICAgICBgICBjLmhlYWRlcignJHtoZWFkZXJOYW1lfScsICR7SlNPTi5zdHJpbmdpZnkoY3NwQ29uZmlnLnBvbGljeSl9KWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBsaW5lcy5wdXNoKGB9KWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBsaW5lcy5wdXNoKCcnKTtcbn1cblxuLyoqXG4gKiBSZW5kZXIgYW4gQVBJIHJvdXRlIHVzaW5nIEhvbm8ncyBzdGFuZGFyZCBhcHAucm91dGUoKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlckFwaVJvdXRlKGxpbmVzOiBzdHJpbmdbXSwgcm91dGU6IEFwaVJvdXRlRGVjbCk6IHZvaWQge1xuICBsaW5lcy5wdXNoKGAvLyBBUEk6ICR7cm91dGUucGF0aH0gKCR7cm91dGUuZmlsZVBhdGh9KWApO1xuICBsaW5lcy5wdXNoKFxuICAgIGBpZiAoJHtyb3V0ZS52YXJOYW1lfS5kZWZhdWx0ICYmIHR5cGVvZiAke3JvdXRlLnZhck5hbWV9LmRlZmF1bHQuZmV0Y2ggPT09ICdmdW5jdGlvbicpIHtgLFxuICApO1xuICBsaW5lcy5wdXNoKGAgIGFwcC5yb3V0ZSgnJHtyb3V0ZS5wYXRofScsICR7cm91dGUudmFyTmFtZX0uZGVmYXVsdClgKTtcbiAgbGluZXMucHVzaChgfSBlbHNlIGlmICh0eXBlb2YgJHtyb3V0ZS52YXJOYW1lfS5kZWZhdWx0ID09PSAnZnVuY3Rpb24nKSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgYXBwLmFsbCgnJHtyb3V0ZS5wYXRofScsIGFzeW5jIChjKSA9PiB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICByZXR1cm4gYXdhaXQgJHtyb3V0ZS52YXJOYW1lfS5kZWZhdWx0KHtgKTtcbiAgbGluZXMucHVzaChgICAgICAgcmVxdWVzdDogYy5yZXEucmF3LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICBwYXJhbXM6IGMucmVxLnBhcmFtKCkgfHwge30sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIGVudjogYy5lbnYgfHwge30sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHBsYXRmb3JtOiBjLmV4ZWN1dGlvbkN0eCxgKTtcbiAgbGluZXMucHVzaChgICAgIH0pYCk7XG4gIGxpbmVzLnB1c2goYCAgfSlgKTtcbiAgbGluZXMucHVzaChgfSBlbHNlIHtgKTtcbiAgbGluZXMucHVzaChcbiAgICBgICB0aHJvdyBuZXcgRXJyb3IoJ0FQSSByb3V0ZSAke3JvdXRlLnBhdGh9IG11c3QgZGVmYXVsdC1leHBvcnQgYSBIb25vIGFwcCBvciBhIGZ1bmN0aW9uIChjdHgpID0+IFJlc3BvbnNlJylgLFxuICApO1xuICBsaW5lcy5wdXNoKGB9YCk7XG4gIGxpbmVzLnB1c2goJycpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyUGFnZVJvdXRlKFxuICBsaW5lczogc3RyaW5nW10sXG4gIHJvdXRlOiBQYWdlUm91dGVEZWNsLFxuICByZW5kZXJlcnM6IFJlbmRlcmVyRGVjbFtdLFxuICBkb2NDb25maWc6IHtcbiAgICB0aXRsZTogc3RyaW5nO1xuICAgIGxhbmc6IHN0cmluZztcbiAgICBoZWFkRXh0cmFzOiBzdHJpbmc7XG4gICAgYWxsb3dIZWFkRXh0cmFzU2NyaXB0czogYm9vbGVhbjtcbiAgfSxcbiAgaXNTU0c6IGJvb2xlYW4sXG4pOiB2b2lkIHtcbiAgY29uc3QgbWF0Y2hpbmdSZW5kZXJlcnMgPSByZW5kZXJlcnMuZmlsdGVyKChyKSA9PiB7XG4gICAgaWYgKHIuc2NvcGUgPT09ICcvJykgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIHJvdXRlLnBhdGggPT09IHIuc2NvcGUgfHwgcm91dGUucGF0aC5zdGFydHNXaXRoKHIuc2NvcGUgKyAnLycpO1xuICB9KTtcblxuICBsaW5lcy5wdXNoKGAvLyBQYWdlOiAke3JvdXRlLnBhdGh9ICgke3JvdXRlLmZpbGVQYXRofSlgKTtcbiAgY29uc3QgcGF0aFN0ciA9IHJvdXRlLnBhdGgucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpO1xuICBjb25zdCB0YWdOYW1lRXhwciA9IHJvdXRlVGFnTmFtZUV4cHIocm91dGUudmFyTmFtZSwgcm91dGUudGFnTmFtZSk7XG4gIGNvbnN0IHBhZ2VEZWZFeHByID0gcGFnZURlZmluaXRpb25FeHByKHJvdXRlLnZhck5hbWUpO1xuICBjb25zdCByb3V0ZU1ldGEgPSByb3V0ZU1ldGFFeHByKHJvdXRlLnZhck5hbWUpO1xuICBjb25zdCByb3V0ZUNvbnRleHQgPSBgeyBwYXRoOiAke0pTT04uc3RyaW5naWZ5KHJvdXRlLnBhdGgpfSwgZmlsZVBhdGg6ICR7XG4gICAgSlNPTi5zdHJpbmdpZnkocm91dGUuZmlsZVBhdGgpXG4gIH0gfWA7XG4gIGxpbmVzLnB1c2goYC8vIEdFVCBoYW5kbGVyIC0gcmVuZGVycyB0aGUgcGFnZSB3aXRoIGxvYWRlciBkYXRhYCk7XG4gIGxpbmVzLnB1c2goYGFwcC5nZXQoJyR7cGF0aFN0cn0nLCBhc3luYyAoYykgPT4ge2ApO1xuICBsaW5lcy5wdXNoKGAgIGxldCBfX3RhZyA9ICR7dGFnTmFtZUV4cHJ9YCk7XG4gIGxpbmVzLnB1c2goYCAgbGV0IF9fcGFnZSA9ICR7cGFnZURlZkV4cHJ9YCk7XG4gIGxpbmVzLnB1c2goYCAgbGV0IF9fcGFyYW1zID0ge31gKTtcbiAgbGluZXMucHVzaChgICBsZXQgX19yb3V0ZU1ldGEgPSAke3JvdXRlTWV0YX1gKTtcbiAgbGluZXMucHVzaChgICBjb25zdCBfX3JvdXRlQ29udGV4dCA9ICR7cm91dGVDb250ZXh0fWApO1xuICBsaW5lcy5wdXNoKGAgIHRyeSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICBfX3BhcmFtcyA9IGMucmVxLnBhcmFtKCkgfHwge31gKTtcbiAgbGluZXMucHVzaChgICAgIGNvbnN0IF9fbG9hZENvbnRleHQgPSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHBhcmFtczogX19wYXJhbXMsYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHJlcXVlc3Q6IGMucmVxLnJhdyxgKTtcbiAgbGluZXMucHVzaChgICAgICAgZW52OiBjLmVudiB8fCB7fSxgKTtcbiAgbGluZXMucHVzaChcbiAgICBgICAgICAgcGxhdGZvcm06ICgoKSA9PiB7IHRyeSB7IHJldHVybiBjLmV4ZWN1dGlvbkN0eCB9IGNhdGNoIHsgcmV0dXJuIHVuZGVmaW5lZCB9IH0pKCksYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgcm91dGU6IF9fcm91dGVDb250ZXh0LGApO1xuICBsaW5lcy5wdXNoKGAgICAgfWApO1xuICBsaW5lcy5wdXNoKFxuICAgIGAgICAgY29uc3QgX19kYXRhID0gdHlwZW9mICR7cm91dGUudmFyTmFtZX0ubG9hZGVyID09PSBcImZ1bmN0aW9uXCIgPyBhd2FpdCAke3JvdXRlLnZhck5hbWV9LmxvYWRlcihfX2xvYWRDb250ZXh0KSA6IHVuZGVmaW5lZGAsXG4gICk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICBsZXQgbm9kZSA9IGpzeChfX3RhZywgeyAuLi5fX3BhcmFtcywgZGF0YTogX19kYXRhLCBfX29wZW5FbGVtZW50QWN0aW9uRGF0YTogdW5kZWZpbmVkLCBfX29wZW5FbGVtZW50UGFyYW1zOiBfX3BhcmFtcywgX19vcGVuRWxlbWVudFJlcXVlc3Q6IGMucmVxLnJhdywgX19vcGVuRWxlbWVudFJvdXRlOiBfX3JvdXRlQ29udGV4dCwgX19vcGVuRWxlbWVudE1ldGE6IF9fcm91dGVNZXRhIH0pYCxcbiAgKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgY29uc3QgaGVhZEV4dHJhc0V4cHIgPSBpc1NTRyA/ICdfX2hlYWRFeHRyYXMnIDogSlNPTi5zdHJpbmdpZnkoZG9jQ29uZmlnLmhlYWRFeHRyYXMpO1xuXG4gIGlmIChtYXRjaGluZ1JlbmRlcmVycy5sZW5ndGggPiAwKSB7XG4gICAgbGluZXMucHVzaChgICAgIC8vIFJlbmRlcmVyIHRyZWUgd3JhcHBpbmcgKG91dGVyIC0+IGlubmVyKWApO1xuICAgIGZvciAoY29uc3QgcmVuZGVyZXIgb2YgbWF0Y2hpbmdSZW5kZXJlcnMpIHtcbiAgICAgIGxpbmVzLnB1c2goYCAgICBub2RlID0gYXdhaXQgJHtyZW5kZXJlci52YXJOYW1lfS5kZWZhdWx0LndyYXAobm9kZSwgYylgKTtcbiAgICB9XG4gIH1cbiAgbGluZXMucHVzaChcbiAgICBgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBfX3JlbmRlckFwcFNoZWxsKG5vZGUsIGMucmVxLnBhdGggfHwgJHtcbiAgICAgIEpTT04uc3RyaW5naWZ5KHJvdXRlLnBhdGgpXG4gICAgfSwgeyByb3V0ZU1ldGE6IF9fcm91dGVNZXRhIH0pYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgIHJldHVybiBjLmh0bWwod3JhcEluRG9jdW1lbnQoY29udGVudCwge2ApO1xuICBsaW5lcy5wdXNoKGAgICAgICB0aXRsZTogX19wYWdlLmhlYWQ/LnRpdGxlIHx8ICR7SlNPTi5zdHJpbmdpZnkoZG9jQ29uZmlnLnRpdGxlKX0sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIGxhbmc6ICR7SlNPTi5zdHJpbmdpZnkoZG9jQ29uZmlnLmxhbmcpfSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgbWV0YTogeyBkZXNjcmlwdGlvbjogX19wYWdlLmhlYWQ/LmRlc2NyaXB0aW9uLCB0YWdzOiBfX3BhZ2UuaGVhZD8ubWV0YSB9LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICBoZWFkRXh0cmFzOiAke2hlYWRFeHRyYXNFeHByfSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgZGFuZ2Vyb3VzbHlIZWFkRnJhZ21lbnRzOiBfX3BhZ2UuaGVhZD8uZGFuZ2Vyb3VzbHlIZWFkRnJhZ21lbnRzIHx8IFtdLGApO1xuICBsaW5lcy5wdXNoKFxuICAgIGAgICAgICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy5hbGxvd0hlYWRFeHRyYXNTY3JpcHRzKX0sYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgY3NwTm9uY2U6IGMuZ2V0KCdjc3BOb25jZScpLGApO1xuICBsaW5lcy5wdXNoKGAgICAgfSkpYCk7XG5cbiAgbGluZXMucHVzaChgICB9IGNhdGNoIChlcnIpIHtgKTtcbiAgbGluZXMucHVzaChgICAgIGlmIChfX2lzT3BlbkVsZW1lbnRSZWRpcmVjdChlcnIpKSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHJldHVybiBjLnJlZGlyZWN0KGVyci5sb2NhdGlvbiwgZXJyLnN0YXR1cylgKTtcbiAgbGluZXMucHVzaChgICAgIH1gKTtcbiAgbGluZXMucHVzaChgICAgIGlmIChfX2lzT3BlbkVsZW1lbnROb3RGb3VuZChlcnIpKSB7YCk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgIHJldHVybiBjLmh0bWwod3JhcEluRG9jdW1lbnQoX19zdGF0dXNIdG1sKFwiNDA0IE5vdCBGb3VuZFwiLCBlcnIubWVzc2FnZSB8fCBcIk5vdCBGb3VuZFwiKSwge2AsXG4gICk7XG4gIGxpbmVzLnB1c2goYCAgICAgICAgdGl0bGU6IFwiNDA0IE5vdCBGb3VuZFwiLGApO1xuICBsaW5lcy5wdXNoKGAgICAgICAgIGxhbmc6ICR7SlNPTi5zdHJpbmdpZnkoZG9jQ29uZmlnLmxhbmcpfSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgICBoZWFkRXh0cmFzOiAke2hlYWRFeHRyYXNFeHByfSxgKTtcbiAgbGluZXMucHVzaChcbiAgICBgICAgICAgICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy5hbGxvd0hlYWRFeHRyYXNTY3JpcHRzKX0sYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgICBjc3BOb25jZTogYy5nZXQoJ2NzcE5vbmNlJyksYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIH0pLCA0MDQpYCk7XG4gIGxpbmVzLnB1c2goYCAgICB9YCk7XG4gIGxpbmVzLnB1c2goYCAgICBpZiAodHlwZW9mIF9fcGFnZS5lcnJvciA9PT0gXCJmdW5jdGlvblwiKSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHRyeSB7YCk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgICAgY29uc3QgZXJyb3JOb2RlID0ganN4KF9fdGFnLCB7IC4uLl9fcGFyYW1zLCBfX29wZW5FbGVtZW50UGFyYW1zOiBfX3BhcmFtcywgX19vcGVuRWxlbWVudEVycm9yOiBlcnIsIF9fb3BlbkVsZW1lbnRSZXF1ZXN0OiBjLnJlcS5yYXcsIF9fb3BlbkVsZW1lbnRSb3V0ZTogX19yb3V0ZUNvbnRleHQsIF9fb3BlbkVsZW1lbnRNZXRhOiBfX3JvdXRlTWV0YSB9KWAsXG4gICk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgICAgY29uc3QgZXJyb3JDb250ZW50ID0gYXdhaXQgX19yZW5kZXJBcHBTaGVsbChlcnJvck5vZGUsIGMucmVxLnBhdGggfHwgJHtcbiAgICAgIEpTT04uc3RyaW5naWZ5KHJvdXRlLnBhdGgpXG4gICAgfSwgeyByb3V0ZU1ldGE6IF9fcm91dGVNZXRhIH0pYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgICByZXR1cm4gYy5odG1sKHdyYXBJbkRvY3VtZW50KGVycm9yQ29udGVudCwge2ApO1xuICBsaW5lcy5wdXNoKGAgICAgICAgICAgdGl0bGU6IF9fcGFnZS5oZWFkPy50aXRsZSB8fCAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy50aXRsZSl9LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICAgICAgbGFuZzogJHtKU09OLnN0cmluZ2lmeShkb2NDb25maWcubGFuZyl9LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICAgICAgbWV0YTogeyBkZXNjcmlwdGlvbjogX19wYWdlLmhlYWQ/LmRlc2NyaXB0aW9uLCB0YWdzOiBfX3BhZ2UuaGVhZD8ubWV0YSB9LGApO1xuICBsaW5lcy5wdXNoKGAgICAgICAgICAgaGVhZEV4dHJhczogJHtoZWFkRXh0cmFzRXhwcn0sYCk7XG4gIGxpbmVzLnB1c2goYCAgICAgICAgICBkYW5nZXJvdXNseUhlYWRGcmFnbWVudHM6IF9fcGFnZS5oZWFkPy5kYW5nZXJvdXNseUhlYWRGcmFnbWVudHMgfHwgW10sYCk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgICAgICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiAke0pTT04uc3RyaW5naWZ5KGRvY0NvbmZpZy5hbGxvd0hlYWRFeHRyYXNTY3JpcHRzKX0sYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgICAgIGNzcE5vbmNlOiBjLmdldCgnY3NwTm9uY2UnKSxgKTtcbiAgbGluZXMucHVzaChgICAgICAgICB9KSwgNTAwKWApO1xuICBsaW5lcy5wdXNoKGAgICAgICB9IGNhdGNoIChlcnJvclJlbmRlckZhaWx1cmUpIHtgKTtcbiAgbGluZXMucHVzaChcbiAgICBgICAgICAgICBjb25zb2xlLmVycm9yKCdbb3BlbkVsZW1lbnRdIFJvdXRlIGVycm9yIHJlbmRlcmVyIGZhaWxlZCBmb3IgJHtwYXRoU3RyfTonLCBlcnJvclJlbmRlckZhaWx1cmUpYCxcbiAgKTtcbiAgbGluZXMucHVzaChgICAgICAgfWApO1xuICBsaW5lcy5wdXNoKGAgICAgfWApO1xuICBsaW5lcy5wdXNoKFxuICAgIGAgICAgY29uc29sZS5lcnJvcignW29wZW5FbGVtZW50XSBSb3V0ZSByZW5kZXIgZmFpbGVkIGZvciAke3BhdGhTdHJ9OicsIGVycilgLFxuICApO1xuICBsaW5lcy5wdXNoKGAgICAgaWYgKGltcG9ydC5tZXRhLmVudi5QUk9EKSB7YCk7XG4gIGxpbmVzLnB1c2goYCAgICAgIHJldHVybiBjLmh0bWwoJzxoMT41MDAgSW50ZXJuYWwgU2VydmVyIEVycm9yPC9oMT4nLCA1MDApYCk7XG4gIGxpbmVzLnB1c2goYCAgICB9IGVsc2Uge2ApO1xuICBsaW5lcy5wdXNoKGAgICAgICBjb25zdCBzYWZlRXJyID0gZXNjYXBlSHRtbChTdHJpbmcoZXJyLnN0YWNrIHx8IGVycikpYCk7XG4gIGxpbmVzLnB1c2goXG4gICAgYCAgICAgIHJldHVybiBjLmh0bWwoJzxoMT41MDA8L2gxPjxwcmU+JyArIHNhZmVFcnIgKyAnPC9wcmU+JywgNTAwKWAsXG4gICk7XG4gIGxpbmVzLnB1c2goYCAgICB9YCk7XG4gIGxpbmVzLnB1c2goYCAgfWApO1xuICBsaW5lcy5wdXNoKGB9KWApO1xuICBsaW5lcy5wdXNoKCcnKTtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7OztDQU9DLEdBV0QsT0FBTyxTQUFTLGFBQWEsR0FBZTtFQUMxQyxNQUFNLFFBQVEsSUFBSSxLQUFLLEdBQUcsR0FBRyxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLElBQUksS0FBSyxFQUFFLEdBQUcsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDO0VBQzdFLE9BQU8sQ0FBQyxTQUFTLEVBQUUsTUFBTSxTQUFTLEVBQUUsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2pEO0FB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
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @openelement/ssg - Runtime helper code generation
3
+ *
4
+ * Generates the JavaScript/TypeScript code for runtime helper functions
5
+ * that are embedded in the generated Hono entry module.
6
+ *
7
+ * These helpers provide SSR rendering, locale resolution, lifecycle
8
+ * control (redirect/not-found), status page HTML, and app shell
9
+ * rendering.
10
+ */ /**
11
+ * Render all runtime helper function definitions as a single code block.
12
+ *
13
+ * Generated functions:
14
+ * - __ssr — render a registered custom element to DSD HTML
15
+ * - __localeFromPath — extract locale from a URL path
16
+ * - __isOpenElementRedirect — detect redirect lifecycle errors
17
+ * - __isOpenElementNotFound — detect not-found lifecycle errors
18
+ * - __statusHtml — render a simple status page HTML string
19
+ * - __resolveAppShell — resolve app shell from route meta
20
+ * - __renderAppShell — render route content inside the app shell layout
21
+ */ export function renderRuntimeHelpers(appShell) {
22
+ const lines = [];
23
+ lines.push('// SSR helper: render a registered custom element to DSD HTML');
24
+ lines.push('// Outputs standard DSD; no client render markers needed');
25
+ lines.push('async function __ssr(tag, props = {}, sourceInfo = {}) {');
26
+ lines.push(' // Validate tag name - must be a valid Custom Element (contains hyphen)');
27
+ lines.push(' if (!tag || !tag.includes("-")) {');
28
+ lines.push(' throw new Error("[openElement] Invalid custom element tag: " + String(tag) + ". Must contain a hyphen.")');
29
+ lines.push(' }');
30
+ lines.push(' const Cls = customElements.get(tag)');
31
+ lines.push(' if (!Cls) {');
32
+ lines.push(' log.warn("<" + tag + "> not registered - rendering empty")');
33
+ lines.push(' return "<" + tag + "></" + tag + ">"');
34
+ lines.push(' }');
35
+ lines.push(' const out = await renderDsd(tag, { componentClass: Cls, props, sourceInfo })');
36
+ lines.push(' return out.html');
37
+ lines.push('}');
38
+ lines.push('');
39
+ lines.push('function __localeFromPath(path, fallback) {');
40
+ lines.push(' const first = String(path || "/").split("/").filter(Boolean)[0];');
41
+ lines.push(' return __locales.includes(first) ? first : fallback;');
42
+ lines.push('}');
43
+ lines.push('');
44
+ lines.push('function __isOpenElementRedirect(error) {');
45
+ lines.push(' return error && error.name === "OpenElementRedirect" && typeof error.location === "string" && typeof error.status === "number";');
46
+ lines.push('}');
47
+ lines.push('');
48
+ lines.push('function __isOpenElementNotFound(error) {');
49
+ lines.push(' return error && error.name === "OpenElementNotFound" && error.status === 404;');
50
+ lines.push('}');
51
+ lines.push('');
52
+ lines.push('function __statusHtml(title, message) {');
53
+ lines.push(' return "<main><h1>" + escapeHtml(String(title)) + "</h1><p>" + escapeHtml(String(message)) + "</p></main>";');
54
+ lines.push('}');
55
+ lines.push('');
56
+ lines.push(`const __appShellPlan = ${JSON.stringify(appShell, null, 2)};`);
57
+ lines.push('');
58
+ lines.push('function __resolveAppShell(routeMeta = {}) {');
59
+ lines.push(' const layout = Object.prototype.hasOwnProperty.call(routeMeta, "layout") ? routeMeta.layout : undefined;');
60
+ lines.push(' if (layout === false) return false;');
61
+ lines.push(' if (typeof layout === "string") return __appShellPlan.layouts[layout] ?? __appShellPlan.default;');
62
+ lines.push(' return __appShellPlan.default;');
63
+ lines.push('}');
64
+ lines.push('');
65
+ lines.push('async function __renderAppShell(routeNode, routePath, options = {}) {');
66
+ lines.push(' const defaultLocale = __getDefaultLocale();');
67
+ lines.push(' const locale = options.locale || __localeFromPath(routePath, defaultLocale);');
68
+ lines.push(' const routeMeta = options.routeMeta || {};');
69
+ lines.push(' const shell = __resolveAppShell(routeMeta);');
70
+ lines.push(' const isHome = routePath === "/";');
71
+ lines.push(' // routeNode may be a VNode (jsx output) or HTML string. Render VNodes.');
72
+ lines.push(' const pageHtml = typeof routeNode === "object" && routeNode !== null');
73
+ lines.push(' ? await renderDsdTree(routeNode)');
74
+ lines.push(' : String(routeNode);');
75
+ lines.push(' if (!shell) return pageHtml;');
76
+ lines.push(' const layoutProps = {');
77
+ lines.push(' currentPath: routePath,');
78
+ lines.push(' locale,');
79
+ lines.push(' locales: __locales,');
80
+ lines.push(' navItems: __navSections,');
81
+ lines.push(' headerNav: __headerNav,');
82
+ lines.push(' home: isHome || undefined,');
83
+ lines.push(' routeMeta,');
84
+ lines.push(' ...(shell.props || {}),');
85
+ lines.push(' };');
86
+ lines.push(' const layoutResult = await renderDsd(shell.tagName, { props: layoutProps });');
87
+ lines.push(' const closingTag = "</" + shell.tagName + ">";');
88
+ lines.push(' const index = layoutResult.html.lastIndexOf(closingTag);');
89
+ lines.push(' if (index === -1) return layoutResult.html + pageHtml;');
90
+ lines.push(' return layoutResult.html.slice(0, index) + pageHtml + layoutResult.html.slice(index);');
91
+ lines.push('}');
92
+ return lines.join('\n');
93
+ }
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9zc2cvc3JjL2VudHJ5LXJlbmRlci1ydW50aW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG9wZW5lbGVtZW50L3NzZyAtIFJ1bnRpbWUgaGVscGVyIGNvZGUgZ2VuZXJhdGlvblxuICpcbiAqIEdlbmVyYXRlcyB0aGUgSmF2YVNjcmlwdC9UeXBlU2NyaXB0IGNvZGUgZm9yIHJ1bnRpbWUgaGVscGVyIGZ1bmN0aW9uc1xuICogdGhhdCBhcmUgZW1iZWRkZWQgaW4gdGhlIGdlbmVyYXRlZCBIb25vIGVudHJ5IG1vZHVsZS5cbiAqXG4gKiBUaGVzZSBoZWxwZXJzIHByb3ZpZGUgU1NSIHJlbmRlcmluZywgbG9jYWxlIHJlc29sdXRpb24sIGxpZmVjeWNsZVxuICogY29udHJvbCAocmVkaXJlY3Qvbm90LWZvdW5kKSwgc3RhdHVzIHBhZ2UgSFRNTCwgYW5kIGFwcCBzaGVsbFxuICogcmVuZGVyaW5nLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQXBwU2hlbGxQbGFuIH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL3NzZyc7XG5cbi8qKlxuICogUmVuZGVyIGFsbCBydW50aW1lIGhlbHBlciBmdW5jdGlvbiBkZWZpbml0aW9ucyBhcyBhIHNpbmdsZSBjb2RlIGJsb2NrLlxuICpcbiAqIEdlbmVyYXRlZCBmdW5jdGlvbnM6XG4gKiAgIC0gX19zc3IgICAgICAg4oCUIHJlbmRlciBhIHJlZ2lzdGVyZWQgY3VzdG9tIGVsZW1lbnQgdG8gRFNEIEhUTUxcbiAqICAgLSBfX2xvY2FsZUZyb21QYXRoIOKAlCBleHRyYWN0IGxvY2FsZSBmcm9tIGEgVVJMIHBhdGhcbiAqICAgLSBfX2lzT3BlbkVsZW1lbnRSZWRpcmVjdCDigJQgZGV0ZWN0IHJlZGlyZWN0IGxpZmVjeWNsZSBlcnJvcnNcbiAqICAgLSBfX2lzT3BlbkVsZW1lbnROb3RGb3VuZCDigJQgZGV0ZWN0IG5vdC1mb3VuZCBsaWZlY3ljbGUgZXJyb3JzXG4gKiAgIC0gX19zdGF0dXNIdG1sIOKAlCByZW5kZXIgYSBzaW1wbGUgc3RhdHVzIHBhZ2UgSFRNTCBzdHJpbmdcbiAqICAgLSBfX3Jlc29sdmVBcHBTaGVsbCDigJQgcmVzb2x2ZSBhcHAgc2hlbGwgZnJvbSByb3V0ZSBtZXRhXG4gKiAgIC0gX19yZW5kZXJBcHBTaGVsbCDigJQgcmVuZGVyIHJvdXRlIGNvbnRlbnQgaW5zaWRlIHRoZSBhcHAgc2hlbGwgbGF5b3V0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJSdW50aW1lSGVscGVycyhhcHBTaGVsbDogQXBwU2hlbGxQbGFuKTogc3RyaW5nIHtcbiAgY29uc3QgbGluZXM6IHN0cmluZ1tdID0gW107XG5cbiAgbGluZXMucHVzaCgnLy8gU1NSIGhlbHBlcjogcmVuZGVyIGEgcmVnaXN0ZXJlZCBjdXN0b20gZWxlbWVudCB0byBEU0QgSFRNTCcpO1xuICBsaW5lcy5wdXNoKCcvLyBPdXRwdXRzIHN0YW5kYXJkIERTRDsgbm8gY2xpZW50IHJlbmRlciBtYXJrZXJzIG5lZWRlZCcpO1xuICBsaW5lcy5wdXNoKCdhc3luYyBmdW5jdGlvbiBfX3Nzcih0YWcsIHByb3BzID0ge30sIHNvdXJjZUluZm8gPSB7fSkgeycpO1xuICBsaW5lcy5wdXNoKFxuICAgICcgIC8vIFZhbGlkYXRlIHRhZyBuYW1lIC0gbXVzdCBiZSBhIHZhbGlkIEN1c3RvbSBFbGVtZW50IChjb250YWlucyBoeXBoZW4pJyxcbiAgKTtcbiAgbGluZXMucHVzaCgnICBpZiAoIXRhZyB8fCAhdGFnLmluY2x1ZGVzKFwiLVwiKSkgeycpO1xuICBsaW5lcy5wdXNoKFxuICAgICcgICAgdGhyb3cgbmV3IEVycm9yKFwiW29wZW5FbGVtZW50XSBJbnZhbGlkIGN1c3RvbSBlbGVtZW50IHRhZzogXCIgKyBTdHJpbmcodGFnKSArIFwiLiBNdXN0IGNvbnRhaW4gYSBoeXBoZW4uXCIpJyxcbiAgKTtcbiAgbGluZXMucHVzaCgnICB9Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgQ2xzID0gY3VzdG9tRWxlbWVudHMuZ2V0KHRhZyknKTtcbiAgbGluZXMucHVzaCgnICBpZiAoIUNscykgeycpO1xuICBsaW5lcy5wdXNoKCcgICAgbG9nLndhcm4oXCI8XCIgKyB0YWcgKyBcIj4gbm90IHJlZ2lzdGVyZWQgLSByZW5kZXJpbmcgZW1wdHlcIiknKTtcbiAgbGluZXMucHVzaCgnICAgIHJldHVybiBcIjxcIiArIHRhZyArIFwiPjwvXCIgKyB0YWcgKyBcIj5cIicpO1xuICBsaW5lcy5wdXNoKCcgIH0nKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBvdXQgPSBhd2FpdCByZW5kZXJEc2QodGFnLCB7IGNvbXBvbmVudENsYXNzOiBDbHMsIHByb3BzLCBzb3VyY2VJbmZvIH0pJyk7XG4gIGxpbmVzLnB1c2goJyAgcmV0dXJuIG91dC5odG1sJyk7XG4gIGxpbmVzLnB1c2goJ30nKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgbGluZXMucHVzaCgnZnVuY3Rpb24gX19sb2NhbGVGcm9tUGF0aChwYXRoLCBmYWxsYmFjaykgeycpO1xuICBsaW5lcy5wdXNoKCcgIGNvbnN0IGZpcnN0ID0gU3RyaW5nKHBhdGggfHwgXCIvXCIpLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbilbMF07Jyk7XG4gIGxpbmVzLnB1c2goJyAgcmV0dXJuIF9fbG9jYWxlcy5pbmNsdWRlcyhmaXJzdCkgPyBmaXJzdCA6IGZhbGxiYWNrOycpO1xuICBsaW5lcy5wdXNoKCd9Jyk7XG4gIGxpbmVzLnB1c2goJycpO1xuXG4gIGxpbmVzLnB1c2goJ2Z1bmN0aW9uIF9faXNPcGVuRWxlbWVudFJlZGlyZWN0KGVycm9yKSB7Jyk7XG4gIGxpbmVzLnB1c2goXG4gICAgJyAgcmV0dXJuIGVycm9yICYmIGVycm9yLm5hbWUgPT09IFwiT3BlbkVsZW1lbnRSZWRpcmVjdFwiICYmIHR5cGVvZiBlcnJvci5sb2NhdGlvbiA9PT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgZXJyb3Iuc3RhdHVzID09PSBcIm51bWJlclwiOycsXG4gICk7XG4gIGxpbmVzLnB1c2goJ30nKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgbGluZXMucHVzaCgnZnVuY3Rpb24gX19pc09wZW5FbGVtZW50Tm90Rm91bmQoZXJyb3IpIHsnKTtcbiAgbGluZXMucHVzaCgnICByZXR1cm4gZXJyb3IgJiYgZXJyb3IubmFtZSA9PT0gXCJPcGVuRWxlbWVudE5vdEZvdW5kXCIgJiYgZXJyb3Iuc3RhdHVzID09PSA0MDQ7Jyk7XG4gIGxpbmVzLnB1c2goJ30nKTtcbiAgbGluZXMucHVzaCgnJyk7XG5cbiAgbGluZXMucHVzaCgnZnVuY3Rpb24gX19zdGF0dXNIdG1sKHRpdGxlLCBtZXNzYWdlKSB7Jyk7XG4gIGxpbmVzLnB1c2goXG4gICAgJyAgcmV0dXJuIFwiPG1haW4+PGgxPlwiICsgZXNjYXBlSHRtbChTdHJpbmcodGl0bGUpKSArIFwiPC9oMT48cD5cIiArIGVzY2FwZUh0bWwoU3RyaW5nKG1lc3NhZ2UpKSArIFwiPC9wPjwvbWFpbj5cIjsnLFxuICApO1xuICBsaW5lcy5wdXNoKCd9Jyk7XG4gIGxpbmVzLnB1c2goJycpO1xuXG4gIGxpbmVzLnB1c2goYGNvbnN0IF9fYXBwU2hlbGxQbGFuID0gJHtKU09OLnN0cmluZ2lmeShhcHBTaGVsbCwgbnVsbCwgMil9O2ApO1xuICBsaW5lcy5wdXNoKCcnKTtcblxuICBsaW5lcy5wdXNoKCdmdW5jdGlvbiBfX3Jlc29sdmVBcHBTaGVsbChyb3V0ZU1ldGEgPSB7fSkgeycpO1xuICBsaW5lcy5wdXNoKFxuICAgICcgIGNvbnN0IGxheW91dCA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChyb3V0ZU1ldGEsIFwibGF5b3V0XCIpID8gcm91dGVNZXRhLmxheW91dCA6IHVuZGVmaW5lZDsnLFxuICApO1xuICBsaW5lcy5wdXNoKCcgIGlmIChsYXlvdXQgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7Jyk7XG4gIGxpbmVzLnB1c2goXG4gICAgJyAgaWYgKHR5cGVvZiBsYXlvdXQgPT09IFwic3RyaW5nXCIpIHJldHVybiBfX2FwcFNoZWxsUGxhbi5sYXlvdXRzW2xheW91dF0gPz8gX19hcHBTaGVsbFBsYW4uZGVmYXVsdDsnLFxuICApO1xuICBsaW5lcy5wdXNoKCcgIHJldHVybiBfX2FwcFNoZWxsUGxhbi5kZWZhdWx0OycpO1xuICBsaW5lcy5wdXNoKCd9Jyk7XG4gIGxpbmVzLnB1c2goJycpO1xuXG4gIGxpbmVzLnB1c2goJ2FzeW5jIGZ1bmN0aW9uIF9fcmVuZGVyQXBwU2hlbGwocm91dGVOb2RlLCByb3V0ZVBhdGgsIG9wdGlvbnMgPSB7fSkgeycpO1xuICBsaW5lcy5wdXNoKCcgIGNvbnN0IGRlZmF1bHRMb2NhbGUgPSBfX2dldERlZmF1bHRMb2NhbGUoKTsnKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBsb2NhbGUgPSBvcHRpb25zLmxvY2FsZSB8fCBfX2xvY2FsZUZyb21QYXRoKHJvdXRlUGF0aCwgZGVmYXVsdExvY2FsZSk7Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3Qgcm91dGVNZXRhID0gb3B0aW9ucy5yb3V0ZU1ldGEgfHwge307Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3Qgc2hlbGwgPSBfX3Jlc29sdmVBcHBTaGVsbChyb3V0ZU1ldGEpOycpO1xuICBsaW5lcy5wdXNoKCcgIGNvbnN0IGlzSG9tZSA9IHJvdXRlUGF0aCA9PT0gXCIvXCI7Jyk7XG4gIGxpbmVzLnB1c2goJyAgLy8gcm91dGVOb2RlIG1heSBiZSBhIFZOb2RlIChqc3ggb3V0cHV0KSBvciBIVE1MIHN0cmluZy4gUmVuZGVyIFZOb2Rlcy4nKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBwYWdlSHRtbCA9IHR5cGVvZiByb3V0ZU5vZGUgPT09IFwib2JqZWN0XCIgJiYgcm91dGVOb2RlICE9PSBudWxsJyk7XG4gIGxpbmVzLnB1c2goJyAgICA/IGF3YWl0IHJlbmRlckRzZFRyZWUocm91dGVOb2RlKScpO1xuICBsaW5lcy5wdXNoKCcgICAgOiBTdHJpbmcocm91dGVOb2RlKTsnKTtcbiAgbGluZXMucHVzaCgnICBpZiAoIXNoZWxsKSByZXR1cm4gcGFnZUh0bWw7Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgbGF5b3V0UHJvcHMgPSB7Jyk7XG4gIGxpbmVzLnB1c2goJyAgICBjdXJyZW50UGF0aDogcm91dGVQYXRoLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgbG9jYWxlLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgbG9jYWxlczogX19sb2NhbGVzLCcpO1xuICBsaW5lcy5wdXNoKCcgICAgbmF2SXRlbXM6IF9fbmF2U2VjdGlvbnMsJyk7XG4gIGxpbmVzLnB1c2goJyAgICBoZWFkZXJOYXY6IF9faGVhZGVyTmF2LCcpO1xuICBsaW5lcy5wdXNoKCcgICAgaG9tZTogaXNIb21lIHx8IHVuZGVmaW5lZCwnKTtcbiAgbGluZXMucHVzaCgnICAgIHJvdXRlTWV0YSwnKTtcbiAgbGluZXMucHVzaCgnICAgIC4uLihzaGVsbC5wcm9wcyB8fCB7fSksJyk7XG4gIGxpbmVzLnB1c2goJyAgfTsnKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBsYXlvdXRSZXN1bHQgPSBhd2FpdCByZW5kZXJEc2Qoc2hlbGwudGFnTmFtZSwgeyBwcm9wczogbGF5b3V0UHJvcHMgfSk7Jyk7XG4gIGxpbmVzLnB1c2goJyAgY29uc3QgY2xvc2luZ1RhZyA9IFwiPC9cIiArIHNoZWxsLnRhZ05hbWUgKyBcIj5cIjsnKTtcbiAgbGluZXMucHVzaCgnICBjb25zdCBpbmRleCA9IGxheW91dFJlc3VsdC5odG1sLmxhc3RJbmRleE9mKGNsb3NpbmdUYWcpOycpO1xuICBsaW5lcy5wdXNoKCcgIGlmIChpbmRleCA9PT0gLTEpIHJldHVybiBsYXlvdXRSZXN1bHQuaHRtbCArIHBhZ2VIdG1sOycpO1xuICBsaW5lcy5wdXNoKFxuICAgICcgIHJldHVybiBsYXlvdXRSZXN1bHQuaHRtbC5zbGljZSgwLCBpbmRleCkgKyBwYWdlSHRtbCArIGxheW91dFJlc3VsdC5odG1sLnNsaWNlKGluZGV4KTsnLFxuICApO1xuICBsaW5lcy5wdXNoKCd9Jyk7XG5cbiAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Q0FTQyxHQUlEOzs7Ozs7Ozs7OztDQVdDLEdBQ0QsT0FBTyxTQUFTLHFCQUFxQixRQUFzQjtFQUN6RCxNQUFNLFFBQWtCLEVBQUU7RUFFMUIsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1I7RUFFRixNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFFWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBRVgsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFFWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUVYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1I7RUFFRixNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBRVgsTUFBTSxJQUFJLENBQUMsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLFNBQVMsQ0FBQyxVQUFVLE1BQU0sR0FBRyxDQUFDLENBQUM7RUFDekUsTUFBTSxJQUFJLENBQUM7RUFFWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUNSO0VBRUYsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FDUjtFQUVGLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUVYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQUM7RUFDWCxNQUFNLElBQUksQ0FBQztFQUNYLE1BQU0sSUFBSSxDQUFDO0VBQ1gsTUFBTSxJQUFJLENBQ1I7RUFFRixNQUFNLElBQUksQ0FBQztFQUVYLE9BQU8sTUFBTSxJQUFJLENBQUM7QUFDcEIifQ==