frappe-builder 1.1.0-dev.25 → 1.1.0-dev.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.fb/state.db CHANGED
Binary file
@@ -2,13 +2,13 @@ feature_id: po-approval
2
2
  feature_name: "PO Approval"
3
3
  mode: full
4
4
  phase: testing
5
- updated_at: 2026-03-28T14:37:54.966Z
5
+ updated_at: 2026-03-28T14:38:26.634Z
6
6
 
7
7
  components:
8
8
  - id: final-comp
9
9
  sort_order: 0
10
10
  status: complete
11
- completed_at: 2026-03-28T14:37:54.965Z
11
+ completed_at: 2026-03-28T14:38:26.633Z
12
12
 
13
13
  progress:
14
14
  done: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frappe-builder",
3
- "version": "1.1.0-dev.25",
3
+ "version": "1.1.0-dev.26",
4
4
  "description": "Frappe-native AI co-pilot for building and customising Frappe/ERPNext applications",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,318 +0,0 @@
1
- __vite_ssr_exportName__("patchGitignore", () => { try { return patchGitignore } catch {} });
2
- __vite_ssr_exportName__("runInit", () => { try { return runInit } catch {} });
3
- __vite_ssr_exportName__("setupContextMode", () => { try { return setupContextMode } catch {} });
4
- __vite_ssr_exportName__("setupMcp2cli", () => { try { return setupMcp2cli } catch {} });
5
- const __vite_ssr_import_0__ = await __vite_ssr_import__("node:fs", {"importedNames":["mkdirSync","existsSync","readFileSync","writeFileSync","renameSync"]});
6
- const __vite_ssr_import_1__ = await __vite_ssr_import__("node:path", {"importedNames":["join"]});
7
- const __vite_ssr_import_2__ = await __vite_ssr_import__("node:os", {"importedNames":["homedir"]});
8
- const __vite_ssr_import_3__ = await __vite_ssr_import__("node:readline", {"importedNames":["createInterface"]});
9
- const __vite_ssr_import_4__ = await __vite_ssr_import__("node:child_process", {"importedNames":["spawnSync"]});
10
- /**
11
- * src/init.ts — interactive setup wizard for frappe-builder
12
- *
13
- * Handles: global config (~/.frappe-builder/config.json),
14
- * project config (.frappe-builder-config.json),
15
- * and .gitignore patching.
16
- *
17
- * No imports from state/, extensions/, or gates/.
18
- * Uses Node.js built-ins only — no external prompt libraries.
19
- */
20
-
21
-
22
-
23
-
24
-
25
- let cancelled = false;
26
- process.on("SIGINT", () => {
27
- cancelled = true;
28
- });
29
- function promptLine(question) {
30
- return new Promise((resolve) => {
31
- if (cancelled) {
32
- resolve("");
33
- return;
34
- };
35
- const rl = (0,__vite_ssr_import_3__.createInterface)({
36
- input: process.stdin,
37
- output: process.stdout
38
- });
39
- rl.question(question, (answer) => {
40
- rl.close();
41
- resolve(answer);
42
- });
43
- });
44
- }
45
- async function promptYN(question) {
46
- const answer = await promptLine(question + " (y/N): ");
47
- return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
48
- }
49
- function writeAtomic(filePath, content) {
50
- const tmp = filePath + ".tmp";
51
- (0,__vite_ssr_import_0__.writeFileSync)(tmp, content, "utf-8");
52
- (0,__vite_ssr_import_0__.renameSync)(tmp, filePath);
53
- }
54
- /** Patches .gitignore to include the exact entry if not already present. */
55
- function patchGitignore(projectRoot, entry) {
56
- const gitignorePath = (0,__vite_ssr_import_1__.join)(projectRoot, ".gitignore");
57
- if (!(0,__vite_ssr_import_0__.existsSync)(gitignorePath)) {
58
- (0,__vite_ssr_import_0__.writeFileSync)(gitignorePath, entry + "\n", "utf-8");
59
- return "created";
60
- };
61
- const content = (0,__vite_ssr_import_0__.readFileSync)(gitignorePath, "utf-8");
62
- const lines = content.split("\n");
63
- if (lines.includes(entry)) {
64
- return "already-present";
65
- };
66
- const patched = content.endsWith("\n") ? content + entry + "\n" : content + "\n" + entry + "\n";
67
- (0,__vite_ssr_import_0__.writeFileSync)(gitignorePath, patched, "utf-8");
68
- return "patched";
69
- };
70
- async function runInit(opts = {}) {
71
- const projectRoot = opts.projectRoot ?? process.cwd();
72
- const homeDir = (0,__vite_ssr_import_2__.homedir)();
73
- const globalConfigDir = (0,__vite_ssr_import_1__.join)(homeDir, ".frappe-builder");
74
- const globalConfigPath = (0,__vite_ssr_import_1__.join)(globalConfigDir, "config.json");
75
- const projectConfigPath = (0,__vite_ssr_import_1__.join)(projectRoot, ".frappe-builder-config.json");
76
- console.log("\n=== frappe-builder Setup ===\n");
77
- // ── Global config ────────────────────────────────────────────────────────
78
- console.log(`[Global config: ${globalConfigPath}]`);
79
- let globalConfig = {};
80
- let globalAction = "written";
81
- if ((0,__vite_ssr_import_0__.existsSync)(globalConfigPath)) {
82
- try {
83
- globalConfig = JSON.parse((0,__vite_ssr_import_0__.readFileSync)(globalConfigPath, "utf-8"));
84
- } catch {};
85
- if (!cancelled) {
86
- const overwrite = await promptYN(`Overwrite existing ${globalConfigPath}?`);
87
- if (cancelled) {
88
- printCancelled();
89
- return;
90
- };
91
- if (!overwrite) {
92
- globalAction = "skipped";
93
- console.log(" Keeping existing global config.\n");
94
- }
95
- }
96
- };
97
- if (!cancelled && globalAction === "written") {
98
- const llmKey = await promptLine("LLM API key (leave blank to skip): ");
99
- if (cancelled) {
100
- printCancelled();
101
- return;
102
- };
103
- globalConfig.llm_api_key = llmKey.trim();
104
- };
105
- // ── Project config ───────────────────────────────────────────────────────
106
- console.log(`\n[Project config: ${projectConfigPath}]`);
107
- let projectConfig = {};
108
- let projectAction = "written";
109
- if ((0,__vite_ssr_import_0__.existsSync)(projectConfigPath)) {
110
- try {
111
- projectConfig = JSON.parse((0,__vite_ssr_import_0__.readFileSync)(projectConfigPath, "utf-8"));
112
- } catch {};
113
- if (!cancelled) {
114
- const overwrite = await promptYN(`Overwrite existing ${projectConfigPath}?`);
115
- if (cancelled) {
116
- printCancelled();
117
- return;
118
- };
119
- if (!overwrite) {
120
- projectAction = "skipped";
121
- console.log(" Keeping existing project config.\n");
122
- }
123
- }
124
- };
125
- if (!cancelled && projectAction === "written") {
126
- const siteUrl = await promptLine("Frappe site URL (e.g. http://site1.localhost): ");
127
- if (cancelled) {
128
- printCancelled();
129
- return;
130
- };
131
- const apiKey = await promptLine("Frappe API key: ");
132
- if (cancelled) {
133
- printCancelled();
134
- return;
135
- };
136
- const apiSecret = await promptLine("Frappe API secret: ");
137
- if (cancelled) {
138
- printCancelled();
139
- return;
140
- };
141
- projectConfig = {
142
- site_url: siteUrl.trim(),
143
- api_key: apiKey.trim(),
144
- api_secret: apiSecret.trim()
145
- };
146
- };
147
- // ── All prompts collected — now write files ──────────────────────────────
148
- const written = [];
149
- const skipped = [];
150
- // Global config
151
- if (globalAction === "written") {
152
- (0,__vite_ssr_import_0__.mkdirSync)(globalConfigDir, { recursive: true });
153
- writeAtomic(globalConfigPath, JSON.stringify(globalConfig, null, 2) + "\n");
154
- written.push(`~/.frappe-builder/config.json`);
155
- } else {
156
- skipped.push(`~/.frappe-builder/config.json`);
157
- };
158
- // Project config
159
- if (projectAction === "written") {
160
- writeAtomic(projectConfigPath, JSON.stringify(projectConfig, null, 2) + "\n");
161
- written.push(`.frappe-builder-config.json`);
162
- } else {
163
- skipped.push(`.frappe-builder-config.json`);
164
- };
165
- // Gitignore patch
166
- const gitignoreResult = patchGitignore(projectRoot, ".frappe-builder-config.json");
167
- if (gitignoreResult === "patched") {
168
- written.push(".gitignore (patched)");
169
- } else if (gitignoreResult === "created") {
170
- written.push(".gitignore (created)");
171
- } else {
172
- skipped.push(".gitignore (entry already present)");
173
- };
174
- // ── context-mode MCP extension ───────────────────────────────────────────
175
- await setupContextMode(homeDir);
176
- // ── mcp2cli skill + context-mode bake ────────────────────────────────────
177
- setupMcp2cli(homeDir);
178
- // ── Summary ──────────────────────────────────────────────────────────────
179
- console.log("\nFiles written:");
180
- for (const f of written) {
181
- console.log(` ✓ ${f}`);
182
- };
183
- if (skipped.length > 0) {
184
- console.log("Skipped:");
185
- for (const f of skipped) {
186
- console.log(` - ${f}`);
187
- }
188
- };
189
- console.log("\nReady. Run: frappe-builder\n");
190
- };
191
- function printCancelled() {
192
- console.log("\nSetup cancelled. No files were written.\n");
193
- }
194
- /**
195
- * Installs and configures the context-mode pi MCP extension.
196
- * Clones https://github.com/mksglu/context-mode into ~/.pi/extensions/context-mode,
197
- * builds it, and patches ~/.pi/settings/mcp.json with the server entry.
198
- *
199
- * Non-fatal — failures are logged as warnings, never abort init.
200
- */
201
- async function setupContextMode(homeDir) {
202
- const extDir = (0,__vite_ssr_import_1__.join)(homeDir, ".pi", "extensions", "context-mode");
203
- const mcpSettingsDir = (0,__vite_ssr_import_1__.join)(homeDir, ".pi", "settings");
204
- const mcpSettingsPath = (0,__vite_ssr_import_1__.join)(mcpSettingsDir, "mcp.json");
205
- const startScript = (0,__vite_ssr_import_1__.join)(extDir, "node_modules", "context-mode", "start.mjs");
206
- console.log("\n[context-mode MCP extension]");
207
- // ── Already installed? ──────────────────────────────────────────────────
208
- if ((0,__vite_ssr_import_0__.existsSync)(extDir)) {
209
- console.log(" ✓ context-mode already installed at ~/.pi/extensions/context-mode");
210
- } else {
211
- console.log(" context-mode not found — installing (requires git + Node.js)...");
212
- (0,__vite_ssr_import_0__.mkdirSync)((0,__vite_ssr_import_1__.join)(homeDir, ".pi", "extensions"), { recursive: true });
213
- const clone = (0,__vite_ssr_import_4__.spawnSync)("git", [
214
- "clone",
215
- "https://github.com/mksglu/context-mode.git",
216
- extDir
217
- ], { stdio: "pipe" });
218
- if (clone.status !== 0) {
219
- console.warn(` ⚠ git clone failed: ${clone.stderr?.toString().trim()}`);
220
- console.warn(" Skipping context-mode setup. Install manually: https://github.com/mksglu/context-mode");
221
- return;
222
- };
223
- const install = (0,__vite_ssr_import_4__.spawnSync)("npm", ["install"], {
224
- cwd: extDir,
225
- stdio: "pipe"
226
- });
227
- if (install.status !== 0) {
228
- console.warn(` ⚠ npm install failed: ${install.stderr?.toString().trim()}`);
229
- return;
230
- };
231
- const build = (0,__vite_ssr_import_4__.spawnSync)("npm", ["run", "build"], {
232
- cwd: extDir,
233
- stdio: "pipe"
234
- });
235
- if (build.status !== 0) {
236
- console.warn(` ⚠ npm run build failed: ${build.stderr?.toString().trim()}`);
237
- return;
238
- };
239
- console.log(" ✓ context-mode installed and built");
240
- };
241
- // ── Patch ~/.pi/settings/mcp.json ──────────────────────────────────────
242
- (0,__vite_ssr_import_0__.mkdirSync)(mcpSettingsDir, { recursive: true });
243
- let mcpConfig = {};
244
- if ((0,__vite_ssr_import_0__.existsSync)(mcpSettingsPath)) {
245
- try {
246
- mcpConfig = JSON.parse((0,__vite_ssr_import_0__.readFileSync)(mcpSettingsPath, "utf-8"));
247
- } catch {}
248
- };
249
- const servers = mcpConfig.mcpServers ?? {};
250
- if (servers["context-mode"]) {
251
- console.log(" ✓ context-mode already in ~/.pi/settings/mcp.json");
252
- return;
253
- };
254
- servers["context-mode"] = {
255
- command: "node",
256
- args: [startScript]
257
- };
258
- mcpConfig.mcpServers = servers;
259
- writeAtomic(mcpSettingsPath, JSON.stringify(mcpConfig, null, 2) + "\n");
260
- console.log(" ✓ Added context-mode to ~/.pi/settings/mcp.json");
261
- console.log(" Restart pi (or frappe-builder) for context-mode to activate.");
262
- };
263
- /**
264
- * Installs the mcp2cli Claude Code skill and bakes the context-mode connection
265
- * so the agent can call `mcp2cli @context-mode <tool>` without repeating flags.
266
- *
267
- * Non-fatal — failures are logged as warnings, never abort init.
268
- */
269
- function setupMcp2cli(homeDir) {
270
- const startScript = (0,__vite_ssr_import_1__.join)(homeDir, ".pi", "extensions", "context-mode", "node_modules", "context-mode", "start.mjs");
271
- console.log("\n[mcp2cli skill + context-mode bake]");
272
- // ── Install mcp2cli Claude Code skill ───────────────────────────────────
273
- const skillAdd = (0,__vite_ssr_import_4__.spawnSync)("npx", [
274
- "skills",
275
- "add",
276
- "knowsuchagency/mcp2cli",
277
- "--skill",
278
- "mcp2cli"
279
- ], { stdio: "pipe" });
280
- if (skillAdd.status !== 0) {
281
- console.warn(` ⚠ mcp2cli skill install failed: ${skillAdd.stderr?.toString().trim()}`);
282
- console.warn(" Install manually: npx skills add knowsuchagency/mcp2cli --skill mcp2cli");
283
- } else {
284
- console.log(" ✓ mcp2cli skill installed");
285
- };
286
- // ── Bake context-mode connection ─────────────────────────────────────────
287
- // Check if already baked
288
- const bakeShow = (0,__vite_ssr_import_4__.spawnSync)("mcp2cli", [
289
- "bake",
290
- "show",
291
- "context-mode"
292
- ], { stdio: "pipe" });
293
- if (bakeShow.status === 0) {
294
- console.log(" ✓ mcp2cli @context-mode already baked");
295
- return;
296
- };
297
- if (!(0,__vite_ssr_import_0__.existsSync)(startScript)) {
298
- console.warn(" ⚠ context-mode start.mjs not found — skipping bake (run init again after context-mode installs)");
299
- return;
300
- };
301
- const bakeCreate = (0,__vite_ssr_import_4__.spawnSync)("mcp2cli", [
302
- "bake",
303
- "create",
304
- "context-mode",
305
- "--mcp-stdio",
306
- `node ${startScript}`
307
- ], { stdio: "pipe" });
308
- if (bakeCreate.status !== 0) {
309
- console.warn(` ⚠ mcp2cli bake failed: ${bakeCreate.stderr?.toString().trim()}`);
310
- console.warn(" Install mcp2cli first: pip install mcp2cli");
311
- } else {
312
- console.log(" ✓ mcp2cli @context-mode baked — agent can now call: mcp2cli @context-mode <tool>");
313
- }
314
- }
315
- //# sourceMappingSource=vite-generated
316
- //# sourceMappingURL=data:application/json;base64,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LEdBQUc7QUFDekIsVUFBUSxLQUFLLHFDQUFxQyxTQUFTLFFBQVEsVUFBVSxDQUFDLE1BQU0sR0FBRztBQUN2RixVQUFRLEtBQUssNEVBQTRFO1FBQ3BGO0FBQ0wsVUFBUSxJQUFJLDhCQUE4Qjs7OztDQUs1QyxNQUFNLGNBQVcsaUNBQVUsV0FBVztFQUFDO0VBQVE7RUFBUTtFQUFlLEVBQUUsRUFBRSxPQUFPLFFBQVEsQ0FBQztBQUMxRixLQUFJLFNBQVMsV0FBVyxHQUFHO0FBQ3pCLFVBQVEsSUFBSSwwQ0FBMEM7QUFDdEQ7O0FBR0YsS0FBSSxJQUFDLGtDQUFXLFlBQVksRUFBRTtBQUM1QixVQUFRLEtBQUssb0dBQW9HO0FBQ2pIOztDQUdGLE1BQU0sZ0JBQWEsaUNBQ2pCLFdBQ0E7RUFBQztFQUFRO0VBQVU7RUFBZ0I7RUFBZSxRQUFRO0VBQWMsRUFDeEUsRUFBRSxPQUFPLFFBQVEsQ0FDbEI7QUFDRCxLQUFJLFdBQVcsV0FBVyxHQUFHO0FBQzNCLFVBQVEsS0FBSyw0QkFBNEIsV0FBVyxRQUFRLFVBQVUsQ0FBQyxNQUFNLEdBQUc7QUFDaEYsVUFBUSxLQUFLLCtDQUErQztRQUN2RDtBQUNMLFVBQVEsSUFBSSxxRkFBcUYiLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VzIjpbImluaXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBzcmMvaW5pdC50cyDigJQgaW50ZXJhY3RpdmUgc2V0dXAgd2l6YXJkIGZvciBmcmFwcGUtYnVpbGRlclxuICpcbiAqIEhhbmRsZXM6IGdsb2JhbCBjb25maWcgKH4vLmZyYXBwZS1idWlsZGVyL2NvbmZpZy5qc29uKSxcbiAqICAgICAgICAgIHByb2plY3QgY29uZmlnICguZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb24pLFxuICogICAgICAgICAgYW5kIC5naXRpZ25vcmUgcGF0Y2hpbmcuXG4gKlxuICogTm8gaW1wb3J0cyBmcm9tIHN0YXRlLywgZXh0ZW5zaW9ucy8sIG9yIGdhdGVzLy5cbiAqIFVzZXMgTm9kZS5qcyBidWlsdC1pbnMgb25seSDigJQgbm8gZXh0ZXJuYWwgcHJvbXB0IGxpYnJhcmllcy5cbiAqL1xuXG5pbXBvcnQgeyBta2RpclN5bmMsIGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luYywgcmVuYW1lU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBjcmVhdGVJbnRlcmZhY2UgfSBmcm9tIFwibm9kZTpyZWFkbGluZVwiO1xuaW1wb3J0IHsgc3Bhd25TeW5jIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuXG5sZXQgY2FuY2VsbGVkID0gZmFsc2U7XG5cbnByb2Nlc3Mub24oXCJTSUdJTlRcIiwgKCkgPT4ge1xuICBjYW5jZWxsZWQgPSB0cnVlO1xufSk7XG5cbmZ1bmN0aW9uIHByb21wdExpbmUocXVlc3Rpb246IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGlmIChjYW5jZWxsZWQpIHsgcmVzb2x2ZShcIlwiKTsgcmV0dXJuOyB9XG4gICAgY29uc3QgcmwgPSBjcmVhdGVJbnRlcmZhY2UoeyBpbnB1dDogcHJvY2Vzcy5zdGRpbiwgb3V0cHV0OiBwcm9jZXNzLnN0ZG91dCB9KTtcbiAgICBybC5xdWVzdGlvbihxdWVzdGlvbiwgKGFuc3dlcikgPT4ge1xuICAgICAgcmwuY2xvc2UoKTtcbiAgICAgIHJlc29sdmUoYW5zd2VyKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHByb21wdFlOKHF1ZXN0aW9uOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgY29uc3QgYW5zd2VyID0gYXdhaXQgcHJvbXB0TGluZShxdWVzdGlvbiArIFwiICh5L04pOiBcIik7XG4gIHJldHVybiBhbnN3ZXIudHJpbSgpLnRvTG93ZXJDYXNlKCkgPT09IFwieVwiIHx8IGFuc3dlci50cmltKCkudG9Mb3dlckNhc2UoKSA9PT0gXCJ5ZXNcIjtcbn1cblxuZnVuY3Rpb24gd3JpdGVBdG9taWMoZmlsZVBhdGg6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHRtcCA9IGZpbGVQYXRoICsgXCIudG1wXCI7XG4gIHdyaXRlRmlsZVN5bmModG1wLCBjb250ZW50LCBcInV0Zi04XCIpO1xuICByZW5hbWVTeW5jKHRtcCwgZmlsZVBhdGgpO1xufVxuXG4vKiogUGF0Y2hlcyAuZ2l0aWdub3JlIHRvIGluY2x1ZGUgdGhlIGV4YWN0IGVudHJ5IGlmIG5vdCBhbHJlYWR5IHByZXNlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gcGF0Y2hHaXRpZ25vcmUocHJvamVjdFJvb3Q6IHN0cmluZywgZW50cnk6IHN0cmluZyk6IFwicGF0Y2hlZFwiIHwgXCJhbHJlYWR5LXByZXNlbnRcIiB8IFwiY3JlYXRlZFwiIHtcbiAgY29uc3QgZ2l0aWdub3JlUGF0aCA9IGpvaW4ocHJvamVjdFJvb3QsIFwiLmdpdGlnbm9yZVwiKTtcbiAgaWYgKCFleGlzdHNTeW5jKGdpdGlnbm9yZVBhdGgpKSB7XG4gICAgd3JpdGVGaWxlU3luYyhnaXRpZ25vcmVQYXRoLCBlbnRyeSArIFwiXFxuXCIsIFwidXRmLThcIik7XG4gICAgcmV0dXJuIFwiY3JlYXRlZFwiO1xuICB9XG4gIGNvbnN0IGNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZ2l0aWdub3JlUGF0aCwgXCJ1dGYtOFwiKTtcbiAgY29uc3QgbGluZXMgPSBjb250ZW50LnNwbGl0KFwiXFxuXCIpO1xuICBpZiAobGluZXMuaW5jbHVkZXMoZW50cnkpKSB7XG4gICAgcmV0dXJuIFwiYWxyZWFkeS1wcmVzZW50XCI7XG4gIH1cbiAgY29uc3QgcGF0Y2hlZCA9IGNvbnRlbnQuZW5kc1dpdGgoXCJcXG5cIikgPyBjb250ZW50ICsgZW50cnkgKyBcIlxcblwiIDogY29udGVudCArIFwiXFxuXCIgKyBlbnRyeSArIFwiXFxuXCI7XG4gIHdyaXRlRmlsZVN5bmMoZ2l0aWdub3JlUGF0aCwgcGF0Y2hlZCwgXCJ1dGYtOFwiKTtcbiAgcmV0dXJuIFwicGF0Y2hlZFwiO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuSW5pdChvcHRzOiB7IHByb2plY3RSb290Pzogc3RyaW5nIH0gPSB7fSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBwcm9qZWN0Um9vdCA9IG9wdHMucHJvamVjdFJvb3QgPz8gcHJvY2Vzcy5jd2QoKTtcbiAgY29uc3QgaG9tZURpciA9IGhvbWVkaXIoKTtcbiAgY29uc3QgZ2xvYmFsQ29uZmlnRGlyID0gam9pbihob21lRGlyLCBcIi5mcmFwcGUtYnVpbGRlclwiKTtcbiAgY29uc3QgZ2xvYmFsQ29uZmlnUGF0aCA9IGpvaW4oZ2xvYmFsQ29uZmlnRGlyLCBcImNvbmZpZy5qc29uXCIpO1xuICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aCA9IGpvaW4ocHJvamVjdFJvb3QsIFwiLmZyYXBwZS1idWlsZGVyLWNvbmZpZy5qc29uXCIpO1xuXG4gIGNvbnNvbGUubG9nKFwiXFxuPT09IGZyYXBwZS1idWlsZGVyIFNldHVwID09PVxcblwiKTtcblxuICAvLyDilIDilIAgR2xvYmFsIGNvbmZpZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgY29uc29sZS5sb2coYFtHbG9iYWwgY29uZmlnOiAke2dsb2JhbENvbmZpZ1BhdGh9XWApO1xuXG4gIGxldCBnbG9iYWxDb25maWc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gIGxldCBnbG9iYWxBY3Rpb246IFwid3JpdHRlblwiIHwgXCJza2lwcGVkXCIgPSBcIndyaXR0ZW5cIjtcblxuICBpZiAoZXhpc3RzU3luYyhnbG9iYWxDb25maWdQYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBnbG9iYWxDb25maWcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhnbG9iYWxDb25maWdQYXRoLCBcInV0Zi04XCIpKSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICB9IGNhdGNoIHsgLyogaWdub3JlIG1hbGZvcm1lZCBmaWxlIOKAlCBvdmVyd3JpdGUgKi8gfVxuICAgIGlmICghY2FuY2VsbGVkKSB7XG4gICAgICBjb25zdCBvdmVyd3JpdGUgPSBhd2FpdCBwcm9tcHRZTihgT3ZlcndyaXRlIGV4aXN0aW5nICR7Z2xvYmFsQ29uZmlnUGF0aH0/YCk7XG4gICAgICBpZiAoY2FuY2VsbGVkKSB7IHByaW50Q2FuY2VsbGVkKCk7IHJldHVybjsgfVxuICAgICAgaWYgKCFvdmVyd3JpdGUpIHtcbiAgICAgICAgZ2xvYmFsQWN0aW9uID0gXCJza2lwcGVkXCI7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiICBLZWVwaW5nIGV4aXN0aW5nIGdsb2JhbCBjb25maWcuXFxuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICghY2FuY2VsbGVkICYmIGdsb2JhbEFjdGlvbiA9PT0gXCJ3cml0dGVuXCIpIHtcbiAgICBjb25zdCBsbG1LZXkgPSBhd2FpdCBwcm9tcHRMaW5lKFwiTExNIEFQSSBrZXkgKGxlYXZlIGJsYW5rIHRvIHNraXApOiBcIik7XG4gICAgaWYgKGNhbmNlbGxlZCkgeyBwcmludENhbmNlbGxlZCgpOyByZXR1cm47IH1cbiAgICBnbG9iYWxDb25maWcubGxtX2FwaV9rZXkgPSBsbG1LZXkudHJpbSgpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFByb2plY3QgY29uZmlnIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBjb25zb2xlLmxvZyhgXFxuW1Byb2plY3QgY29uZmlnOiAke3Byb2plY3RDb25maWdQYXRofV1gKTtcblxuICBsZXQgcHJvamVjdENvbmZpZzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgbGV0IHByb2plY3RBY3Rpb246IFwid3JpdHRlblwiIHwgXCJza2lwcGVkXCIgPSBcIndyaXR0ZW5cIjtcblxuICBpZiAoZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnUGF0aCkpIHtcbiAgICB0cnkge1xuICAgICAgcHJvamVjdENvbmZpZyA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHByb2plY3RDb25maWdQYXRoLCBcInV0Zi04XCIpKSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICB9IGNhdGNoIHsgLyogaWdub3JlIG1hbGZvcm1lZCBmaWxlIOKAlCBvdmVyd3JpdGUgKi8gfVxuICAgIGlmICghY2FuY2VsbGVkKSB7XG4gICAgICBjb25zdCBvdmVyd3JpdGUgPSBhd2FpdCBwcm9tcHRZTihgT3ZlcndyaXRlIGV4aXN0aW5nICR7cHJvamVjdENvbmZpZ1BhdGh9P2ApO1xuICAgICAgaWYgKGNhbmNlbGxlZCkgeyBwcmludENhbmNlbGxlZCgpOyByZXR1cm47IH1cbiAgICAgIGlmICghb3ZlcndyaXRlKSB7XG4gICAgICAgIHByb2plY3RBY3Rpb24gPSBcInNraXBwZWRcIjtcbiAgICAgICAgY29uc29sZS5sb2coXCIgIEtlZXBpbmcgZXhpc3RpbmcgcHJvamVjdCBjb25maWcuXFxuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICghY2FuY2VsbGVkICYmIHByb2plY3RBY3Rpb24gPT09IFwid3JpdHRlblwiKSB7XG4gICAgY29uc3Qgc2l0ZVVybCA9IGF3YWl0IHByb21wdExpbmUoXCJGcmFwcGUgc2l0ZSBVUkwgKGUuZy4gaHR0cDovL3NpdGUxLmxvY2FsaG9zdCk6IFwiKTtcbiAgICBpZiAoY2FuY2VsbGVkKSB7IHByaW50Q2FuY2VsbGVkKCk7IHJldHVybjsgfVxuICAgIGNvbnN0IGFwaUtleSA9IGF3YWl0IHByb21wdExpbmUoXCJGcmFwcGUgQVBJIGtleTogXCIpO1xuICAgIGlmIChjYW5jZWxsZWQpIHsgcHJpbnRDYW5jZWxsZWQoKTsgcmV0dXJuOyB9XG4gICAgY29uc3QgYXBpU2VjcmV0ID0gYXdhaXQgcHJvbXB0TGluZShcIkZyYXBwZSBBUEkgc2VjcmV0OiBcIik7XG4gICAgaWYgKGNhbmNlbGxlZCkgeyBwcmludENhbmNlbGxlZCgpOyByZXR1cm47IH1cbiAgICBwcm9qZWN0Q29uZmlnID0ge1xuICAgICAgc2l0ZV91cmw6IHNpdGVVcmwudHJpbSgpLFxuICAgICAgYXBpX2tleTogYXBpS2V5LnRyaW0oKSxcbiAgICAgIGFwaV9zZWNyZXQ6IGFwaVNlY3JldC50cmltKCksXG4gICAgfTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBBbGwgcHJvbXB0cyBjb2xsZWN0ZWQg4oCUIG5vdyB3cml0ZSBmaWxlcyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgY29uc3Qgd3JpdHRlbjogc3RyaW5nW10gPSBbXTtcbiAgY29uc3Qgc2tpcHBlZDogc3RyaW5nW10gPSBbXTtcblxuICAvLyBHbG9iYWwgY29uZmlnXG4gIGlmIChnbG9iYWxBY3Rpb24gPT09IFwid3JpdHRlblwiKSB7XG4gICAgbWtkaXJTeW5jKGdsb2JhbENvbmZpZ0RpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgd3JpdGVBdG9taWMoZ2xvYmFsQ29uZmlnUGF0aCwgSlNPTi5zdHJpbmdpZnkoZ2xvYmFsQ29uZmlnLCBudWxsLCAyKSArIFwiXFxuXCIpO1xuICAgIHdyaXR0ZW4ucHVzaChgfi8uZnJhcHBlLWJ1aWxkZXIvY29uZmlnLmpzb25gKTtcbiAgfSBlbHNlIHtcbiAgICBza2lwcGVkLnB1c2goYH4vLmZyYXBwZS1idWlsZGVyL2NvbmZpZy5qc29uYCk7XG4gIH1cblxuICAvLyBQcm9qZWN0IGNvbmZpZ1xuICBpZiAocHJvamVjdEFjdGlvbiA9PT0gXCJ3cml0dGVuXCIpIHtcbiAgICB3cml0ZUF0b21pYyhwcm9qZWN0Q29uZmlnUGF0aCwgSlNPTi5zdHJpbmdpZnkocHJvamVjdENvbmZpZywgbnVsbCwgMikgKyBcIlxcblwiKTtcbiAgICB3cml0dGVuLnB1c2goYC5mcmFwcGUtYnVpbGRlci1jb25maWcuanNvbmApO1xuICB9IGVsc2Uge1xuICAgIHNraXBwZWQucHVzaChgLmZyYXBwZS1idWlsZGVyLWNvbmZpZy5qc29uYCk7XG4gIH1cblxuICAvLyBHaXRpZ25vcmUgcGF0Y2hcbiAgY29uc3QgZ2l0aWdub3JlUmVzdWx0ID0gcGF0Y2hHaXRpZ25vcmUocHJvamVjdFJvb3QsIFwiLmZyYXBwZS1idWlsZGVyLWNvbmZpZy5qc29uXCIpO1xuICBpZiAoZ2l0aWdub3JlUmVzdWx0ID09PSBcInBhdGNoZWRcIikge1xuICAgIHdyaXR0ZW4ucHVzaChcIi5naXRpZ25vcmUgKHBhdGNoZWQpXCIpO1xuICB9IGVsc2UgaWYgKGdpdGlnbm9yZVJlc3VsdCA9PT0gXCJjcmVhdGVkXCIpIHtcbiAgICB3cml0dGVuLnB1c2goXCIuZ2l0aWdub3JlIChjcmVhdGVkKVwiKTtcbiAgfSBlbHNlIHtcbiAgICBza2lwcGVkLnB1c2goXCIuZ2l0aWdub3JlIChlbnRyeSBhbHJlYWR5IHByZXNlbnQpXCIpO1xuICB9XG5cbiAgLy8g4pSA4pSAIGNvbnRleHQtbW9kZSBNQ1AgZXh0ZW5zaW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBhd2FpdCBzZXR1cENvbnRleHRNb2RlKGhvbWVEaXIpO1xuXG4gIC8vIOKUgOKUgCBtY3AyY2xpIHNraWxsICsgY29udGV4dC1tb2RlIGJha2Ug4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIHNldHVwTWNwMmNsaShob21lRGlyKTtcblxuICAvLyDilIDilIAgU3VtbWFyeSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgY29uc29sZS5sb2coXCJcXG5GaWxlcyB3cml0dGVuOlwiKTtcbiAgZm9yIChjb25zdCBmIG9mIHdyaXR0ZW4pIHtcbiAgICBjb25zb2xlLmxvZyhgICDinJMgJHtmfWApO1xuICB9XG4gIGlmIChza2lwcGVkLmxlbmd0aCA+IDApIHtcbiAgICBjb25zb2xlLmxvZyhcIlNraXBwZWQ6XCIpO1xuICAgIGZvciAoY29uc3QgZiBvZiBza2lwcGVkKSB7XG4gICAgICBjb25zb2xlLmxvZyhgICAtICR7Zn1gKTtcbiAgICB9XG4gIH1cblxuICBjb25zb2xlLmxvZyhcIlxcblJlYWR5LiBSdW46IGZyYXBwZS1idWlsZGVyXFxuXCIpO1xufVxuXG5mdW5jdGlvbiBwcmludENhbmNlbGxlZCgpOiB2b2lkIHtcbiAgY29uc29sZS5sb2coXCJcXG5TZXR1cCBjYW5jZWxsZWQuIE5vIGZpbGVzIHdlcmUgd3JpdHRlbi5cXG5cIik7XG59XG5cbi8qKlxuICogSW5zdGFsbHMgYW5kIGNvbmZpZ3VyZXMgdGhlIGNvbnRleHQtbW9kZSBwaSBNQ1AgZXh0ZW5zaW9uLlxuICogQ2xvbmVzIGh0dHBzOi8vZ2l0aHViLmNvbS9ta3NnbHUvY29udGV4dC1tb2RlIGludG8gfi8ucGkvZXh0ZW5zaW9ucy9jb250ZXh0LW1vZGUsXG4gKiBidWlsZHMgaXQsIGFuZCBwYXRjaGVzIH4vLnBpL3NldHRpbmdzL21jcC5qc29uIHdpdGggdGhlIHNlcnZlciBlbnRyeS5cbiAqXG4gKiBOb24tZmF0YWwg4oCUIGZhaWx1cmVzIGFyZSBsb2dnZWQgYXMgd2FybmluZ3MsIG5ldmVyIGFib3J0IGluaXQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXR1cENvbnRleHRNb2RlKGhvbWVEaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBleHREaXIgPSBqb2luKGhvbWVEaXIsIFwiLnBpXCIsIFwiZXh0ZW5zaW9uc1wiLCBcImNvbnRleHQtbW9kZVwiKTtcbiAgY29uc3QgbWNwU2V0dGluZ3NEaXIgPSBqb2luKGhvbWVEaXIsIFwiLnBpXCIsIFwic2V0dGluZ3NcIik7XG4gIGNvbnN0IG1jcFNldHRpbmdzUGF0aCA9IGpvaW4obWNwU2V0dGluZ3NEaXIsIFwibWNwLmpzb25cIik7XG4gIGNvbnN0IHN0YXJ0U2NyaXB0ID0gam9pbihleHREaXIsIFwibm9kZV9tb2R1bGVzXCIsIFwiY29udGV4dC1tb2RlXCIsIFwic3RhcnQubWpzXCIpO1xuXG4gIGNvbnNvbGUubG9nKFwiXFxuW2NvbnRleHQtbW9kZSBNQ1AgZXh0ZW5zaW9uXVwiKTtcblxuICAvLyDilIDilIAgQWxyZWFkeSBpbnN0YWxsZWQ/IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBpZiAoZXhpc3RzU3luYyhleHREaXIpKSB7XG4gICAgY29uc29sZS5sb2coXCIgIOKckyBjb250ZXh0LW1vZGUgYWxyZWFkeSBpbnN0YWxsZWQgYXQgfi8ucGkvZXh0ZW5zaW9ucy9jb250ZXh0LW1vZGVcIik7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2coXCIgIGNvbnRleHQtbW9kZSBub3QgZm91bmQg4oCUIGluc3RhbGxpbmcgKHJlcXVpcmVzIGdpdCArIE5vZGUuanMpLi4uXCIpO1xuICAgIG1rZGlyU3luYyhqb2luKGhvbWVEaXIsIFwiLnBpXCIsIFwiZXh0ZW5zaW9uc1wiKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICBjb25zdCBjbG9uZSA9IHNwYXduU3luYyhcImdpdFwiLCBbXG4gICAgICBcImNsb25lXCIsIFwiaHR0cHM6Ly9naXRodWIuY29tL21rc2dsdS9jb250ZXh0LW1vZGUuZ2l0XCIsIGV4dERpcixcbiAgICBdLCB7IHN0ZGlvOiBcInBpcGVcIiB9KTtcblxuICAgIGlmIChjbG9uZS5zdGF0dXMgIT09IDApIHtcbiAgICAgIGNvbnNvbGUud2FybihgICDimqAgZ2l0IGNsb25lIGZhaWxlZDogJHtjbG9uZS5zdGRlcnI/LnRvU3RyaW5nKCkudHJpbSgpfWApO1xuICAgICAgY29uc29sZS53YXJuKFwiICBTa2lwcGluZyBjb250ZXh0LW1vZGUgc2V0dXAuIEluc3RhbGwgbWFudWFsbHk6IGh0dHBzOi8vZ2l0aHViLmNvbS9ta3NnbHUvY29udGV4dC1tb2RlXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGluc3RhbGwgPSBzcGF3blN5bmMoXCJucG1cIiwgW1wiaW5zdGFsbFwiXSwgeyBjd2Q6IGV4dERpciwgc3RkaW86IFwicGlwZVwiIH0pO1xuICAgIGlmIChpbnN0YWxsLnN0YXR1cyAhPT0gMCkge1xuICAgICAgY29uc29sZS53YXJuKGAgIOKaoCBucG0gaW5zdGFsbCBmYWlsZWQ6ICR7aW5zdGFsbC5zdGRlcnI/LnRvU3RyaW5nKCkudHJpbSgpfWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1aWxkID0gc3Bhd25TeW5jKFwibnBtXCIsIFtcInJ1blwiLCBcImJ1aWxkXCJdLCB7IGN3ZDogZXh0RGlyLCBzdGRpbzogXCJwaXBlXCIgfSk7XG4gICAgaWYgKGJ1aWxkLnN0YXR1cyAhPT0gMCkge1xuICAgICAgY29uc29sZS53YXJuKGAgIOKaoCBucG0gcnVuIGJ1aWxkIGZhaWxlZDogJHtidWlsZC5zdGRlcnI/LnRvU3RyaW5nKCkudHJpbSgpfWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKFwiICDinJMgY29udGV4dC1tb2RlIGluc3RhbGxlZCBhbmQgYnVpbHRcIik7XG4gIH1cblxuICAvLyDilIDilIAgUGF0Y2ggfi8ucGkvc2V0dGluZ3MvbWNwLmpzb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIG1rZGlyU3luYyhtY3BTZXR0aW5nc0RpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgbGV0IG1jcENvbmZpZzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgaWYgKGV4aXN0c1N5bmMobWNwU2V0dGluZ3NQYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBtY3BDb25maWcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhtY3BTZXR0aW5nc1BhdGgsIFwidXRmLThcIikpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIH0gY2F0Y2ggeyAvKiBvdmVyd3JpdGUgbWFsZm9ybWVkIGZpbGUgKi8gfVxuICB9XG5cbiAgY29uc3Qgc2VydmVycyA9IChtY3BDb25maWcubWNwU2VydmVycyA/PyB7fSkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGlmIChzZXJ2ZXJzW1wiY29udGV4dC1tb2RlXCJdKSB7XG4gICAgY29uc29sZS5sb2coXCIgIOKckyBjb250ZXh0LW1vZGUgYWxyZWFkeSBpbiB+Ly5waS9zZXR0aW5ncy9tY3AuanNvblwiKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBzZXJ2ZXJzW1wiY29udGV4dC1tb2RlXCJdID0ge1xuICAgIGNvbW1hbmQ6IFwibm9kZVwiLFxuICAgIGFyZ3M6IFtzdGFydFNjcmlwdF0sXG4gIH07XG4gIG1jcENvbmZpZy5tY3BTZXJ2ZXJzID0gc2VydmVycztcblxuICB3cml0ZUF0b21pYyhtY3BTZXR0aW5nc1BhdGgsIEpTT04uc3RyaW5naWZ5KG1jcENvbmZpZywgbnVsbCwgMikgKyBcIlxcblwiKTtcbiAgY29uc29sZS5sb2coXCIgIOKckyBBZGRlZCBjb250ZXh0LW1vZGUgdG8gfi8ucGkvc2V0dGluZ3MvbWNwLmpzb25cIik7XG4gIGNvbnNvbGUubG9nKFwiICBSZXN0YXJ0IHBpIChvciBmcmFwcGUtYnVpbGRlcikgZm9yIGNvbnRleHQtbW9kZSB0byBhY3RpdmF0ZS5cIik7XG59XG5cbi8qKlxuICogSW5zdGFsbHMgdGhlIG1jcDJjbGkgQ2xhdWRlIENvZGUgc2tpbGwgYW5kIGJha2VzIHRoZSBjb250ZXh0LW1vZGUgY29ubmVjdGlvblxuICogc28gdGhlIGFnZW50IGNhbiBjYWxsIGBtY3AyY2xpIEBjb250ZXh0LW1vZGUgPHRvb2w+YCB3aXRob3V0IHJlcGVhdGluZyBmbGFncy5cbiAqXG4gKiBOb24tZmF0YWwg4oCUIGZhaWx1cmVzIGFyZSBsb2dnZWQgYXMgd2FybmluZ3MsIG5ldmVyIGFib3J0IGluaXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cE1jcDJjbGkoaG9tZURpcjogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHN0YXJ0U2NyaXB0ID0gam9pbihcbiAgICBob21lRGlyLCBcIi5waVwiLCBcImV4dGVuc2lvbnNcIiwgXCJjb250ZXh0LW1vZGVcIixcbiAgICBcIm5vZGVfbW9kdWxlc1wiLCBcImNvbnRleHQtbW9kZVwiLCBcInN0YXJ0Lm1qc1wiXG4gICk7XG5cbiAgY29uc29sZS5sb2coXCJcXG5bbWNwMmNsaSBza2lsbCArIGNvbnRleHQtbW9kZSBiYWtlXVwiKTtcblxuICAvLyDilIDilIAgSW5zdGFsbCBtY3AyY2xpIENsYXVkZSBDb2RlIHNraWxsIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICBjb25zdCBza2lsbEFkZCA9IHNwYXduU3luYyhcbiAgICBcIm5weFwiLFxuICAgIFtcInNraWxsc1wiLCBcImFkZFwiLCBcImtub3dzdWNoYWdlbmN5L21jcDJjbGlcIiwgXCItLXNraWxsXCIsIFwibWNwMmNsaVwiXSxcbiAgICB7IHN0ZGlvOiBcInBpcGVcIiB9XG4gICk7XG4gIGlmIChza2lsbEFkZC5zdGF0dXMgIT09IDApIHtcbiAgICBjb25zb2xlLndhcm4oYCAg4pqgIG1jcDJjbGkgc2tpbGwgaW5zdGFsbCBmYWlsZWQ6ICR7c2tpbGxBZGQuc3RkZXJyPy50b1N0cmluZygpLnRyaW0oKX1gKTtcbiAgICBjb25zb2xlLndhcm4oXCIgIEluc3RhbGwgbWFudWFsbHk6IG5weCBza2lsbHMgYWRkIGtub3dzdWNoYWdlbmN5L21jcDJjbGkgLS1za2lsbCBtY3AyY2xpXCIpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUubG9nKFwiICDinJMgbWNwMmNsaSBza2lsbCBpbnN0YWxsZWRcIik7XG4gIH1cblxuICAvLyDilIDilIAgQmFrZSBjb250ZXh0LW1vZGUgY29ubmVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gQ2hlY2sgaWYgYWxyZWFkeSBiYWtlZFxuICBjb25zdCBiYWtlU2hvdyA9IHNwYXduU3luYyhcIm1jcDJjbGlcIiwgW1wiYmFrZVwiLCBcInNob3dcIiwgXCJjb250ZXh0LW1vZGVcIl0sIHsgc3RkaW86IFwicGlwZVwiIH0pO1xuICBpZiAoYmFrZVNob3cuc3RhdHVzID09PSAwKSB7XG4gICAgY29uc29sZS5sb2coXCIgIOKckyBtY3AyY2xpIEBjb250ZXh0LW1vZGUgYWxyZWFkeSBiYWtlZFwiKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIWV4aXN0c1N5bmMoc3RhcnRTY3JpcHQpKSB7XG4gICAgY29uc29sZS53YXJuKFwiICDimqAgY29udGV4dC1tb2RlIHN0YXJ0Lm1qcyBub3QgZm91bmQg4oCUIHNraXBwaW5nIGJha2UgKHJ1biBpbml0IGFnYWluIGFmdGVyIGNvbnRleHQtbW9kZSBpbnN0YWxscylcIik7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgYmFrZUNyZWF0ZSA9IHNwYXduU3luYyhcbiAgICBcIm1jcDJjbGlcIixcbiAgICBbXCJiYWtlXCIsIFwiY3JlYXRlXCIsIFwiY29udGV4dC1tb2RlXCIsIFwiLS1tY3Atc3RkaW9cIiwgYG5vZGUgJHtzdGFydFNjcmlwdH1gXSxcbiAgICB7IHN0ZGlvOiBcInBpcGVcIiB9XG4gICk7XG4gIGlmIChiYWtlQ3JlYXRlLnN0YXR1cyAhPT0gMCkge1xuICAgIGNvbnNvbGUud2FybihgICDimqAgbWNwMmNsaSBiYWtlIGZhaWxlZDogJHtiYWtlQ3JlYXRlLnN0ZGVycj8udG9TdHJpbmcoKS50cmltKCl9YCk7XG4gICAgY29uc29sZS53YXJuKFwiICBJbnN0YWxsIG1jcDJjbGkgZmlyc3Q6IHBpcCBpbnN0YWxsIG1jcDJjbGlcIik7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2coXCIgIOKckyBtY3AyY2xpIEBjb250ZXh0LW1vZGUgYmFrZWQg4oCUIGFnZW50IGNhbiBub3cgY2FsbDogbWNwMmNsaSBAY29udGV4dC1tb2RlIDx0b29sPlwiKTtcbiAgfVxufVxuIl0sImZpbGUiOiIvc3JjL2luaXQudHMifQ==
317
-
318
- //# vitestCache=W3siZmlsZSI6IjEiLCJpZCI6IjEiLCJ1cmwiOiIyIiwiaW1wb3J0ZWRVcmxzIjoiMyIsIm1hcHBpbmdzIjpmYWxzZX0sIi9ob21lL3Jpei9mcmFwcGUtYnVpbGRlci9zcmMvaW5pdC50cyIsIi9zcmMvaW5pdC50cyIsW11d
@@ -1,207 +0,0 @@
1
- const __vite_ssr_import_0__ = await __vite_ssr_import__("/node_modules/vitest/dist/index.js", {"importedNames":["describe","it","expect","vi","beforeEach","afterEach"]});
2
- __vite_ssr_import_0__.vi.mock("node:os", async (importOriginal) => {
3
- const actual = await importOriginal();
4
- return {
5
- ...actual,
6
- homedir: __vite_ssr_import_0__.vi.fn(() => actual.homedir())
7
- };
8
- });
9
- __vite_ssr_import_0__.vi.mock("node:readline", () => ({ createInterface: __vite_ssr_import_0__.vi.fn(() => ({
10
- question: __vite_ssr_import_0__.vi.fn((_q, cb) => {
11
- cb(mockAnswers.shift() ?? "");
12
- }),
13
- close: __vite_ssr_import_0__.vi.fn()
14
- })) }));
15
- const __vi_import_0__ = await __vite_ssr_dynamic_import__("node:fs");
16
- const __vi_import_1__ = await __vite_ssr_dynamic_import__("node:path");
17
- const __vi_import_2__ = await __vite_ssr_dynamic_import__("node:os");
18
- const __vi_import_3__ = await __vite_ssr_dynamic_import__("/src/init.ts");
19
-
20
-
21
-
22
- // ── Top-level mocks — must be hoisted before any imports that use them ───────
23
- // Shared answer queue — tests push answers before calling runInit
24
- const mockAnswers = [];
25
-
26
-
27
- // ── patchGitignore ───────────────────────────────────────────────────────────
28
- (0,__vite_ssr_import_0__.describe)("patchGitignore", () => {
29
- let tmpDir;
30
- (0,__vite_ssr_import_0__.beforeEach)(() => {
31
- tmpDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-gitignore-"));
32
- });
33
- (0,__vite_ssr_import_0__.afterEach)(() => {
34
- __vi_import_0__.rmSync(tmpDir, {
35
- recursive: true,
36
- force: true
37
- });
38
- });
39
- (0,__vite_ssr_import_0__.it)("creates .gitignore from scratch when absent and adds the entry", () => {
40
- const result = __vi_import_3__.patchGitignore(tmpDir, ".frappe-builder-config.json");
41
- (0,__vite_ssr_import_0__.expect)(result).toBe("created");
42
- const content = __vi_import_0__.readFileSync(__vi_import_1__.join(tmpDir, ".gitignore"), "utf-8");
43
- (0,__vite_ssr_import_0__.expect)(content).toContain(".frappe-builder-config.json");
44
- });
45
- (0,__vite_ssr_import_0__.it)("appends line when .gitignore exists but entry is absent", () => {
46
- __vi_import_0__.writeFileSync(__vi_import_1__.join(tmpDir, ".gitignore"), "node_modules\n.env\n", "utf-8");
47
- const result = __vi_import_3__.patchGitignore(tmpDir, ".frappe-builder-config.json");
48
- (0,__vite_ssr_import_0__.expect)(result).toBe("patched");
49
- const content = __vi_import_0__.readFileSync(__vi_import_1__.join(tmpDir, ".gitignore"), "utf-8");
50
- const lines = content.split("\n");
51
- (0,__vite_ssr_import_0__.expect)(lines).toContain(".frappe-builder-config.json");
52
- (0,__vite_ssr_import_0__.expect)(lines).toContain("node_modules");
53
- (0,__vite_ssr_import_0__.expect)(lines).toContain(".env");
54
- });
55
- (0,__vite_ssr_import_0__.it)("does NOT duplicate entry when already present", () => {
56
- __vi_import_0__.writeFileSync(__vi_import_1__.join(tmpDir, ".gitignore"), "node_modules\n.frappe-builder-config.json\n.env\n", "utf-8");
57
- const result = __vi_import_3__.patchGitignore(tmpDir, ".frappe-builder-config.json");
58
- (0,__vite_ssr_import_0__.expect)(result).toBe("already-present");
59
- const content = __vi_import_0__.readFileSync(__vi_import_1__.join(tmpDir, ".gitignore"), "utf-8");
60
- const count = content.split("\n").filter((l) => l === ".frappe-builder-config.json").length;
61
- (0,__vite_ssr_import_0__.expect)(count).toBe(1);
62
- });
63
- (0,__vite_ssr_import_0__.it)("does NOT accept a glob pattern as a match — requires exact filename", () => {
64
- __vi_import_0__.writeFileSync(__vi_import_1__.join(tmpDir, ".gitignore"), "*.json\n", "utf-8");
65
- const result = __vi_import_3__.patchGitignore(tmpDir, ".frappe-builder-config.json");
66
- (0,__vite_ssr_import_0__.expect)(result).toBe("patched");
67
- });
68
- });
69
- // ── runInit — file writes ────────────────────────────────────────────────────
70
- (0,__vite_ssr_import_0__.describe)("runInit — file writes", () => {
71
- let projectDir;
72
- let homeDir;
73
- (0,__vite_ssr_import_0__.beforeEach)(() => {
74
- projectDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-proj-"));
75
- homeDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-home-"));
76
- __vite_ssr_import_0__.vi.mocked(__vi_import_2__.homedir).mockReturnValue(homeDir);
77
- mockAnswers.length = 0;
78
- });
79
- (0,__vite_ssr_import_0__.afterEach)(() => {
80
- __vite_ssr_import_0__.vi.clearAllMocks();
81
- __vi_import_0__.rmSync(projectDir, {
82
- recursive: true,
83
- force: true
84
- });
85
- __vi_import_0__.rmSync(homeDir, {
86
- recursive: true,
87
- force: true
88
- });
89
- });
90
- (0,__vite_ssr_import_0__.it)("writes global config to ~/.frappe-builder/config.json", async () => {
91
- // Answers: llm_api_key, site_url, api_key, api_secret
92
- mockAnswers.push("sk-test", "http://erp.localhost", "key123", "secret456");
93
- await __vi_import_3__.runInit({ projectRoot: projectDir });
94
- const configPath = __vi_import_1__.join(homeDir, ".frappe-builder", "config.json");
95
- (0,__vite_ssr_import_0__.expect)(__vi_import_0__.existsSync(configPath)).toBe(true);
96
- const cfg = JSON.parse(__vi_import_0__.readFileSync(configPath, "utf-8"));
97
- (0,__vite_ssr_import_0__.expect)(cfg.llm_api_key).toBe("sk-test");
98
- });
99
- (0,__vite_ssr_import_0__.it)("writes project config to {projectRoot}/.frappe-builder-config.json", async () => {
100
- mockAnswers.push("sk-test", "http://erp.localhost", "key123", "secret456");
101
- await __vi_import_3__.runInit({ projectRoot: projectDir });
102
- const configPath = __vi_import_1__.join(projectDir, ".frappe-builder-config.json");
103
- (0,__vite_ssr_import_0__.expect)(__vi_import_0__.existsSync(configPath)).toBe(true);
104
- const cfg = JSON.parse(__vi_import_0__.readFileSync(configPath, "utf-8"));
105
- (0,__vite_ssr_import_0__.expect)(cfg.site_url).toBe("http://erp.localhost");
106
- (0,__vite_ssr_import_0__.expect)(cfg.api_key).toBe("key123");
107
- (0,__vite_ssr_import_0__.expect)(cfg.api_secret).toBe("secret456");
108
- });
109
- (0,__vite_ssr_import_0__.it)("patches .gitignore automatically", async () => {
110
- mockAnswers.push("sk-test", "http://erp.localhost", "key123", "secret456");
111
- await __vi_import_3__.runInit({ projectRoot: projectDir });
112
- const content = __vi_import_0__.readFileSync(__vi_import_1__.join(projectDir, ".gitignore"), "utf-8");
113
- (0,__vite_ssr_import_0__.expect)(content).toContain(".frappe-builder-config.json");
114
- });
115
- (0,__vite_ssr_import_0__.it)("creates ~/.frappe-builder/ directory if it does not exist", async () => {
116
- mockAnswers.push("", "http://site.localhost", "k", "s");
117
- await __vi_import_3__.runInit({ projectRoot: projectDir });
118
- (0,__vite_ssr_import_0__.expect)(__vi_import_0__.existsSync(__vi_import_1__.join(homeDir, ".frappe-builder"))).toBe(true);
119
- });
120
- });
121
- // ── runInit — overwrite guard ────────────────────────────────────────────────
122
- (0,__vite_ssr_import_0__.describe)("runInit — overwrite guard", () => {
123
- let projectDir;
124
- let homeDir;
125
- (0,__vite_ssr_import_0__.beforeEach)(() => {
126
- projectDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-guard-proj-"));
127
- homeDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-guard-home-"));
128
- __vite_ssr_import_0__.vi.mocked(__vi_import_2__.homedir).mockReturnValue(homeDir);
129
- mockAnswers.length = 0;
130
- });
131
- (0,__vite_ssr_import_0__.afterEach)(() => {
132
- __vite_ssr_import_0__.vi.clearAllMocks();
133
- __vi_import_0__.rmSync(projectDir, {
134
- recursive: true,
135
- force: true
136
- });
137
- __vi_import_0__.rmSync(homeDir, {
138
- recursive: true,
139
- force: true
140
- });
141
- });
142
- (0,__vite_ssr_import_0__.it)("does NOT overwrite existing global config when user declines", async () => {
143
- const configDir = __vi_import_1__.join(homeDir, ".frappe-builder");
144
- __vi_import_0__.mkdirSync(configDir, { recursive: true });
145
- const globalPath = __vi_import_1__.join(configDir, "config.json");
146
- __vi_import_0__.writeFileSync(globalPath, JSON.stringify({ llm_api_key: "original-key" }), "utf-8");
147
- // Overwrite global? → "n" | Overwrite project? → "n"
148
- mockAnswers.push("n", "n");
149
- await __vi_import_3__.runInit({ projectRoot: projectDir });
150
- const cfg = JSON.parse(__vi_import_0__.readFileSync(globalPath, "utf-8"));
151
- (0,__vite_ssr_import_0__.expect)(cfg.llm_api_key).toBe("original-key");
152
- });
153
- (0,__vite_ssr_import_0__.it)("overwrites existing global config when user confirms", async () => {
154
- const configDir = __vi_import_1__.join(homeDir, ".frappe-builder");
155
- __vi_import_0__.mkdirSync(configDir, { recursive: true });
156
- const globalPath = __vi_import_1__.join(configDir, "config.json");
157
- __vi_import_0__.writeFileSync(globalPath, JSON.stringify({ llm_api_key: "old-key" }), "utf-8");
158
- // Overwrite global? → "y", new llm_key, site_url, api_key, api_secret
159
- mockAnswers.push("y", "new-key", "http://site.localhost", "k", "s");
160
- await __vi_import_3__.runInit({ projectRoot: projectDir });
161
- const cfg = JSON.parse(__vi_import_0__.readFileSync(globalPath, "utf-8"));
162
- (0,__vite_ssr_import_0__.expect)(cfg.llm_api_key).toBe("new-key");
163
- });
164
- (0,__vite_ssr_import_0__.it)("does NOT overwrite existing project config when user declines", async () => {
165
- const projConfigPath = __vi_import_1__.join(projectDir, ".frappe-builder-config.json");
166
- __vi_import_0__.writeFileSync(projConfigPath, JSON.stringify({
167
- site_url: "http://original.localhost",
168
- api_key: "orig",
169
- api_secret: "s"
170
- }), "utf-8");
171
- // llm_api_key prompt (no existing global), overwrite project? → "n"
172
- mockAnswers.push("sk-new", "n");
173
- await __vi_import_3__.runInit({ projectRoot: projectDir });
174
- const cfg = JSON.parse(__vi_import_0__.readFileSync(projConfigPath, "utf-8"));
175
- (0,__vite_ssr_import_0__.expect)(cfg.site_url).toBe("http://original.localhost");
176
- });
177
- });
178
- // ── runInit — clean exit ─────────────────────────────────────────────────────
179
- (0,__vite_ssr_import_0__.describe)("runInit — clean exit", () => {
180
- let projectDir;
181
- let homeDir;
182
- (0,__vite_ssr_import_0__.beforeEach)(() => {
183
- projectDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-exit-"));
184
- homeDir = __vi_import_0__.mkdtempSync(__vi_import_1__.join("/tmp", "fb-init-exit-home-"));
185
- __vite_ssr_import_0__.vi.mocked(__vi_import_2__.homedir).mockReturnValue(homeDir);
186
- mockAnswers.length = 0;
187
- });
188
- (0,__vite_ssr_import_0__.afterEach)(() => {
189
- __vite_ssr_import_0__.vi.clearAllMocks();
190
- __vi_import_0__.rmSync(projectDir, {
191
- recursive: true,
192
- force: true
193
- });
194
- __vi_import_0__.rmSync(homeDir, {
195
- recursive: true,
196
- force: true
197
- });
198
- });
199
- (0,__vite_ssr_import_0__.it)("resolves without throwing when all prompts return empty strings", async () => {
200
- mockAnswers.push("", "", "", "");
201
- await (0,__vite_ssr_import_0__.expect)(__vi_import_3__.runInit({ projectRoot: projectDir })).resolves.toBeUndefined();
202
- });
203
- });
204
- //# sourceMappingSource=vite-generated
205
- //# sourceMappingURL=data:application/json;base64,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b3JlTGlzdCI6W10sInNvdXJjZXMiOlsiaW5pdC50ZXN0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRlc2NyaWJlLCBpdCwgZXhwZWN0LCB2aSwgYmVmb3JlRWFjaCwgYWZ0ZXJFYWNoIH0gZnJvbSBcInZpdGVzdFwiO1xuaW1wb3J0IHsgbWtkdGVtcFN5bmMsIHJtU3luYywgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jLCBleGlzdHNTeW5jLCBta2RpclN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcblxuLy8g4pSA4pSAIFRvcC1sZXZlbCBtb2NrcyDigJQgbXVzdCBiZSBob2lzdGVkIGJlZm9yZSBhbnkgaW1wb3J0cyB0aGF0IHVzZSB0aGVtIOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG52aS5tb2NrKFwibm9kZTpvc1wiLCBhc3luYyAoaW1wb3J0T3JpZ2luYWwpID0+IHtcbiAgY29uc3QgYWN0dWFsID0gYXdhaXQgaW1wb3J0T3JpZ2luYWw8dHlwZW9mIGltcG9ydChcIm5vZGU6b3NcIik+KCk7XG4gIHJldHVybiB7IC4uLmFjdHVhbCwgaG9tZWRpcjogdmkuZm4oKCkgPT4gYWN0dWFsLmhvbWVkaXIoKSkgfTtcbn0pO1xuXG4vLyBTaGFyZWQgYW5zd2VyIHF1ZXVlIOKAlCB0ZXN0cyBwdXNoIGFuc3dlcnMgYmVmb3JlIGNhbGxpbmcgcnVuSW5pdFxuY29uc3QgbW9ja0Fuc3dlcnM6IHN0cmluZ1tdID0gW107XG5cbnZpLm1vY2soXCJub2RlOnJlYWRsaW5lXCIsICgpID0+ICh7XG4gIGNyZWF0ZUludGVyZmFjZTogdmkuZm4oKCkgPT4gKHtcbiAgICBxdWVzdGlvbjogdmkuZm4oKF9xOiBzdHJpbmcsIGNiOiAoYTogc3RyaW5nKSA9PiB2b2lkKSA9PiB7XG4gICAgICBjYihtb2NrQW5zd2Vycy5zaGlmdCgpID8/IFwiXCIpO1xuICAgIH0pLFxuICAgIGNsb3NlOiB2aS5mbigpLFxuICB9KSksXG59KSk7XG5cbmltcG9ydCAqIGFzIG9zIGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBwYXRjaEdpdGlnbm9yZSwgcnVuSW5pdCB9IGZyb20gXCIuL2luaXQuanNcIjtcblxuLy8g4pSA4pSAIHBhdGNoR2l0aWdub3JlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5kZXNjcmliZShcInBhdGNoR2l0aWdub3JlXCIsICgpID0+IHtcbiAgbGV0IHRtcERpcjogc3RyaW5nO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIHRtcERpciA9IG1rZHRlbXBTeW5jKGpvaW4oXCIvdG1wXCIsIFwiZmItaW5pdC1naXRpZ25vcmUtXCIpKTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBybVN5bmModG1wRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gIH0pO1xuXG4gIGl0KFwiY3JlYXRlcyAuZ2l0aWdub3JlIGZyb20gc2NyYXRjaCB3aGVuIGFic2VudCBhbmQgYWRkcyB0aGUgZW50cnlcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHBhdGNoR2l0aWdub3JlKHRtcERpciwgXCIuZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb25cIik7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9CZShcImNyZWF0ZWRcIik7XG4gICAgY29uc3QgY29udGVudCA9IHJlYWRGaWxlU3luYyhqb2luKHRtcERpciwgXCIuZ2l0aWdub3JlXCIpLCBcInV0Zi04XCIpO1xuICAgIGV4cGVjdChjb250ZW50KS50b0NvbnRhaW4oXCIuZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb25cIik7XG4gIH0pO1xuXG4gIGl0KFwiYXBwZW5kcyBsaW5lIHdoZW4gLmdpdGlnbm9yZSBleGlzdHMgYnV0IGVudHJ5IGlzIGFic2VudFwiLCAoKSA9PiB7XG4gICAgd3JpdGVGaWxlU3luYyhqb2luKHRtcERpciwgXCIuZ2l0aWdub3JlXCIpLCBcIm5vZGVfbW9kdWxlc1xcbi5lbnZcXG5cIiwgXCJ1dGYtOFwiKTtcbiAgICBjb25zdCByZXN1bHQgPSBwYXRjaEdpdGlnbm9yZSh0bXBEaXIsIFwiLmZyYXBwZS1idWlsZGVyLWNvbmZpZy5qc29uXCIpO1xuICAgIGV4cGVjdChyZXN1bHQpLnRvQmUoXCJwYXRjaGVkXCIpO1xuICAgIGNvbnN0IGNvbnRlbnQgPSByZWFkRmlsZVN5bmMoam9pbih0bXBEaXIsIFwiLmdpdGlnbm9yZVwiKSwgXCJ1dGYtOFwiKTtcbiAgICBjb25zdCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoXCJcXG5cIik7XG4gICAgZXhwZWN0KGxpbmVzKS50b0NvbnRhaW4oXCIuZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb25cIik7XG4gICAgZXhwZWN0KGxpbmVzKS50b0NvbnRhaW4oXCJub2RlX21vZHVsZXNcIik7XG4gICAgZXhwZWN0KGxpbmVzKS50b0NvbnRhaW4oXCIuZW52XCIpO1xuICB9KTtcblxuICBpdChcImRvZXMgTk9UIGR1cGxpY2F0ZSBlbnRyeSB3aGVuIGFscmVhZHkgcHJlc2VudFwiLCAoKSA9PiB7XG4gICAgd3JpdGVGaWxlU3luYyhcbiAgICAgIGpvaW4odG1wRGlyLCBcIi5naXRpZ25vcmVcIiksXG4gICAgICBcIm5vZGVfbW9kdWxlc1xcbi5mcmFwcGUtYnVpbGRlci1jb25maWcuanNvblxcbi5lbnZcXG5cIixcbiAgICAgIFwidXRmLThcIlxuICAgICk7XG4gICAgY29uc3QgcmVzdWx0ID0gcGF0Y2hHaXRpZ25vcmUodG1wRGlyLCBcIi5mcmFwcGUtYnVpbGRlci1jb25maWcuanNvblwiKTtcbiAgICBleHBlY3QocmVzdWx0KS50b0JlKFwiYWxyZWFkeS1wcmVzZW50XCIpO1xuICAgIGNvbnN0IGNvbnRlbnQgPSByZWFkRmlsZVN5bmMoam9pbih0bXBEaXIsIFwiLmdpdGlnbm9yZVwiKSwgXCJ1dGYtOFwiKTtcbiAgICBjb25zdCBjb3VudCA9IGNvbnRlbnQuc3BsaXQoXCJcXG5cIikuZmlsdGVyKChsKSA9PiBsID09PSBcIi5mcmFwcGUtYnVpbGRlci1jb25maWcuanNvblwiKS5sZW5ndGg7XG4gICAgZXhwZWN0KGNvdW50KS50b0JlKDEpO1xuICB9KTtcblxuICBpdChcImRvZXMgTk9UIGFjY2VwdCBhIGdsb2IgcGF0dGVybiBhcyBhIG1hdGNoIOKAlCByZXF1aXJlcyBleGFjdCBmaWxlbmFtZVwiLCAoKSA9PiB7XG4gICAgd3JpdGVGaWxlU3luYyhqb2luKHRtcERpciwgXCIuZ2l0aWdub3JlXCIpLCBcIiouanNvblxcblwiLCBcInV0Zi04XCIpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHBhdGNoR2l0aWdub3JlKHRtcERpciwgXCIuZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb25cIik7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9CZShcInBhdGNoZWRcIik7XG4gIH0pO1xufSk7XG5cbi8vIOKUgOKUgCBydW5Jbml0IOKAlCBmaWxlIHdyaXRlcyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuZGVzY3JpYmUoXCJydW5Jbml0IOKAlCBmaWxlIHdyaXRlc1wiLCAoKSA9PiB7XG4gIGxldCBwcm9qZWN0RGlyOiBzdHJpbmc7XG4gIGxldCBob21lRGlyOiBzdHJpbmc7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgcHJvamVjdERpciA9IG1rZHRlbXBTeW5jKGpvaW4oXCIvdG1wXCIsIFwiZmItaW5pdC1wcm9qLVwiKSk7XG4gICAgaG9tZURpciA9IG1rZHRlbXBTeW5jKGpvaW4oXCIvdG1wXCIsIFwiZmItaW5pdC1ob21lLVwiKSk7XG4gICAgdmkubW9ja2VkKG9zLmhvbWVkaXIpLm1vY2tSZXR1cm5WYWx1ZShob21lRGlyKTtcbiAgICBtb2NrQW5zd2Vycy5sZW5ndGggPSAwO1xuICB9KTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIHZpLmNsZWFyQWxsTW9ja3MoKTtcbiAgICBybVN5bmMocHJvamVjdERpciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIHJtU3luYyhob21lRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gIH0pO1xuXG4gIGl0KFwid3JpdGVzIGdsb2JhbCBjb25maWcgdG8gfi8uZnJhcHBlLWJ1aWxkZXIvY29uZmlnLmpzb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEFuc3dlcnM6IGxsbV9hcGlfa2V5LCBzaXRlX3VybCwgYXBpX2tleSwgYXBpX3NlY3JldFxuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJzay10ZXN0XCIsIFwiaHR0cDovL2VycC5sb2NhbGhvc3RcIiwgXCJrZXkxMjNcIiwgXCJzZWNyZXQ0NTZcIik7XG4gICAgYXdhaXQgcnVuSW5pdCh7IHByb2plY3RSb290OiBwcm9qZWN0RGlyIH0pO1xuXG4gICAgY29uc3QgY29uZmlnUGF0aCA9IGpvaW4oaG9tZURpciwgXCIuZnJhcHBlLWJ1aWxkZXJcIiwgXCJjb25maWcuanNvblwiKTtcbiAgICBleHBlY3QoZXhpc3RzU3luYyhjb25maWdQYXRoKSkudG9CZSh0cnVlKTtcbiAgICBjb25zdCBjZmcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhjb25maWdQYXRoLCBcInV0Zi04XCIpKSBhcyB7IGxsbV9hcGlfa2V5OiBzdHJpbmcgfTtcbiAgICBleHBlY3QoY2ZnLmxsbV9hcGlfa2V5KS50b0JlKFwic2stdGVzdFwiKTtcbiAgfSk7XG5cbiAgaXQoXCJ3cml0ZXMgcHJvamVjdCBjb25maWcgdG8ge3Byb2plY3RSb290fS8uZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJzay10ZXN0XCIsIFwiaHR0cDovL2VycC5sb2NhbGhvc3RcIiwgXCJrZXkxMjNcIiwgXCJzZWNyZXQ0NTZcIik7XG4gICAgYXdhaXQgcnVuSW5pdCh7IHByb2plY3RSb290OiBwcm9qZWN0RGlyIH0pO1xuXG4gICAgY29uc3QgY29uZmlnUGF0aCA9IGpvaW4ocHJvamVjdERpciwgXCIuZnJhcHBlLWJ1aWxkZXItY29uZmlnLmpzb25cIik7XG4gICAgZXhwZWN0KGV4aXN0c1N5bmMoY29uZmlnUGF0aCkpLnRvQmUodHJ1ZSk7XG4gICAgY29uc3QgY2ZnID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMoY29uZmlnUGF0aCwgXCJ1dGYtOFwiKSkgYXMge1xuICAgICAgc2l0ZV91cmw6IHN0cmluZztcbiAgICAgIGFwaV9rZXk6IHN0cmluZztcbiAgICAgIGFwaV9zZWNyZXQ6IHN0cmluZztcbiAgICB9O1xuICAgIGV4cGVjdChjZmcuc2l0ZV91cmwpLnRvQmUoXCJodHRwOi8vZXJwLmxvY2FsaG9zdFwiKTtcbiAgICBleHBlY3QoY2ZnLmFwaV9rZXkpLnRvQmUoXCJrZXkxMjNcIik7XG4gICAgZXhwZWN0KGNmZy5hcGlfc2VjcmV0KS50b0JlKFwic2VjcmV0NDU2XCIpO1xuICB9KTtcblxuICBpdChcInBhdGNoZXMgLmdpdGlnbm9yZSBhdXRvbWF0aWNhbGx5XCIsIGFzeW5jICgpID0+IHtcbiAgICBtb2NrQW5zd2Vycy5wdXNoKFwic2stdGVzdFwiLCBcImh0dHA6Ly9lcnAubG9jYWxob3N0XCIsIFwia2V5MTIzXCIsIFwic2VjcmV0NDU2XCIpO1xuICAgIGF3YWl0IHJ1bkluaXQoeyBwcm9qZWN0Um9vdDogcHJvamVjdERpciB9KTtcblxuICAgIGNvbnN0IGNvbnRlbnQgPSByZWFkRmlsZVN5bmMoam9pbihwcm9qZWN0RGlyLCBcIi5naXRpZ25vcmVcIiksIFwidXRmLThcIik7XG4gICAgZXhwZWN0KGNvbnRlbnQpLnRvQ29udGFpbihcIi5mcmFwcGUtYnVpbGRlci1jb25maWcuanNvblwiKTtcbiAgfSk7XG5cbiAgaXQoXCJjcmVhdGVzIH4vLmZyYXBwZS1idWlsZGVyLyBkaXJlY3RvcnkgaWYgaXQgZG9lcyBub3QgZXhpc3RcIiwgYXN5bmMgKCkgPT4ge1xuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJcIiwgXCJodHRwOi8vc2l0ZS5sb2NhbGhvc3RcIiwgXCJrXCIsIFwic1wiKTtcbiAgICBhd2FpdCBydW5Jbml0KHsgcHJvamVjdFJvb3Q6IHByb2plY3REaXIgfSk7XG5cbiAgICBleHBlY3QoZXhpc3RzU3luYyhqb2luKGhvbWVEaXIsIFwiLmZyYXBwZS1idWlsZGVyXCIpKSkudG9CZSh0cnVlKTtcbiAgfSk7XG59KTtcblxuLy8g4pSA4pSAIHJ1bkluaXQg4oCUIG92ZXJ3cml0ZSBndWFyZCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuZGVzY3JpYmUoXCJydW5Jbml0IOKAlCBvdmVyd3JpdGUgZ3VhcmRcIiwgKCkgPT4ge1xuICBsZXQgcHJvamVjdERpcjogc3RyaW5nO1xuICBsZXQgaG9tZURpcjogc3RyaW5nO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIHByb2plY3REaXIgPSBta2R0ZW1wU3luYyhqb2luKFwiL3RtcFwiLCBcImZiLWluaXQtZ3VhcmQtcHJvai1cIikpO1xuICAgIGhvbWVEaXIgPSBta2R0ZW1wU3luYyhqb2luKFwiL3RtcFwiLCBcImZiLWluaXQtZ3VhcmQtaG9tZS1cIikpO1xuICAgIHZpLm1vY2tlZChvcy5ob21lZGlyKS5tb2NrUmV0dXJuVmFsdWUoaG9tZURpcik7XG4gICAgbW9ja0Fuc3dlcnMubGVuZ3RoID0gMDtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICB2aS5jbGVhckFsbE1vY2tzKCk7XG4gICAgcm1TeW5jKHByb2plY3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICBybVN5bmMoaG9tZURpciwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICB9KTtcblxuICBpdChcImRvZXMgTk9UIG92ZXJ3cml0ZSBleGlzdGluZyBnbG9iYWwgY29uZmlnIHdoZW4gdXNlciBkZWNsaW5lc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY29uZmlnRGlyID0gam9pbihob21lRGlyLCBcIi5mcmFwcGUtYnVpbGRlclwiKTtcbiAgICBta2RpclN5bmMoY29uZmlnRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBjb25zdCBnbG9iYWxQYXRoID0gam9pbihjb25maWdEaXIsIFwiY29uZmlnLmpzb25cIik7XG4gICAgd3JpdGVGaWxlU3luYyhnbG9iYWxQYXRoLCBKU09OLnN0cmluZ2lmeSh7IGxsbV9hcGlfa2V5OiBcIm9yaWdpbmFsLWtleVwiIH0pLCBcInV0Zi04XCIpO1xuXG4gICAgLy8gT3ZlcndyaXRlIGdsb2JhbD8g4oaSIFwiblwiIHwgT3ZlcndyaXRlIHByb2plY3Q/IOKGkiBcIm5cIlxuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJuXCIsIFwiblwiKTtcbiAgICBhd2FpdCBydW5Jbml0KHsgcHJvamVjdFJvb3Q6IHByb2plY3REaXIgfSk7XG5cbiAgICBjb25zdCBjZmcgPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhnbG9iYWxQYXRoLCBcInV0Zi04XCIpKSBhcyB7IGxsbV9hcGlfa2V5OiBzdHJpbmcgfTtcbiAgICBleHBlY3QoY2ZnLmxsbV9hcGlfa2V5KS50b0JlKFwib3JpZ2luYWwta2V5XCIpO1xuICB9KTtcblxuICBpdChcIm92ZXJ3cml0ZXMgZXhpc3RpbmcgZ2xvYmFsIGNvbmZpZyB3aGVuIHVzZXIgY29uZmlybXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNvbmZpZ0RpciA9IGpvaW4oaG9tZURpciwgXCIuZnJhcHBlLWJ1aWxkZXJcIik7XG4gICAgbWtkaXJTeW5jKGNvbmZpZ0RpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgY29uc3QgZ2xvYmFsUGF0aCA9IGpvaW4oY29uZmlnRGlyLCBcImNvbmZpZy5qc29uXCIpO1xuICAgIHdyaXRlRmlsZVN5bmMoZ2xvYmFsUGF0aCwgSlNPTi5zdHJpbmdpZnkoeyBsbG1fYXBpX2tleTogXCJvbGQta2V5XCIgfSksIFwidXRmLThcIik7XG5cbiAgICAvLyBPdmVyd3JpdGUgZ2xvYmFsPyDihpIgXCJ5XCIsIG5ldyBsbG1fa2V5LCBzaXRlX3VybCwgYXBpX2tleSwgYXBpX3NlY3JldFxuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJ5XCIsIFwibmV3LWtleVwiLCBcImh0dHA6Ly9zaXRlLmxvY2FsaG9zdFwiLCBcImtcIiwgXCJzXCIpO1xuICAgIGF3YWl0IHJ1bkluaXQoeyBwcm9qZWN0Um9vdDogcHJvamVjdERpciB9KTtcblxuICAgIGNvbnN0IGNmZyA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGdsb2JhbFBhdGgsIFwidXRmLThcIikpIGFzIHsgbGxtX2FwaV9rZXk6IHN0cmluZyB9O1xuICAgIGV4cGVjdChjZmcubGxtX2FwaV9rZXkpLnRvQmUoXCJuZXcta2V5XCIpO1xuICB9KTtcblxuICBpdChcImRvZXMgTk9UIG92ZXJ3cml0ZSBleGlzdGluZyBwcm9qZWN0IGNvbmZpZyB3aGVuIHVzZXIgZGVjbGluZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHByb2pDb25maWdQYXRoID0gam9pbihwcm9qZWN0RGlyLCBcIi5mcmFwcGUtYnVpbGRlci1jb25maWcuanNvblwiKTtcbiAgICB3cml0ZUZpbGVTeW5jKFxuICAgICAgcHJvakNvbmZpZ1BhdGgsXG4gICAgICBKU09OLnN0cmluZ2lmeSh7IHNpdGVfdXJsOiBcImh0dHA6Ly9vcmlnaW5hbC5sb2NhbGhvc3RcIiwgYXBpX2tleTogXCJvcmlnXCIsIGFwaV9zZWNyZXQ6IFwic1wiIH0pLFxuICAgICAgXCJ1dGYtOFwiXG4gICAgKTtcblxuICAgIC8vIGxsbV9hcGlfa2V5IHByb21wdCAobm8gZXhpc3RpbmcgZ2xvYmFsKSwgb3ZlcndyaXRlIHByb2plY3Q/IOKGkiBcIm5cIlxuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJzay1uZXdcIiwgXCJuXCIpO1xuICAgIGF3YWl0IHJ1bkluaXQoeyBwcm9qZWN0Um9vdDogcHJvamVjdERpciB9KTtcblxuICAgIGNvbnN0IGNmZyA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKHByb2pDb25maWdQYXRoLCBcInV0Zi04XCIpKSBhcyB7IHNpdGVfdXJsOiBzdHJpbmcgfTtcbiAgICBleHBlY3QoY2ZnLnNpdGVfdXJsKS50b0JlKFwiaHR0cDovL29yaWdpbmFsLmxvY2FsaG9zdFwiKTtcbiAgfSk7XG59KTtcblxuLy8g4pSA4pSAIHJ1bkluaXQg4oCUIGNsZWFuIGV4aXQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmRlc2NyaWJlKFwicnVuSW5pdCDigJQgY2xlYW4gZXhpdFwiLCAoKSA9PiB7XG4gIGxldCBwcm9qZWN0RGlyOiBzdHJpbmc7XG4gIGxldCBob21lRGlyOiBzdHJpbmc7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgcHJvamVjdERpciA9IG1rZHRlbXBTeW5jKGpvaW4oXCIvdG1wXCIsIFwiZmItaW5pdC1leGl0LVwiKSk7XG4gICAgaG9tZURpciA9IG1rZHRlbXBTeW5jKGpvaW4oXCIvdG1wXCIsIFwiZmItaW5pdC1leGl0LWhvbWUtXCIpKTtcbiAgICB2aS5tb2NrZWQob3MuaG9tZWRpcikubW9ja1JldHVyblZhbHVlKGhvbWVEaXIpO1xuICAgIG1vY2tBbnN3ZXJzLmxlbmd0aCA9IDA7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgdmkuY2xlYXJBbGxNb2NrcygpO1xuICAgIHJtU3luYyhwcm9qZWN0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgcm1TeW5jKGhvbWVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgfSk7XG5cbiAgaXQoXCJyZXNvbHZlcyB3aXRob3V0IHRocm93aW5nIHdoZW4gYWxsIHByb21wdHMgcmV0dXJuIGVtcHR5IHN0cmluZ3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIG1vY2tBbnN3ZXJzLnB1c2goXCJcIiwgXCJcIiwgXCJcIiwgXCJcIik7XG4gICAgYXdhaXQgZXhwZWN0KHJ1bkluaXQoeyBwcm9qZWN0Um9vdDogcHJvamVjdERpciB9KSkucmVzb2x2ZXMudG9CZVVuZGVmaW5lZCgpO1xuICB9KTtcbn0pO1xuIl0sImZpbGUiOiIvc3JjL2luaXQudGVzdC50cyJ9
206
-
207
- //# vitestCache=W3siZmlsZSI6IjEiLCJpZCI6IjEiLCJ1cmwiOiIyIiwiaW1wb3J0ZWRVcmxzIjoiMyIsIm1hcHBpbmdzIjpmYWxzZX0sIi9ob21lL3Jpei9mcmFwcGUtYnVpbGRlci9zcmMvaW5pdC50ZXN0LnRzIiwiL3NyYy9pbml0LnRlc3QudHMiLFtdXQ==