@decohere/create 0.0.1-dev.48 → 0.0.1-dev.49

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 (124) hide show
  1. package/commonjs/src/cli.js +3 -3
  2. package/commonjs/src/resolve-launch.js +53 -0
  3. package/commonjs/src/runner.js +5 -45
  4. package/commonjs/src/version.js +1 -1
  5. package/es6/src/cli.js +3 -3
  6. package/es6/src/resolve-launch.js +46 -0
  7. package/es6/src/runner.js +8 -57
  8. package/es6/src/version.js +3 -3
  9. package/pack-builder-tgz.mjs +1 -1
  10. package/package.json +4 -11
  11. package/types/src/resolve-launch.d.ts +10 -0
  12. package/types/src/runner.d.ts +3 -13
  13. package/types/src/version.d.ts +0 -2
  14. package/commonjs/src/domain/prompt.js +0 -64
  15. package/commonjs/src/models/compose.model.js +0 -138
  16. package/commonjs/src/models/config-yaml.model.js +0 -88
  17. package/commonjs/src/models/const.js +0 -31
  18. package/commonjs/src/models/dev-container.model.js +0 -100
  19. package/commonjs/src/models/docker-image.model.js +0 -221
  20. package/commonjs/src/models/env-file.model.js +0 -47
  21. package/commonjs/src/models/gitignore.model.js +0 -31
  22. package/commonjs/src/models/launch-json.model.js +0 -74
  23. package/commonjs/src/models/package-json.model.js +0 -133
  24. package/commonjs/src/models/project.model.js +0 -134
  25. package/commonjs/src/models/source-file.js +0 -6
  26. package/commonjs/src/models/tsconfig.model.js +0 -34
  27. package/commonjs/src/models/vscode-settings.model.js +0 -31
  28. package/commonjs/src/program.js +0 -135
  29. package/commonjs/src/resolve-target-dir.js +0 -19
  30. package/commonjs/src/services/scaffold.service.js +0 -62
  31. package/commonjs/src/webapi/api-name.js +0 -95
  32. package/commonjs/src/webapi/const.js +0 -50
  33. package/commonjs/src/webapi/create-api.js +0 -285
  34. package/commonjs/src/webapi/features/auth.feature.js +0 -463
  35. package/commonjs/src/webapi/features/auth0-cli.js +0 -406
  36. package/commonjs/src/webapi/features/biome-format.js +0 -49
  37. package/commonjs/src/webapi/features/database.feature.js +0 -273
  38. package/commonjs/src/webapi/features/finalize.feature.js +0 -91
  39. package/commonjs/src/webapi/features/postman.feature.js +0 -319
  40. package/commonjs/src/webapi/models/api-package-json.model.js +0 -63
  41. package/commonjs/src/webapi/models/auth-config.model.js +0 -26
  42. package/commonjs/src/webapi/models/controller-source-file.model.js +0 -188
  43. package/commonjs/src/webapi/models/github-ci.model.js +0 -193
  44. package/commonjs/src/webapi/models/main-source-file.model.js +0 -165
  45. package/commonjs/src/webapi/models/production-dockerfile.model.js +0 -138
  46. package/commonjs/src/webapi/models/sample-files.model.js +0 -60
  47. package/commonjs/src/webapi/models/webapi-image.model.js +0 -22
  48. package/commonjs/src/webapi/postman/hello-openapi.js +0 -175
  49. package/commonjs/src/webapi/postman/local-view.js +0 -184
  50. package/commonjs/src/webapi/postman/openapi-to-postman.js +0 -202
  51. package/es6/src/domain/prompt.js +0 -43
  52. package/es6/src/models/compose.model.js +0 -132
  53. package/es6/src/models/config-yaml.model.js +0 -76
  54. package/es6/src/models/const.js +0 -21
  55. package/es6/src/models/dev-container.model.js +0 -90
  56. package/es6/src/models/docker-image.model.js +0 -185
  57. package/es6/src/models/env-file.model.js +0 -43
  58. package/es6/src/models/gitignore.model.js +0 -21
  59. package/es6/src/models/launch-json.model.js +0 -64
  60. package/es6/src/models/package-json.model.js +0 -129
  61. package/es6/src/models/project.model.js +0 -119
  62. package/es6/src/models/source-file.js +0 -3
  63. package/es6/src/models/tsconfig.model.js +0 -24
  64. package/es6/src/models/vscode-settings.model.js +0 -21
  65. package/es6/src/program.js +0 -76
  66. package/es6/src/resolve-target-dir.js +0 -9
  67. package/es6/src/services/scaffold.service.js +0 -52
  68. package/es6/src/webapi/api-name.js +0 -59
  69. package/es6/src/webapi/const.js +0 -20
  70. package/es6/src/webapi/create-api.js +0 -265
  71. package/es6/src/webapi/features/auth.feature.js +0 -412
  72. package/es6/src/webapi/features/auth0-cli.js +0 -348
  73. package/es6/src/webapi/features/biome-format.js +0 -42
  74. package/es6/src/webapi/features/database.feature.js +0 -263
  75. package/es6/src/webapi/features/finalize.feature.js +0 -81
  76. package/es6/src/webapi/features/postman.feature.js +0 -253
  77. package/es6/src/webapi/models/api-package-json.model.js +0 -58
  78. package/es6/src/webapi/models/auth-config.model.js +0 -22
  79. package/es6/src/webapi/models/controller-source-file.model.js +0 -179
  80. package/es6/src/webapi/models/github-ci.model.js +0 -186
  81. package/es6/src/webapi/models/main-source-file.model.js +0 -161
  82. package/es6/src/webapi/models/production-dockerfile.model.js +0 -126
  83. package/es6/src/webapi/models/sample-files.model.js +0 -42
  84. package/es6/src/webapi/models/webapi-image.model.js +0 -12
  85. package/es6/src/webapi/postman/hello-openapi.js +0 -168
  86. package/es6/src/webapi/postman/local-view.js +0 -169
  87. package/es6/src/webapi/postman/openapi-to-postman.js +0 -179
  88. package/types/src/domain/prompt.d.ts +0 -4
  89. package/types/src/models/compose.model.d.ts +0 -59
  90. package/types/src/models/config-yaml.model.d.ts +0 -27
  91. package/types/src/models/const.d.ts +0 -19
  92. package/types/src/models/dev-container.model.d.ts +0 -33
  93. package/types/src/models/docker-image.model.d.ts +0 -56
  94. package/types/src/models/env-file.model.d.ts +0 -15
  95. package/types/src/models/gitignore.model.d.ts +0 -6
  96. package/types/src/models/launch-json.model.d.ts +0 -7
  97. package/types/src/models/package-json.model.d.ts +0 -32
  98. package/types/src/models/project.model.d.ts +0 -60
  99. package/types/src/models/source-file.d.ts +0 -11
  100. package/types/src/models/tsconfig.model.d.ts +0 -5
  101. package/types/src/models/vscode-settings.model.d.ts +0 -7
  102. package/types/src/program.d.ts +0 -3
  103. package/types/src/resolve-target-dir.d.ts +0 -5
  104. package/types/src/services/scaffold.service.d.ts +0 -22
  105. package/types/src/webapi/api-name.d.ts +0 -14
  106. package/types/src/webapi/const.d.ts +0 -17
  107. package/types/src/webapi/create-api.d.ts +0 -15
  108. package/types/src/webapi/features/auth.feature.d.ts +0 -10
  109. package/types/src/webapi/features/auth0-cli.d.ts +0 -72
  110. package/types/src/webapi/features/biome-format.d.ts +0 -5
  111. package/types/src/webapi/features/database.feature.d.ts +0 -5
  112. package/types/src/webapi/features/finalize.feature.d.ts +0 -2
  113. package/types/src/webapi/features/postman.feature.d.ts +0 -16
  114. package/types/src/webapi/models/api-package-json.model.d.ts +0 -18
  115. package/types/src/webapi/models/auth-config.model.d.ts +0 -26
  116. package/types/src/webapi/models/controller-source-file.model.d.ts +0 -45
  117. package/types/src/webapi/models/github-ci.model.d.ts +0 -9
  118. package/types/src/webapi/models/main-source-file.model.d.ts +0 -54
  119. package/types/src/webapi/models/production-dockerfile.model.d.ts +0 -20
  120. package/types/src/webapi/models/sample-files.model.d.ts +0 -7
  121. package/types/src/webapi/models/webapi-image.model.d.ts +0 -5
  122. package/types/src/webapi/postman/hello-openapi.d.ts +0 -19
  123. package/types/src/webapi/postman/local-view.d.ts +0 -17
  124. package/types/src/webapi/postman/openapi-to-postman.d.ts +0 -62
@@ -1,265 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { basename, join, resolve } from "node:path";
3
- import { DockerCompose } from "../models/compose.model.js";
4
- import { ConfigYaml } from "../models/config-yaml.model.js";
5
- import { WELL_KNOWN_FILES } from "../models/const.js";
6
- import { DevContainer } from "../models/dev-container.model.js";
7
- import { EnvFile } from "../models/env-file.model.js";
8
- import { Gitignore } from "../models/gitignore.model.js";
9
- import { LaunchJson } from "../models/launch-json.model.js";
10
- import { PackageJson } from "../models/package-json.model.js";
11
- import { MonoRepoScaffold, ProjectScaffold } from "../models/project.model.js";
12
- import { TsConfig } from "../models/tsconfig.model.js";
13
- import { VSCodeSettings } from "../models/vscode-settings.model.js";
14
- import { ScaffoldService } from "../services/scaffold.service.js";
15
- import { CreateCliError, isDecohereWorkspace, listExistingApiNames, parseApiNames } from "./api-name.js";
16
- import { DEFAULT_WEBAPI_NAME, webapiPackageName, webapiPort, webapiProjectDir, webapiReleaseEntry } from "./const.js";
17
- import { AuthFeature } from "./features/auth.feature.js";
18
- import { DatabaseFeature } from "./features/database.feature.js";
19
- import { FinalizeFeature } from "./features/finalize.feature.js";
20
- import { PostmanFeature } from "./features/postman.feature.js";
21
- import { ApiPackageJson } from "./models/api-package-json.model.js";
22
- import { ControllerSourceFile } from "./models/controller-source-file.model.js";
23
- import { GithubCiWorkflows } from "./models/github-ci.model.js";
24
- import { MainSourceFile } from "./models/main-source-file.model.js";
25
- import { WebapiProductionDockerfile } from "./models/production-dockerfile.model.js";
26
- import { SampleConfigModel, SampleServiceModel } from "./models/sample-files.model.js";
27
- import { WebapiDevContainer } from "./models/webapi-image.model.js";
28
- export { WEBAPI_PROJECT_DIR, WEBAPI_RELEASE_ENTRY } from "./const.js";
29
- const features = [
30
- DatabaseFeature,
31
- AuthFeature,
32
- PostmanFeature,
33
- FinalizeFeature
34
- ];
35
- export async function scaffoldApi(cliOptions) {
36
- const targetDir = resolve(cliOptions.d ?? ".");
37
- const projectName = cliOptions.projectName?.trim() || process.env.DECOHERE_PROJECT_NAME?.trim() || basename(targetDir);
38
- const names = parseApiNames(cliOptions.names);
39
- const workspace = cliOptions.add ? createAddWorkspace(targetDir, projectName, names) : createWorkspace(targetDir, projectName, names);
40
- await ScaffoldService.scaffold(workspace, {
41
- ...cliOptions,
42
- names
43
- }, features);
44
- }
45
- function createWorkspace(targetDir, projectName, apiNames) {
46
- const monoRepo = new MonoRepoScaffold();
47
- monoRepo.targetDir = targetDir;
48
- monoRepo.setName(projectName);
49
- const name = monoRepo.name;
50
- const compose = new DockerCompose().setProjectName(name).addNetwork(name, {
51
- name: `samples-${name}`
52
- }).addService("devcontainer", {
53
- build: ".",
54
- volumes: [
55
- // Workspace-local (created by initialize.sh as the host user).
56
- // Do NOT bind ${HOME}/.npm/... — Docker creates missing host paths as root.
57
- "./npm-auth:/home/node/.npm-config",
58
- "webapi-node-modules:/workspace/node_modules"
59
- ],
60
- environment: {
61
- NPM_CONFIG_USERCONFIG: "/home/node/.npm-config/.npmrc"
62
- },
63
- command: "sleep infinity",
64
- networks: [
65
- name
66
- ]
67
- }).addVolume("webapi-node-modules");
68
- const devContainer = new DevContainer().addExtension("biomejs.biome", "vitest.explorer").setInitializeCommand("bash .devcontainer/initialize.sh").setPostStartCommand("bash .devcontainer/post-start.sh").useCompose();
69
- for (const [index, apiName] of apiNames.entries()){
70
- const port = webapiPort(index);
71
- devContainer.forwardPort(port);
72
- devContainer.setPortAttributes(port, {
73
- label: apiName === DEFAULT_WEBAPI_NAME ? "API" : apiName,
74
- requireLocalPort: true
75
- });
76
- }
77
- // Workspace-level models (repo root)
78
- monoRepo.addModel(compose);
79
- monoRepo.addModel(devContainer);
80
- monoRepo.addModel(new WebapiDevContainer());
81
- monoRepo.addModel(new WebapiProductionDockerfile(apiNames));
82
- monoRepo.addModel(new GithubCiWorkflows());
83
- monoRepo.addModel(new VSCodeSettings(name));
84
- monoRepo.addModel(new LaunchJson(apiNames));
85
- monoRepo.addModel(new TsConfig());
86
- monoRepo.addModel(new PackageJson(`${name}.api`, {
87
- apiNames,
88
- workspaceName: name
89
- }));
90
- monoRepo.addModel(new ConfigYaml(WELL_KNOWN_FILES.CONFIG_YAML, "config/config.yaml", ""));
91
- monoRepo.addModel(new ConfigYaml(WELL_KNOWN_FILES.CONFIG_DEV_YAML, "config/config.dev.yaml", ""));
92
- monoRepo.addModel(new Gitignore());
93
- monoRepo.addModel(new EnvFile());
94
- // Biome formatter/linter config
95
- monoRepo.addFile({
96
- files: ()=>[
97
- {
98
- filePath: "biome.json",
99
- content: JSON.stringify({
100
- $schema: "https://biomejs.dev/schemas/2.0.0/schema.json",
101
- files: {
102
- includes: [
103
- "**/*.ts",
104
- "**/*.js",
105
- "**/*.json",
106
- "**/*.yml",
107
- "**/*.yaml"
108
- ]
109
- },
110
- assist: {
111
- actions: {
112
- source: {
113
- organizeImports: "on"
114
- }
115
- }
116
- },
117
- vcs: {
118
- enabled: true,
119
- clientKind: "git",
120
- useIgnoreFile: true
121
- },
122
- formatter: {
123
- enabled: true,
124
- formatWithErrors: true,
125
- indentStyle: "tab",
126
- lineWidth: 95
127
- },
128
- javascript: {
129
- parser: {
130
- unsafeParameterDecoratorsEnabled: true
131
- }
132
- },
133
- linter: {
134
- rules: {
135
- style: {
136
- useConsistentMemberAccessibility: {
137
- level: "error",
138
- options: {
139
- accessibility: "explicit"
140
- }
141
- }
142
- }
143
- }
144
- },
145
- overrides: [
146
- {
147
- includes: [
148
- "**/*.json"
149
- ],
150
- formatter: {
151
- indentStyle: "space",
152
- indentWidth: 2
153
- }
154
- }
155
- ]
156
- }, null, 2)
157
- }
158
- ]
159
- });
160
- monoRepo.addFile({
161
- files: ()=>[
162
- {
163
- filePath: ".devcontainer/initialize.sh",
164
- content: [
165
- "#!/usr/bin/env bash",
166
- "# Runs on the host before the container is created (devcontainer initializeCommand).",
167
- "# Creates npm-auth as the host user so the bind mount is not root-owned.",
168
- "# Do not scaffold npm-auth/ from the builder (that runs as root).",
169
- "set -euo pipefail",
170
- "",
171
- 'root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"',
172
- 'npm_dir="$root/.devcontainer/npm-auth"',
173
- 'if ! mkdir -p "$npm_dir" 2>/dev/null; then',
174
- '\techo "Cannot create $npm_dir (permission denied)." >&2',
175
- '\techo "The scaffold container likely left .devcontainer root-owned. Fix with:" >&2',
176
- '\techo " sudo chown -R \\"$USER:$USER\\" \\"$root\\"" >&2',
177
- "\texit 1",
178
- "fi",
179
- "{",
180
- '\techo "*"',
181
- '\techo "!.gitignore"',
182
- '} >"$npm_dir/.gitignore"',
183
- "",
184
- 'if [[ ! -f "$npm_dir/.npmrc" ]]; then',
185
- '\tif [[ -f "${HOME}/.npmrc" ]]; then',
186
- '\t\tcp -a "${HOME}/.npmrc" "$npm_dir/.npmrc"',
187
- "\tfi",
188
- "fi",
189
- ""
190
- ].join("\n")
191
- },
192
- {
193
- filePath: ".devcontainer/post-start.sh",
194
- content: [
195
- "#!/usr/bin/env bash",
196
- "# Runs on every container start (devcontainer postStartCommand).",
197
- "set -euo pipefail",
198
- "",
199
- 'AUTH_REGISTRY="https://registry.npmjs.org"',
200
- "",
201
- 'if npm whoami --registry "$AUTH_REGISTRY" >/dev/null 2>&1; then',
202
- '\techo "npm: logged in as $(npm whoami --registry "$AUTH_REGISTRY")"',
203
- "\texit 0",
204
- "fi",
205
- "",
206
- "if [[ -t 0 && -t 1 ]]; then",
207
- '\techo "npm: not authenticated — starting login..."',
208
- '\tnpm login --registry "$AUTH_REGISTRY"',
209
- "\texit 0",
210
- "fi",
211
- "",
212
- 'echo "npm: not authenticated. Open a terminal and run: npm login" >&2',
213
- 'echo " (creds persist in .devcontainer/npm-auth/)" >&2',
214
- "exit 1",
215
- ""
216
- ].join("\n")
217
- }
218
- ]
219
- });
220
- for (const apiName of apiNames){
221
- addApiProject(monoRepo, name, apiName);
222
- }
223
- return monoRepo;
224
- }
225
- function createAddWorkspace(targetDir, projectName, apiNames) {
226
- if (!isDecohereWorkspace(targetDir)) {
227
- throw new CreateCliError(`Not a Decohere workspace: ${targetDir}. Scaffold one first with \`npx @decohere/create webapi\`.`);
228
- }
229
- const existing = listExistingApiNames(targetDir);
230
- for (const apiName of apiNames){
231
- if (existing.includes(apiName)) {
232
- throw new CreateCliError(`API "${apiName}" already exists at ${webapiProjectDir(apiName)}.`);
233
- }
234
- }
235
- const monoRepo = new MonoRepoScaffold();
236
- monoRepo.targetDir = targetDir;
237
- monoRepo.setName(projectName);
238
- const name = monoRepo.name;
239
- const pkg = PackageJson.fromFile(join(targetDir, "package.json"));
240
- monoRepo.addModel(pkg);
241
- monoRepo.addModel(existsSync(join(targetDir, ".env")) ? EnvFile.fromFile(join(targetDir, ".env")) : new EnvFile());
242
- monoRepo.addModel(existsSync(join(targetDir, "config/config.yaml")) ? ConfigYaml.fromFile(WELL_KNOWN_FILES.CONFIG_YAML, "config/config.yaml", join(targetDir, "config/config.yaml")) : new ConfigYaml(WELL_KNOWN_FILES.CONFIG_YAML, "config/config.yaml", ""));
243
- monoRepo.addModel(existsSync(join(targetDir, "config/config.dev.yaml")) ? ConfigYaml.fromFile(WELL_KNOWN_FILES.CONFIG_DEV_YAML, "config/config.dev.yaml", join(targetDir, "config/config.dev.yaml")) : new ConfigYaml(WELL_KNOWN_FILES.CONFIG_DEV_YAML, "config/config.dev.yaml", ""));
244
- for (const [offset, apiName] of apiNames.entries()){
245
- const port = webapiPort(existing.length + offset);
246
- pkg.addScript(`start:${apiName}`, `node ${webapiReleaseEntry(apiName)}`);
247
- pkg.addScript(`dev:${apiName}`, `PORT=${port} flux serve --project ${webapiPackageName(name, apiName)}`);
248
- addApiProject(monoRepo, name, apiName);
249
- }
250
- monoRepo.addModel(new WebapiProductionDockerfile(apiNames, {
251
- namedOnly: true
252
- }));
253
- return monoRepo;
254
- }
255
- function addApiProject(monoRepo, workspaceName, apiName) {
256
- const apiProject = new ProjectScaffold(webapiProjectDir(apiName));
257
- apiProject.addModel(new ApiPackageJson(workspaceName, apiName));
258
- apiProject.addModel(new MainSourceFile(`${workspaceName}.${apiName}`));
259
- apiProject.addModel(new ControllerSourceFile());
260
- apiProject.addFile(new SampleConfigModel());
261
- apiProject.addFile(new SampleServiceModel());
262
- monoRepo.addProject(apiProject);
263
- }
264
-
265
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL2NyZWF0ZS9zcmMvd2ViYXBpL2NyZWF0ZS1hcGkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhpc3RzU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBiYXNlbmFtZSwgam9pbiwgcmVzb2x2ZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IERvY2tlckNvbXBvc2UgfSBmcm9tIFwiLi4vbW9kZWxzL2NvbXBvc2UubW9kZWwuanNcIjtcbmltcG9ydCB7IENvbmZpZ1lhbWwgfSBmcm9tIFwiLi4vbW9kZWxzL2NvbmZpZy15YW1sLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBXRUxMX0tOT1dOX0ZJTEVTIH0gZnJvbSBcIi4uL21vZGVscy9jb25zdC5qc1wiO1xuaW1wb3J0IHsgRGV2Q29udGFpbmVyIH0gZnJvbSBcIi4uL21vZGVscy9kZXYtY29udGFpbmVyLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBFbnZGaWxlIH0gZnJvbSBcIi4uL21vZGVscy9lbnYtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgR2l0aWdub3JlIH0gZnJvbSBcIi4uL21vZGVscy9naXRpZ25vcmUubW9kZWwuanNcIjtcbmltcG9ydCB7IExhdW5jaEpzb24gfSBmcm9tIFwiLi4vbW9kZWxzL2xhdW5jaC1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBQYWNrYWdlSnNvbiB9IGZyb20gXCIuLi9tb2RlbHMvcGFja2FnZS1qc29uLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBNb25vUmVwb1NjYWZmb2xkLCBQcm9qZWN0U2NhZmZvbGQgfSBmcm9tIFwiLi4vbW9kZWxzL3Byb2plY3QubW9kZWwuanNcIjtcbmltcG9ydCB7IFRzQ29uZmlnIH0gZnJvbSBcIi4uL21vZGVscy90c2NvbmZpZy5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgVlNDb2RlU2V0dGluZ3MgfSBmcm9tIFwiLi4vbW9kZWxzL3ZzY29kZS1zZXR0aW5ncy5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgU2NhZmZvbGRTZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2VzL3NjYWZmb2xkLnNlcnZpY2UuanNcIjtcbmltcG9ydCB7XG5cdENyZWF0ZUNsaUVycm9yLFxuXHRpc0RlY29oZXJlV29ya3NwYWNlLFxuXHRsaXN0RXhpc3RpbmdBcGlOYW1lcyxcblx0cGFyc2VBcGlOYW1lcyxcbn0gZnJvbSBcIi4vYXBpLW5hbWUuanNcIjtcbmltcG9ydCB7XG5cdERFRkFVTFRfV0VCQVBJX05BTUUsXG5cdHdlYmFwaVBhY2thZ2VOYW1lLFxuXHR3ZWJhcGlQb3J0LFxuXHR3ZWJhcGlQcm9qZWN0RGlyLFxuXHR3ZWJhcGlSZWxlYXNlRW50cnksXG59IGZyb20gXCIuL2NvbnN0LmpzXCI7XG5pbXBvcnQgeyBBdXRoRmVhdHVyZSB9IGZyb20gXCIuL2ZlYXR1cmVzL2F1dGguZmVhdHVyZS5qc1wiO1xuaW1wb3J0IHsgRGF0YWJhc2VGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvZGF0YWJhc2UuZmVhdHVyZS5qc1wiO1xuaW1wb3J0IHsgRmluYWxpemVGZWF0dXJlIH0gZnJvbSBcIi4vZmVhdHVyZXMvZmluYWxpemUuZmVhdHVyZS5qc1wiO1xuaW1wb3J0IHsgUG9zdG1hbkZlYXR1cmUgfSBmcm9tIFwiLi9mZWF0dXJlcy9wb3N0bWFuLmZlYXR1cmUuanNcIjtcbmltcG9ydCB7IEFwaVBhY2thZ2VKc29uIH0gZnJvbSBcIi4vbW9kZWxzL2FwaS1wYWNrYWdlLWpzb24ubW9kZWwuanNcIjtcbmltcG9ydCB7IENvbnRyb2xsZXJTb3VyY2VGaWxlIH0gZnJvbSBcIi4vbW9kZWxzL2NvbnRyb2xsZXItc291cmNlLWZpbGUubW9kZWwuanNcIjtcbmltcG9ydCB7IEdpdGh1YkNpV29ya2Zsb3dzIH0gZnJvbSBcIi4vbW9kZWxzL2dpdGh1Yi1jaS5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgTWFpblNvdXJjZUZpbGUgfSBmcm9tIFwiLi9tb2RlbHMvbWFpbi1zb3VyY2UtZmlsZS5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgV2ViYXBpUHJvZHVjdGlvbkRvY2tlcmZpbGUgfSBmcm9tIFwiLi9tb2RlbHMvcHJvZHVjdGlvbi1kb2NrZXJmaWxlLm1vZGVsLmpzXCI7XG5pbXBvcnQgeyBTYW1wbGVDb25maWdNb2RlbCwgU2FtcGxlU2VydmljZU1vZGVsIH0gZnJvbSBcIi4vbW9kZWxzL3NhbXBsZS1maWxlcy5tb2RlbC5qc1wiO1xuaW1wb3J0IHsgV2ViYXBpRGV2Q29udGFpbmVyIH0gZnJvbSBcIi4vbW9kZWxzL3dlYmFwaS1pbWFnZS5tb2RlbC5qc1wiO1xuXG5leHBvcnQgeyBXRUJBUElfUFJPSkVDVF9ESVIsIFdFQkFQSV9SRUxFQVNFX0VOVFJZIH0gZnJvbSBcIi4vY29uc3QuanNcIjtcblxuZXhwb3J0IHR5cGUgQXBpT3B0aW9ucyA9IHtcblx0ZD86IHN0cmluZztcblx0LyoqIEhvc3QgcHJvamVjdCBuYW1lIChkaXJlY3RvcnkgYmFzZW5hbWUpLiBSZXF1aXJlZCB3aGVuIHNjYWZmb2xkaW5nIGludG8gYC93b3Jrc3BhY2VgLiAqL1xuXHRwcm9qZWN0TmFtZT86IHN0cmluZztcblx0LyoqIEFQSSBzbHVncyB1bmRlciBgcHJvamVjdHMvYC4gRGVmYXVsdCBgW1wiYXBpXCJdYC4gUmVwZWF0YWJsZSBgLS1uYW1lYC4gKi9cblx0bmFtZXM/OiBzdHJpbmdbXTtcblx0LyoqIEFkZCBBUElzIHRvIGFuIGV4aXN0aW5nIERlY29oZXJlIHdvcmtzcGFjZSBpbnN0ZWFkIG9mIGNyZWF0aW5nIGEgbmV3IG9uZS4gKi9cblx0YWRkPzogYm9vbGVhbjtcblx0YXV0aFByb3ZpZGVyPzogXCJhdXRoMFwiIHwgXCJub25lXCI7XG5cdGRhdGFiYXNlUHJvdmlkZXI/OiBcIm5vbmVcIiB8IFwicG9zdGdyZXMvdHlwZW9ybVwiO1xuXHRwb3N0bWFuUHJvdmlkZXI/OiBcImFwaVwiIHwgXCJsb2NhbFwiIHwgXCJub25lXCI7XG5cdGluc3RhbGxEZXBlbmRlbmNpZXM/OiBcInllc1wiIHwgXCJub1wiO1xufTtcblxuY29uc3QgZmVhdHVyZXMgPSBbRGF0YWJhc2VGZWF0dXJlLCBBdXRoRmVhdHVyZSwgUG9zdG1hbkZlYXR1cmUsIEZpbmFsaXplRmVhdHVyZV07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzY2FmZm9sZEFwaShjbGlPcHRpb25zOiBBcGlPcHRpb25zKSB7XG5cdGNvbnN0IHRhcmdldERpciA9IHJlc29sdmUoY2xpT3B0aW9ucy5kID8/IFwiLlwiKTtcblx0Y29uc3QgcHJvamVjdE5hbWUgPVxuXHRcdGNsaU9wdGlvbnMucHJvamVjdE5hbWU/LnRyaW0oKSB8fFxuXHRcdHByb2Nlc3MuZW52LkRFQ09IRVJFX1BST0pFQ1RfTkFNRT8udHJpbSgpIHx8XG5cdFx0YmFzZW5hbWUodGFyZ2V0RGlyKTtcblx0Y29uc3QgbmFtZXMgPSBwYXJzZUFwaU5hbWVzKGNsaU9wdGlvbnMubmFtZXMpO1xuXHRjb25zdCB3b3Jrc3BhY2UgPSBjbGlPcHRpb25zLmFkZFxuXHRcdD8gY3JlYXRlQWRkV29ya3NwYWNlKHRhcmdldERpciwgcHJvamVjdE5hbWUsIG5hbWVzKVxuXHRcdDogY3JlYXRlV29ya3NwYWNlKHRhcmdldERpciwgcHJvamVjdE5hbWUsIG5hbWVzKTtcblx0YXdhaXQgU2NhZmZvbGRTZXJ2aWNlLnNjYWZmb2xkKHdvcmtzcGFjZSwgeyAuLi5jbGlPcHRpb25zLCBuYW1lcyB9LCBmZWF0dXJlcyk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVdvcmtzcGFjZShcblx0dGFyZ2V0RGlyOiBzdHJpbmcsXG5cdHByb2plY3ROYW1lOiBzdHJpbmcsXG5cdGFwaU5hbWVzOiByZWFkb25seSBzdHJpbmdbXSxcbik6IE1vbm9SZXBvU2NhZmZvbGQge1xuXHRjb25zdCBtb25vUmVwbyA9IG5ldyBNb25vUmVwb1NjYWZmb2xkKCk7XG5cdG1vbm9SZXBvLnRhcmdldERpciA9IHRhcmdldERpcjtcblx0bW9ub1JlcG8uc2V0TmFtZShwcm9qZWN0TmFtZSk7XG5cdGNvbnN0IG5hbWUgPSBtb25vUmVwby5uYW1lO1xuXG5cdGNvbnN0IGNvbXBvc2UgPSBuZXcgRG9ja2VyQ29tcG9zZSgpXG5cdFx0LnNldFByb2plY3ROYW1lKG5hbWUpXG5cdFx0LmFkZE5ldHdvcmsobmFtZSwgeyBuYW1lOiBgc2FtcGxlcy0ke25hbWV9YCB9KVxuXHRcdC5hZGRTZXJ2aWNlKFwiZGV2Y29udGFpbmVyXCIsIHtcblx0XHRcdGJ1aWxkOiBcIi5cIixcblx0XHRcdHZvbHVtZXM6IFtcblx0XHRcdFx0Ly8gV29ya3NwYWNlLWxvY2FsIChjcmVhdGVkIGJ5IGluaXRpYWxpemUuc2ggYXMgdGhlIGhvc3QgdXNlcikuXG5cdFx0XHRcdC8vIERvIE5PVCBiaW5kICR7SE9NRX0vLm5wbS8uLi4g4oCUIERvY2tlciBjcmVhdGVzIG1pc3NpbmcgaG9zdCBwYXRocyBhcyByb290LlxuXHRcdFx0XHRcIi4vbnBtLWF1dGg6L2hvbWUvbm9kZS8ubnBtLWNvbmZpZ1wiLFxuXHRcdFx0XHRcIndlYmFwaS1ub2RlLW1vZHVsZXM6L3dvcmtzcGFjZS9ub2RlX21vZHVsZXNcIixcblx0XHRcdF0sXG5cdFx0XHRlbnZpcm9ubWVudDogeyBOUE1fQ09ORklHX1VTRVJDT05GSUc6IFwiL2hvbWUvbm9kZS8ubnBtLWNvbmZpZy8ubnBtcmNcIiB9LFxuXHRcdFx0Y29tbWFuZDogXCJzbGVlcCBpbmZpbml0eVwiLFxuXHRcdFx0bmV0d29ya3M6IFtuYW1lXSxcblx0XHR9KVxuXHRcdC5hZGRWb2x1bWUoXCJ3ZWJhcGktbm9kZS1tb2R1bGVzXCIpO1xuXG5cdGNvbnN0IGRldkNvbnRhaW5lciA9IG5ldyBEZXZDb250YWluZXIoKVxuXHRcdC5hZGRFeHRlbnNpb24oXCJiaW9tZWpzLmJpb21lXCIsIFwidml0ZXN0LmV4cGxvcmVyXCIpXG5cdFx0LnNldEluaXRpYWxpemVDb21tYW5kKFwiYmFzaCAuZGV2Y29udGFpbmVyL2luaXRpYWxpemUuc2hcIilcblx0XHQuc2V0UG9zdFN0YXJ0Q29tbWFuZChcImJhc2ggLmRldmNvbnRhaW5lci9wb3N0LXN0YXJ0LnNoXCIpXG5cdFx0LnVzZUNvbXBvc2UoKTtcblxuXHRmb3IgKGNvbnN0IFtpbmRleCwgYXBpTmFtZV0gb2YgYXBpTmFtZXMuZW50cmllcygpKSB7XG5cdFx0Y29uc3QgcG9ydCA9IHdlYmFwaVBvcnQoaW5kZXgpO1xuXHRcdGRldkNvbnRhaW5lci5mb3J3YXJkUG9ydChwb3J0KTtcblx0XHRkZXZDb250YWluZXIuc2V0UG9ydEF0dHJpYnV0ZXMocG9ydCwge1xuXHRcdFx0bGFiZWw6IGFwaU5hbWUgPT09IERFRkFVTFRfV0VCQVBJX05BTUUgPyBcIkFQSVwiIDogYXBpTmFtZSxcblx0XHRcdHJlcXVpcmVMb2NhbFBvcnQ6IHRydWUsXG5cdFx0fSk7XG5cdH1cblxuXHQvLyBXb3Jrc3BhY2UtbGV2ZWwgbW9kZWxzIChyZXBvIHJvb3QpXG5cdG1vbm9SZXBvLmFkZE1vZGVsKGNvbXBvc2UpO1xuXHRtb25vUmVwby5hZGRNb2RlbChkZXZDb250YWluZXIpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgV2ViYXBpRGV2Q29udGFpbmVyKCkpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgV2ViYXBpUHJvZHVjdGlvbkRvY2tlcmZpbGUoYXBpTmFtZXMpKTtcblx0bW9ub1JlcG8uYWRkTW9kZWwobmV3IEdpdGh1YkNpV29ya2Zsb3dzKCkpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgVlNDb2RlU2V0dGluZ3MobmFtZSkpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgTGF1bmNoSnNvbihhcGlOYW1lcykpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgVHNDb25maWcoKSk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKG5ldyBQYWNrYWdlSnNvbihgJHtuYW1lfS5hcGlgLCB7IGFwaU5hbWVzLCB3b3Jrc3BhY2VOYW1lOiBuYW1lIH0pKTtcblx0bW9ub1JlcG8uYWRkTW9kZWwobmV3IENvbmZpZ1lhbWwoV0VMTF9LTk9XTl9GSUxFUy5DT05GSUdfWUFNTCwgXCJjb25maWcvY29uZmlnLnlhbWxcIiwgXCJcIikpO1xuXHRtb25vUmVwby5hZGRNb2RlbChcblx0XHRuZXcgQ29uZmlnWWFtbChXRUxMX0tOT1dOX0ZJTEVTLkNPTkZJR19ERVZfWUFNTCwgXCJjb25maWcvY29uZmlnLmRldi55YW1sXCIsIFwiXCIpLFxuXHQpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgR2l0aWdub3JlKCkpO1xuXHRtb25vUmVwby5hZGRNb2RlbChuZXcgRW52RmlsZSgpKTtcblxuXHQvLyBCaW9tZSBmb3JtYXR0ZXIvbGludGVyIGNvbmZpZ1xuXHRtb25vUmVwby5hZGRGaWxlKHtcblx0XHRmaWxlczogKCkgPT4gW1xuXHRcdFx0e1xuXHRcdFx0XHRmaWxlUGF0aDogXCJiaW9tZS5qc29uXCIsXG5cdFx0XHRcdGNvbnRlbnQ6IEpTT04uc3RyaW5naWZ5KFxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdCRzY2hlbWE6IFwiaHR0cHM6Ly9iaW9tZWpzLmRldi9zY2hlbWFzLzIuMC4wL3NjaGVtYS5qc29uXCIsXG5cdFx0XHRcdFx0XHRmaWxlczoge1xuXHRcdFx0XHRcdFx0XHRpbmNsdWRlczogW1wiKiovKi50c1wiLCBcIioqLyouanNcIiwgXCIqKi8qLmpzb25cIiwgXCIqKi8qLnltbFwiLCBcIioqLyoueWFtbFwiXSxcblx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRhc3Npc3Q6IHsgYWN0aW9uczogeyBzb3VyY2U6IHsgb3JnYW5pemVJbXBvcnRzOiBcIm9uXCIgfSB9IH0sXG5cdFx0XHRcdFx0XHR2Y3M6IHsgZW5hYmxlZDogdHJ1ZSwgY2xpZW50S2luZDogXCJnaXRcIiwgdXNlSWdub3JlRmlsZTogdHJ1ZSB9LFxuXHRcdFx0XHRcdFx0Zm9ybWF0dGVyOiB7XG5cdFx0XHRcdFx0XHRcdGVuYWJsZWQ6IHRydWUsXG5cdFx0XHRcdFx0XHRcdGZvcm1hdFdpdGhFcnJvcnM6IHRydWUsXG5cdFx0XHRcdFx0XHRcdGluZGVudFN0eWxlOiBcInRhYlwiLFxuXHRcdFx0XHRcdFx0XHRsaW5lV2lkdGg6IDk1LFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdGphdmFzY3JpcHQ6IHsgcGFyc2VyOiB7IHVuc2FmZVBhcmFtZXRlckRlY29yYXRvcnNFbmFibGVkOiB0cnVlIH0gfSxcblx0XHRcdFx0XHRcdGxpbnRlcjoge1xuXHRcdFx0XHRcdFx0XHRydWxlczoge1xuXHRcdFx0XHRcdFx0XHRcdHN0eWxlOiB7XG5cdFx0XHRcdFx0XHRcdFx0XHR1c2VDb25zaXN0ZW50TWVtYmVyQWNjZXNzaWJpbGl0eToge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRsZXZlbDogXCJlcnJvclwiLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRvcHRpb25zOiB7IGFjY2Vzc2liaWxpdHk6IFwiZXhwbGljaXRcIiB9LFxuXHRcdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdG92ZXJyaWRlczogW1xuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0aW5jbHVkZXM6IFtcIioqLyouanNvblwiXSxcblx0XHRcdFx0XHRcdFx0XHRmb3JtYXR0ZXI6IHsgaW5kZW50U3R5bGU6IFwic3BhY2VcIiwgaW5kZW50V2lkdGg6IDIgfSxcblx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdF0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRudWxsLFxuXHRcdFx0XHRcdDIsXG5cdFx0XHRcdCksXG5cdFx0XHR9LFxuXHRcdF0sXG5cdH0pO1xuXG5cdG1vbm9SZXBvLmFkZEZpbGUoe1xuXHRcdGZpbGVzOiAoKSA9PiBbXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5kZXZjb250YWluZXIvaW5pdGlhbGl6ZS5zaFwiLFxuXHRcdFx0XHRjb250ZW50OiBbXG5cdFx0XHRcdFx0XCIjIS91c3IvYmluL2VudiBiYXNoXCIsXG5cdFx0XHRcdFx0XCIjIFJ1bnMgb24gdGhlIGhvc3QgYmVmb3JlIHRoZSBjb250YWluZXIgaXMgY3JlYXRlZCAoZGV2Y29udGFpbmVyIGluaXRpYWxpemVDb21tYW5kKS5cIixcblx0XHRcdFx0XHRcIiMgQ3JlYXRlcyBucG0tYXV0aCBhcyB0aGUgaG9zdCB1c2VyIHNvIHRoZSBiaW5kIG1vdW50IGlzIG5vdCByb290LW93bmVkLlwiLFxuXHRcdFx0XHRcdFwiIyBEbyBub3Qgc2NhZmZvbGQgbnBtLWF1dGgvIGZyb20gdGhlIGJ1aWxkZXIgKHRoYXQgcnVucyBhcyByb290KS5cIixcblx0XHRcdFx0XHRcInNldCAtZXVvIHBpcGVmYWlsXCIsXG5cdFx0XHRcdFx0XCJcIixcblx0XHRcdFx0XHQncm9vdD1cIiQoY2QgXCIkKGRpcm5hbWUgXCIke0JBU0hfU09VUkNFWzBdfVwiKS8uLlwiICYmIHB3ZClcIicsXG5cdFx0XHRcdFx0J25wbV9kaXI9XCIkcm9vdC8uZGV2Y29udGFpbmVyL25wbS1hdXRoXCInLFxuXHRcdFx0XHRcdCdpZiAhIG1rZGlyIC1wIFwiJG5wbV9kaXJcIiAyPi9kZXYvbnVsbDsgdGhlbicsXG5cdFx0XHRcdFx0J1xcdGVjaG8gXCJDYW5ub3QgY3JlYXRlICRucG1fZGlyIChwZXJtaXNzaW9uIGRlbmllZCkuXCIgPiYyJyxcblx0XHRcdFx0XHQnXFx0ZWNobyBcIlRoZSBzY2FmZm9sZCBjb250YWluZXIgbGlrZWx5IGxlZnQgLmRldmNvbnRhaW5lciByb290LW93bmVkLiBGaXggd2l0aDpcIiA+JjInLFxuXHRcdFx0XHRcdCdcXHRlY2hvIFwiICBzdWRvIGNob3duIC1SIFxcXFxcIiRVU0VSOiRVU0VSXFxcXFwiIFxcXFxcIiRyb290XFxcXFwiXCIgPiYyJyxcblx0XHRcdFx0XHRcIlxcdGV4aXQgMVwiLFxuXHRcdFx0XHRcdFwiZmlcIixcblx0XHRcdFx0XHRcIntcIixcblx0XHRcdFx0XHQnXFx0ZWNobyBcIipcIicsXG5cdFx0XHRcdFx0J1xcdGVjaG8gXCIhLmdpdGlnbm9yZVwiJyxcblx0XHRcdFx0XHQnfSA+XCIkbnBtX2Rpci8uZ2l0aWdub3JlXCInLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0J2lmIFtbICEgLWYgXCIkbnBtX2Rpci8ubnBtcmNcIiBdXTsgdGhlbicsXG5cdFx0XHRcdFx0J1xcdGlmIFtbIC1mIFwiJHtIT01FfS8ubnBtcmNcIiBdXTsgdGhlbicsXG5cdFx0XHRcdFx0J1xcdFxcdGNwIC1hIFwiJHtIT01FfS8ubnBtcmNcIiBcIiRucG1fZGlyLy5ucG1yY1wiJyxcblx0XHRcdFx0XHRcIlxcdGZpXCIsXG5cdFx0XHRcdFx0XCJmaVwiLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdF0uam9pbihcIlxcblwiKSxcblx0XHRcdH0sXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5kZXZjb250YWluZXIvcG9zdC1zdGFydC5zaFwiLFxuXHRcdFx0XHRjb250ZW50OiBbXG5cdFx0XHRcdFx0XCIjIS91c3IvYmluL2VudiBiYXNoXCIsXG5cdFx0XHRcdFx0XCIjIFJ1bnMgb24gZXZlcnkgY29udGFpbmVyIHN0YXJ0IChkZXZjb250YWluZXIgcG9zdFN0YXJ0Q29tbWFuZCkuXCIsXG5cdFx0XHRcdFx0XCJzZXQgLWV1byBwaXBlZmFpbFwiLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0J0FVVEhfUkVHSVNUUlk9XCJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZ1wiJyxcblx0XHRcdFx0XHRcIlwiLFxuXHRcdFx0XHRcdCdpZiBucG0gd2hvYW1pIC0tcmVnaXN0cnkgXCIkQVVUSF9SRUdJU1RSWVwiID4vZGV2L251bGwgMj4mMTsgdGhlbicsXG5cdFx0XHRcdFx0J1xcdGVjaG8gXCJucG06IGxvZ2dlZCBpbiBhcyAkKG5wbSB3aG9hbWkgLS1yZWdpc3RyeSBcIiRBVVRIX1JFR0lTVFJZXCIpXCInLFxuXHRcdFx0XHRcdFwiXFx0ZXhpdCAwXCIsXG5cdFx0XHRcdFx0XCJmaVwiLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0XCJpZiBbWyAtdCAwICYmIC10IDEgXV07IHRoZW5cIixcblx0XHRcdFx0XHQnXFx0ZWNobyBcIm5wbTogbm90IGF1dGhlbnRpY2F0ZWQg4oCUIHN0YXJ0aW5nIGxvZ2luLi4uXCInLFxuXHRcdFx0XHRcdCdcXHRucG0gbG9naW4gLS1yZWdpc3RyeSBcIiRBVVRIX1JFR0lTVFJZXCInLFxuXHRcdFx0XHRcdFwiXFx0ZXhpdCAwXCIsXG5cdFx0XHRcdFx0XCJmaVwiLFxuXHRcdFx0XHRcdFwiXCIsXG5cdFx0XHRcdFx0J2VjaG8gXCJucG06IG5vdCBhdXRoZW50aWNhdGVkLiBPcGVuIGEgdGVybWluYWwgYW5kIHJ1bjogbnBtIGxvZ2luXCIgPiYyJyxcblx0XHRcdFx0XHQnZWNobyBcIiAgICAoY3JlZHMgcGVyc2lzdCBpbiAuZGV2Y29udGFpbmVyL25wbS1hdXRoLylcIiA+JjInLFxuXHRcdFx0XHRcdFwiZXhpdCAxXCIsXG5cdFx0XHRcdFx0XCJcIixcblx0XHRcdFx0XS5qb2luKFwiXFxuXCIpLFxuXHRcdFx0fSxcblx0XHRdLFxuXHR9KTtcblxuXHRmb3IgKGNvbnN0IGFwaU5hbWUgb2YgYXBpTmFtZXMpIHtcblx0XHRhZGRBcGlQcm9qZWN0KG1vbm9SZXBvLCBuYW1lLCBhcGlOYW1lKTtcblx0fVxuXG5cdHJldHVybiBtb25vUmVwbztcbn1cblxuZnVuY3Rpb24gY3JlYXRlQWRkV29ya3NwYWNlKFxuXHR0YXJnZXREaXI6IHN0cmluZyxcblx0cHJvamVjdE5hbWU6IHN0cmluZyxcblx0YXBpTmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuKTogTW9ub1JlcG9TY2FmZm9sZCB7XG5cdGlmICghaXNEZWNvaGVyZVdvcmtzcGFjZSh0YXJnZXREaXIpKSB7XG5cdFx0dGhyb3cgbmV3IENyZWF0ZUNsaUVycm9yKFxuXHRcdFx0YE5vdCBhIERlY29oZXJlIHdvcmtzcGFjZTogJHt0YXJnZXREaXJ9LiBTY2FmZm9sZCBvbmUgZmlyc3Qgd2l0aCBcXGBucHggQGRlY29oZXJlL2NyZWF0ZSB3ZWJhcGlcXGAuYCxcblx0XHQpO1xuXHR9XG5cblx0Y29uc3QgZXhpc3RpbmcgPSBsaXN0RXhpc3RpbmdBcGlOYW1lcyh0YXJnZXREaXIpO1xuXHRmb3IgKGNvbnN0IGFwaU5hbWUgb2YgYXBpTmFtZXMpIHtcblx0XHRpZiAoZXhpc3RpbmcuaW5jbHVkZXMoYXBpTmFtZSkpIHtcblx0XHRcdHRocm93IG5ldyBDcmVhdGVDbGlFcnJvcihcblx0XHRcdFx0YEFQSSBcIiR7YXBpTmFtZX1cIiBhbHJlYWR5IGV4aXN0cyBhdCAke3dlYmFwaVByb2plY3REaXIoYXBpTmFtZSl9LmAsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdGNvbnN0IG1vbm9SZXBvID0gbmV3IE1vbm9SZXBvU2NhZmZvbGQoKTtcblx0bW9ub1JlcG8udGFyZ2V0RGlyID0gdGFyZ2V0RGlyO1xuXHRtb25vUmVwby5zZXROYW1lKHByb2plY3ROYW1lKTtcblx0Y29uc3QgbmFtZSA9IG1vbm9SZXBvLm5hbWU7XG5cblx0Y29uc3QgcGtnID0gUGFja2FnZUpzb24uZnJvbUZpbGUoam9pbih0YXJnZXREaXIsIFwicGFja2FnZS5qc29uXCIpKTtcblx0bW9ub1JlcG8uYWRkTW9kZWwocGtnKTtcblx0bW9ub1JlcG8uYWRkTW9kZWwoXG5cdFx0ZXhpc3RzU3luYyhqb2luKHRhcmdldERpciwgXCIuZW52XCIpKVxuXHRcdFx0PyBFbnZGaWxlLmZyb21GaWxlKGpvaW4odGFyZ2V0RGlyLCBcIi5lbnZcIikpXG5cdFx0XHQ6IG5ldyBFbnZGaWxlKCksXG5cdCk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKFxuXHRcdGV4aXN0c1N5bmMoam9pbih0YXJnZXREaXIsIFwiY29uZmlnL2NvbmZpZy55YW1sXCIpKVxuXHRcdFx0PyBDb25maWdZYW1sLmZyb21GaWxlKFxuXHRcdFx0XHRcdFdFTExfS05PV05fRklMRVMuQ09ORklHX1lBTUwsXG5cdFx0XHRcdFx0XCJjb25maWcvY29uZmlnLnlhbWxcIixcblx0XHRcdFx0XHRqb2luKHRhcmdldERpciwgXCJjb25maWcvY29uZmlnLnlhbWxcIiksXG5cdFx0XHRcdClcblx0XHRcdDogbmV3IENvbmZpZ1lhbWwoV0VMTF9LTk9XTl9GSUxFUy5DT05GSUdfWUFNTCwgXCJjb25maWcvY29uZmlnLnlhbWxcIiwgXCJcIiksXG5cdCk7XG5cdG1vbm9SZXBvLmFkZE1vZGVsKFxuXHRcdGV4aXN0c1N5bmMoam9pbih0YXJnZXREaXIsIFwiY29uZmlnL2NvbmZpZy5kZXYueWFtbFwiKSlcblx0XHRcdD8gQ29uZmlnWWFtbC5mcm9tRmlsZShcblx0XHRcdFx0XHRXRUxMX0tOT1dOX0ZJTEVTLkNPTkZJR19ERVZfWUFNTCxcblx0XHRcdFx0XHRcImNvbmZpZy9jb25maWcuZGV2LnlhbWxcIixcblx0XHRcdFx0XHRqb2luKHRhcmdldERpciwgXCJjb25maWcvY29uZmlnLmRldi55YW1sXCIpLFxuXHRcdFx0XHQpXG5cdFx0XHQ6IG5ldyBDb25maWdZYW1sKFdFTExfS05PV05fRklMRVMuQ09ORklHX0RFVl9ZQU1MLCBcImNvbmZpZy9jb25maWcuZGV2LnlhbWxcIiwgXCJcIiksXG5cdCk7XG5cblx0Zm9yIChjb25zdCBbb2Zmc2V0LCBhcGlOYW1lXSBvZiBhcGlOYW1lcy5lbnRyaWVzKCkpIHtcblx0XHRjb25zdCBwb3J0ID0gd2ViYXBpUG9ydChleGlzdGluZy5sZW5ndGggKyBvZmZzZXQpO1xuXHRcdHBrZy5hZGRTY3JpcHQoYHN0YXJ0OiR7YXBpTmFtZX1gLCBgbm9kZSAke3dlYmFwaVJlbGVhc2VFbnRyeShhcGlOYW1lKX1gKTtcblx0XHRwa2cuYWRkU2NyaXB0KFxuXHRcdFx0YGRldjoke2FwaU5hbWV9YCxcblx0XHRcdGBQT1JUPSR7cG9ydH0gZmx1eCBzZXJ2ZSAtLXByb2plY3QgJHt3ZWJhcGlQYWNrYWdlTmFtZShuYW1lLCBhcGlOYW1lKX1gLFxuXHRcdCk7XG5cdFx0YWRkQXBpUHJvamVjdChtb25vUmVwbywgbmFtZSwgYXBpTmFtZSk7XG5cdH1cblx0bW9ub1JlcG8uYWRkTW9kZWwobmV3IFdlYmFwaVByb2R1Y3Rpb25Eb2NrZXJmaWxlKGFwaU5hbWVzLCB7IG5hbWVkT25seTogdHJ1ZSB9KSk7XG5cblx0cmV0dXJuIG1vbm9SZXBvO1xufVxuXG5mdW5jdGlvbiBhZGRBcGlQcm9qZWN0KFxuXHRtb25vUmVwbzogTW9ub1JlcG9TY2FmZm9sZCxcblx0d29ya3NwYWNlTmFtZTogc3RyaW5nLFxuXHRhcGlOYW1lOiBzdHJpbmcsXG4pOiB2b2lkIHtcblx0Y29uc3QgYXBpUHJvamVjdCA9IG5ldyBQcm9qZWN0U2NhZmZvbGQod2ViYXBpUHJvamVjdERpcihhcGlOYW1lKSk7XG5cdGFwaVByb2plY3QuYWRkTW9kZWwobmV3IEFwaVBhY2thZ2VKc29uKHdvcmtzcGFjZU5hbWUsIGFwaU5hbWUpKTtcblx0YXBpUHJvamVjdC5hZGRNb2RlbChuZXcgTWFpblNvdXJjZUZpbGUoYCR7d29ya3NwYWNlTmFtZX0uJHthcGlOYW1lfWApKTtcblx0YXBpUHJvamVjdC5hZGRNb2RlbChuZXcgQ29udHJvbGxlclNvdXJjZUZpbGUoKSk7XG5cdGFwaVByb2plY3QuYWRkRmlsZShuZXcgU2FtcGxlQ29uZmlnTW9kZWwoKSk7XG5cdGFwaVByb2plY3QuYWRkRmlsZShuZXcgU2FtcGxlU2VydmljZU1vZGVsKCkpO1xuXHRtb25vUmVwby5hZGRQcm9qZWN0KGFwaVByb2plY3QpO1xufVxuIl0sIm5hbWVzIjpbImV4aXN0c1N5bmMiLCJiYXNlbmFtZSIsImpvaW4iLCJyZXNvbHZlIiwiRG9ja2VyQ29tcG9zZSIsIkNvbmZpZ1lhbWwiLCJXRUxMX0tOT1dOX0ZJTEVTIiwiRGV2Q29udGFpbmVyIiwiRW52RmlsZSIsIkdpdGlnbm9yZSIsIkxhdW5jaEpzb24iLCJQYWNrYWdlSnNvbiIsIk1vbm9SZXBvU2NhZmZvbGQiLCJQcm9qZWN0U2NhZmZvbGQiLCJUc0NvbmZpZyIsIlZTQ29kZVNldHRpbmdzIiwiU2NhZmZvbGRTZXJ2aWNlIiwiQ3JlYXRlQ2xpRXJyb3IiLCJpc0RlY29oZXJlV29ya3NwYWNlIiwibGlzdEV4aXN0aW5nQXBpTmFtZXMiLCJwYXJzZUFwaU5hbWVzIiwiREVGQVVMVF9XRUJBUElfTkFNRSIsIndlYmFwaVBhY2thZ2VOYW1lIiwid2ViYXBpUG9ydCIsIndlYmFwaVByb2plY3REaXIiLCJ3ZWJhcGlSZWxlYXNlRW50cnkiLCJBdXRoRmVhdHVyZSIsIkRhdGFiYXNlRmVhdHVyZSIsIkZpbmFsaXplRmVhdHVyZSIsIlBvc3RtYW5GZWF0dXJlIiwiQXBpUGFja2FnZUpzb24iLCJDb250cm9sbGVyU291cmNlRmlsZSIsIkdpdGh1YkNpV29ya2Zsb3dzIiwiTWFpblNvdXJjZUZpbGUiLCJXZWJhcGlQcm9kdWN0aW9uRG9ja2VyZmlsZSIsIlNhbXBsZUNvbmZpZ01vZGVsIiwiU2FtcGxlU2VydmljZU1vZGVsIiwiV2ViYXBpRGV2Q29udGFpbmVyIiwiV0VCQVBJX1BST0pFQ1RfRElSIiwiV0VCQVBJX1JFTEVBU0VfRU5UUlkiLCJmZWF0dXJlcyIsInNjYWZmb2xkQXBpIiwiY2xpT3B0aW9ucyIsInRhcmdldERpciIsImQiLCJwcm9qZWN0TmFtZSIsInRyaW0iLCJwcm9jZXNzIiwiZW52IiwiREVDT0hFUkVfUFJPSkVDVF9OQU1FIiwibmFtZXMiLCJ3b3Jrc3BhY2UiLCJhZGQiLCJjcmVhdGVBZGRXb3Jrc3BhY2UiLCJjcmVhdGVXb3Jrc3BhY2UiLCJzY2FmZm9sZCIsImFwaU5hbWVzIiwibW9ub1JlcG8iLCJzZXROYW1lIiwibmFtZSIsImNvbXBvc2UiLCJzZXRQcm9qZWN0TmFtZSIsImFkZE5ldHdvcmsiLCJhZGRTZXJ2aWNlIiwiYnVpbGQiLCJ2b2x1bWVzIiwiZW52aXJvbm1lbnQiLCJOUE1fQ09ORklHX1VTRVJDT05GSUciLCJjb21tYW5kIiwibmV0d29ya3MiLCJhZGRWb2x1bWUiLCJkZXZDb250YWluZXIiLCJhZGRFeHRlbnNpb24iLCJzZXRJbml0aWFsaXplQ29tbWFuZCIsInNldFBvc3RTdGFydENvbW1hbmQiLCJ1c2VDb21wb3NlIiwiaW5kZXgiLCJhcGlOYW1lIiwiZW50cmllcyIsInBvcnQiLCJmb3J3YXJkUG9ydCIsInNldFBvcnRBdHRyaWJ1dGVzIiwibGFiZWwiLCJyZXF1aXJlTG9jYWxQb3J0IiwiYWRkTW9kZWwiLCJ3b3Jrc3BhY2VOYW1lIiwiQ09ORklHX1lBTUwiLCJDT05GSUdfREVWX1lBTUwiLCJhZGRGaWxlIiwiZmlsZXMiLCJmaWxlUGF0aCIsImNvbnRlbnQiLCJKU09OIiwic3RyaW5naWZ5IiwiJHNjaGVtYSIsImluY2x1ZGVzIiwiYXNzaXN0IiwiYWN0aW9ucyIsInNvdXJjZSIsIm9yZ2FuaXplSW1wb3J0cyIsInZjcyIsImVuYWJsZWQiLCJjbGllbnRLaW5kIiwidXNlSWdub3JlRmlsZSIsImZvcm1hdHRlciIsImZvcm1hdFdpdGhFcnJvcnMiLCJpbmRlbnRTdHlsZSIsImxpbmVXaWR0aCIsImphdmFzY3JpcHQiLCJwYXJzZXIiLCJ1bnNhZmVQYXJhbWV0ZXJEZWNvcmF0b3JzRW5hYmxlZCIsImxpbnRlciIsInJ1bGVzIiwic3R5bGUiLCJ1c2VDb25zaXN0ZW50TWVtYmVyQWNjZXNzaWJpbGl0eSIsImxldmVsIiwib3B0aW9ucyIsImFjY2Vzc2liaWxpdHkiLCJvdmVycmlkZXMiLCJpbmRlbnRXaWR0aCIsImFkZEFwaVByb2plY3QiLCJleGlzdGluZyIsInBrZyIsImZyb21GaWxlIiwib2Zmc2V0IiwibGVuZ3RoIiwiYWRkU2NyaXB0IiwibmFtZWRPbmx5IiwiYXBpUHJvamVjdCIsImFkZFByb2plY3QiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFVBQVUsUUFBUSxVQUFVO0FBQ3JDLFNBQVNDLFFBQVEsRUFBRUMsSUFBSSxFQUFFQyxPQUFPLFFBQVEsWUFBWTtBQUNwRCxTQUFTQyxhQUFhLFFBQVEsNkJBQTZCO0FBQzNELFNBQVNDLFVBQVUsUUFBUSxpQ0FBaUM7QUFDNUQsU0FBU0MsZ0JBQWdCLFFBQVEscUJBQXFCO0FBQ3RELFNBQVNDLFlBQVksUUFBUSxtQ0FBbUM7QUFDaEUsU0FBU0MsT0FBTyxRQUFRLDhCQUE4QjtBQUN0RCxTQUFTQyxTQUFTLFFBQVEsK0JBQStCO0FBQ3pELFNBQVNDLFVBQVUsUUFBUSxpQ0FBaUM7QUFDNUQsU0FBU0MsV0FBVyxRQUFRLGtDQUFrQztBQUM5RCxTQUFTQyxnQkFBZ0IsRUFBRUMsZUFB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