@nlabs/lex 1.48.7 → 1.49.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.
Files changed (105) hide show
  1. package/.storybook/main.ts +9 -2
  2. package/.vscode/settings.json +1 -6
  3. package/README.md +249 -0
  4. package/eslint.config.mjs +24 -0
  5. package/examples/lex.config.js +18 -8
  6. package/examples/serverless-example/README.md +109 -0
  7. package/examples/serverless-example/dist/handlers/echo.js +15 -0
  8. package/examples/serverless-example/dist/handlers/graphql.js +137 -0
  9. package/examples/serverless-example/dist/handlers/hello.js +15 -0
  10. package/examples/serverless-example/dist/handlers/test.js +17 -0
  11. package/examples/serverless-example/dist/handlers/websocket.js +14 -0
  12. package/examples/serverless-example/lex.config.mjs +74 -0
  13. package/jest.config.mjs +13 -12
  14. package/{dist → lib}/LexConfig.d.ts +7 -6
  15. package/lib/LexConfig.js +268 -0
  16. package/lib/commands/ai/ai.js +303 -0
  17. package/{dist → lib}/commands/build/build.d.ts +3 -0
  18. package/lib/commands/build/build.js +494 -0
  19. package/{dist → lib}/commands/clean/clean.js +1 -1
  20. package/lib/commands/compile/compile.js +241 -0
  21. package/lib/commands/copy/copy.js +38 -0
  22. package/{dist → lib}/commands/create/create.js +1 -1
  23. package/{dist → lib}/commands/dev/dev.d.ts +2 -0
  24. package/lib/commands/dev/dev.js +286 -0
  25. package/{dist → lib}/commands/init/init.js +1 -1
  26. package/lib/commands/lint/lint.js +962 -0
  27. package/{dist → lib}/commands/migrate/migrate.js +1 -1
  28. package/lib/commands/publish/publish.js +104 -0
  29. package/lib/commands/serverless/serverless.d.ts +17 -0
  30. package/lib/commands/serverless/serverless.js +662 -0
  31. package/lib/commands/storybook/storybook.js +249 -0
  32. package/lib/commands/test/test.js +428 -0
  33. package/lib/commands/update/update.js +128 -0
  34. package/{dist → lib}/create/changelog.js +1 -1
  35. package/{dist → lib}/index.d.ts +1 -0
  36. package/{dist → lib}/index.js +2 -1
  37. package/lib/lex.js +73 -0
  38. package/lib/utils/aiService.d.ts +9 -0
  39. package/lib/utils/aiService.js +299 -0
  40. package/{dist → lib}/utils/app.d.ts +3 -0
  41. package/lib/utils/app.js +296 -0
  42. package/{dist → lib}/utils/file.d.ts +7 -3
  43. package/lib/utils/file.js +229 -0
  44. package/lib/utils/translations.d.ts +1 -0
  45. package/lib/utils/translations.js +74 -0
  46. package/package.json +60 -54
  47. package/postcss.config.js +5 -3
  48. package/tsconfig.build.json +2 -2
  49. package/webpack.config.js +229 -39
  50. package/dist/LexConfig.js +0 -287
  51. package/dist/commands/ai/ai.js +0 -303
  52. package/dist/commands/build/build.js +0 -404
  53. package/dist/commands/compile/compile.js +0 -234
  54. package/dist/commands/copy/copy.js +0 -38
  55. package/dist/commands/dev/dev.js +0 -74
  56. package/dist/commands/lint/lint.js +0 -993
  57. package/dist/commands/publish/publish.js +0 -104
  58. package/dist/commands/storybook/storybook.js +0 -249
  59. package/dist/commands/test/test.js +0 -429
  60. package/dist/commands/update/update.js +0 -132
  61. package/dist/lex.js +0 -70
  62. package/dist/utils/aiService.d.ts +0 -9
  63. package/dist/utils/aiService.js +0 -299
  64. package/dist/utils/app.js +0 -267
  65. package/dist/utils/file.js +0 -185
  66. package/emptyModule.js +0 -0
  67. package/eslint.config.js +0 -3
  68. /package/{dist → lib}/Button.stories.d.ts +0 -0
  69. /package/{dist → lib}/commands/ai/ai.d.ts +0 -0
  70. /package/{dist → lib}/commands/ai/index.d.ts +0 -0
  71. /package/{dist → lib}/commands/ai/index.js +0 -0
  72. /package/{dist → lib}/commands/clean/clean.d.ts +0 -0
  73. /package/{dist → lib}/commands/compile/compile.d.ts +0 -0
  74. /package/{dist → lib}/commands/config/config.d.ts +0 -0
  75. /package/{dist → lib}/commands/config/config.js +0 -0
  76. /package/{dist → lib}/commands/copy/copy.d.ts +0 -0
  77. /package/{dist → lib}/commands/create/create.d.ts +0 -0
  78. /package/{dist → lib}/commands/init/init.d.ts +0 -0
  79. /package/{dist → lib}/commands/link/link.d.ts +0 -0
  80. /package/{dist → lib}/commands/link/link.js +0 -0
  81. /package/{dist → lib}/commands/lint/autofix.d.ts +0 -0
  82. /package/{dist → lib}/commands/lint/lint.d.ts +0 -0
  83. /package/{dist → lib}/commands/migrate/migrate.d.ts +0 -0
  84. /package/{dist → lib}/commands/publish/publish.d.ts +0 -0
  85. /package/{dist → lib}/commands/storybook/storybook.d.ts +0 -0
  86. /package/{dist → lib}/commands/test/test.d.ts +0 -0
  87. /package/{dist → lib}/commands/update/update.d.ts +0 -0
  88. /package/{dist → lib}/commands/upgrade/upgrade.d.ts +0 -0
  89. /package/{dist → lib}/commands/upgrade/upgrade.js +0 -0
  90. /package/{dist → lib}/commands/versions/versions.d.ts +0 -0
  91. /package/{dist → lib}/commands/versions/versions.js +0 -0
  92. /package/{dist → lib}/create/changelog.d.ts +0 -0
  93. /package/{dist → lib}/lex.d.ts +0 -0
  94. /package/{dist → lib}/storybook/index.d.ts +0 -0
  95. /package/{dist → lib}/storybook/index.js +0 -0
  96. /package/{dist → lib}/test-react/index.d.ts +0 -0
  97. /package/{dist → lib}/test-react/index.js +0 -0
  98. /package/{dist → lib}/types.d.ts +0 -0
  99. /package/{dist → lib}/types.js +0 -0
  100. /package/{dist → lib}/utils/deepMerge.d.ts +0 -0
  101. /package/{dist → lib}/utils/deepMerge.js +0 -0
  102. /package/{dist → lib}/utils/log.d.ts +0 -0
  103. /package/{dist → lib}/utils/log.js +0 -0
  104. /package/{dist → lib}/utils/reactShim.d.ts +0 -0
  105. /package/{dist → lib}/utils/reactShim.js +0 -0
package/dist/LexConfig.js DELETED
@@ -1,287 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync } from "fs";
2
- import { dirname, extname as pathExtname, resolve as pathResolve } from "path";
3
- import { URL } from "url";
4
- import { getDirName, getLexPackageJsonPath, relativeFilePath } from "./utils/file.js";
5
- import { log } from "./utils/log.js";
6
- const cwd = process.cwd();
7
- const defaultConfigValues = {
8
- ai: {
9
- provider: "none",
10
- model: "gpt-4o",
11
- maxTokens: 4e3,
12
- temperature: 0.1
13
- },
14
- configFiles: [],
15
- copyFiles: [],
16
- entryHTML: "index.html",
17
- entryJs: "index.js",
18
- eslint: {},
19
- esbuild: {
20
- minify: true,
21
- treeShaking: true,
22
- drop: ["console", "debugger"],
23
- pure: ["console.log", "console.warn", "console.error"],
24
- legalComments: "none",
25
- splitting: true,
26
- metafile: false,
27
- sourcemap: false
28
- },
29
- env: null,
30
- jest: {},
31
- outputFullPath: pathResolve(cwd, "./dist"),
32
- outputHash: false,
33
- outputPath: "./dist",
34
- packageManager: "npm",
35
- preset: "web",
36
- sourceFullPath: pathResolve(cwd, "./src"),
37
- sourcePath: "./src",
38
- targetEnvironment: "web",
39
- useGraphQl: false,
40
- useTypescript: false,
41
- webpack: {}
42
- };
43
- function findLexRoot(startDir) {
44
- let dir = startDir;
45
- while (dir !== "/" && dir !== ".") {
46
- const pkgPath = pathResolve(dir, "package.json");
47
- if (existsSync(pkgPath)) {
48
- try {
49
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
50
- if (pkg.name === "@nlabs/lex") {
51
- return dir;
52
- }
53
- } catch {
54
- }
55
- }
56
- const parent = dirname(dir);
57
- if (parent === dir) {
58
- break;
59
- }
60
- dir = parent;
61
- }
62
- throw new Error("Could not find @nlabs/lex root");
63
- }
64
- function getTypeScriptConfigPath(configName) {
65
- const cwd2 = process.cwd();
66
- if (configName === "tsconfig.build.json") {
67
- const projectBuildConfig = pathResolve(cwd2, "tsconfig.build.json");
68
- if (existsSync(projectBuildConfig)) {
69
- return projectBuildConfig;
70
- }
71
- }
72
- if (configName === "tsconfig.lint.json") {
73
- const projectLintConfig = pathResolve(cwd2, "tsconfig.eslint.json");
74
- if (existsSync(projectLintConfig)) {
75
- return projectLintConfig;
76
- }
77
- }
78
- if (configName === "tsconfig.test.json") {
79
- const projectTestConfig = pathResolve(cwd2, "tsconfig.test.json");
80
- if (existsSync(projectTestConfig)) {
81
- return projectTestConfig;
82
- }
83
- }
84
- const projectConfigPath = pathResolve(cwd2, configName);
85
- if (existsSync(projectConfigPath)) {
86
- return projectConfigPath;
87
- }
88
- const lexDir = LexConfig.getLexDir();
89
- return pathResolve(lexDir, configName);
90
- }
91
- class LexConfig {
92
- static config = {
93
- ...defaultConfigValues
94
- };
95
- static getLexDir() {
96
- return dirname(getLexPackageJsonPath());
97
- }
98
- static set useTypescript(value) {
99
- LexConfig.config.useTypescript = value;
100
- const { sourceFullPath } = LexConfig.config;
101
- const { entryJs } = LexConfig.config;
102
- if (entryJs === "index.js" && value) {
103
- const indexPath = pathResolve(cwd, sourceFullPath, "index.tsx");
104
- const hasIndexTsx = existsSync(indexPath);
105
- if (hasIndexTsx) {
106
- LexConfig.config.entryJs = "index.tsx";
107
- } else {
108
- LexConfig.config.entryJs = "index.ts";
109
- }
110
- }
111
- }
112
- static updateConfig(updatedConfig) {
113
- const { outputFullPath, outputPath, sourcePath, sourceFullPath, useTypescript, ai } = updatedConfig;
114
- const cwd2 = process.cwd();
115
- if (useTypescript !== void 0) {
116
- LexConfig.useTypescript = useTypescript;
117
- }
118
- if (outputPath !== void 0 && outputFullPath === void 0) {
119
- updatedConfig.outputFullPath = pathResolve(cwd2, outputPath);
120
- }
121
- if (sourcePath !== void 0 && sourceFullPath === void 0) {
122
- updatedConfig.sourceFullPath = pathResolve(cwd2, sourcePath);
123
- }
124
- if (ai) {
125
- LexConfig.config.ai = { ...LexConfig.config.ai, ...ai };
126
- if (process.env.CURSOR_IDE === "true" && LexConfig.config.ai.provider === "none") {
127
- LexConfig.config.ai.provider = "cursor";
128
- }
129
- }
130
- LexConfig.config = { ...LexConfig.config, ...updatedConfig };
131
- return LexConfig.config;
132
- }
133
- static addConfigParams(cmd, params) {
134
- const nameProperty = "_name";
135
- const { environment, outputPath, sourcePath, typescript } = cmd;
136
- if (outputPath !== void 0) {
137
- params.outputPath = outputPath;
138
- params.outputFullPath = pathResolve(cwd, outputPath);
139
- }
140
- if (sourcePath !== void 0) {
141
- params.sourcePath = sourcePath;
142
- params.sourceFullPath = pathResolve(cwd, sourcePath);
143
- }
144
- if (typescript !== void 0) {
145
- params.useTypescript = true;
146
- }
147
- if (environment !== void 0) {
148
- params.targetEnvironment = environment === "web" ? "web" : "node";
149
- }
150
- process.env.LEX_CONFIG = JSON.stringify(
151
- {
152
- ...LexConfig.updateConfig(params),
153
- commandName: cmd[nameProperty],
154
- isStatic: cmd.static
155
- },
156
- null,
157
- 0
158
- );
159
- }
160
- static async parseConfig(cmd, isRoot = true) {
161
- const { cliName = "Lex", lexConfig, lexConfigName, quiet, typescript, debug = false } = cmd;
162
- const configFormats = ["js", "mjs", "cjs", "ts", "json"];
163
- const configBaseName = lexConfigName || "lex.config";
164
- let configPath = lexConfig || "";
165
- let configExists = lexConfig ? existsSync(configPath) : false;
166
- if (!configPath || !configExists) {
167
- if (debug) {
168
- log(`Searching for config files with base name: ${configBaseName}`, "info", quiet);
169
- }
170
- for (const format of configFormats) {
171
- const potentialPath = isRoot ? pathResolve(cwd, `./${configBaseName}.${format}`) : relativeFilePath(`${configBaseName}.${format}`, cwd);
172
- if (debug) {
173
- log(`Checking for config file: ${potentialPath}`, "info", quiet);
174
- }
175
- if (existsSync(potentialPath)) {
176
- configPath = potentialPath;
177
- configExists = true;
178
- break;
179
- }
180
- }
181
- }
182
- if (configExists) {
183
- log(`Using ${cliName} configuration file: ${configPath}`, "note", quiet);
184
- const ext = pathExtname(configPath);
185
- if (ext === ".json") {
186
- const configContent = readFileSync(configPath, "utf8");
187
- if (configContent) {
188
- let configJson;
189
- try {
190
- configJson = JSON.parse(configContent)?.default || {};
191
- } catch (error) {
192
- log(`
193
- ${cliName} Error: Failed to parse JSON config: ${error.message}`, "error", quiet);
194
- configJson = {};
195
- }
196
- LexConfig.addConfigParams(cmd, configJson);
197
- } else {
198
- log(`
199
- ${cliName} Error: Config file malformed, ${configPath}`, "error", quiet);
200
- }
201
- } else if ([".js", ".mjs", ".cjs", ".ts"].includes(ext)) {
202
- try {
203
- let lexCustomConfig;
204
- if (ext === ".cjs") {
205
- const fileUrl = new URL(`file:///${pathResolve(configPath)}`).href;
206
- if (debug) {
207
- log(`Loading CommonJS config from: ${fileUrl}`, "info", quiet);
208
- }
209
- lexCustomConfig = await import(fileUrl);
210
- } else {
211
- if (debug) {
212
- log(`Loading ESM/TS config from: ${configPath}`, "info", quiet);
213
- }
214
- lexCustomConfig = await import(configPath);
215
- }
216
- const config = lexCustomConfig.default || lexCustomConfig;
217
- if (debug) {
218
- log(`Loaded config: ${JSON.stringify(config, null, 2)}`, "info", quiet);
219
- }
220
- if (!config) {
221
- log(`
222
- ${cliName} Warning: Config file loaded but no configuration found`, "warn", quiet);
223
- }
224
- LexConfig.addConfigParams(cmd, config || {});
225
- } catch (error) {
226
- log(`
227
- ${cliName} Error: Failed to load config file: ${error.message}`, "error", quiet);
228
- if (debug) {
229
- console.error(error);
230
- }
231
- }
232
- } else {
233
- log(`
234
- ${cliName} Error: Config file must be a JS, CJS, MJS, TS, or JSON file.`, "error", quiet);
235
- }
236
- } else {
237
- if (debug) {
238
- log("No config file found. Using default configuration.", "info", quiet);
239
- }
240
- LexConfig.useTypescript = !!typescript;
241
- LexConfig.addConfigParams(cmd, LexConfig.config);
242
- }
243
- }
244
- static checkTypescriptConfig() {
245
- const tsconfigPath = pathResolve(cwd, "./tsconfig.json");
246
- if (!existsSync(tsconfigPath)) {
247
- const dirName = getDirName();
248
- writeFileSync(tsconfigPath, readFileSync(pathResolve(dirName, "../../../tsconfig.base.json")));
249
- }
250
- }
251
- static checkCompileTypescriptConfig() {
252
- const lexDir = LexConfig.getLexDir();
253
- const tsconfigCompilePath = pathResolve(lexDir, "./tsconfig.build.json");
254
- if (!existsSync(tsconfigCompilePath)) {
255
- const templatePath = pathResolve(lexDir, "tsconfig.build.json");
256
- if (existsSync(templatePath)) {
257
- writeFileSync(tsconfigCompilePath, readFileSync(templatePath));
258
- }
259
- }
260
- }
261
- static checkLintTypescriptConfig() {
262
- const lexDir = LexConfig.getLexDir();
263
- const tsconfigLintPath = pathResolve(lexDir, "./tsconfig.lint.json");
264
- if (!existsSync(tsconfigLintPath)) {
265
- const templatePath = pathResolve(lexDir, "tsconfig.lint.json");
266
- if (existsSync(templatePath)) {
267
- writeFileSync(tsconfigLintPath, readFileSync(templatePath));
268
- }
269
- }
270
- }
271
- static checkTestTypescriptConfig() {
272
- const lexDir = LexConfig.getLexDir();
273
- const tsconfigTestPath = pathResolve(lexDir, "./tsconfig.test.json");
274
- if (!existsSync(tsconfigTestPath)) {
275
- const templatePath = pathResolve(lexDir, "tsconfig.test.json");
276
- if (existsSync(templatePath)) {
277
- writeFileSync(tsconfigTestPath, readFileSync(templatePath));
278
- }
279
- }
280
- }
281
- }
282
- export {
283
- LexConfig,
284
- defaultConfigValues,
285
- getTypeScriptConfigPath
286
- };
287
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL0xleENvbmZpZy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7ZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2Rpcm5hbWUsIGV4dG5hbWUgYXMgcGF0aEV4dG5hbWUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtVUkx9IGZyb20gJ3VybCc7XG5cbmltcG9ydCB7Z2V0RGlyTmFtZSwgZ2V0TGV4UGFja2FnZUpzb25QYXRoLCByZWxhdGl2ZUZpbGVQYXRofSBmcm9tICcuL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4vdXRpbHMvbG9nLmpzJztcblxuaW1wb3J0IHR5cGUge0xpbnRlcn0gZnJvbSAnZXNsaW50JztcblxuY29uc3QgY3dkOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVzYnVpbGRDb25maWcge1xuICBlbnRyeVBvaW50cz86IHN0cmluZ1tdO1xuICBvdXRkaXI/OiBzdHJpbmc7XG4gIHBsYXRmb3JtPzogJ25vZGUnIHwgJ2Jyb3dzZXInO1xuICB0YXJnZXQ/OiBzdHJpbmc7XG4gIGZvcm1hdD86ICdjanMnIHwgJ2VzbSc7XG4gIG1pbmlmeT86IGJvb2xlYW47XG4gIHRyZWVTaGFraW5nPzogYm9vbGVhbjtcbiAgZHJvcD86IHN0cmluZ1tdO1xuICBwdXJlPzogc3RyaW5nW107XG4gIGV4dGVybmFsPzogc3RyaW5nW107XG4gIHNwbGl0dGluZz86IGJvb2xlYW47XG4gIG1ldGFmaWxlPzogYm9vbGVhbjtcbiAgc291cmNlbWFwPzogYm9vbGVhbiB8ICdpbmxpbmUnIHwgJ2V4dGVybmFsJztcbiAgbGVnYWxDb21tZW50cz86ICdub25lJyB8ICdpbmxpbmUnIHwgJ2VvZicgfCAnbGlua2VkJyB8ICdzZXBhcmF0ZSc7XG4gIGJhbm5lcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGZvb3Rlcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGRlZmluZT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIFtrZXk6IHN0cmluZ106IHVua25vd247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSmVzdENvbmZpZyB7XG4gIHJvb3RzPzogc3RyaW5nW107XG4gIHRlc3RFbnZpcm9ubWVudD86IHN0cmluZztcbiAgdHJhbnNmb3JtPzogUmVjb3JkPHN0cmluZywgW3N0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj5dPjtcbiAgdHJhbnNmb3JtSWdub3JlUGF0dGVybnM/OiBzdHJpbmdbXTtcbiAgbW9kdWxlTmFtZU1hcHBlcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGV4dGVuc2lvbnNUb1RyZWF0QXNFc20/OiBzdHJpbmdbXTtcbiAgcHJlc2V0Pzogc3RyaW5nO1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYnBhY2tDb25maWcge1xuICBlbnRyeT86IHN0cmluZyB8IHN0cmluZ1tdO1xuICBvdXRwdXQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgbW9kdWxlPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHBsdWdpbnM/OiB1bmtub3duW107XG4gIFtrZXk6IHN0cmluZ106IHVua25vd247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQUlDb25maWcge1xuICBwcm92aWRlcj86ICdjdXJzb3InIHwgJ2NvcGlsb3QnIHwgJ29wZW5haScgfCAnYW50aHJvcGljJyB8ICdub25lJztcbiAgYXBpS2V5Pzogc3RyaW5nO1xuICBtb2RlbD86IHN0cmluZztcbiAgbWF4VG9rZW5zPzogbnVtYmVyO1xuICB0ZW1wZXJhdHVyZT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFU0xpbnRDb25maWcge1xuICBleHRlbmRzPzogc3RyaW5nW107XG4gIHJ1bGVzPzogTGludGVyLlJ1bGVzUmVjb3JkO1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExleENvbmZpZ1R5cGUge1xuICBhaT86IEFJQ29uZmlnO1xuICBjb25maWdGaWxlcz86IHN0cmluZ1tdO1xuICBjb3B5RmlsZXM/OiBzdHJpbmdbXTtcbiAgZW50cnlIVE1MPzogc3RyaW5nO1xuICBlbnRyeUpzPzogc3RyaW5nO1xuICBlbnY/OiBvYmplY3Q7XG4gIGVzYnVpbGQ/OiBFc2J1aWxkQ29uZmlnO1xuICBlc2xpbnQ/OiBFU0xpbnRDb25maWc7XG4gIGdpdFVybD86IHN0cmluZztcbiAgamVzdD86IEplc3RDb25maWc7XG4gIGxpYnJhcnlOYW1lPzogc3RyaW5nO1xuICBsaWJyYXJ5VGFyZ2V0Pzogc3RyaW5nO1xuICBvdXRwdXRGaWxlPzogc3RyaW5nO1xuICBvdXRwdXRGdWxsUGF0aD86IHN0cmluZztcbiAgb3V0cHV0SGFzaD86IGJvb2xlYW47XG4gIG91dHB1dFBhdGg/OiBzdHJpbmc7XG4gIHBhY2thZ2VNYW5hZ2VyPzogJ25wbScgfCAneWFybic7XG4gIHByZXNldD86ICd3ZWInIHwgJ25vZGUnIHwgJ2xhbWJkYScgfCAnbW9iaWxlJztcbiAgc291cmNlRnVsbFBhdGg/OiBzdHJpbmc7XG4gIHNvdXJjZVBhdGg/OiBzdHJpbmc7XG4gIHRhcmdldEVudmlyb25tZW50PzogJ25vZGUnIHwgJ3dlYic7XG4gIHVzZUdyYXBoUWw/OiBib29sZWFuO1xuICB1c2VUeXBlc2NyaXB0PzogYm9vbGVhbjtcbiAgd2VicGFjaz86IFdlYnBhY2tDb25maWc7XG59XG5cbmV4cG9ydCB0eXBlIENvbmZpZyA9IExleENvbmZpZ1R5cGU7XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0Q29uZmlnVmFsdWVzOiBMZXhDb25maWdUeXBlID0ge1xuICBhaToge1xuICAgIHByb3ZpZGVyOiAnbm9uZScsXG4gICAgbW9kZWw6ICdncHQtNG8nLFxuICAgIG1heFRva2VuczogNDAwMCxcbiAgICB0ZW1wZXJhdHVyZTogMC4xXG4gIH0sXG4gIGNvbmZpZ0ZpbGVzOiBbXSxcbiAgY29weUZpbGVzOiBbXSxcbiAgZW50cnlIVE1MOiAnaW5kZXguaHRtbCcsXG4gIGVudHJ5SnM6ICdpbmRleC5qcycsXG4gIGVzbGludDoge30sXG4gIGVzYnVpbGQ6IHtcbiAgICBtaW5pZnk6IHRydWUsXG4gICAgdHJlZVNoYWtpbmc6IHRydWUsXG4gICAgZHJvcDogWydjb25zb2xlJywgJ2RlYnVnZ2VyJ10sXG4gICAgcHVyZTogWydjb25zb2xlLmxvZycsICdjb25zb2xlLndhcm4nLCAnY29uc29sZS5lcnJvciddLFxuICAgIGxlZ2FsQ29tbWVudHM6ICdub25lJyxcbiAgICBzcGxpdHRpbmc6IHRydWUsXG4gICAgbWV0YWZpbGU6IGZhbHNlLFxuICAgIHNvdXJjZW1hcDogZmFsc2VcbiAgfSxcbiAgZW52OiBudWxsLFxuICBqZXN0OiB7fSxcbiAgb3V0cHV0RnVsbFBhdGg6IHBhdGhSZXNvbHZlKGN3ZCwgJy4vZGlzdCcpLFxuICBvdXRwdXRIYXNoOiBmYWxzZSxcbiAgb3V0cHV0UGF0aDogJy4vZGlzdCcsXG4gIHBhY2thZ2VNYW5hZ2VyOiAnbnBtJyxcbiAgcHJlc2V0OiAnd2ViJyxcbiAgc291cmNlRnVsbFBhdGg6IHBhdGhSZXNvbHZlKGN3ZCwgJy4vc3JjJyksXG4gIHNvdXJjZVBhdGg6ICcuL3NyYycsXG4gIHRhcmdldEVudmlyb25tZW50OiAnd2ViJyxcbiAgdXNlR3JhcGhRbDogZmFsc2UsXG4gIHVzZVR5cGVzY3JpcHQ6IGZhbHNlLFxuICB3ZWJwYWNrOiB7fVxufTtcblxuZnVuY3Rpb24gZmluZExleFJvb3Qoc3RhcnREaXI6IHN0cmluZyk6IHN0cmluZyB7XG4gIGxldCBkaXIgPSBzdGFydERpcjtcbiAgd2hpbGUoZGlyICE9PSAnLycgJiYgZGlyICE9PSAnLicpIHtcbiAgICBjb25zdCBwa2dQYXRoID0gcGF0aFJlc29sdmUoZGlyLCAncGFja2FnZS5qc29uJyk7XG4gICAgaWYoZXhpc3RzU3luYyhwa2dQYXRoKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGtnID0gSlNPTi5wYXJzZShyZWFkRmlsZVN5bmMocGtnUGF0aCwgJ3V0ZjgnKSk7XG4gICAgICAgIGlmKHBrZy5uYW1lID09PSAnQG5sYWJzL2xleCcpIHtcbiAgICAgICAgICByZXR1cm4gZGlyO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoe31cbiAgICB9XG4gICAgY29uc3QgcGFyZW50ID0gZGlybmFtZShkaXIpO1xuICAgIGlmKHBhcmVudCA9PT0gZGlyKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgZGlyID0gcGFyZW50O1xuICB9XG4gIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgQG5sYWJzL2xleCByb290Jyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUeXBlU2NyaXB0Q29uZmlnUGF0aChjb25maWdOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBjd2QgPSBwcm9jZXNzLmN3ZCgpO1xuXG4gIGlmKGNvbmZpZ05hbWUgPT09ICd0c2NvbmZpZy5idWlsZC5qc29uJykge1xuICAgIGNvbnN0IHByb2plY3RCdWlsZENvbmZpZyA9IHBhdGhSZXNvbHZlKGN3ZCwgJ3RzY29uZmlnLmJ1aWxkLmpzb24nKTtcbiAgICBpZihleGlzdHNTeW5jKHByb2plY3RCdWlsZENvbmZpZykpIHtcbiAgICAgIHJldHVybiBwcm9qZWN0QnVpbGRDb25maWc7XG4gICAgfVxuICB9XG5cbiAgaWYoY29uZmlnTmFtZSA9PT0gJ3RzY29uZmlnLmxpbnQuanNvbicpIHtcbiAgICBjb25zdCBwcm9qZWN0TGludENvbmZpZyA9IHBhdGhSZXNvbHZlKGN3ZCwgJ3RzY29uZmlnLmVzbGludC5qc29uJyk7XG4gICAgaWYoZXhpc3RzU3luYyhwcm9qZWN0TGludENvbmZpZykpIHtcbiAgICAgIHJldHVybiBwcm9qZWN0TGludENvbmZpZztcbiAgICB9XG4gIH1cblxuICBpZihjb25maWdOYW1lID09PSAndHNjb25maWcudGVzdC5qc29uJykge1xuICAgIGNvbnN0IHByb2plY3RUZXN0Q29uZmlnID0gcGF0aFJlc29sdmUoY3dkLCAndHNjb25maWcudGVzdC5qc29uJyk7XG4gICAgaWYoZXhpc3RzU3luYyhwcm9qZWN0VGVzdENvbmZpZykpIHtcbiAgICAgIHJldHVybiBwcm9qZWN0VGVzdENvbmZpZztcbiAgICB9XG4gIH1cblxuICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgY29uZmlnTmFtZSk7XG4gIGlmKGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGgpKSB7XG4gICAgcmV0dXJuIHByb2plY3RDb25maWdQYXRoO1xuICB9XG5cbiAgY29uc3QgbGV4RGlyID0gTGV4Q29uZmlnLmdldExleERpcigpO1xuICByZXR1cm4gcGF0aFJlc29sdmUobGV4RGlyLCBjb25maWdOYW1lKTtcbn1cblxuZXhwb3J0IGNsYXNzIExleENvbmZpZyB7XG4gIHN0YXRpYyBjb25maWc6IExleENvbmZpZ1R5cGUgPSB7XG4gICAgLi4uZGVmYXVsdENvbmZpZ1ZhbHVlc1xuICB9O1xuXG4gIHN0YXRpYyBnZXRMZXhEaXIoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gZGlybmFtZShnZXRMZXhQYWNrYWdlSnNvblBhdGgoKSk7XG4gIH1cblxuICBzdGF0aWMgc2V0IHVzZVR5cGVzY3JpcHQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICBMZXhDb25maWcuY29uZmlnLnVzZVR5cGVzY3JpcHQgPSB2YWx1ZTtcbiAgICBjb25zdCB7c291cmNlRnVsbFBhdGh9ID0gTGV4Q29uZmlnLmNvbmZpZztcblxuICAgIGNvbnN0IHtlbnRyeUpzfSA9IExleENvbmZpZy5jb25maWc7XG5cbiAgICBpZihlbnRyeUpzID09PSAnaW5kZXguanMnICYmIHZhbHVlKSB7XG4gICAgICBjb25zdCBpbmRleFBhdGg6IHN0cmluZyA9IHBhdGhSZXNvbHZlKGN3ZCwgc291cmNlRnVsbFBhdGgsICdpbmRleC50c3gnKTtcbiAgICAgIGNvbnN0IGhhc0luZGV4VHN4OiBib29sZWFuID0gZXhpc3RzU3luYyhpbmRleFBhdGgpO1xuXG4gICAgICBpZihoYXNJbmRleFRzeCkge1xuICAgICAgICBMZXhDb25maWcuY29uZmlnLmVudHJ5SnMgPSAnaW5kZXgudHN4JztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIExleENvbmZpZy5jb25maWcuZW50cnlKcyA9ICdpbmRleC50cyc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHVwZGF0ZUNvbmZpZyh1cGRhdGVkQ29uZmlnOiBMZXhDb25maWdUeXBlKTogTGV4Q29uZmlnVHlwZSB7XG4gICAgY29uc3Qge291dHB1dEZ1bGxQYXRoLCBvdXRwdXRQYXRoLCBzb3VyY2VQYXRoLCBzb3VyY2VGdWxsUGF0aCwgdXNlVHlwZXNjcmlwdCwgYWl9ID0gdXBkYXRlZENvbmZpZztcbiAgICBjb25zdCBjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCk7XG5cbiAgICBpZih1c2VUeXBlc2NyaXB0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIExleENvbmZpZy51c2VUeXBlc2NyaXB0ID0gdXNlVHlwZXNjcmlwdDtcbiAgICB9XG5cbiAgICBpZihvdXRwdXRQYXRoICE9PSB1bmRlZmluZWQgJiYgb3V0cHV0RnVsbFBhdGggPT09IHVuZGVmaW5lZCkge1xuICAgICAgdXBkYXRlZENvbmZpZy5vdXRwdXRGdWxsUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgb3V0cHV0UGF0aCk7XG4gICAgfVxuXG4gICAgaWYoc291cmNlUGF0aCAhPT0gdW5kZWZpbmVkICYmIHNvdXJjZUZ1bGxQYXRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHVwZGF0ZWRDb25maWcuc291cmNlRnVsbFBhdGggPSBwYXRoUmVzb2x2ZShjd2QsIHNvdXJjZVBhdGgpO1xuICAgIH1cblxuICAgIGlmKGFpKSB7XG4gICAgICBMZXhDb25maWcuY29uZmlnLmFpID0gey4uLkxleENvbmZpZy5jb25maWcuYWksIC4uLmFpfTtcblxuICAgICAgaWYocHJvY2Vzcy5lbnYuQ1VSU09SX0lERSA9PT0gJ3RydWUnICYmIExleENvbmZpZy5jb25maWcuYWkucHJvdmlkZXIgPT09ICdub25lJykge1xuICAgICAgICBMZXhDb25maWcuY29uZmlnLmFpLnByb3ZpZGVyID0gJ2N1cnNvcic7XG4gICAgICB9XG4gICAgfVxuXG4gICAgTGV4Q29uZmlnLmNvbmZpZyA9IHsuLi5MZXhDb25maWcuY29uZmlnLCAuLi51cGRhdGVkQ29uZmlnfTtcblxuICAgIHJldHVybiBMZXhDb25maWcuY29uZmlnO1xuICB9XG5cbiAgc3RhdGljIGFkZENvbmZpZ1BhcmFtcyhjbWQsIHBhcmFtczogTGV4Q29uZmlnVHlwZSkge1xuICAgIGNvbnN0IG5hbWVQcm9wZXJ0eTogc3RyaW5nID0gJ19uYW1lJztcbiAgICBjb25zdCB7ZW52aXJvbm1lbnQsIG91dHB1dFBhdGgsIHNvdXJjZVBhdGgsIHR5cGVzY3JpcHR9ID0gY21kO1xuXG4gICAgaWYob3V0cHV0UGF0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXJhbXMub3V0cHV0UGF0aCA9IG91dHB1dFBhdGg7XG4gICAgICBwYXJhbXMub3V0cHV0RnVsbFBhdGggPSBwYXRoUmVzb2x2ZShjd2QsIG91dHB1dFBhdGgpO1xuICAgIH1cblxuICAgIGlmKHNvdXJjZVBhdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgcGFyYW1zLnNvdXJjZVBhdGggPSBzb3VyY2VQYXRoO1xuICAgICAgcGFyYW1zLnNvdXJjZUZ1bGxQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBzb3VyY2VQYXRoKTtcbiAgICB9XG5cbiAgICBpZih0eXBlc2NyaXB0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHBhcmFtcy51c2VUeXBlc2NyaXB0ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZihlbnZpcm9ubWVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXJhbXMudGFyZ2V0RW52aXJvbm1lbnQgPSBlbnZpcm9ubWVudCA9PT0gJ3dlYicgPyAnd2ViJyA6ICdub2RlJztcbiAgICB9XG5cbiAgICBwcm9jZXNzLmVudi5MRVhfQ09ORklHID0gSlNPTi5zdHJpbmdpZnkoXG4gICAgICB7XG4gICAgICAgIC4uLkxleENvbmZpZy51cGRhdGVDb25maWcocGFyYW1zKSxcbiAgICAgICAgY29tbWFuZE5hbWU6IGNtZFtuYW1lUHJvcGVydHldLFxuICAgICAgICBpc1N0YXRpYzogY21kLnN0YXRpY1xuICAgICAgfSwgbnVsbCwgMFxuICAgICk7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgcGFyc2VDb25maWcoY21kLCBpc1Jvb3Q6IGJvb2xlYW4gPSB0cnVlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qge2NsaU5hbWUgPSAnTGV4JywgbGV4Q29uZmlnLCBsZXhDb25maWdOYW1lLCBxdWlldCwgdHlwZXNjcmlwdCwgZGVidWcgPSBmYWxzZX0gPSBjbWQ7XG4gICAgY29uc3QgY29uZmlnRm9ybWF0cyA9IFsnanMnLCAnbWpzJywgJ2NqcycsICd0cycsICdqc29uJ107XG4gICAgY29uc3QgY29uZmlnQmFzZU5hbWU6IHN0cmluZyA9IGxleENvbmZpZ05hbWUgfHwgJ2xleC5jb25maWcnO1xuICAgIGxldCBjb25maWdQYXRoOiBzdHJpbmcgPSBsZXhDb25maWcgfHwgJyc7XG4gICAgbGV0IGNvbmZpZ0V4aXN0czogYm9vbGVhbiA9IGxleENvbmZpZyA/IGV4aXN0c1N5bmMoY29uZmlnUGF0aCkgOiBmYWxzZTtcblxuICAgIGlmKCFjb25maWdQYXRoIHx8ICFjb25maWdFeGlzdHMpIHtcbiAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgIGxvZyhgU2VhcmNoaW5nIGZvciBjb25maWcgZmlsZXMgd2l0aCBiYXNlIG5hbWU6ICR7Y29uZmlnQmFzZU5hbWV9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG5cbiAgICAgIGZvcihjb25zdCBmb3JtYXQgb2YgY29uZmlnRm9ybWF0cykge1xuICAgICAgICBjb25zdCBwb3RlbnRpYWxQYXRoID0gaXNSb290XG4gICAgICAgICAgPyBwYXRoUmVzb2x2ZShjd2QsIGAuLyR7Y29uZmlnQmFzZU5hbWV9LiR7Zm9ybWF0fWApXG4gICAgICAgICAgOiByZWxhdGl2ZUZpbGVQYXRoKGAke2NvbmZpZ0Jhc2VOYW1lfS4ke2Zvcm1hdH1gLCBjd2QpO1xuXG4gICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgbG9nKGBDaGVja2luZyBmb3IgY29uZmlnIGZpbGU6ICR7cG90ZW50aWFsUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGV4aXN0c1N5bmMocG90ZW50aWFsUGF0aCkpIHtcbiAgICAgICAgICBjb25maWdQYXRoID0gcG90ZW50aWFsUGF0aDtcbiAgICAgICAgICBjb25maWdFeGlzdHMgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYoY29uZmlnRXhpc3RzKSB7XG4gICAgICBsb2coYFVzaW5nICR7Y2xpTmFtZX0gY29uZmlndXJhdGlvbiBmaWxlOiAke2NvbmZpZ1BhdGh9YCwgJ25vdGUnLCBxdWlldCk7XG4gICAgICBjb25zdCBleHQ6IHN0cmluZyA9IHBhdGhFeHRuYW1lKGNvbmZpZ1BhdGgpO1xuXG4gICAgICBpZihleHQgPT09ICcuanNvbicpIHtcbiAgICAgICAgY29uc3QgY29uZmlnQ29udGVudDogc3RyaW5nID0gcmVhZEZpbGVTeW5jKGNvbmZpZ1BhdGgsICd1dGY4Jyk7XG5cbiAgICAgICAgaWYoY29uZmlnQ29udGVudCkge1xuICAgICAgICAgIGxldCBjb25maWdKc29uOiBMZXhDb25maWdUeXBlO1xuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbmZpZ0pzb24gPSBKU09OLnBhcnNlKGNvbmZpZ0NvbnRlbnQpPy5kZWZhdWx0IHx8IHt9O1xuICAgICAgICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogRmFpbGVkIHRvIHBhcnNlIEpTT04gY29uZmlnOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgICAgICAgY29uZmlnSnNvbiA9IHt9O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIExleENvbmZpZy5hZGRDb25maWdQYXJhbXMoY21kLCBjb25maWdKc29uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6IENvbmZpZyBmaWxlIG1hbGZvcm1lZCwgJHtjb25maWdQYXRofWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmKFsnLmpzJywgJy5tanMnLCAnLmNqcycsICcudHMnXS5pbmNsdWRlcyhleHQpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbGV0IGxleEN1c3RvbUNvbmZpZztcblxuICAgICAgICAgIGlmKGV4dCA9PT0gJy5janMnKSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlVXJsID0gbmV3IFVSTChgZmlsZTovLy8ke3BhdGhSZXNvbHZlKGNvbmZpZ1BhdGgpfWApLmhyZWY7XG5cbiAgICAgICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgICAgIGxvZyhgTG9hZGluZyBDb21tb25KUyBjb25maWcgZnJvbTogJHtmaWxlVXJsfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV4Q3VzdG9tQ29uZmlnID0gYXdhaXQgaW1wb3J0KGZpbGVVcmwpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgICBsb2coYExvYWRpbmcgRVNNL1RTIGNvbmZpZyBmcm9tOiAke2NvbmZpZ1BhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxleEN1c3RvbUNvbmZpZyA9IGF3YWl0IGltcG9ydChjb25maWdQYXRoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBjb25maWcgPSBsZXhDdXN0b21Db25maWcuZGVmYXVsdCB8fCBsZXhDdXN0b21Db25maWc7XG5cbiAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgbG9nKGBMb2FkZWQgY29uZmlnOiAke0pTT04uc3RyaW5naWZ5KGNvbmZpZywgbnVsbCwgMil9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYoIWNvbmZpZykge1xuICAgICAgICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IFdhcm5pbmc6IENvbmZpZyBmaWxlIGxvYWRlZCBidXQgbm8gY29uZmlndXJhdGlvbiBmb3VuZGAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIExleENvbmZpZy5hZGRDb25maWdQYXJhbXMoY21kLCBjb25maWcgfHwge30pO1xuICAgICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBGYWlsZWQgdG8gbG9hZCBjb25maWcgZmlsZTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6IENvbmZpZyBmaWxlIG11c3QgYmUgYSBKUywgQ0pTLCBNSlMsIFRTLCBvciBKU09OIGZpbGUuYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coJ05vIGNvbmZpZyBmaWxlIGZvdW5kLiBVc2luZyBkZWZhdWx0IGNvbmZpZ3VyYXRpb24uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICB9XG5cbiAgICAgIExleENvbmZpZy51c2VUeXBlc2NyaXB0ID0gISF0eXBlc2NyaXB0O1xuICAgICAgTGV4Q29uZmlnLmFkZENvbmZpZ1BhcmFtcyhjbWQsIExleENvbmZpZy5jb25maWcpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBjaGVja1R5cGVzY3JpcHRDb25maWcoKSB7XG4gICAgY29uc3QgdHNjb25maWdQYXRoOiBzdHJpbmcgPSBwYXRoUmVzb2x2ZShjd2QsICcuL3RzY29uZmlnLmpzb24nKTtcblxuICAgIGlmKCFleGlzdHNTeW5jKHRzY29uZmlnUGF0aCkpIHtcbiAgICAgIGNvbnN0IGRpck5hbWUgPSBnZXREaXJOYW1lKCk7XG4gICAgICB3cml0ZUZpbGVTeW5jKHRzY29uZmlnUGF0aCwgcmVhZEZpbGVTeW5jKHBhdGhSZXNvbHZlKGRpck5hbWUsICcuLi8uLi8uLi90c2NvbmZpZy5iYXNlLmpzb24nKSkpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBjaGVja0NvbXBpbGVUeXBlc2NyaXB0Q29uZmlnKCkge1xuICAgIGNvbnN0IGxleERpciA9IExleENvbmZpZy5nZXRMZXhEaXIoKTtcbiAgICBjb25zdCB0c2NvbmZpZ0NvbXBpbGVQYXRoOiBzdHJpbmcgPSBwYXRoUmVzb2x2ZShsZXhEaXIsICcuL3RzY29uZmlnLmJ1aWxkLmpzb24nKTtcblxuICAgIGlmKCFleGlzdHNTeW5jKHRzY29uZmlnQ29tcGlsZVBhdGgpKSB7XG4gICAgICBjb25zdCB0ZW1wbGF0ZVBhdGggPSBwYXRoUmVzb2x2ZShsZXhEaXIsICd0c2NvbmZpZy5idWlsZC5qc29uJyk7XG4gICAgICBpZihleGlzdHNTeW5jKHRlbXBsYXRlUGF0aCkpIHtcbiAgICAgICAgd3JpdGVGaWxlU3luYyh0c2NvbmZpZ0NvbXBpbGVQYXRoLCByZWFkRmlsZVN5bmModGVtcGxhdGVQYXRoKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGNoZWNrTGludFR5cGVzY3JpcHRDb25maWcoKSB7XG4gICAgY29uc3QgbGV4RGlyID0gTGV4Q29uZmlnLmdldExleERpcigpO1xuICAgIGNvbnN0IHRzY29uZmlnTGludFBhdGg6IHN0cmluZyA9IHBhdGhSZXNvbHZlKGxleERpciwgJy4vdHNjb25maWcubGludC5qc29uJyk7XG5cbiAgICBpZighZXhpc3RzU3luYyh0c2NvbmZpZ0xpbnRQYXRoKSkge1xuICAgICAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aFJlc29sdmUobGV4RGlyLCAndHNjb25maWcubGludC5qc29uJyk7XG4gICAgICBpZihleGlzdHNTeW5jKHRlbXBsYXRlUGF0aCkpIHtcbiAgICAgICAgd3JpdGVGaWxlU3luYyh0c2NvbmZpZ0xpbnRQYXRoLCByZWFkRmlsZVN5bmModGVtcGxhdGVQYXRoKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGNoZWNrVGVzdFR5cGVzY3JpcHRDb25maWcoKSB7XG4gICAgY29uc3QgbGV4RGlyID0gTGV4Q29uZmlnLmdldExleERpcigpO1xuICAgIGNvbnN0IHRzY29uZmlnVGVzdFBhdGg6IHN0cmluZyA9IHBhdGhSZXNvbHZlKGxleERpciwgJy4vdHNjb25maWcudGVzdC5qc29uJyk7XG5cbiAgICBpZighZXhpc3RzU3luYyh0c2NvbmZpZ1Rlc3RQYXRoKSkge1xuICAgICAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aFJlc29sdmUobGV4RGlyLCAndHNjb25maWcudGVzdC5qc29uJyk7XG4gICAgICBpZihleGlzdHNTeW5jKHRlbXBsYXRlUGF0aCkpIHtcbiAgICAgICAgd3JpdGVGaWxlU3luYyh0c2NvbmZpZ1Rlc3RQYXRoLCByZWFkRmlsZVN5bmModGVtcGxhdGVQYXRoKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59Il0sCiAgIm1hcHBpbmdzIjogIkFBSUEsU0FBUSxZQUFZ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