sonamu 0.10.13 → 0.11.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 (233) hide show
  1. package/dist/ai/agents/agent.d.ts.map +1 -1
  2. package/dist/ai/providers/rtzr/error.d.ts.map +1 -1
  3. package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
  4. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
  5. package/dist/api/base-frame.d.ts.map +1 -1
  6. package/dist/api/decorators.d.ts.map +1 -1
  7. package/dist/api/sonamu.d.ts.map +1 -1
  8. package/dist/api/sonamu.js +3 -2
  9. package/dist/api/validator.d.ts.map +1 -1
  10. package/dist/auth/audit-log/events.d.ts.map +1 -1
  11. package/dist/auth/index.d.ts +1 -1
  12. package/dist/auth/index.d.ts.map +1 -1
  13. package/dist/auth/index.js +3 -3
  14. package/dist/auth/knex-adapter.d.ts.map +1 -1
  15. package/dist/auth/plugins/wrappers/admin.d.ts +4 -4
  16. package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
  17. package/dist/auth/plugins/wrappers/anonymous.d.ts.map +1 -1
  18. package/dist/auth/plugins/wrappers/api-key.d.ts.map +1 -1
  19. package/dist/auth/plugins/wrappers/jwt.d.ts.map +1 -1
  20. package/dist/auth/plugins/wrappers/organization.d.ts.map +1 -1
  21. package/dist/auth/plugins/wrappers/passkey.d.ts.map +1 -1
  22. package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
  23. package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -1
  24. package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
  25. package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
  26. package/dist/bin/build-config.d.ts +10 -0
  27. package/dist/bin/build-config.d.ts.map +1 -1
  28. package/dist/bin/build-config.js +130 -6
  29. package/dist/bin/fixture.d.ts +7 -4
  30. package/dist/bin/fixture.d.ts.map +1 -1
  31. package/dist/bin/fixture.js +161 -13
  32. package/dist/bin/test-command.d.ts +7 -0
  33. package/dist/bin/test-command.d.ts.map +1 -1
  34. package/dist/bin/test-command.js +18 -4
  35. package/dist/bin/typecheck-web.d.ts +2 -0
  36. package/dist/bin/typecheck-web.d.ts.map +1 -0
  37. package/dist/bin/typecheck-web.js +36 -0
  38. package/dist/cache/decorator.d.ts.map +1 -1
  39. package/dist/cache/drivers.d.ts.map +1 -1
  40. package/dist/cache-control/cache-control.d.ts.map +1 -1
  41. package/dist/compress/compress.d.ts.map +1 -1
  42. package/dist/cone/cone-generator.js +1 -1
  43. package/dist/database/base-model.d.ts.map +1 -1
  44. package/dist/database/base-model.types.d.ts +0 -1
  45. package/dist/database/base-model.types.d.ts.map +1 -1
  46. package/dist/database/db.d.ts.map +1 -1
  47. package/dist/database/puri-subset.types.d.ts +0 -1
  48. package/dist/database/puri-subset.types.d.ts.map +1 -1
  49. package/dist/database/puri-wrapper.d.ts +0 -1
  50. package/dist/database/puri-wrapper.d.ts.map +1 -1
  51. package/dist/database/puri.d.ts +0 -1
  52. package/dist/database/puri.d.ts.map +1 -1
  53. package/dist/database/puri.types.d.ts +0 -1
  54. package/dist/database/puri.types.d.ts.map +1 -1
  55. package/dist/database/transaction-context.d.ts.map +1 -1
  56. package/dist/database/upsert-builder.d.ts.map +1 -1
  57. package/dist/dict/en.d.ts +58 -58
  58. package/dist/dict/en.d.ts.map +1 -1
  59. package/dist/dict/ko.d.ts +58 -58
  60. package/dist/dict/ko.d.ts.map +1 -1
  61. package/dist/dict/rc-keys.d.ts.map +1 -1
  62. package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
  63. package/dist/dict/sonamu-dictionary.js +2 -2
  64. package/dist/dict/utils.d.ts.map +1 -1
  65. package/dist/entity/entity-manager.d.ts +115 -113
  66. package/dist/entity/entity-manager.d.ts.map +1 -1
  67. package/dist/entity/entity-manager.js +25 -19
  68. package/dist/entity/entity-template-cone.d.ts +4 -4
  69. package/dist/entity/entity.d.ts +6 -1
  70. package/dist/entity/entity.d.ts.map +1 -1
  71. package/dist/entity/entity.js +8 -3
  72. package/dist/env.d.ts.map +1 -1
  73. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  74. package/dist/filter/types.d.ts.map +1 -1
  75. package/dist/index.js +6 -6
  76. package/dist/logger/configure.d.ts +10 -1
  77. package/dist/logger/configure.d.ts.map +1 -1
  78. package/dist/logger/configure.js +30 -5
  79. package/dist/migration/migration-set.d.ts.map +1 -1
  80. package/dist/migration/migration-set.js +17 -6
  81. package/dist/migration/migrator.d.ts +12 -1
  82. package/dist/migration/migrator.d.ts.map +1 -1
  83. package/dist/migration/migrator.js +77 -30
  84. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  85. package/dist/migration/slack-confirm.d.ts.map +1 -1
  86. package/dist/naite/messaging-types.d.ts +0 -1
  87. package/dist/naite/messaging-types.d.ts.map +1 -1
  88. package/dist/naite/naite-reporter.d.ts +0 -1
  89. package/dist/naite/naite-reporter.d.ts.map +1 -1
  90. package/dist/naite/naite.d.ts.map +1 -1
  91. package/dist/storage/base-file.d.ts.map +1 -1
  92. package/dist/storage/buffered-file.d.ts.map +1 -1
  93. package/dist/storage/drivers.d.ts.map +1 -1
  94. package/dist/storage/s3-driver.d.ts.map +1 -1
  95. package/dist/storage/storage-manager.d.ts.map +1 -1
  96. package/dist/storage/uploaded-file.d.ts.map +1 -1
  97. package/dist/stream/ws-audience-resolver.d.ts.map +1 -1
  98. package/dist/stream/ws-audience.d.ts.map +1 -1
  99. package/dist/stream/ws-cluster-bus.d.ts.map +1 -1
  100. package/dist/stream/ws-delivery.d.ts.map +1 -1
  101. package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
  102. package/dist/stream/ws-presence-store.d.ts.map +1 -1
  103. package/dist/stream/ws-registry.d.ts.map +1 -1
  104. package/dist/stream/ws-telemetry-memory.d.ts.map +1 -1
  105. package/dist/stream/ws-telemetry.d.ts.map +1 -1
  106. package/dist/stream/ws.d.ts.map +1 -1
  107. package/dist/syncer/api-parser.js +2 -2
  108. package/dist/syncer/file-patterns.d.ts +17 -17
  109. package/dist/syncer/filesystem-dependencies.js +1 -1
  110. package/dist/syncer/syncer.d.ts.map +1 -1
  111. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  112. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  113. package/dist/template/implementations/entity.template.d.ts +2 -2
  114. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  115. package/dist/template/implementations/entry-server.template.d.ts +2 -2
  116. package/dist/template/implementations/entry-server.template.d.ts.map +1 -1
  117. package/dist/template/implementations/generated.template.d.ts +2 -2
  118. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  119. package/dist/template/implementations/generated_http.template.d.ts +2 -2
  120. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  121. package/dist/template/implementations/generated_sso.template.d.ts +2 -2
  122. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  123. package/dist/template/implementations/http_validators.template.d.ts +2 -2
  124. package/dist/template/implementations/http_validators.template.d.ts.map +1 -1
  125. package/dist/template/implementations/init_types.template.d.ts +2 -2
  126. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  127. package/dist/template/implementations/model.template.d.ts +2 -2
  128. package/dist/template/implementations/model.template.d.ts.map +1 -1
  129. package/dist/template/implementations/model_test.template.d.ts +2 -2
  130. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  131. package/dist/template/implementations/queries.template.d.ts +2 -2
  132. package/dist/template/implementations/queries.template.d.ts.map +1 -1
  133. package/dist/template/implementations/sd.template.d.ts +2 -2
  134. package/dist/template/implementations/sd.template.d.ts.map +1 -1
  135. package/dist/template/implementations/sd.template.js +1 -1
  136. package/dist/template/implementations/services.template.d.ts +2 -2
  137. package/dist/template/implementations/services.template.d.ts.map +1 -1
  138. package/dist/template/implementations/view_form.template.d.ts +3 -3
  139. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  140. package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
  141. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  142. package/dist/template/implementations/view_list.template.d.ts +2 -2
  143. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  144. package/dist/template/implementations/view_search_input.template.d.ts +2 -2
  145. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  146. package/dist/template/template-manager.d.ts.map +1 -1
  147. package/dist/template/template.d.ts.map +1 -1
  148. package/dist/template/zod-converter.d.ts.map +1 -1
  149. package/dist/testing/_relation-graph.d.ts.map +1 -1
  150. package/dist/testing/data-explorer.d.ts +2 -2
  151. package/dist/testing/data-explorer.d.ts.map +1 -1
  152. package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
  153. package/dist/testing/faker-mappings.d.ts.map +1 -1
  154. package/dist/testing/fixture-generator.d.ts.map +1 -1
  155. package/dist/testing/fixture-generator.js +1 -1
  156. package/dist/testing/fixture-loader.d.ts.map +1 -1
  157. package/dist/testing/fixture-manager.d.ts +4 -0
  158. package/dist/testing/fixture-manager.d.ts.map +1 -1
  159. package/dist/testing/fixture-manager.js +99 -25
  160. package/dist/testing/naite-vitest-reporter.d.ts.map +1 -1
  161. package/dist/testing/parallel-db-manager.d.ts.map +1 -1
  162. package/dist/tooling/__tests__/helpers/sonamu-test-root.d.ts +10 -0
  163. package/dist/tooling/__tests__/helpers/sonamu-test-root.d.ts.map +1 -0
  164. package/dist/tooling/__tests__/helpers/sonamu-test-root.js +42 -0
  165. package/dist/tooling/cdd-service.d.ts +87 -0
  166. package/dist/tooling/cdd-service.d.ts.map +1 -0
  167. package/dist/tooling/cdd-service.js +215 -0
  168. package/dist/tooling/cli-tooling.d.ts +11 -0
  169. package/dist/tooling/cli-tooling.d.ts.map +1 -0
  170. package/dist/tooling/cli-tooling.js +901 -0
  171. package/dist/tooling/fixture-service.d.ts +29 -0
  172. package/dist/tooling/fixture-service.d.ts.map +1 -0
  173. package/dist/tooling/fixture-service.js +53 -0
  174. package/dist/tooling/index.d.ts +2 -0
  175. package/dist/tooling/index.d.ts.map +1 -0
  176. package/dist/tooling/index.js +2 -0
  177. package/dist/tooling/test-run-client.d.ts +27 -0
  178. package/dist/tooling/test-run-client.d.ts.map +1 -0
  179. package/dist/tooling/test-run-client.js +120 -0
  180. package/dist/tsdown.api.config.js +48 -0
  181. package/dist/types/types.d.ts +527 -527
  182. package/dist/types/types.d.ts.map +1 -1
  183. package/dist/ui/ai-client.d.ts.map +1 -1
  184. package/dist/utils/formatter.d.ts +6 -0
  185. package/dist/utils/formatter.d.ts.map +1 -1
  186. package/dist/utils/formatter.js +42 -11
  187. package/dist/utils/model.d.ts +1 -1
  188. package/dist/vector/chunking.d.ts.map +1 -1
  189. package/dist/vector/embedding.d.ts.map +1 -1
  190. package/package.json +13 -12
  191. package/src/api/sonamu.ts +2 -1
  192. package/src/auth/index.ts +1 -1
  193. package/src/bin/__tests__/zod-compiler-build.test.ts +67 -0
  194. package/src/bin/build-config.ts +151 -5
  195. package/src/bin/fixture.ts +204 -21
  196. package/src/bin/test-command.ts +27 -4
  197. package/src/bin/typecheck-web.ts +56 -0
  198. package/src/dict/sonamu-dictionary.ts +1 -1
  199. package/src/entity/__tests__/entity-manager-autoload.contract.test.ts +55 -0
  200. package/src/entity/__tests__/entity-manager-explicit-root-registration.contract.test.ts +107 -0
  201. package/src/entity/entity-manager.ts +31 -19
  202. package/src/entity/entity.ts +7 -2
  203. package/src/logger/__tests__/configure.test.ts +33 -0
  204. package/src/logger/configure.ts +45 -3
  205. package/src/migration/__tests__/migrator.test.ts +51 -0
  206. package/src/migration/migration-set.ts +22 -5
  207. package/src/migration/migrator.ts +103 -34
  208. package/src/syncer/api-parser.ts +1 -1
  209. package/src/testing/fixture-manager.ts +124 -32
  210. package/src/tooling/__tests__/cdd-rule-bootstrap.contract.test.ts +118 -0
  211. package/src/tooling/__tests__/cli-tooling-auth.contract.test.ts +72 -0
  212. package/src/tooling/__tests__/cli-tooling-cone-locale.contract.test.ts +150 -0
  213. package/src/tooling/__tests__/cli-tooling-entity-patch.contract.test.ts +131 -0
  214. package/src/tooling/__tests__/cli-tooling-fixture-transfer.contract.test.ts +255 -0
  215. package/src/tooling/__tests__/cli-tooling-i18n-update.contract.test.ts +104 -0
  216. package/src/tooling/__tests__/cli-tooling-scaffold.contract.test.ts +86 -0
  217. package/src/tooling/__tests__/cli-tooling-stub-practice.contract.test.ts +147 -0
  218. package/src/tooling/__tests__/default-cdd-adapter.contract.test.ts +73 -0
  219. package/src/tooling/__tests__/helpers/sonamu-test-root.ts +42 -0
  220. package/src/tooling/__tests__/test-run-client-config.contract.test.ts +154 -0
  221. package/src/tooling/cdd-service.ts +256 -0
  222. package/src/tooling/cli-tooling.ts +937 -0
  223. package/src/tooling/fixture-service.ts +72 -0
  224. package/src/tooling/index.ts +1 -0
  225. package/src/tooling/test-run-client.ts +196 -0
  226. package/src/utils/__tests__/formatter-bin.test.ts +99 -0
  227. package/src/utils/formatter.ts +74 -10
  228. package/tsdown.api.config.ts +8 -10
  229. package/bin/cli.js +0 -75
  230. package/dist/bin/cli.d.ts +0 -2
  231. package/dist/bin/cli.d.ts.map +0 -1
  232. package/dist/bin/cli.js +0 -956
  233. package/src/bin/cli.ts +0 -1166
@@ -0,0 +1,901 @@
1
+ import { z } from "zod";
2
+ //#region src/tooling/cli-tooling.ts
3
+ const jsonValueSchema = z.json();
4
+ const MIGRATION_TARGETS = /* @__PURE__ */ new Set([
5
+ "development",
6
+ "staging",
7
+ "production",
8
+ "fixture",
9
+ "test"
10
+ ]);
11
+ function assertMigrationTarget(target) {
12
+ if (MIGRATION_TARGETS.has(target)) return;
13
+ throw Object.assign(/* @__PURE__ */ new Error(`Unsupported migration target: ${target}`), {
14
+ code: "INVALID_MIGRATION_TARGET",
15
+ exitCode: 2
16
+ });
17
+ }
18
+ function assertShadowMigrationTarget(target) {
19
+ if (target === "fixture" || target === "test") return;
20
+ throw Object.assign(/* @__PURE__ */ new Error(`Invalid shadow migration target: ${target}`), {
21
+ code: "INVALID_SHADOW_MIGRATION_TARGET",
22
+ target,
23
+ exitCode: 2
24
+ });
25
+ }
26
+ async function migrationPlan(target, migrations, action = "apply") {
27
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify({
28
+ action,
29
+ target,
30
+ migrations
31
+ })));
32
+ return {
33
+ kind: "migration-plan",
34
+ action,
35
+ target,
36
+ migrations,
37
+ fingerprint: Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")
38
+ };
39
+ }
40
+ const REQUIRED_METHODS = {
41
+ core: ["sync"],
42
+ entity: [
43
+ "list",
44
+ "show",
45
+ "search",
46
+ "applyPatch",
47
+ "create",
48
+ "cones"
49
+ ],
50
+ scaffold: [
51
+ "model",
52
+ "model_test",
53
+ "view_list",
54
+ "view_form",
55
+ "status",
56
+ "preview",
57
+ "batch"
58
+ ],
59
+ migration: [
60
+ "run",
61
+ "generate",
62
+ "status",
63
+ "connections",
64
+ "code",
65
+ "preview",
66
+ "shadow",
67
+ "rollback"
68
+ ],
69
+ fixture: [
70
+ "init",
71
+ "import",
72
+ "sync",
73
+ "gen",
74
+ "fetch",
75
+ "explore"
76
+ ],
77
+ build: [
78
+ "all",
79
+ "api",
80
+ "web"
81
+ ],
82
+ test: ["run", "status"],
83
+ auth: ["generate", "addCompanions"],
84
+ i18n: [
85
+ "list",
86
+ "check",
87
+ "import",
88
+ "export",
89
+ "create",
90
+ "update",
91
+ "remove"
92
+ ],
93
+ task: [
94
+ "definitions",
95
+ "runs",
96
+ "show",
97
+ "steps",
98
+ "watch",
99
+ "pause",
100
+ "resume",
101
+ "cancel"
102
+ ],
103
+ cdd: [
104
+ "tree",
105
+ "read",
106
+ "rules",
107
+ "showRule",
108
+ "addRule",
109
+ "addAcceptanceCriterion"
110
+ ],
111
+ stub: ["practice"]
112
+ };
113
+ let initialization;
114
+ async function ensureSonamu() {
115
+ const { Sonamu } = await import("../api/sonamu.js");
116
+ if (Sonamu.isInitialized) return;
117
+ initialization ??= Sonamu.init(true, false);
118
+ await initialization;
119
+ }
120
+ async function syncOperation(input) {
121
+ await ensureSonamu();
122
+ const { Sonamu } = await import("../api/sonamu.js");
123
+ return input.force === true ? Sonamu.syncer.forceSync() : Sonamu.syncer.sync();
124
+ }
125
+ function text(input, key) {
126
+ const value = z.string().safeParse(input[key]);
127
+ return value.success ? value.data : void 0;
128
+ }
129
+ function strings(input, key) {
130
+ const value = z.array(z.string()).safeParse(input[key]);
131
+ return value.success ? value.data : [];
132
+ }
133
+ function requiredText(input, key) {
134
+ const value = text(input, key);
135
+ if (value !== void 0 && value.length > 0) return value;
136
+ throw Object.assign(/* @__PURE__ */ new Error(`Missing ${key}.`), {
137
+ code: "MISSING_ARGUMENT",
138
+ exitCode: 2
139
+ });
140
+ }
141
+ /**
142
+ * 생략한 값은 `undefined`로 통과시키되, 값이 있는데 문자열이 아니면 인자 오류로 거절합니다.
143
+ *
144
+ * `text()`처럼 조용히 무시하면 잘못된 타입의 입력이 기본값으로 둔갑합니다.
145
+ */
146
+ function optionalText(input, key) {
147
+ const value = input[key];
148
+ if (value === void 0 || value === null) return void 0;
149
+ const parsed = z.string().safeParse(value);
150
+ if (parsed.success) return parsed.data;
151
+ throw Object.assign(/* @__PURE__ */ new Error(`Invalid ${key}.`), {
152
+ code: "INVALID_ARGUMENT",
153
+ exitCode: 2
154
+ });
155
+ }
156
+ function parseJson(contents, code, schema) {
157
+ try {
158
+ return schema.parse(JSON.parse(contents));
159
+ } catch (cause) {
160
+ throw Object.assign(/* @__PURE__ */ new Error("Invalid JSON input."), {
161
+ code,
162
+ exitCode: 2,
163
+ cause
164
+ });
165
+ }
166
+ }
167
+ function mutationRequested(input) {
168
+ return input.execute === true || input.dryRun === false;
169
+ }
170
+ function explicitlyDryRun(input) {
171
+ return input.dryRun === true || input.execute === false;
172
+ }
173
+ const entityPatchSchema = z.object({
174
+ entityId: z.string().min(1),
175
+ operations: z.array(z.object({
176
+ op: z.literal("add"),
177
+ path: z.literal("/props/-"),
178
+ value: z.object({
179
+ name: z.string().min(1),
180
+ type: z.string().min(1)
181
+ }).catchall(jsonValueSchema)
182
+ }))
183
+ });
184
+ const i18nEntriesSchema = z.array(z.object({
185
+ key: z.string(),
186
+ values: z.record(z.string(), z.string())
187
+ }));
188
+ const dictionaryValuesSchema = z.record(z.string(), z.string());
189
+ const dictionarySourceSchema = z.enum([
190
+ "entity",
191
+ "project",
192
+ "sonamu"
193
+ ]);
194
+ const coneLocaleSchema = z.enum([
195
+ "ko",
196
+ "en",
197
+ "ja"
198
+ ]);
199
+ /**
200
+ * cone 생성에 사용할 locale을 결정합니다.
201
+ *
202
+ * 명시한 locale이 최우선이고, 없으면 프로젝트 i18n 기본 locale, 그마저 없으면 "ko"를 사용합니다.
203
+ */
204
+ async function resolveConeLocale(input) {
205
+ const explicit = coneLocaleSchema.safeParse(input.locale);
206
+ if (explicit.success) return explicit.data;
207
+ const { Sonamu } = await import("../api/sonamu.js");
208
+ let configuredLocale;
209
+ try {
210
+ configuredLocale = Sonamu.config.i18n?.defaultLocale;
211
+ } catch {}
212
+ const configured = coneLocaleSchema.safeParse(configuredLocale);
213
+ return configured.success ? configured.data : "ko";
214
+ }
215
+ async function entityOperation(method, input) {
216
+ await ensureSonamu();
217
+ const { EntityManager } = await import("../entity/entity-manager.js");
218
+ const entities = EntityManager.getAllEntities();
219
+ if (method === "list") return entities.map((entity) => entity.toJson());
220
+ if (method === "show") {
221
+ const entityId = requiredText(input, "entityId");
222
+ if (!EntityManager.exists(entityId)) throw Object.assign(/* @__PURE__ */ new Error(`Entity not found: ${entityId}`), { code: "ENTITY_NOT_FOUND" });
223
+ return EntityManager.get(entityId).toJson();
224
+ }
225
+ if (method === "search") {
226
+ const query = requiredText(input, "query").toLocaleLowerCase();
227
+ return entities.map((entity) => entity.toJson()).filter((entity) => JSON.stringify(entity).toLocaleLowerCase().includes(query));
228
+ }
229
+ if (method === "create") {
230
+ const entityId = requiredText(input, "name");
231
+ const { Sonamu } = await import("../api/sonamu.js");
232
+ await Sonamu.syncer.createEntity({
233
+ entityId,
234
+ title: entityId
235
+ });
236
+ if (input.noCones === true) return {
237
+ entityId,
238
+ cones: "skipped"
239
+ };
240
+ const entity = EntityManager.get(entityId);
241
+ if (input.ai === true) return entity.generateCones({
242
+ preserveExisting: false,
243
+ onlyEmpty: false,
244
+ locale: await resolveConeLocale(input)
245
+ });
246
+ await entity.generateTemplateCones();
247
+ return {
248
+ entityId,
249
+ cones: "template"
250
+ };
251
+ }
252
+ if (method === "cones") {
253
+ const entityId = requiredText(input, "entityId");
254
+ const targets = input.all === true || entityId === "all" ? EntityManager.getAllEntities() : EntityManager.exists(entityId) ? [EntityManager.get(entityId)] : [];
255
+ if (targets.length === 0) throw Object.assign(/* @__PURE__ */ new Error(`Entity not found: ${entityId}`), { code: "ENTITY_NOT_FOUND" });
256
+ const regenerate = input.regenerate === true;
257
+ const selectedLocale = await resolveConeLocale(input);
258
+ const settled = await Promise.allSettled(targets.map(async (entity) => ({
259
+ entityId: entity.id,
260
+ ...await entity.generateCones({
261
+ preserveExisting: !regenerate,
262
+ onlyEmpty: !regenerate,
263
+ locale: selectedLocale
264
+ })
265
+ })));
266
+ const results = [];
267
+ const failures = [];
268
+ for (const [index, outcome] of settled.entries()) {
269
+ if (outcome.status === "fulfilled") {
270
+ results.push(outcome.value);
271
+ continue;
272
+ }
273
+ failures.push({
274
+ entityId: targets[index].id,
275
+ message: outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason)
276
+ });
277
+ }
278
+ if (failures.length === 0) return results;
279
+ throw Object.assign(/* @__PURE__ */ new Error(`Cone generation failed for ${failures.length} entity(s).`), {
280
+ code: "CONE_GENERATION_FAILED",
281
+ details: {
282
+ results,
283
+ failures
284
+ }
285
+ });
286
+ }
287
+ const file = requiredText(input, "file");
288
+ const { readFile } = await import("node:fs/promises");
289
+ const patch = parseJson(file === "-" ? await (async () => {
290
+ const chunks = [];
291
+ for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
292
+ return Buffer.concat(chunks).toString("utf8");
293
+ })() : await readFile(file, "utf8"), "INVALID_ENTITY_PATCH", entityPatchSchema);
294
+ if (!EntityManager.exists(patch.entityId)) throw Object.assign(/* @__PURE__ */ new Error(`Entity not found: ${patch.entityId}`), { code: "ENTITY_NOT_FOUND" });
295
+ const target = EntityManager.get(patch.entityId);
296
+ const before = target.toJson();
297
+ const after = structuredClone(before);
298
+ const nextProps = [...after.props, ...patch.operations.map(({ value }) => structuredClone(value))];
299
+ const { EntityJsonSchema } = await import("../types/types.js");
300
+ const validation = EntityJsonSchema.safeParse({
301
+ ...after,
302
+ props: nextProps
303
+ });
304
+ if (!validation.success) throw Object.assign(/* @__PURE__ */ new Error("Invalid entity patch."), {
305
+ code: "INVALID_ENTITY_PATCH",
306
+ exitCode: 2,
307
+ cause: validation.error
308
+ });
309
+ after.props = nextProps;
310
+ if (mutationRequested(input)) {
311
+ target.props = after.props;
312
+ await target.save();
313
+ }
314
+ return {
315
+ changed: patch.operations.length > 0,
316
+ before,
317
+ after
318
+ };
319
+ }
320
+ async function renderScaffolds(input) {
321
+ await ensureSonamu();
322
+ const { renderTemplate } = await import("../syncer/code-generator.js");
323
+ const entities = strings(input, "entities");
324
+ const templates = strings(input, "templates");
325
+ const rendered = [];
326
+ for (const entityId of entities) for (const template of templates) {
327
+ const templateKey = z.enum([
328
+ "model",
329
+ "model_test",
330
+ "view_list",
331
+ "view_form",
332
+ "view_search_input"
333
+ ]).parse(template);
334
+ const files = await renderTemplate(templateKey, { entityId });
335
+ rendered.push({
336
+ entityId,
337
+ template: templateKey,
338
+ files
339
+ });
340
+ }
341
+ return rendered;
342
+ }
343
+ async function scaffoldOperation(method, input) {
344
+ const directTemplate = z.enum([
345
+ "model",
346
+ "model_test",
347
+ "view_list",
348
+ "view_form"
349
+ ]).safeParse(method);
350
+ if (directTemplate.success) {
351
+ await ensureSonamu();
352
+ const { Sonamu } = await import("../api/sonamu.js");
353
+ const entityId = requiredText(input, "entityId");
354
+ return directTemplate.data === "view_list" ? Sonamu.syncer.generateTemplate("view_list", {
355
+ entityId,
356
+ extra: input.extra
357
+ }) : Sonamu.syncer.generateTemplate(directTemplate.data, { entityId });
358
+ }
359
+ const rendered = await renderScaffolds(input);
360
+ const { access } = await import("node:fs/promises");
361
+ const path = await import("node:path");
362
+ const { Sonamu } = await import("../api/sonamu.js");
363
+ const items = await Promise.all(rendered.flatMap(({ entityId, template, files }) => files.map(async (file) => {
364
+ const target = path.default.join(Sonamu.appRootPath, file.path.replace("/:target/", "/web/"));
365
+ let exists = true;
366
+ try {
367
+ await access(target);
368
+ } catch {
369
+ exists = false;
370
+ }
371
+ return {
372
+ entityId,
373
+ template,
374
+ target,
375
+ exists,
376
+ content: file.code
377
+ };
378
+ })));
379
+ if (method === "status") return items.map(({ content: _content, ...item }) => item);
380
+ if (method === "preview" || method === "batch" && explicitlyDryRun(input)) return items;
381
+ const results = [];
382
+ for (const item of items) {
383
+ const { content: _content, ...summary } = item;
384
+ if (item.exists && input.overwrite !== true) {
385
+ results.push({
386
+ ...summary,
387
+ status: "skipped"
388
+ });
389
+ continue;
390
+ }
391
+ await Sonamu.syncer.generateTemplate(item.template, { entityId: item.entityId }, { overwrite: input.overwrite === true });
392
+ results.push({
393
+ ...summary,
394
+ status: "written"
395
+ });
396
+ }
397
+ return { items: results };
398
+ }
399
+ async function migrationOperation(method, input) {
400
+ let shadowTarget;
401
+ if (method === "shadow") {
402
+ const requestedTarget = requiredText(input, "target");
403
+ assertMigrationTarget(requestedTarget);
404
+ assertShadowMigrationTarget(requestedTarget);
405
+ shadowTarget = requestedTarget;
406
+ }
407
+ await ensureSonamu();
408
+ const { Migrator } = await import("../migration/migrator.js");
409
+ const migrator = new Migrator();
410
+ if (method === "status") return migrator.getStatus();
411
+ if (method === "generate") {
412
+ if (!(await migrator.getStatus()).conns.some((connection) => connection.status === 0)) throw Object.assign(/* @__PURE__ */ new Error("Pending migrations must be applied before generation."), { code: "MIGRATION_NOT_READY" });
413
+ return { count: await migrator.generatePreparedCodes() };
414
+ }
415
+ if (method === "run") {
416
+ if (!mutationRequested(input)) return { dryRun: true };
417
+ const { getSonamuEnvironment } = await import("../env.js");
418
+ const environment = getSonamuEnvironment();
419
+ return migrator.apply(environment === "test" ? ["test", "fixture"] : [environment]);
420
+ }
421
+ if (method === "connections") return migrator.getConnections();
422
+ if (method === "apply") {
423
+ const rawTargets = strings(input, "targets");
424
+ if (rawTargets.length === 0) throw Object.assign(/* @__PURE__ */ new Error("Missing targets."), {
425
+ code: "MISSING_ARGUMENT",
426
+ exitCode: 2
427
+ });
428
+ const targets = rawTargets.map((target) => {
429
+ assertMigrationTarget(target);
430
+ return target;
431
+ });
432
+ if (mutationRequested(input)) return migrator.apply(targets);
433
+ return Promise.all(targets.map(async (target) => {
434
+ return migrationPlan(target, (await migrator.getConnectionStatus(target)).pending);
435
+ }));
436
+ }
437
+ if (method === "shadow") {
438
+ if (shadowTarget === void 0) throw new Error("Shadow target validation was skipped.");
439
+ if (mutationRequested(input)) {
440
+ const result = await migrator.runShadowTest({ target: shadowTarget });
441
+ return Array.isArray(result) ? {
442
+ ok: true,
443
+ target: shadowTarget,
444
+ migrations: result.flatMap(({ applied }) => applied)
445
+ } : result;
446
+ }
447
+ const status = await migrator.getConnectionStatus(shadowTarget);
448
+ return migrationPlan(shadowTarget, status.pending);
449
+ }
450
+ const target = requiredText(input, "target");
451
+ assertMigrationTarget(target);
452
+ if (method === "code") return migrator.getPreparedCodes(target);
453
+ const action = method === "rollback" || text(input, "action") === "rollback" ? "rollback" : "apply";
454
+ const plan = await migrationPlan(target, action === "apply" ? (await migrator.getConnectionStatus(target)).pending : (await migrator.getLatestAppliedBatch(target)).files, action);
455
+ if (method !== "rollback" || !mutationRequested(input)) return plan;
456
+ return migrator.rollback([target]);
457
+ }
458
+ async function fixtureOperation(method, input) {
459
+ await ensureSonamu();
460
+ const [fixtureCommands, { FixtureManager }, fixtureService, { Sonamu }] = await Promise.all([
461
+ import("../bin/fixture.js"),
462
+ import("../testing/fixture-manager.js"),
463
+ import("./fixture-service.js"),
464
+ import("../api/sonamu.js")
465
+ ]);
466
+ if (method === "init") return mutationRequested(input) ? fixtureCommands.fixtureInitCommand() : { dryRun: true };
467
+ if (method === "import") {
468
+ if (!mutationRequested(input)) return { dryRun: true };
469
+ FixtureManager.init();
470
+ await FixtureManager.importFixture(requiredText(input, "entityId"), z.array(z.number()).parse(input.recordIds));
471
+ await FixtureManager.sync();
472
+ return { imported: true };
473
+ }
474
+ if (method === "sync") {
475
+ if (!mutationRequested(input)) return { dryRun: true };
476
+ FixtureManager.init();
477
+ await FixtureManager.sync();
478
+ return { synced: true };
479
+ }
480
+ const legacyCommand = z.enum([
481
+ "gen",
482
+ "fetch",
483
+ "explore"
484
+ ]).parse(method);
485
+ if (![
486
+ "entityId",
487
+ "source",
488
+ "target",
489
+ "field",
490
+ "values",
491
+ "relations",
492
+ "depth"
493
+ ].some((key) => input[key] !== void 0)) {
494
+ const options = fixtureService.normalizeLegacyFixtureCommandOptions(legacyCommand, input);
495
+ const strategy = z.enum([
496
+ "sample",
497
+ "ids",
498
+ "query",
499
+ "file",
500
+ "recent",
501
+ "random"
502
+ ]).optional().parse(options.strategy);
503
+ const fixtureOptions = {
504
+ ...options,
505
+ strategy
506
+ };
507
+ if (legacyCommand !== "explore" && !mutationRequested(input)) return {
508
+ dryRun: true,
509
+ request: fixtureOptions
510
+ };
511
+ if (legacyCommand === "gen") return fixtureCommands.fixtureGenCommand(fixtureOptions);
512
+ if (legacyCommand === "explore") return fixtureCommands.fixtureExploreCommand(fixtureOptions);
513
+ return fixtureCommands.fixtureFetchCommand(fixtureOptions);
514
+ }
515
+ const entityId = requiredText(input, "entityId");
516
+ const source = requiredText(input, "source");
517
+ const target = requiredText(input, "target");
518
+ const field = requiredText(input, "field");
519
+ const values = strings(input, "values");
520
+ const relations = requiredText(input, "relations");
521
+ const depth = z.number().int().nonnegative().safeParse(input.depth);
522
+ if (!Object.hasOwn(Sonamu.dbConfig, source) || !Object.hasOwn(Sonamu.dbConfig, target) || values.length === 0 || ![
523
+ "include",
524
+ "exclude",
525
+ "none"
526
+ ].includes(relations) || !depth.success) throw Object.assign(/* @__PURE__ */ new Error("Invalid fixture transfer selector."), {
527
+ code: "INVALID_FIXTURE_TRANSFER",
528
+ exitCode: 2
529
+ });
530
+ const sourceKey = source;
531
+ const targetKey = target;
532
+ const records = (await Promise.all(values.map((value) => FixtureManager.getFixtures(sourceKey, targetKey, {
533
+ entityId,
534
+ field,
535
+ value,
536
+ searchType: "equals"
537
+ }, {
538
+ includeRelations: relations === "include",
539
+ maxDepth: depth.data
540
+ })))).flat();
541
+ if (explicitlyDryRun(input)) return {
542
+ dryRun: true,
543
+ records
544
+ };
545
+ if (records.length > 0) await FixtureManager.insertFixtures(targetKey, records);
546
+ return { records };
547
+ }
548
+ async function buildOperation(method) {
549
+ const { buildApiCommand, buildWebCommand } = await import("../bin/build-config.js");
550
+ if (method === "api") return buildApiCommand();
551
+ if (method === "web") return buildWebCommand();
552
+ await buildApiCommand();
553
+ return buildWebCommand({ skipIfMissing: true });
554
+ }
555
+ async function testOperation(method, input) {
556
+ const { createDefaultTestRunClient } = await import("./test-run-client.js");
557
+ const client = createDefaultTestRunClient();
558
+ if (method === "status") return client.status();
559
+ const request = {
560
+ files: z.array(z.string()).catch([]).parse(input.files),
561
+ pattern: z.string().optional().parse(input.pattern),
562
+ traces: input.traces === true
563
+ };
564
+ return {
565
+ request,
566
+ result: await client.run(request)
567
+ };
568
+ }
569
+ const betterAuthPluginSchema = z.enum([
570
+ "2fa",
571
+ "admin",
572
+ "anonymous",
573
+ "api-key",
574
+ "audit-log",
575
+ "jwt",
576
+ "organization",
577
+ "passkey",
578
+ "phone-number",
579
+ "sso",
580
+ "username"
581
+ ]);
582
+ async function authOperation(method, input) {
583
+ const { addCompanionsToEntities, generateBetterAuthEntities } = await import("../auth/index.js");
584
+ if (method === "addCompanions") return addCompanionsToEntities();
585
+ return generateBetterAuthEntities({ plugins: z.array(betterAuthPluginSchema).parse((optionalText(input, "plugins") ?? "").split(",").map((plugin) => plugin.trim()).filter(Boolean)) });
586
+ }
587
+ async function i18nOperation(method, input) {
588
+ await ensureSonamu();
589
+ const { sonamuDictionary } = await import("../dict/sonamu-dictionary.js");
590
+ if (method === "list") {
591
+ const dictionary = await sonamuDictionary.getDictionary();
592
+ const locale = text(input, "locale");
593
+ return locale === void 0 ? dictionary : {
594
+ ...dictionary,
595
+ locales: [locale],
596
+ rows: dictionary.rows.map((row) => ({
597
+ key: row.key,
598
+ source: row.source,
599
+ [locale]: row[locale]
600
+ }))
601
+ };
602
+ }
603
+ if (method === "check") {
604
+ const dictionary = await sonamuDictionary.getDictionary();
605
+ return sonamuDictionary.checkUsage(dictionary.rows.map((row) => row.key));
606
+ }
607
+ if (method === "export" || method === "import") {
608
+ const file = requiredText(input, "file");
609
+ if (explicitlyDryRun(input)) return {
610
+ operation: method,
611
+ dryRun: true
612
+ };
613
+ const { readFile, writeFile } = await import("node:fs/promises");
614
+ const format = text(input, "format") === "json" ? "json" : "workbook";
615
+ if (method === "export" && format === "workbook") {
616
+ const { buffer } = await sonamuDictionary.exportToExcel();
617
+ await writeFile(file, buffer);
618
+ return { exported: 1 };
619
+ }
620
+ if (method === "import" && format === "workbook") return sonamuDictionary.importFromExcel(await readFile(file));
621
+ if (method === "export") {
622
+ const dictionary = await sonamuDictionary.getDictionary();
623
+ const locale = text(input, "locale");
624
+ const rows = dictionary.rows.map(({ key, source: _source, isFunction: _isFunction, ...values }) => ({
625
+ key,
626
+ values: locale === void 0 ? values : { [locale]: z.string().catch("").parse(values[locale]) }
627
+ }));
628
+ await writeFile(file, JSON.stringify(rows, null, 2));
629
+ return { exported: rows.length };
630
+ }
631
+ const entries = parseJson((await readFile(file)).toString("utf8"), "I18N_INVALID_JSON", i18nEntriesSchema);
632
+ const current = await sonamuDictionary.getDictionary();
633
+ const existingKeys = new Set(current.rows.map(({ key }) => key));
634
+ for (const entry of entries) if (existingKeys.has(entry.key)) await sonamuDictionary.updateEntry({
635
+ oldKey: entry.key,
636
+ newKey: entry.key,
637
+ source: "project",
638
+ values: entry.values
639
+ });
640
+ else await sonamuDictionary.createEntry(entry);
641
+ return { imported: entries.length };
642
+ }
643
+ const key = requiredText(input, "key");
644
+ if (method === "create") {
645
+ if (explicitlyDryRun(input)) return {
646
+ operation: "create",
647
+ input,
648
+ dryRun: true
649
+ };
650
+ return sonamuDictionary.createEntry({
651
+ key,
652
+ values: dictionaryValuesSchema.parse(input.values)
653
+ });
654
+ }
655
+ if (method === "update") {
656
+ if (explicitlyDryRun(input)) return {
657
+ operation: "update",
658
+ input,
659
+ dryRun: true
660
+ };
661
+ const explicitSource = text(input, "source");
662
+ const resolvedSource = explicitSource === void 0 ? (await sonamuDictionary.getDictionary()).rows.find((row) => row.key === key)?.source ?? "project" : explicitSource;
663
+ return sonamuDictionary.updateEntry({
664
+ oldKey: key,
665
+ newKey: text(input, "newKey") ?? key,
666
+ source: dictionarySourceSchema.parse(resolvedSource),
667
+ values: dictionaryValuesSchema.parse(input.values)
668
+ });
669
+ }
670
+ if (!mutationRequested(input)) return {
671
+ key,
672
+ operation: "remove",
673
+ dryRun: true
674
+ };
675
+ return sonamuDictionary.deleteEntry(key);
676
+ }
677
+ async function taskOperation(method, input) {
678
+ await ensureSonamu();
679
+ const { Sonamu } = await import("../api/sonamu.js");
680
+ const workflows = Sonamu.workflows;
681
+ const backend = workflows.backend;
682
+ if (method === "definitions") return { definitions: workflows.workflowDefinitions };
683
+ if (method === "runs") return backend.listWorkflowRuns({ limit: 50 });
684
+ const workflowRunId = requiredText(input, "runId");
685
+ if (method === "show") return backend.getWorkflowRun({ workflowRunId });
686
+ if (method === "watch") {
687
+ const { isDeepStrictEqual } = await import("node:util");
688
+ return (async function* watch() {
689
+ let previous;
690
+ while (true) {
691
+ const snapshot = await backend.getWorkflowRun({ workflowRunId });
692
+ if (snapshot === null) throw Object.assign(/* @__PURE__ */ new Error(`Workflow run not found: ${workflowRunId}`), { code: "TASK_RUN_NOT_FOUND" });
693
+ const rawState = snapshot.status === "succeeded" ? "completed" : snapshot.status;
694
+ const state = rawState === "canceled" ? "cancelled" : rawState;
695
+ const current = {
696
+ ...snapshot,
697
+ state
698
+ };
699
+ if (!isDeepStrictEqual(current, previous)) {
700
+ previous = structuredClone(current);
701
+ yield current;
702
+ }
703
+ if ([
704
+ "completed",
705
+ "failed",
706
+ "cancelled"
707
+ ].includes(state)) return;
708
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
709
+ }
710
+ })();
711
+ }
712
+ if (method === "steps") return backend.listStepAttempts({
713
+ workflowRunId,
714
+ limit: 100
715
+ });
716
+ if (!mutationRequested(input)) return {
717
+ operation: method,
718
+ workflowRunId,
719
+ dryRun: true
720
+ };
721
+ if (method === "pause") return backend.pauseWorkflowRun({ workflowRunId });
722
+ if (method === "resume") return backend.resumeWorkflowRun({ workflowRunId });
723
+ return backend.cancelWorkflowRun({ workflowRunId });
724
+ }
725
+ async function cddRootPath() {
726
+ const [{ Sonamu }, path] = await Promise.all([import("../api/sonamu.js"), import("node:path")]);
727
+ return path.join(Sonamu.appRootPath, "contract");
728
+ }
729
+ const practiceSequencePattern = /^p([0-9]+)-/;
730
+ const practiceNamePattern = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
731
+ function invalidPracticeName(name) {
732
+ return Object.assign(/* @__PURE__ */ new Error(`Invalid practice name: ${name}. Use letters, digits, ".", "-", and "_" only, starting with a letter or digit.`), {
733
+ code: "INVALID_PRACTICE_NAME",
734
+ exitCode: 2
735
+ });
736
+ }
737
+ function invalidPracticeDirectory(directory) {
738
+ return Object.assign(/* @__PURE__ */ new Error(`Practice directory escapes the API root: ${directory}`), {
739
+ code: "INVALID_PRACTICE_PATH",
740
+ exitCode: 2
741
+ });
742
+ }
743
+ /**
744
+ * `src/practices` 아래에 다음 시퀀스 번호를 가진 practice 스텁 파일을 만듭니다.
745
+ *
746
+ * 구 CLI(`stub practice`)의 파일명 규칙과 스텁 본문을 그대로 유지합니다.
747
+ */
748
+ async function stubPracticeOperation(input) {
749
+ const name = requiredText(input, "name");
750
+ if (!practiceNamePattern.test(name)) throw invalidPracticeName(name);
751
+ await ensureSonamu();
752
+ const [{ Sonamu }, { constants }, { mkdir, open, readdir, realpath }, path] = await Promise.all([
753
+ import("../api/sonamu.js"),
754
+ import("node:fs"),
755
+ import("node:fs/promises"),
756
+ import("node:path")
757
+ ]);
758
+ const practiceDirectory = path.default.join(Sonamu.apiRootPath, "src", "practices");
759
+ await mkdir(practiceDirectory, { recursive: true });
760
+ const [canonicalApiRoot, canonicalDirectory] = await Promise.all([realpath(Sonamu.apiRootPath), realpath(practiceDirectory)]);
761
+ const directoryRelative = path.default.relative(canonicalApiRoot, canonicalDirectory);
762
+ if (directoryRelative.startsWith("..") || path.default.isAbsolute(directoryRelative)) throw invalidPracticeDirectory(practiceDirectory);
763
+ const fileName = `p${(await readdir(practiceDirectory)).filter((fileName) => fileName.startsWith("p") && fileName.endsWith(".ts")).reduce((largest, fileName) => {
764
+ const matched = practiceSequencePattern.exec(fileName);
765
+ return matched === null ? largest : Math.max(largest, Number.parseInt(matched[1], 10));
766
+ }, 0) + 1}-${name}.ts`;
767
+ const filePath = path.default.resolve(practiceDirectory, fileName);
768
+ const stubCode = [
769
+ `import { Sonamu } from "sonamu";`,
770
+ "",
771
+ `console.clear();`,
772
+ `console.log("${fileName}");`,
773
+ "",
774
+ `Sonamu.runScript(async () => {`,
775
+ ` // TODO`,
776
+ `});`,
777
+ ""
778
+ ].join("\n");
779
+ let handle;
780
+ try {
781
+ handle = await open(filePath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 438);
782
+ await handle.writeFile(stubCode, "utf8");
783
+ } catch (error) {
784
+ const errorCode = error.code;
785
+ if (errorCode === "EEXIST" || errorCode === "ELOOP") throw Object.assign(/* @__PURE__ */ new Error(`Practice file already exists: ${filePath}`), {
786
+ code: "PRACTICE_FILE_EXISTS",
787
+ exitCode: 2,
788
+ cause: error
789
+ });
790
+ throw error;
791
+ } finally {
792
+ await handle?.close();
793
+ }
794
+ return {
795
+ fileName,
796
+ path: filePath
797
+ };
798
+ }
799
+ async function readCddTree(directory, root) {
800
+ const [{ readdir }, path] = await Promise.all([import("node:fs/promises"), import("node:path")]);
801
+ const entries = await readdir(directory, { withFileTypes: true });
802
+ const nodes = [];
803
+ for (const entry of entries) {
804
+ if (entry.name === "rules") continue;
805
+ const absolutePath = path.join(directory, entry.name);
806
+ const relativePath = path.relative(root, absolutePath);
807
+ if (entry.isDirectory()) {
808
+ const children = await readCddTree(absolutePath, root);
809
+ if (children.length > 0) nodes.push({
810
+ name: entry.name,
811
+ path: relativePath,
812
+ type: "directory",
813
+ children
814
+ });
815
+ } else if (entry.isFile() && entry.name.endsWith(".contract.md")) nodes.push({
816
+ name: entry.name,
817
+ path: relativePath,
818
+ type: "file",
819
+ fileType: "contract"
820
+ });
821
+ }
822
+ return nodes;
823
+ }
824
+ async function cddOperation(method, input) {
825
+ await ensureSonamu();
826
+ const [{ access }, { createDefaultCddToolingAdapter }] = await Promise.all([import("node:fs/promises"), import("./cdd-service.js")]);
827
+ const adapter = createDefaultCddToolingAdapter({ contractRoot: await cddRootPath() });
828
+ if (method === "tree") {
829
+ const root = await cddRootPath();
830
+ try {
831
+ await access(root);
832
+ } catch {
833
+ return {
834
+ exists: false,
835
+ tree: []
836
+ };
837
+ }
838
+ return {
839
+ exists: true,
840
+ tree: await readCddTree(root, root)
841
+ };
842
+ }
843
+ if (method === "read") {
844
+ const relativePath = requiredText(input, "path");
845
+ return adapter.read({ path: relativePath });
846
+ }
847
+ if (method === "rules") return adapter.rules();
848
+ if (method === "showRule") {
849
+ const ruleId = requiredText(input, "ruleId");
850
+ return adapter.showRule({ ruleId });
851
+ }
852
+ if (method === "addRule") {
853
+ const ruleKey = requiredText(input, "ruleKey");
854
+ const id = requiredText(input, "id");
855
+ const when = requiredText(input, "when");
856
+ const ruleText = text(input, "instruction") ?? requiredText(input, "text");
857
+ return adapter.addRule({
858
+ ruleKey,
859
+ id,
860
+ when,
861
+ text: ruleText,
862
+ examples: strings(input, "examples"),
863
+ dryRun: explicitlyDryRun(input)
864
+ });
865
+ }
866
+ if (explicitlyDryRun(input)) return {
867
+ operation: "addAcceptanceCriterion",
868
+ input,
869
+ dryRun: true
870
+ };
871
+ const document = requiredText(input, "document");
872
+ const criterion = requiredText(input, "text");
873
+ return adapter.addAcceptanceCriterion({
874
+ document,
875
+ text: criterion,
876
+ dryRun: false
877
+ });
878
+ }
879
+ async function invokeDefault(group, method, input) {
880
+ if (group === "core") return syncOperation(input);
881
+ if (group === "entity") return entityOperation(method, input);
882
+ if (group === "scaffold") return scaffoldOperation(method, input);
883
+ if (group === "migration") return migrationOperation(method, input);
884
+ if (group === "fixture") return fixtureOperation(method, input);
885
+ if (group === "build") return buildOperation(method);
886
+ if (group === "test") return testOperation(method, input);
887
+ if (group === "auth") return authOperation(method, input);
888
+ if (group === "i18n") return i18nOperation(method, input);
889
+ if (group === "task") return taskOperation(method, input);
890
+ if (group === "stub") return stubPracticeOperation(input);
891
+ return cddOperation(method, input);
892
+ }
893
+ const tooling = Object.fromEntries(Object.entries(REQUIRED_METHODS).map(([group, methods]) => [group, Object.fromEntries(methods.map((method) => [method, (input) => invokeDefault(group, method, input)]))]));
894
+ Object.defineProperty(tooling.migration, "apply", {
895
+ enumerable: false,
896
+ value: (input) => invokeDefault("migration", "apply", input)
897
+ });
898
+ //#endregion
899
+ export { tooling };
900
+
901
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLXRvb2xpbmcuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rvb2xpbmcvY2xpLXRvb2xpbmcudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcblxuaW1wb3J0IHsgdHlwZSBGaXh0dXJlQ29tbWFuZE9wdGlvbnMgfSBmcm9tIFwiLi4vYmluL2ZpeHR1cmVcIjtcblxuY29uc3QganNvblZhbHVlU2NoZW1hID0gei5qc29uKCk7XG50eXBlIENvbW1hbmRWYWx1ZSA9IHouaW5mZXI8dHlwZW9mIGpzb25WYWx1ZVNjaGVtYT4gfCB1bmRlZmluZWQ7XG50eXBlIENvbW1hbmRJbnB1dCA9IFJlY29yZDxzdHJpbmcsIENvbW1hbmRWYWx1ZT47XG50eXBlIFRvb2xpbmdSZXN1bHQgPSBvYmplY3QgfCBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbCB8IHZvaWQgfCBBc3luY0l0ZXJhYmxlPG9iamVjdD47XG50eXBlIFRvb2xpbmdPcGVyYXRpb24gPSAoaW5wdXQ6IENvbW1hbmRJbnB1dCkgPT4gVG9vbGluZ1Jlc3VsdCB8IFByb21pc2U8VG9vbGluZ1Jlc3VsdD47XG50eXBlIFRvb2xpbmdHcm91cCA9IFJlY29yZDxzdHJpbmcsIFRvb2xpbmdPcGVyYXRpb24+O1xuZXhwb3J0IHR5cGUgQ2xpVG9vbGluZ09wZXJhdGlvbnMgPSBSZWNvcmQ8c3RyaW5nLCBUb29saW5nR3JvdXA+O1xuXG50eXBlIE1pZ3JhdGlvblRhcmdldCA9IFwiZGV2ZWxvcG1lbnRcIiB8IFwic3RhZ2luZ1wiIHwgXCJwcm9kdWN0aW9uXCIgfCBcImZpeHR1cmVcIiB8IFwidGVzdFwiO1xuXG5jb25zdCBNSUdSQVRJT05fVEFSR0VUUyA9IG5ldyBTZXQ8c3RyaW5nPihbXG4gIFwiZGV2ZWxvcG1lbnRcIixcbiAgXCJzdGFnaW5nXCIsXG4gIFwicHJvZHVjdGlvblwiLFxuICBcImZpeHR1cmVcIixcbiAgXCJ0ZXN0XCIsXG5dKTtcblxuZnVuY3Rpb24gYXNzZXJ0TWlncmF0aW9uVGFyZ2V0KHRhcmdldDogc3RyaW5nKTogYXNzZXJ0cyB0YXJnZXQgaXMgTWlncmF0aW9uVGFyZ2V0IHtcbiAgLy8gREIg7IOB7YOc66W8IOyhsO2ajO2VmOqxsOuCmCDrs4Dqsr3tlZjquLAg7KCE7JeQIOuqqOuToCDsmbjrtoAg64yA7IOB7J2EIOqygOymne2VqeuLiOuLpC5cbiAgaWYgKE1JR1JBVElPTl9UQVJHRVRTLmhhcyh0YXJnZXQpKSByZXR1cm47XG4gIHRocm93IE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGBVbnN1cHBvcnRlZCBtaWdyYXRpb24gdGFyZ2V0OiAke3RhcmdldH1gKSwge1xuICAgIGNvZGU6IFwiSU5WQUxJRF9NSUdSQVRJT05fVEFSR0VUXCIsXG4gICAgZXhpdENvZGU6IDIsXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBhc3NlcnRTaGFkb3dNaWdyYXRpb25UYXJnZXQoXG4gIHRhcmdldDogTWlncmF0aW9uVGFyZ2V0LFxuKTogYXNzZXJ0cyB0YXJnZXQgaXMgRXh0cmFjdDxNaWdyYXRpb25UYXJnZXQsIFwiZml4dHVyZVwiIHwgXCJ0ZXN0XCI+IHtcbiAgaWYgKHRhcmdldCA9PT0gXCJmaXh0dXJlXCIgfHwgdGFyZ2V0ID09PSBcInRlc3RcIikgcmV0dXJuO1xuXG4gIC8vIFNoYWRvdyBEQuuKlCDsmrTsmIEg6rOE7Je0IOyXsOqysOyXkCDsoJHqt7ztlZjquLAg7KCE7JeQIO2XiOyaqSDrjIDsg4HsnYQg7KCc7ZWc7ZWp64uI64ukLlxuICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihgSW52YWxpZCBzaGFkb3cgbWlncmF0aW9uIHRhcmdldDogJHt0YXJnZXR9YCksIHtcbiAgICBjb2RlOiBcIklOVkFMSURfU0hBRE9XX01JR1JBVElPTl9UQVJHRVRcIixcbiAgICB0YXJnZXQsXG4gICAgZXhpdENvZGU6IDIsXG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtaWdyYXRpb25QbGFuKFxuICB0YXJnZXQ6IE1pZ3JhdGlvblRhcmdldCxcbiAgbWlncmF0aW9uczogc3RyaW5nW10sXG4gIGFjdGlvbjogXCJhcHBseVwiIHwgXCJyb2xsYmFja1wiID0gXCJhcHBseVwiLFxuKSB7XG4gIGNvbnN0IGRpZ2VzdCA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuZGlnZXN0KFxuICAgIFwiU0hBLTI1NlwiLFxuICAgIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShKU09OLnN0cmluZ2lmeSh7IGFjdGlvbiwgdGFyZ2V0LCBtaWdyYXRpb25zIH0pKSxcbiAgKTtcbiAgcmV0dXJuIHtcbiAgICBraW5kOiBcIm1pZ3JhdGlvbi1wbGFuXCIgYXMgY29uc3QsXG4gICAgYWN0aW9uLFxuICAgIHRhcmdldCxcbiAgICBtaWdyYXRpb25zLFxuICAgIGZpbmdlcnByaW50OiBBcnJheS5mcm9tKG5ldyBVaW50OEFycmF5KGRpZ2VzdCksIChieXRlKSA9PlxuICAgICAgYnl0ZS50b1N0cmluZygxNikucGFkU3RhcnQoMiwgXCIwXCIpLFxuICAgICkuam9pbihcIlwiKSxcbiAgfTtcbn1cblxuY29uc3QgUkVRVUlSRURfTUVUSE9EUyA9IHtcbiAgY29yZTogW1wic3luY1wiXSxcbiAgZW50aXR5OiBbXCJsaXN0XCIsIFwic2hvd1wiLCBcInNlYXJjaFwiLCBcImFwcGx5UGF0Y2hcIiwgXCJjcmVhdGVcIiwgXCJjb25lc1wiXSxcbiAgc2NhZmZvbGQ6IFtcIm1vZGVsXCIsIFwibW9kZWxfdGVzdFwiLCBcInZpZXdfbGlzdFwiLCBcInZpZXdfZm9ybVwiLCBcInN0YXR1c1wiLCBcInByZXZpZXdcIiwgXCJiYXRjaFwiXSxcbiAgbWlncmF0aW9uOiBbXCJydW5cIiwgXCJnZW5lcmF0ZVwiLCBcInN0YXR1c1wiLCBcImNvbm5lY3Rpb25zXCIsIFwiY29kZVwiLCBcInByZXZpZXdcIiwgXCJzaGFkb3dcIiwgXCJyb2xsYmFja1wiXSxcbiAgZml4dHVyZTogW1wiaW5pdFwiLCBcImltcG9ydFwiLCBcInN5bmNcIiwgXCJnZW5cIiwgXCJmZXRjaFwiLCBcImV4cGxvcmVcIl0sXG4gIGJ1aWxkOiBbXCJhbGxcIiwgXCJhcGlcIiwgXCJ3ZWJcIl0sXG4gIHRlc3Q6IFtcInJ1blwiLCBcInN0YXR1c1wiXSxcbiAgYXV0aDogW1wiZ2VuZXJhdGVcIiwgXCJhZGRDb21wYW5pb25zXCJdLFxuICBpMThuOiBbXCJsaXN0XCIsIFwiY2hlY2tcIiwgXCJpbXBvcnRcIiwgXCJleHBvcnRcIiwgXCJjcmVhdGVcIiwgXCJ1cGRhdGVcIiwgXCJyZW1vdmVcIl0sXG4gIHRhc2s6IFtcImRlZmluaXRpb25zXCIsIFwicnVuc1wiLCBcInNob3dcIiwgXCJzdGVwc1wiLCBcIndhdGNoXCIsIFwicGF1c2VcIiwgXCJyZXN1bWVcIiwgXCJjYW5jZWxcIl0sXG4gIGNkZDogW1widHJlZVwiLCBcInJlYWRcIiwgXCJydWxlc1wiLCBcInNob3dSdWxlXCIsIFwiYWRkUnVsZVwiLCBcImFkZEFjY2VwdGFuY2VDcml0ZXJpb25cIl0sXG4gIHN0dWI6IFtcInByYWN0aWNlXCJdLFxufSBhcyBjb25zdDtcblxubGV0IGluaXRpYWxpemF0aW9uOiBQcm9taXNlPHZvaWQ+IHwgdW5kZWZpbmVkO1xuXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVTb25hbXUoKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgU29uYW11IH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9hcGkvc29uYW11XCIpO1xuICBpZiAoU29uYW11LmlzSW5pdGlhbGl6ZWQpIHJldHVybjtcbiAgaW5pdGlhbGl6YXRpb24gPz89IFNvbmFtdS5pbml0KHRydWUsIGZhbHNlKTtcbiAgYXdhaXQgaW5pdGlhbGl6YXRpb247XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN5bmNPcGVyYXRpb24oaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBhd2FpdCBlbnN1cmVTb25hbXUoKTtcbiAgY29uc3QgeyBTb25hbXUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2FwaS9zb25hbXVcIik7XG4gIHJldHVybiBpbnB1dC5mb3JjZSA9PT0gdHJ1ZSA/IFNvbmFtdS5zeW5jZXIuZm9yY2VTeW5jKCkgOiBTb25hbXUuc3luY2VyLnN5bmMoKTtcbn1cblxuZnVuY3Rpb24gdGV4dChpbnB1dDogQ29tbWFuZElucHV0LCBrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHZhbHVlID0gei5zdHJpbmcoKS5zYWZlUGFyc2UoaW5wdXRba2V5XSk7XG4gIHJldHVybiB2YWx1ZS5zdWNjZXNzID8gdmFsdWUuZGF0YSA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gc3RyaW5ncyhpbnB1dDogQ29tbWFuZElucHV0LCBrZXk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgdmFsdWUgPSB6LmFycmF5KHouc3RyaW5nKCkpLnNhZmVQYXJzZShpbnB1dFtrZXldKTtcbiAgcmV0dXJuIHZhbHVlLnN1Y2Nlc3MgPyB2YWx1ZS5kYXRhIDogW107XG59XG5cbmZ1bmN0aW9uIHJlcXVpcmVkVGV4dChpbnB1dDogQ29tbWFuZElucHV0LCBrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHZhbHVlID0gdGV4dChpbnB1dCwga2V5KTtcbiAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUubGVuZ3RoID4gMCkgcmV0dXJuIHZhbHVlO1xuICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihgTWlzc2luZyAke2tleX0uYCksIHsgY29kZTogXCJNSVNTSU5HX0FSR1VNRU5UXCIsIGV4aXRDb2RlOiAyIH0pO1xufVxuXG4vKipcbiAqIOyDneuete2VnCDqsJLsnYAgYHVuZGVmaW5lZGDroZwg7Ya16rO87Iuc7YKk65CYLCDqsJLsnbQg7J6I64qU642wIOusuOyekOyXtOydtCDslYTri4jrqbQg7J247J6QIOyYpOulmOuhnCDqsbDsoIjtlanri4jri6QuXG4gKlxuICogYHRleHQoKWDsspjrn7wg7KGw7Jqp7Z6IIOustOyLnO2VmOuptCDsnpjrqrvrkJwg7YOA7J6F7J2YIOyeheugpeydtCDquLDrs7jqsJLsnLzroZwg65GU6rCR7ZWp64uI64ukLlxuICovXG5mdW5jdGlvbiBvcHRpb25hbFRleHQoaW5wdXQ6IENvbW1hbmRJbnB1dCwga2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCB2YWx1ZSA9IGlucHV0W2tleV07XG4gIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBwYXJzZWQgPSB6LnN0cmluZygpLnNhZmVQYXJzZSh2YWx1ZSk7XG4gIGlmIChwYXJzZWQuc3VjY2VzcykgcmV0dXJuIHBhcnNlZC5kYXRhO1xuICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihgSW52YWxpZCAke2tleX0uYCksIHsgY29kZTogXCJJTlZBTElEX0FSR1VNRU5UXCIsIGV4aXRDb2RlOiAyIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZUpzb248U2NoZW1hIGV4dGVuZHMgei5ab2RUeXBlPihcbiAgY29udGVudHM6IHN0cmluZyxcbiAgY29kZTogc3RyaW5nLFxuICBzY2hlbWE6IFNjaGVtYSxcbik6IHouaW5mZXI8U2NoZW1hPiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHNjaGVtYS5wYXJzZShKU09OLnBhcnNlKGNvbnRlbnRzKSk7XG4gIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgdGhyb3cgT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoXCJJbnZhbGlkIEpTT04gaW5wdXQuXCIpLCB7IGNvZGUsIGV4aXRDb2RlOiAyLCBjYXVzZSB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtdXRhdGlvblJlcXVlc3RlZChpbnB1dDogQ29tbWFuZElucHV0KTogYm9vbGVhbiB7XG4gIHJldHVybiBpbnB1dC5leGVjdXRlID09PSB0cnVlIHx8IGlucHV0LmRyeVJ1biA9PT0gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGV4cGxpY2l0bHlEcnlSdW4oaW5wdXQ6IENvbW1hbmRJbnB1dCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaW5wdXQuZHJ5UnVuID09PSB0cnVlIHx8IGlucHV0LmV4ZWN1dGUgPT09IGZhbHNlO1xufVxuXG5jb25zdCBlbnRpdHlQYXRjaFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgZW50aXR5SWQ6IHouc3RyaW5nKCkubWluKDEpLFxuICBvcGVyYXRpb25zOiB6LmFycmF5KFxuICAgIHoub2JqZWN0KHtcbiAgICAgIG9wOiB6LmxpdGVyYWwoXCJhZGRcIiksXG4gICAgICBwYXRoOiB6LmxpdGVyYWwoXCIvcHJvcHMvLVwiKSxcbiAgICAgIHZhbHVlOiB6XG4gICAgICAgIC5vYmplY3QoeyBuYW1lOiB6LnN0cmluZygpLm1pbigxKSwgdHlwZTogei5zdHJpbmcoKS5taW4oMSkgfSlcbiAgICAgICAgLmNhdGNoYWxsKGpzb25WYWx1ZVNjaGVtYSksXG4gICAgfSksXG4gICksXG59KTtcbmNvbnN0IGkxOG5FbnRyaWVzU2NoZW1hID0gei5hcnJheShcbiAgei5vYmplY3QoeyBrZXk6IHouc3RyaW5nKCksIHZhbHVlczogei5yZWNvcmQoei5zdHJpbmcoKSwgei5zdHJpbmcoKSkgfSksXG4pO1xuY29uc3QgZGljdGlvbmFyeVZhbHVlc1NjaGVtYSA9IHoucmVjb3JkKHouc3RyaW5nKCksIHouc3RyaW5nKCkpO1xuY29uc3QgZGljdGlvbmFyeVNvdXJjZVNjaGVtYSA9IHouZW51bShbXCJlbnRpdHlcIiwgXCJwcm9qZWN0XCIsIFwic29uYW11XCJdKTtcbmNvbnN0IGNvbmVMb2NhbGVTY2hlbWEgPSB6LmVudW0oW1wia29cIiwgXCJlblwiLCBcImphXCJdKTtcblxuLyoqXG4gKiBjb25lIOyDneyEseyXkCDsgqzsmqntlaAgbG9jYWxl7J2EIOqysOygle2VqeuLiOuLpC5cbiAqXG4gKiDrqoXsi5ztlZwgbG9jYWxl7J20IOy1nOyasOyEoOydtOqzoCwg7JeG7Jy866m0IO2UhOuhnOygne2KuCBpMThuIOq4sOuzuCBsb2NhbGUsIOq3uOuniOyggCDsl4bsnLzrqbQgXCJrb1wi66W8IOyCrOyaqe2VqeuLiOuLpC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUNvbmVMb2NhbGUoaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8ei5pbmZlcjx0eXBlb2YgY29uZUxvY2FsZVNjaGVtYT4+IHtcbiAgY29uc3QgZXhwbGljaXQgPSBjb25lTG9jYWxlU2NoZW1hLnNhZmVQYXJzZShpbnB1dC5sb2NhbGUpO1xuICBpZiAoZXhwbGljaXQuc3VjY2VzcykgcmV0dXJuIGV4cGxpY2l0LmRhdGE7XG5cbiAgY29uc3QgeyBTb25hbXUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2FwaS9zb25hbXVcIik7XG4gIGxldCBjb25maWd1cmVkTG9jYWxlOiB1bmtub3duO1xuICB0cnkge1xuICAgIGNvbmZpZ3VyZWRMb2NhbGUgPSBTb25hbXUuY29uZmlnLmkxOG4/LmRlZmF1bHRMb2NhbGU7XG4gIH0gY2F0Y2gge1xuICAgIC8vIOyEpOygleydhCDslYTsp4Eg7J297J2EIOyImCDsl4bripQg7Iuk7ZaJIOqyveuhnOyXkOyEnOuKlCDquLDrs7ggbG9jYWxl66GcIO2PtOuwse2VqeuLiOuLpC5cbiAgfVxuICBjb25zdCBjb25maWd1cmVkID0gY29uZUxvY2FsZVNjaGVtYS5zYWZlUGFyc2UoY29uZmlndXJlZExvY2FsZSk7XG4gIHJldHVybiBjb25maWd1cmVkLnN1Y2Nlc3MgPyBjb25maWd1cmVkLmRhdGEgOiBcImtvXCI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGVudGl0eU9wZXJhdGlvbihtZXRob2Q6IHN0cmluZywgaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBhd2FpdCBlbnN1cmVTb25hbXUoKTtcbiAgY29uc3QgeyBFbnRpdHlNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIik7XG4gIGNvbnN0IGVudGl0aWVzID0gRW50aXR5TWFuYWdlci5nZXRBbGxFbnRpdGllcygpO1xuXG4gIGlmIChtZXRob2QgPT09IFwibGlzdFwiKSByZXR1cm4gZW50aXRpZXMubWFwKChlbnRpdHkpID0+IGVudGl0eS50b0pzb24oKSk7XG4gIGlmIChtZXRob2QgPT09IFwic2hvd1wiKSB7XG4gICAgY29uc3QgZW50aXR5SWQgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwiZW50aXR5SWRcIik7XG4gICAgaWYgKCFFbnRpdHlNYW5hZ2VyLmV4aXN0cyhlbnRpdHlJZCkpIHtcbiAgICAgIHRocm93IE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGBFbnRpdHkgbm90IGZvdW5kOiAke2VudGl0eUlkfWApLCB7XG4gICAgICAgIGNvZGU6IFwiRU5USVRZX05PVF9GT1VORFwiLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkudG9Kc29uKCk7XG4gIH1cbiAgaWYgKG1ldGhvZCA9PT0gXCJzZWFyY2hcIikge1xuICAgIGNvbnN0IHF1ZXJ5ID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcInF1ZXJ5XCIpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgcmV0dXJuIGVudGl0aWVzXG4gICAgICAubWFwKChlbnRpdHkpID0+IGVudGl0eS50b0pzb24oKSlcbiAgICAgIC5maWx0ZXIoKGVudGl0eSkgPT4gSlNPTi5zdHJpbmdpZnkoZW50aXR5KS50b0xvY2FsZUxvd2VyQ2FzZSgpLmluY2x1ZGVzKHF1ZXJ5KSk7XG4gIH1cbiAgaWYgKG1ldGhvZCA9PT0gXCJjcmVhdGVcIikge1xuICAgIGNvbnN0IGVudGl0eUlkID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcIm5hbWVcIik7XG4gICAgY29uc3QgeyBTb25hbXUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2FwaS9zb25hbXVcIik7XG4gICAgYXdhaXQgU29uYW11LnN5bmNlci5jcmVhdGVFbnRpdHkoeyBlbnRpdHlJZCwgdGl0bGU6IGVudGl0eUlkIH0pO1xuICAgIGlmIChpbnB1dC5ub0NvbmVzID09PSB0cnVlKSByZXR1cm4geyBlbnRpdHlJZCwgY29uZXM6IFwic2tpcHBlZFwiIH07XG4gICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgIGlmIChpbnB1dC5haSA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIGVudGl0eS5nZW5lcmF0ZUNvbmVzKHtcbiAgICAgICAgcHJlc2VydmVFeGlzdGluZzogZmFsc2UsXG4gICAgICAgIG9ubHlFbXB0eTogZmFsc2UsXG4gICAgICAgIGxvY2FsZTogYXdhaXQgcmVzb2x2ZUNvbmVMb2NhbGUoaW5wdXQpLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGF3YWl0IGVudGl0eS5nZW5lcmF0ZVRlbXBsYXRlQ29uZXMoKTtcbiAgICByZXR1cm4geyBlbnRpdHlJZCwgY29uZXM6IFwidGVtcGxhdGVcIiB9O1xuICB9XG4gIGlmIChtZXRob2QgPT09IFwiY29uZXNcIikge1xuICAgIGNvbnN0IGVudGl0eUlkID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcImVudGl0eUlkXCIpO1xuICAgIGNvbnN0IHRhcmdldHMgPVxuICAgICAgaW5wdXQuYWxsID09PSB0cnVlIHx8IGVudGl0eUlkID09PSBcImFsbFwiXG4gICAgICAgID8gRW50aXR5TWFuYWdlci5nZXRBbGxFbnRpdGllcygpXG4gICAgICAgIDogRW50aXR5TWFuYWdlci5leGlzdHMoZW50aXR5SWQpXG4gICAgICAgICAgPyBbRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpXVxuICAgICAgICAgIDogW107XG4gICAgaWYgKHRhcmdldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihgRW50aXR5IG5vdCBmb3VuZDogJHtlbnRpdHlJZH1gKSwge1xuICAgICAgICBjb2RlOiBcIkVOVElUWV9OT1RfRk9VTkRcIixcbiAgICAgIH0pO1xuICAgIH1cbiAgICBjb25zdCByZWdlbmVyYXRlID0gaW5wdXQucmVnZW5lcmF0ZSA9PT0gdHJ1ZTtcbiAgICBjb25zdCBzZWxlY3RlZExvY2FsZSA9IGF3YWl0IHJlc29sdmVDb25lTG9jYWxlKGlucHV0KTtcbiAgICAvLyDtlZwg7JeU7Yuw7Yuw7J2YIOyLpO2MqOqwgCDrgpjrqLjsp4Ag7JeU7Yuw7Yuw7J2YIGNvbmUg7IOd7ISx7J2EIOy3qOyGjO2VmOyngCDslYrrj4TroZ0g7KCE67aAIOuBneq5jOyngCDsi6Ttlontlanri4jri6QuXG4gICAgY29uc3Qgc2V0dGxlZCA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIHRhcmdldHMubWFwKGFzeW5jIChlbnRpdHkpID0+ICh7XG4gICAgICAgIGVudGl0eUlkOiBlbnRpdHkuaWQsXG4gICAgICAgIC4uLihhd2FpdCBlbnRpdHkuZ2VuZXJhdGVDb25lcyh7XG4gICAgICAgICAgcHJlc2VydmVFeGlzdGluZzogIXJlZ2VuZXJhdGUsXG4gICAgICAgICAgb25seUVtcHR5OiAhcmVnZW5lcmF0ZSxcbiAgICAgICAgICBsb2NhbGU6IHNlbGVjdGVkTG9jYWxlLFxuICAgICAgICB9KSksXG4gICAgICB9KSksXG4gICAgKTtcbiAgICBjb25zdCByZXN1bHRzID0gW107XG4gICAgY29uc3QgZmFpbHVyZXMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgb3V0Y29tZV0gb2Ygc2V0dGxlZC5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChvdXRjb21lLnN0YXR1cyA9PT0gXCJmdWxmaWxsZWRcIikge1xuICAgICAgICByZXN1bHRzLnB1c2gob3V0Y29tZS52YWx1ZSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgZmFpbHVyZXMucHVzaCh7XG4gICAgICAgIGVudGl0eUlkOiB0YXJnZXRzW2luZGV4XS5pZCxcbiAgICAgICAgbWVzc2FnZTogb3V0Y29tZS5yZWFzb24gaW5zdGFuY2VvZiBFcnJvciA/IG91dGNvbWUucmVhc29uLm1lc3NhZ2UgOiBTdHJpbmcob3V0Y29tZS5yZWFzb24pLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChmYWlsdXJlcy5sZW5ndGggPT09IDApIHJldHVybiByZXN1bHRzO1xuICAgIHRocm93IE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGBDb25lIGdlbmVyYXRpb24gZmFpbGVkIGZvciAke2ZhaWx1cmVzLmxlbmd0aH0gZW50aXR5KHMpLmApLCB7XG4gICAgICBjb2RlOiBcIkNPTkVfR0VORVJBVElPTl9GQUlMRURcIixcbiAgICAgIGRldGFpbHM6IHsgcmVzdWx0cywgZmFpbHVyZXMgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IGZpbGUgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwiZmlsZVwiKTtcbiAgY29uc3QgeyByZWFkRmlsZSB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpmcy9wcm9taXNlc1wiKTtcbiAgY29uc3QgY29udGVudHMgPVxuICAgIGZpbGUgPT09IFwiLVwiXG4gICAgICA/IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgY2h1bmtzID0gW107XG4gICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBjaHVuayBvZiBwcm9jZXNzLnN0ZGluKSBjaHVua3MucHVzaChCdWZmZXIuZnJvbShjaHVuaykpO1xuICAgICAgICAgIHJldHVybiBCdWZmZXIuY29uY2F0KGNodW5rcykudG9TdHJpbmcoXCJ1dGY4XCIpO1xuICAgICAgICB9KSgpXG4gICAgICA6IGF3YWl0IHJlYWRGaWxlKGZpbGUsIFwidXRmOFwiKTtcbiAgY29uc3QgcGF0Y2ggPSBwYXJzZUpzb24oY29udGVudHMsIFwiSU5WQUxJRF9FTlRJVFlfUEFUQ0hcIiwgZW50aXR5UGF0Y2hTY2hlbWEpO1xuICBpZiAoIUVudGl0eU1hbmFnZXIuZXhpc3RzKHBhdGNoLmVudGl0eUlkKSkge1xuICAgIHRocm93IE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGBFbnRpdHkgbm90IGZvdW5kOiAke3BhdGNoLmVudGl0eUlkfWApLCB7XG4gICAgICBjb2RlOiBcIkVOVElUWV9OT1RfRk9VTkRcIixcbiAgICB9KTtcbiAgfVxuICBjb25zdCB0YXJnZXQgPSBFbnRpdHlNYW5hZ2VyLmdldChwYXRjaC5lbnRpdHlJZCk7XG4gIGNvbnN0IGJlZm9yZSA9IHRhcmdldC50b0pzb24oKTtcbiAgY29uc3QgYWZ0ZXIgPSBzdHJ1Y3R1cmVkQ2xvbmUoYmVmb3JlKTtcbiAgY29uc3QgbmV4dFByb3BzID0gW1xuICAgIC4uLmFmdGVyLnByb3BzLFxuICAgIC4uLnBhdGNoLm9wZXJhdGlvbnMubWFwKCh7IHZhbHVlIH0pID0+IHN0cnVjdHVyZWRDbG9uZSh2YWx1ZSkpLFxuICBdO1xuICAvLyDtjIzsnbzsnbTrgpgg65Ox66Gd65CcIOyXlO2LsO2LsOulvCDqsbTrk5zrpqzquLAg7KCE7JeQIHBhdGNoIOyggeyaqSDqsrDqs7wg7KCE7LK066W8IGVudGl0eSDsiqTtgqTrp4jroZwg6rKA7Kad7ZWp64uI64ukLlxuICBjb25zdCB7IEVudGl0eUpzb25TY2hlbWEgfSA9IGF3YWl0IGltcG9ydChcIi4uL3R5cGVzL3R5cGVzXCIpO1xuICBjb25zdCB2YWxpZGF0aW9uID0gRW50aXR5SnNvblNjaGVtYS5zYWZlUGFyc2UoeyAuLi5hZnRlciwgcHJvcHM6IG5leHRQcm9wcyB9KTtcbiAgaWYgKCF2YWxpZGF0aW9uLnN1Y2Nlc3MpIHtcbiAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihcIkludmFsaWQgZW50aXR5IHBhdGNoLlwiKSwge1xuICAgICAgY29kZTogXCJJTlZBTElEX0VOVElUWV9QQVRDSFwiLFxuICAgICAgZXhpdENvZGU6IDIsXG4gICAgICBjYXVzZTogdmFsaWRhdGlvbi5lcnJvcixcbiAgICB9KTtcbiAgfVxuICAvLyBTQUZFVFk6IEVudGl0eUpzb25TY2hlbWHqsIAgcGF0Y2gg7KCB7JqpIOqysOqzvCDsoITssrTrpbwg6rKA7Kad7ZaI7Iq164uI64ukLlxuICBhZnRlci5wcm9wcyA9IG5leHRQcm9wcyBhcyB0eXBlb2YgYWZ0ZXIucHJvcHM7XG4gIGlmIChtdXRhdGlvblJlcXVlc3RlZChpbnB1dCkpIHtcbiAgICAvLyBTQUZFVFk6IGFmdGVyLnByb3BzIG9yaWdpbmF0ZXMgZnJvbSB0aGUgY3VycmVudCBlbnRpdHkgcGx1cyBzY2hlbWEtdmFsaWRhdGVkIHByb3AgYWRkaXRpb25zLlxuICAgIHRhcmdldC5wcm9wcyA9IGFmdGVyLnByb3BzIGFzIHR5cGVvZiB0YXJnZXQucHJvcHM7XG4gICAgYXdhaXQgdGFyZ2V0LnNhdmUoKTtcbiAgfVxuICByZXR1cm4geyBjaGFuZ2VkOiBwYXRjaC5vcGVyYXRpb25zLmxlbmd0aCA+IDAsIGJlZm9yZSwgYWZ0ZXIgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVuZGVyU2NhZmZvbGRzKGlucHV0OiBDb21tYW5kSW5wdXQpIHtcbiAgYXdhaXQgZW5zdXJlU29uYW11KCk7XG4gIGNvbnN0IHsgcmVuZGVyVGVtcGxhdGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3N5bmNlci9jb2RlLWdlbmVyYXRvclwiKTtcbiAgY29uc3QgZW50aXRpZXMgPSBzdHJpbmdzKGlucHV0LCBcImVudGl0aWVzXCIpO1xuICBjb25zdCB0ZW1wbGF0ZXMgPSBzdHJpbmdzKGlucHV0LCBcInRlbXBsYXRlc1wiKTtcbiAgY29uc3QgcmVuZGVyZWQgPSBbXTtcbiAgZm9yIChjb25zdCBlbnRpdHlJZCBvZiBlbnRpdGllcykge1xuICAgIGZvciAoY29uc3QgdGVtcGxhdGUgb2YgdGVtcGxhdGVzKSB7XG4gICAgICBjb25zdCB0ZW1wbGF0ZUtleSA9IHpcbiAgICAgICAgLmVudW0oW1wibW9kZWxcIiwgXCJtb2RlbF90ZXN0XCIsIFwidmlld19saXN0XCIsIFwidmlld19mb3JtXCIsIFwidmlld19zZWFyY2hfaW5wdXRcIl0pXG4gICAgICAgIC5wYXJzZSh0ZW1wbGF0ZSk7XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlbmRlclRlbXBsYXRlKHRlbXBsYXRlS2V5LCB7IGVudGl0eUlkIH0pO1xuICAgICAgcmVuZGVyZWQucHVzaCh7IGVudGl0eUlkLCB0ZW1wbGF0ZTogdGVtcGxhdGVLZXksIGZpbGVzIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVuZGVyZWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjYWZmb2xkT3BlcmF0aW9uKG1ldGhvZDogc3RyaW5nLCBpbnB1dDogQ29tbWFuZElucHV0KTogUHJvbWlzZTxUb29saW5nUmVzdWx0PiB7XG4gIGNvbnN0IGRpcmVjdFRlbXBsYXRlID0gelxuICAgIC5lbnVtKFtcIm1vZGVsXCIsIFwibW9kZWxfdGVzdFwiLCBcInZpZXdfbGlzdFwiLCBcInZpZXdfZm9ybVwiXSlcbiAgICAuc2FmZVBhcnNlKG1ldGhvZCk7XG4gIGlmIChkaXJlY3RUZW1wbGF0ZS5zdWNjZXNzKSB7XG4gICAgYXdhaXQgZW5zdXJlU29uYW11KCk7XG4gICAgY29uc3QgeyBTb25hbXUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2FwaS9zb25hbXVcIik7XG4gICAgY29uc3QgZW50aXR5SWQgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwiZW50aXR5SWRcIik7XG4gICAgcmV0dXJuIGRpcmVjdFRlbXBsYXRlLmRhdGEgPT09IFwidmlld19saXN0XCJcbiAgICAgID8gU29uYW11LnN5bmNlci5nZW5lcmF0ZVRlbXBsYXRlKFwidmlld19saXN0XCIsIHsgZW50aXR5SWQsIGV4dHJhOiBpbnB1dC5leHRyYSB9KVxuICAgICAgOiBTb25hbXUuc3luY2VyLmdlbmVyYXRlVGVtcGxhdGUoZGlyZWN0VGVtcGxhdGUuZGF0YSwgeyBlbnRpdHlJZCB9KTtcbiAgfVxuICBjb25zdCByZW5kZXJlZCA9IGF3YWl0IHJlbmRlclNjYWZmb2xkcyhpbnB1dCk7XG4gIGNvbnN0IHsgYWNjZXNzIH0gPSBhd2FpdCBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpO1xuICBjb25zdCBwYXRoID0gYXdhaXQgaW1wb3J0KFwibm9kZTpwYXRoXCIpO1xuICBjb25zdCB7IFNvbmFtdSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vYXBpL3NvbmFtdVwiKTtcbiAgY29uc3QgaXRlbXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICByZW5kZXJlZC5mbGF0TWFwKCh7IGVudGl0eUlkLCB0ZW1wbGF0ZSwgZmlsZXMgfSkgPT5cbiAgICAgIGZpbGVzLm1hcChhc3luYyAoZmlsZSkgPT4ge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBwYXRoLmRlZmF1bHQuam9pbihcbiAgICAgICAgICBTb25hbXUuYXBwUm9vdFBhdGgsXG4gICAgICAgICAgZmlsZS5wYXRoLnJlcGxhY2UoXCIvOnRhcmdldC9cIiwgXCIvd2ViL1wiKSxcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IGV4aXN0cyA9IHRydWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgYWNjZXNzKHRhcmdldCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIGV4aXN0cyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IGVudGl0eUlkLCB0ZW1wbGF0ZSwgdGFyZ2V0LCBleGlzdHMsIGNvbnRlbnQ6IGZpbGUuY29kZSB9O1xuICAgICAgfSksXG4gICAgKSxcbiAgKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJzdGF0dXNcIikgcmV0dXJuIGl0ZW1zLm1hcCgoeyBjb250ZW50OiBfY29udGVudCwgLi4uaXRlbSB9KSA9PiBpdGVtKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJwcmV2aWV3XCIgfHwgKG1ldGhvZCA9PT0gXCJiYXRjaFwiICYmIGV4cGxpY2l0bHlEcnlSdW4oaW5wdXQpKSkgcmV0dXJuIGl0ZW1zO1xuXG4gIGNvbnN0IHJlc3VsdHMgPSBbXTtcbiAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XG4gICAgY29uc3QgeyBjb250ZW50OiBfY29udGVudCwgLi4uc3VtbWFyeSB9ID0gaXRlbTtcbiAgICBpZiAoaXRlbS5leGlzdHMgJiYgaW5wdXQub3ZlcndyaXRlICE9PSB0cnVlKSB7XG4gICAgICByZXN1bHRzLnB1c2goeyAuLi5zdW1tYXJ5LCBzdGF0dXM6IFwic2tpcHBlZFwiIH0pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGF3YWl0IFNvbmFtdS5zeW5jZXIuZ2VuZXJhdGVUZW1wbGF0ZShcbiAgICAgIGl0ZW0udGVtcGxhdGUsXG4gICAgICB7IGVudGl0eUlkOiBpdGVtLmVudGl0eUlkIH0sXG4gICAgICB7IG92ZXJ3cml0ZTogaW5wdXQub3ZlcndyaXRlID09PSB0cnVlIH0sXG4gICAgKTtcbiAgICByZXN1bHRzLnB1c2goeyAuLi5zdW1tYXJ5LCBzdGF0dXM6IFwid3JpdHRlblwiIH0pO1xuICB9XG4gIHJldHVybiB7IGl0ZW1zOiByZXN1bHRzIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1pZ3JhdGlvbk9wZXJhdGlvbihtZXRob2Q6IHN0cmluZywgaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBsZXQgc2hhZG93VGFyZ2V0OiBFeHRyYWN0PE1pZ3JhdGlvblRhcmdldCwgXCJmaXh0dXJlXCIgfCBcInRlc3RcIj4gfCB1bmRlZmluZWQ7XG4gIGlmIChtZXRob2QgPT09IFwic2hhZG93XCIpIHtcbiAgICBjb25zdCByZXF1ZXN0ZWRUYXJnZXQgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwidGFyZ2V0XCIpO1xuICAgIGFzc2VydE1pZ3JhdGlvblRhcmdldChyZXF1ZXN0ZWRUYXJnZXQpO1xuICAgIGFzc2VydFNoYWRvd01pZ3JhdGlvblRhcmdldChyZXF1ZXN0ZWRUYXJnZXQpO1xuICAgIHNoYWRvd1RhcmdldCA9IHJlcXVlc3RlZFRhcmdldDtcbiAgfVxuXG4gIGF3YWl0IGVuc3VyZVNvbmFtdSgpO1xuICBjb25zdCB7IE1pZ3JhdG9yIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9taWdyYXRpb24vbWlncmF0b3JcIik7XG4gIGNvbnN0IG1pZ3JhdG9yID0gbmV3IE1pZ3JhdG9yKCk7XG4gIGlmIChtZXRob2QgPT09IFwic3RhdHVzXCIpIHJldHVybiBtaWdyYXRvci5nZXRTdGF0dXMoKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJnZW5lcmF0ZVwiKSB7XG4gICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgbWlncmF0b3IuZ2V0U3RhdHVzKCk7XG4gICAgaWYgKCFzdGF0dXMuY29ubnMuc29tZSgoY29ubmVjdGlvbikgPT4gY29ubmVjdGlvbi5zdGF0dXMgPT09IDApKSB7XG4gICAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihcIlBlbmRpbmcgbWlncmF0aW9ucyBtdXN0IGJlIGFwcGxpZWQgYmVmb3JlIGdlbmVyYXRpb24uXCIpLCB7XG4gICAgICAgIGNvZGU6IFwiTUlHUkFUSU9OX05PVF9SRUFEWVwiLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB7IGNvdW50OiBhd2FpdCBtaWdyYXRvci5nZW5lcmF0ZVByZXBhcmVkQ29kZXMoKSB9O1xuICB9XG4gIGlmIChtZXRob2QgPT09IFwicnVuXCIpIHtcbiAgICBpZiAoIW11dGF0aW9uUmVxdWVzdGVkKGlucHV0KSkgcmV0dXJuIHsgZHJ5UnVuOiB0cnVlIH07XG4gICAgY29uc3QgeyBnZXRTb25hbXVFbnZpcm9ubWVudCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vZW52XCIpO1xuICAgIGNvbnN0IGVudmlyb25tZW50ID0gZ2V0U29uYW11RW52aXJvbm1lbnQoKTtcbiAgICByZXR1cm4gbWlncmF0b3IuYXBwbHkoZW52aXJvbm1lbnQgPT09IFwidGVzdFwiID8gW1widGVzdFwiLCBcImZpeHR1cmVcIl0gOiBbZW52aXJvbm1lbnRdKTtcbiAgfVxuICBpZiAobWV0aG9kID09PSBcImNvbm5lY3Rpb25zXCIpIHJldHVybiBtaWdyYXRvci5nZXRDb25uZWN0aW9ucygpO1xuICBpZiAobWV0aG9kID09PSBcImFwcGx5XCIpIHtcbiAgICBjb25zdCByYXdUYXJnZXRzID0gc3RyaW5ncyhpbnB1dCwgXCJ0YXJnZXRzXCIpO1xuICAgIGlmIChyYXdUYXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoXCJNaXNzaW5nIHRhcmdldHMuXCIpLCB7IGNvZGU6IFwiTUlTU0lOR19BUkdVTUVOVFwiLCBleGl0Q29kZTogMiB9KTtcbiAgICB9XG4gICAgY29uc3QgdGFyZ2V0cyA9IHJhd1RhcmdldHMubWFwKCh0YXJnZXQpID0+IHtcbiAgICAgIGFzc2VydE1pZ3JhdGlvblRhcmdldCh0YXJnZXQpO1xuICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICB9KTtcbiAgICBpZiAobXV0YXRpb25SZXF1ZXN0ZWQoaW5wdXQpKSByZXR1cm4gbWlncmF0b3IuYXBwbHkodGFyZ2V0cyk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgdGFyZ2V0cy5tYXAoYXN5bmMgKHRhcmdldCkgPT4ge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCBtaWdyYXRvci5nZXRDb25uZWN0aW9uU3RhdHVzKHRhcmdldCk7XG4gICAgICAgIHJldHVybiBtaWdyYXRpb25QbGFuKHRhcmdldCwgc3RhdHVzLnBlbmRpbmcpO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuICBpZiAobWV0aG9kID09PSBcInNoYWRvd1wiKSB7XG4gICAgaWYgKHNoYWRvd1RhcmdldCA9PT0gdW5kZWZpbmVkKSB0aHJvdyBuZXcgRXJyb3IoXCJTaGFkb3cgdGFyZ2V0IHZhbGlkYXRpb24gd2FzIHNraXBwZWQuXCIpO1xuICAgIGlmIChtdXRhdGlvblJlcXVlc3RlZChpbnB1dCkpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG1pZ3JhdG9yLnJ1blNoYWRvd1Rlc3QoeyB0YXJnZXQ6IHNoYWRvd1RhcmdldCB9KTtcbiAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KHJlc3VsdClcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBvazogdHJ1ZSxcbiAgICAgICAgICAgIHRhcmdldDogc2hhZG93VGFyZ2V0LFxuICAgICAgICAgICAgbWlncmF0aW9uczogcmVzdWx0LmZsYXRNYXAoKHsgYXBwbGllZCB9KSA9PiBhcHBsaWVkKSxcbiAgICAgICAgICB9XG4gICAgICAgIDogcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IG1pZ3JhdG9yLmdldENvbm5lY3Rpb25TdGF0dXMoc2hhZG93VGFyZ2V0KTtcbiAgICByZXR1cm4gbWlncmF0aW9uUGxhbihzaGFkb3dUYXJnZXQsIHN0YXR1cy5wZW5kaW5nKTtcbiAgfVxuXG4gIGNvbnN0IHRhcmdldCA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJ0YXJnZXRcIik7XG4gIGFzc2VydE1pZ3JhdGlvblRhcmdldCh0YXJnZXQpO1xuICBpZiAobWV0aG9kID09PSBcImNvZGVcIikgcmV0dXJuIG1pZ3JhdG9yLmdldFByZXBhcmVkQ29kZXModGFyZ2V0KTtcblxuICBjb25zdCBhY3Rpb24gPVxuICAgIG1ldGhvZCA9PT0gXCJyb2xsYmFja1wiIHx8IHRleHQoaW5wdXQsIFwiYWN0aW9uXCIpID09PSBcInJvbGxiYWNrXCIgPyBcInJvbGxiYWNrXCIgOiBcImFwcGx5XCI7XG4gIGNvbnN0IG1pZ3JhdGlvbnMgPVxuICAgIGFjdGlvbiA9PT0gXCJhcHBseVwiXG4gICAgICA/IChhd2FpdCBtaWdyYXRvci5nZXRDb25uZWN0aW9uU3RhdHVzKHRhcmdldCkpLnBlbmRpbmdcbiAgICAgIDogKGF3YWl0IG1pZ3JhdG9yLmdldExhdGVzdEFwcGxpZWRCYXRjaCh0YXJnZXQpKS5maWxlcztcbiAgY29uc3QgcGxhbiA9IGF3YWl0IG1pZ3JhdGlvblBsYW4odGFyZ2V0LCBtaWdyYXRpb25zLCBhY3Rpb24pO1xuICBpZiAobWV0aG9kICE9PSBcInJvbGxiYWNrXCIgfHwgIW11dGF0aW9uUmVxdWVzdGVkKGlucHV0KSkgcmV0dXJuIHBsYW47XG4gIHJldHVybiBtaWdyYXRvci5yb2xsYmFjayhbdGFyZ2V0XSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpeHR1cmVPcGVyYXRpb24obWV0aG9kOiBzdHJpbmcsIGlucHV0OiBDb21tYW5kSW5wdXQpOiBQcm9taXNlPFRvb2xpbmdSZXN1bHQ+IHtcbiAgYXdhaXQgZW5zdXJlU29uYW11KCk7XG4gIGNvbnN0IFtmaXh0dXJlQ29tbWFuZHMsIHsgRml4dHVyZU1hbmFnZXIgfSwgZml4dHVyZVNlcnZpY2UsIHsgU29uYW11IH1dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGltcG9ydChcIi4uL2Jpbi9maXh0dXJlXCIpLFxuICAgIGltcG9ydChcIi4uL3Rlc3RpbmcvZml4dHVyZS1tYW5hZ2VyXCIpLFxuICAgIGltcG9ydChcIi4vZml4dHVyZS1zZXJ2aWNlXCIpLFxuICAgIGltcG9ydChcIi4uL2FwaS9zb25hbXVcIiksXG4gIF0pO1xuICBpZiAobWV0aG9kID09PSBcImluaXRcIikge1xuICAgIHJldHVybiBtdXRhdGlvblJlcXVlc3RlZChpbnB1dCkgPyBmaXh0dXJlQ29tbWFuZHMuZml4dHVyZUluaXRDb21tYW5kKCkgOiB7IGRyeVJ1bjogdHJ1ZSB9O1xuICB9XG4gIGlmIChtZXRob2QgPT09IFwiaW1wb3J0XCIpIHtcbiAgICBpZiAoIW11dGF0aW9uUmVxdWVzdGVkKGlucHV0KSkgcmV0dXJuIHsgZHJ5UnVuOiB0cnVlIH07XG4gICAgRml4dHVyZU1hbmFnZXIuaW5pdCgpO1xuICAgIGF3YWl0IEZpeHR1cmVNYW5hZ2VyLmltcG9ydEZpeHR1cmUoXG4gICAgICByZXF1aXJlZFRleHQoaW5wdXQsIFwiZW50aXR5SWRcIiksXG4gICAgICB6LmFycmF5KHoubnVtYmVyKCkpLnBhcnNlKGlucHV0LnJlY29yZElkcyksXG4gICAgKTtcbiAgICBhd2FpdCBGaXh0dXJlTWFuYWdlci5zeW5jKCk7XG4gICAgcmV0dXJuIHsgaW1wb3J0ZWQ6IHRydWUgfTtcbiAgfVxuICBpZiAobWV0aG9kID09PSBcInN5bmNcIikge1xuICAgIGlmICghbXV0YXRpb25SZXF1ZXN0ZWQoaW5wdXQpKSByZXR1cm4geyBkcnlSdW46IHRydWUgfTtcbiAgICBGaXh0dXJlTWFuYWdlci5pbml0KCk7XG4gICAgYXdhaXQgRml4dHVyZU1hbmFnZXIuc3luYygpO1xuICAgIHJldHVybiB7IHN5bmNlZDogdHJ1ZSB9O1xuICB9XG4gIGNvbnN0IGxlZ2FjeUNvbW1hbmQgPSB6LmVudW0oW1wiZ2VuXCIsIFwiZmV0Y2hcIiwgXCJleHBsb3JlXCJdKS5wYXJzZShtZXRob2QpO1xuICBjb25zdCBpc1RyYW5zZmVyID0gW1wiZW50aXR5SWRcIiwgXCJzb3VyY2VcIiwgXCJ0YXJnZXRcIiwgXCJmaWVsZFwiLCBcInZhbHVlc1wiLCBcInJlbGF0aW9uc1wiLCBcImRlcHRoXCJdLnNvbWUoXG4gICAgKGtleSkgPT4gaW5wdXRba2V5XSAhPT0gdW5kZWZpbmVkLFxuICApO1xuICBpZiAoIWlzVHJhbnNmZXIpIHtcbiAgICBjb25zdCBvcHRpb25zID0gZml4dHVyZVNlcnZpY2Uubm9ybWFsaXplTGVnYWN5Rml4dHVyZUNvbW1hbmRPcHRpb25zKGxlZ2FjeUNvbW1hbmQsIGlucHV0KTtcbiAgICBjb25zdCBzdHJhdGVneSA9IHpcbiAgICAgIC5lbnVtKFtcInNhbXBsZVwiLCBcImlkc1wiLCBcInF1ZXJ5XCIsIFwiZmlsZVwiLCBcInJlY2VudFwiLCBcInJhbmRvbVwiXSlcbiAgICAgIC5vcHRpb25hbCgpXG4gICAgICAucGFyc2Uob3B0aW9ucy5zdHJhdGVneSk7XG4gICAgY29uc3QgZml4dHVyZU9wdGlvbnMgPSB7IC4uLm9wdGlvbnMsIHN0cmF0ZWd5IH0gc2F0aXNmaWVzIEZpeHR1cmVDb21tYW5kT3B0aW9ucztcbiAgICBpZiAobGVnYWN5Q29tbWFuZCAhPT0gXCJleHBsb3JlXCIgJiYgIW11dGF0aW9uUmVxdWVzdGVkKGlucHV0KSkge1xuICAgICAgcmV0dXJuIHsgZHJ5UnVuOiB0cnVlLCByZXF1ZXN0OiBmaXh0dXJlT3B0aW9ucyB9O1xuICAgIH1cbiAgICBpZiAobGVnYWN5Q29tbWFuZCA9PT0gXCJnZW5cIikgcmV0dXJuIGZpeHR1cmVDb21tYW5kcy5maXh0dXJlR2VuQ29tbWFuZChmaXh0dXJlT3B0aW9ucyk7XG4gICAgaWYgKGxlZ2FjeUNvbW1hbmQgPT09IFwiZXhwbG9yZVwiKSByZXR1cm4gZml4dHVyZUNvbW1hbmRzLmZpeHR1cmVFeHBsb3JlQ29tbWFuZChmaXh0dXJlT3B0aW9ucyk7XG4gICAgcmV0dXJuIGZpeHR1cmVDb21tYW5kcy5maXh0dXJlRmV0Y2hDb21tYW5kKGZpeHR1cmVPcHRpb25zKTtcbiAgfVxuXG4gIGNvbnN0IGVudGl0eUlkID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcImVudGl0eUlkXCIpO1xuICBjb25zdCBzb3VyY2UgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwic291cmNlXCIpO1xuICBjb25zdCB0YXJnZXQgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwidGFyZ2V0XCIpO1xuICBjb25zdCBmaWVsZCA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJmaWVsZFwiKTtcbiAgY29uc3QgdmFsdWVzID0gc3RyaW5ncyhpbnB1dCwgXCJ2YWx1ZXNcIik7XG4gIGNvbnN0IHJlbGF0aW9ucyA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJyZWxhdGlvbnNcIik7XG4gIC8vIENMSSDrrLjrspXsnbQgaW50ZWdlcih7IG1pbjogMCB9KeydtOuvgOuhnCDqtIDqs4Qg7Iic7ZqM66W8IOuBhOuKlCBkZXB0aCAw7J2EIO2XiOyaqe2VqeuLiOuLpC5cbiAgY29uc3QgZGVwdGggPSB6Lm51bWJlcigpLmludCgpLm5vbm5lZ2F0aXZlKCkuc2FmZVBhcnNlKGlucHV0LmRlcHRoKTtcbiAgaWYgKFxuICAgICFPYmplY3QuaGFzT3duKFNvbmFtdS5kYkNvbmZpZywgc291cmNlKSB8fFxuICAgICFPYmplY3QuaGFzT3duKFNvbmFtdS5kYkNvbmZpZywgdGFyZ2V0KSB8fFxuICAgIHZhbHVlcy5sZW5ndGggPT09IDAgfHxcbiAgICAhW1wiaW5jbHVkZVwiLCBcImV4Y2x1ZGVcIiwgXCJub25lXCJdLmluY2x1ZGVzKHJlbGF0aW9ucykgfHxcbiAgICAhZGVwdGguc3VjY2Vzc1xuICApIHtcbiAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihcIkludmFsaWQgZml4dHVyZSB0cmFuc2ZlciBzZWxlY3Rvci5cIiksIHtcbiAgICAgIGNvZGU6IFwiSU5WQUxJRF9GSVhUVVJFX1RSQU5TRkVSXCIsXG4gICAgICBleGl0Q29kZTogMixcbiAgICB9KTtcbiAgfVxuICAvLyBTQUZFVFk6IE9iamVjdC5oYXNPd24gY2hlY2tzIGFib3ZlIGVzdGFibGlzaCBib3RoIGtleXMgYXMgY29uZmlndXJlZCBEQiBwcmVzZXRzLlxuICBjb25zdCBzb3VyY2VLZXkgPSBzb3VyY2UgYXMga2V5b2YgdHlwZW9mIFNvbmFtdS5kYkNvbmZpZztcbiAgLy8gU0FGRVRZOiBPYmplY3QuaGFzT3duIGNoZWNrcyBhYm92ZSBlc3RhYmxpc2ggYm90aCBrZXlzIGFzIGNvbmZpZ3VyZWQgREIgcHJlc2V0cy5cbiAgY29uc3QgdGFyZ2V0S2V5ID0gdGFyZ2V0IGFzIGtleW9mIHR5cGVvZiBTb25hbXUuZGJDb25maWc7XG4gIGNvbnN0IHJlY29yZHMgPSAoXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB2YWx1ZXMubWFwKCh2YWx1ZSkgPT5cbiAgICAgICAgRml4dHVyZU1hbmFnZXIuZ2V0Rml4dHVyZXMoXG4gICAgICAgICAgc291cmNlS2V5LFxuICAgICAgICAgIHRhcmdldEtleSxcbiAgICAgICAgICB7IGVudGl0eUlkLCBmaWVsZCwgdmFsdWUsIHNlYXJjaFR5cGU6IFwiZXF1YWxzXCIgfSxcbiAgICAgICAgICB7IGluY2x1ZGVSZWxhdGlvbnM6IHJlbGF0aW9ucyA9PT0gXCJpbmNsdWRlXCIsIG1heERlcHRoOiBkZXB0aC5kYXRhIH0sXG4gICAgICAgICksXG4gICAgICApLFxuICAgIClcbiAgKS5mbGF0KCk7XG4gIGlmIChleHBsaWNpdGx5RHJ5UnVuKGlucHV0KSkgcmV0dXJuIHsgZHJ5UnVuOiB0cnVlLCByZWNvcmRzIH07XG4gIGlmIChyZWNvcmRzLmxlbmd0aCA+IDApIGF3YWl0IEZpeHR1cmVNYW5hZ2VyLmluc2VydEZpeHR1cmVzKHRhcmdldEtleSwgcmVjb3Jkcyk7XG4gIHJldHVybiB7IHJlY29yZHMgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRPcGVyYXRpb24obWV0aG9kOiBzdHJpbmcpOiBQcm9taXNlPFRvb2xpbmdSZXN1bHQ+IHtcbiAgY29uc3QgeyBidWlsZEFwaUNvbW1hbmQsIGJ1aWxkV2ViQ29tbWFuZCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vYmluL2J1aWxkLWNvbmZpZ1wiKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJhcGlcIikgcmV0dXJuIGJ1aWxkQXBpQ29tbWFuZCgpO1xuICBpZiAobWV0aG9kID09PSBcIndlYlwiKSByZXR1cm4gYnVpbGRXZWJDb21tYW5kKCk7XG4gIGF3YWl0IGJ1aWxkQXBpQ29tbWFuZCgpO1xuICByZXR1cm4gYnVpbGRXZWJDb21tYW5kKHsgc2tpcElmTWlzc2luZzogdHJ1ZSB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdE9wZXJhdGlvbihtZXRob2Q6IHN0cmluZywgaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBjb25zdCB7IGNyZWF0ZURlZmF1bHRUZXN0UnVuQ2xpZW50IH0gPSBhd2FpdCBpbXBvcnQoXCIuL3Rlc3QtcnVuLWNsaWVudFwiKTtcbiAgY29uc3QgY2xpZW50ID0gY3JlYXRlRGVmYXVsdFRlc3RSdW5DbGllbnQoKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJzdGF0dXNcIikgcmV0dXJuIGNsaWVudC5zdGF0dXMoKTtcbiAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICBmaWxlczogei5hcnJheSh6LnN0cmluZygpKS5jYXRjaChbXSkucGFyc2UoaW5wdXQuZmlsZXMpLFxuICAgIHBhdHRlcm46IHouc3RyaW5nKCkub3B0aW9uYWwoKS5wYXJzZShpbnB1dC5wYXR0ZXJuKSxcbiAgICB0cmFjZXM6IGlucHV0LnRyYWNlcyA9PT0gdHJ1ZSxcbiAgfTtcbiAgcmV0dXJuIHsgcmVxdWVzdCwgcmVzdWx0OiBhd2FpdCBjbGllbnQucnVuKHJlcXVlc3QpIH07XG59XG5cbmNvbnN0IGJldHRlckF1dGhQbHVnaW5TY2hlbWEgPSB6LmVudW0oW1xuICBcIjJmYVwiLFxuICBcImFkbWluXCIsXG4gIFwiYW5vbnltb3VzXCIsXG4gIFwiYXBpLWtleVwiLFxuICBcImF1ZGl0LWxvZ1wiLFxuICBcImp3dFwiLFxuICBcIm9yZ2FuaXphdGlvblwiLFxuICBcInBhc3NrZXlcIixcbiAgXCJwaG9uZS1udW1iZXJcIixcbiAgXCJzc29cIixcbiAgXCJ1c2VybmFtZVwiLFxuXSk7XG5cbmFzeW5jIGZ1bmN0aW9uIGF1dGhPcGVyYXRpb24obWV0aG9kOiBzdHJpbmcsIGlucHV0OiBDb21tYW5kSW5wdXQpOiBQcm9taXNlPFRvb2xpbmdSZXN1bHQ+IHtcbiAgY29uc3QgeyBhZGRDb21wYW5pb25zVG9FbnRpdGllcywgZ2VuZXJhdGVCZXR0ZXJBdXRoRW50aXRpZXMgfSA9IGF3YWl0IGltcG9ydChcIi4uL2F1dGhcIik7XG4gIGlmIChtZXRob2QgPT09IFwiYWRkQ29tcGFuaW9uc1wiKSByZXR1cm4gYWRkQ29tcGFuaW9uc1RvRW50aXRpZXMoKTtcbiAgLy8gcGx1Z2luc+uKlCDshKDtg50g7Ji17IWY7J2066+A66GcIOyDneuete2VmOuptCBjb3JlIOyXlO2LsO2LsOunjCDsg53shLHtlanri4jri6QuXG4gIGNvbnN0IHBsdWdpbnMgPSB6LmFycmF5KGJldHRlckF1dGhQbHVnaW5TY2hlbWEpLnBhcnNlKFxuICAgIChvcHRpb25hbFRleHQoaW5wdXQsIFwicGx1Z2luc1wiKSA/PyBcIlwiKVxuICAgICAgLnNwbGl0KFwiLFwiKVxuICAgICAgLm1hcCgocGx1Z2luKSA9PiBwbHVnaW4udHJpbSgpKVxuICAgICAgLmZpbHRlcihCb29sZWFuKSxcbiAgKTtcbiAgcmV0dXJuIGdlbmVyYXRlQmV0dGVyQXV0aEVudGl0aWVzKHsgcGx1Z2lucyB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaTE4bk9wZXJhdGlvbihtZXRob2Q6IHN0cmluZywgaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBhd2FpdCBlbnN1cmVTb25hbXUoKTtcbiAgY29uc3QgeyBzb25hbXVEaWN0aW9uYXJ5IH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9kaWN0L3NvbmFtdS1kaWN0aW9uYXJ5XCIpO1xuICBpZiAobWV0aG9kID09PSBcImxpc3RcIikge1xuICAgIGNvbnN0IGRpY3Rpb25hcnkgPSBhd2FpdCBzb25hbXVEaWN0aW9uYXJ5LmdldERpY3Rpb25hcnkoKTtcbiAgICBjb25zdCBsb2NhbGUgPSB0ZXh0KGlucHV0LCBcImxvY2FsZVwiKTtcbiAgICByZXR1cm4gbG9jYWxlID09PSB1bmRlZmluZWRcbiAgICAgID8gZGljdGlvbmFyeVxuICAgICAgOiB7XG4gICAgICAgICAgLi4uZGljdGlvbmFyeSxcbiAgICAgICAgICBsb2NhbGVzOiBbbG9jYWxlXSxcbiAgICAgICAgICByb3dzOiBkaWN0aW9uYXJ5LnJvd3MubWFwKChyb3cpID0+ICh7XG4gICAgICAgICAgICBrZXk6IHJvdy5rZXksXG4gICAgICAgICAgICBzb3VyY2U6IHJvdy5zb3VyY2UsXG4gICAgICAgICAgICBbbG9jYWxlXTogcm93W2xvY2FsZV0sXG4gICAgICAgICAgfSkpLFxuICAgICAgICB9O1xuICB9XG4gIGlmIChtZXRob2QgPT09IFwiY2hlY2tcIikge1xuICAgIGNvbnN0IGRpY3Rpb25hcnkgPSBhd2FpdCBzb25hbXVEaWN0aW9uYXJ5LmdldERpY3Rpb25hcnkoKTtcbiAgICByZXR1cm4gc29uYW11RGljdGlvbmFyeS5jaGVja1VzYWdlKGRpY3Rpb25hcnkucm93cy5tYXAoKHJvdykgPT4gcm93LmtleSkpO1xuICB9XG4gIGlmIChtZXRob2QgPT09IFwiZXhwb3J0XCIgfHwgbWV0aG9kID09PSBcImltcG9ydFwiKSB7XG4gICAgY29uc3QgZmlsZSA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJmaWxlXCIpO1xuICAgIGlmIChleHBsaWNpdGx5RHJ5UnVuKGlucHV0KSkgcmV0dXJuIHsgb3BlcmF0aW9uOiBtZXRob2QsIGRyeVJ1bjogdHJ1ZSB9O1xuICAgIGNvbnN0IHsgcmVhZEZpbGUsIHdyaXRlRmlsZSB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpmcy9wcm9taXNlc1wiKTtcbiAgICBjb25zdCBmb3JtYXQgPSB0ZXh0KGlucHV0LCBcImZvcm1hdFwiKSA9PT0gXCJqc29uXCIgPyBcImpzb25cIiA6IFwid29ya2Jvb2tcIjtcbiAgICBpZiAobWV0aG9kID09PSBcImV4cG9ydFwiICYmIGZvcm1hdCA9PT0gXCJ3b3JrYm9va1wiKSB7XG4gICAgICBjb25zdCB7IGJ1ZmZlciB9ID0gYXdhaXQgc29uYW11RGljdGlvbmFyeS5leHBvcnRUb0V4Y2VsKCk7XG4gICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZSwgYnVmZmVyKTtcbiAgICAgIHJldHVybiB7IGV4cG9ydGVkOiAxIH07XG4gICAgfVxuICAgIGlmIChtZXRob2QgPT09IFwiaW1wb3J0XCIgJiYgZm9ybWF0ID09PSBcIndvcmtib29rXCIpIHtcbiAgICAgIHJldHVybiBzb25hbXVEaWN0aW9uYXJ5LmltcG9ydEZyb21FeGNlbChhd2FpdCByZWFkRmlsZShmaWxlKSk7XG4gICAgfVxuXG4gICAgaWYgKG1ldGhvZCA9PT0gXCJleHBvcnRcIikge1xuICAgICAgY29uc3QgZGljdGlvbmFyeSA9IGF3YWl0IHNvbmFtdURpY3Rpb25hcnkuZ2V0RGljdGlvbmFyeSgpO1xuICAgICAgY29uc3QgbG9jYWxlID0gdGV4dChpbnB1dCwgXCJsb2NhbGVcIik7XG4gICAgICBjb25zdCByb3dzID0gZGljdGlvbmFyeS5yb3dzLm1hcChcbiAgICAgICAgKHsga2V5LCBzb3VyY2U6IF9zb3VyY2UsIGlzRnVuY3Rpb246IF9pc0Z1bmN0aW9uLCAuLi52YWx1ZXMgfSkgPT4gKHtcbiAgICAgICAgICBrZXksXG4gICAgICAgICAgdmFsdWVzOlxuICAgICAgICAgICAgbG9jYWxlID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgPyB2YWx1ZXNcbiAgICAgICAgICAgICAgOiB7IFtsb2NhbGVdOiB6LnN0cmluZygpLmNhdGNoKFwiXCIpLnBhcnNlKHZhbHVlc1tsb2NhbGVdKSB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZSwgSlNPTi5zdHJpbmdpZnkocm93cywgbnVsbCwgMikpO1xuICAgICAgcmV0dXJuIHsgZXhwb3J0ZWQ6IHJvd3MubGVuZ3RoIH07XG4gICAgfVxuXG4gICAgY29uc3QgZW50cmllcyA9IHBhcnNlSnNvbihcbiAgICAgIChhd2FpdCByZWFkRmlsZShmaWxlKSkudG9TdHJpbmcoXCJ1dGY4XCIpLFxuICAgICAgXCJJMThOX0lOVkFMSURfSlNPTlwiLFxuICAgICAgaTE4bkVudHJpZXNTY2hlbWEsXG4gICAgKTtcbiAgICBjb25zdCBjdXJyZW50ID0gYXdhaXQgc29uYW11RGljdGlvbmFyeS5nZXREaWN0aW9uYXJ5KCk7XG4gICAgY29uc3QgZXhpc3RpbmdLZXlzID0gbmV3IFNldChjdXJyZW50LnJvd3MubWFwKCh7IGtleSB9KSA9PiBrZXkpKTtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgIGlmIChleGlzdGluZ0tleXMuaGFzKGVudHJ5LmtleSkpIHtcbiAgICAgICAgYXdhaXQgc29uYW11RGljdGlvbmFyeS51cGRhdGVFbnRyeSh7XG4gICAgICAgICAgb2xkS2V5OiBlbnRyeS5rZXksXG4gICAgICAgICAgbmV3S2V5OiBlbnRyeS5rZXksXG4gICAgICAgICAgc291cmNlOiBcInByb2plY3RcIixcbiAgICAgICAgICB2YWx1ZXM6IGVudHJ5LnZhbHVlcyxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBzb25hbXVEaWN0aW9uYXJ5LmNyZWF0ZUVudHJ5KGVudHJ5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgaW1wb3J0ZWQ6IGVudHJpZXMubGVuZ3RoIH07XG4gIH1cbiAgY29uc3Qga2V5ID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcImtleVwiKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJjcmVhdGVcIikge1xuICAgIGlmIChleHBsaWNpdGx5RHJ5UnVuKGlucHV0KSkgcmV0dXJuIHsgb3BlcmF0aW9uOiBcImNyZWF0ZVwiLCBpbnB1dCwgZHJ5UnVuOiB0cnVlIH07XG4gICAgcmV0dXJuIHNvbmFtdURpY3Rpb25hcnkuY3JlYXRlRW50cnkoe1xuICAgICAga2V5LFxuICAgICAgdmFsdWVzOiBkaWN0aW9uYXJ5VmFsdWVzU2NoZW1hLnBhcnNlKGlucHV0LnZhbHVlcyksXG4gICAgfSk7XG4gIH1cbiAgaWYgKG1ldGhvZCA9PT0gXCJ1cGRhdGVcIikge1xuICAgIGlmIChleHBsaWNpdGx5RHJ5UnVuKGlucHV0KSkgcmV0dXJuIHsgb3BlcmF0aW9uOiBcInVwZGF0ZVwiLCBpbnB1dCwgZHJ5UnVuOiB0cnVlIH07XG4gICAgY29uc3QgZXhwbGljaXRTb3VyY2UgPSB0ZXh0KGlucHV0LCBcInNvdXJjZVwiKTtcbiAgICAvLyBzb3VyY2Xrpbwg7IOd65617ZWY66m0IOyCrOyghOyXkCDrk7HroZ3rkJwg6riw7KG0IHNvdXJjZeulvCDsnKDsp4DtlbQgZW50aXR5IO2VreuqqeydtCBwcm9qZWN0IG92ZXJyaWRl66GcIOuNruydtOyngCDslYrqsowg7ZWp64uI64ukLlxuICAgIGNvbnN0IHJlc29sdmVkU291cmNlID1cbiAgICAgIGV4cGxpY2l0U291cmNlID09PSB1bmRlZmluZWRcbiAgICAgICAgPyAoKGF3YWl0IHNvbmFtdURpY3Rpb25hcnkuZ2V0RGljdGlvbmFyeSgpKS5yb3dzLmZpbmQoKHJvdykgPT4gcm93LmtleSA9PT0ga2V5KT8uc291cmNlID8/XG4gICAgICAgICAgXCJwcm9qZWN0XCIpXG4gICAgICAgIDogZXhwbGljaXRTb3VyY2U7XG4gICAgcmV0dXJuIHNvbmFtdURpY3Rpb25hcnkudXBkYXRlRW50cnkoe1xuICAgICAgb2xkS2V5OiBrZXksXG4gICAgICBuZXdLZXk6IHRleHQoaW5wdXQsIFwibmV3S2V5XCIpID8/IGtleSxcbiAgICAgIHNvdXJjZTogZGljdGlvbmFyeVNvdXJjZVNjaGVtYS5wYXJzZShyZXNvbHZlZFNvdXJjZSksXG4gICAgICB2YWx1ZXM6IGRpY3Rpb25hcnlWYWx1ZXNTY2hlbWEucGFyc2UoaW5wdXQudmFsdWVzKSxcbiAgICB9KTtcbiAgfVxuICBpZiAoIW11dGF0aW9uUmVxdWVzdGVkKGlucHV0KSkgcmV0dXJuIHsga2V5LCBvcGVyYXRpb246IFwicmVtb3ZlXCIsIGRyeVJ1bjogdHJ1ZSB9O1xuICByZXR1cm4gc29uYW11RGljdGlvbmFyeS5kZWxldGVFbnRyeShrZXkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB0YXNrT3BlcmF0aW9uKG1ldGhvZDogc3RyaW5nLCBpbnB1dDogQ29tbWFuZElucHV0KTogUHJvbWlzZTxUb29saW5nUmVzdWx0PiB7XG4gIGF3YWl0IGVuc3VyZVNvbmFtdSgpO1xuICBjb25zdCB7IFNvbmFtdSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vYXBpL3NvbmFtdVwiKTtcbiAgY29uc3Qgd29ya2Zsb3dzID0gU29uYW11LndvcmtmbG93cztcbiAgY29uc3QgYmFja2VuZCA9IHdvcmtmbG93cy5iYWNrZW5kO1xuICBpZiAobWV0aG9kID09PSBcImRlZmluaXRpb25zXCIpIHJldHVybiB7IGRlZmluaXRpb25zOiB3b3JrZmxvd3Mud29ya2Zsb3dEZWZpbml0aW9ucyB9O1xuICBpZiAobWV0aG9kID09PSBcInJ1bnNcIikgcmV0dXJuIGJhY2tlbmQubGlzdFdvcmtmbG93UnVucyh7IGxpbWl0OiA1MCB9KTtcbiAgY29uc3Qgd29ya2Zsb3dSdW5JZCA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJydW5JZFwiKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJzaG93XCIpIHJldHVybiBiYWNrZW5kLmdldFdvcmtmbG93UnVuKHsgd29ya2Zsb3dSdW5JZCB9KTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJ3YXRjaFwiKSB7XG4gICAgY29uc3QgeyBpc0RlZXBTdHJpY3RFcXVhbCB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTp1dGlsXCIpO1xuICAgIHJldHVybiAoYXN5bmMgZnVuY3Rpb24qIHdhdGNoKCkge1xuICAgICAgbGV0IHByZXZpb3VzOiBvYmplY3QgfCB1bmRlZmluZWQ7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGJhY2tlbmQuZ2V0V29ya2Zsb3dSdW4oeyB3b3JrZmxvd1J1bklkIH0pO1xuICAgICAgICBpZiAoc25hcHNob3QgPT09IG51bGwpIHtcbiAgICAgICAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihgV29ya2Zsb3cgcnVuIG5vdCBmb3VuZDogJHt3b3JrZmxvd1J1bklkfWApLCB7XG4gICAgICAgICAgICBjb2RlOiBcIlRBU0tfUlVOX05PVF9GT1VORFwiLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJhd1N0YXRlID0gc25hcHNob3Quc3RhdHVzID09PSBcInN1Y2NlZWRlZFwiID8gXCJjb21wbGV0ZWRcIiA6IHNuYXBzaG90LnN0YXR1cztcbiAgICAgICAgY29uc3Qgc3RhdGUgPSByYXdTdGF0ZSA9PT0gXCJjYW5jZWxlZFwiID8gXCJjYW5jZWxsZWRcIiA6IHJhd1N0YXRlO1xuICAgICAgICBjb25zdCBjdXJyZW50ID0geyAuLi5zbmFwc2hvdCwgc3RhdGUgfTtcbiAgICAgICAgaWYgKCFpc0RlZXBTdHJpY3RFcXVhbChjdXJyZW50LCBwcmV2aW91cykpIHtcbiAgICAgICAgICBwcmV2aW91cyA9IHN0cnVjdHVyZWRDbG9uZShjdXJyZW50KTtcbiAgICAgICAgICB5aWVsZCBjdXJyZW50O1xuICAgICAgICB9XG4gICAgICAgIGlmIChbXCJjb21wbGV0ZWRcIiwgXCJmYWlsZWRcIiwgXCJjYW5jZWxsZWRcIl0uaW5jbHVkZXMoc3RhdGUpKSByZXR1cm47XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDFfMDAwKSk7XG4gICAgICB9XG4gICAgfSkoKTtcbiAgfVxuICBpZiAobWV0aG9kID09PSBcInN0ZXBzXCIpIHJldHVybiBiYWNrZW5kLmxpc3RTdGVwQXR0ZW1wdHMoeyB3b3JrZmxvd1J1bklkLCBsaW1pdDogMTAwIH0pO1xuICBpZiAoIW11dGF0aW9uUmVxdWVzdGVkKGlucHV0KSkgcmV0dXJuIHsgb3BlcmF0aW9uOiBtZXRob2QsIHdvcmtmbG93UnVuSWQsIGRyeVJ1bjogdHJ1ZSB9O1xuICBpZiAobWV0aG9kID09PSBcInBhdXNlXCIpIHJldHVybiBiYWNrZW5kLnBhdXNlV29ya2Zsb3dSdW4oeyB3b3JrZmxvd1J1bklkIH0pO1xuICBpZiAobWV0aG9kID09PSBcInJlc3VtZVwiKSByZXR1cm4gYmFja2VuZC5yZXN1bWVXb3JrZmxvd1J1bih7IHdvcmtmbG93UnVuSWQgfSk7XG4gIHJldHVybiBiYWNrZW5kLmNhbmNlbFdvcmtmbG93UnVuKHsgd29ya2Zsb3dSdW5JZCB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2RkUm9vdFBhdGgoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgW3sgU29uYW11IH0sIHBhdGhdID0gYXdhaXQgUHJvbWlzZS5hbGwoW2ltcG9ydChcIi4uL2FwaS9zb25hbXVcIiksIGltcG9ydChcIm5vZGU6cGF0aFwiKV0pO1xuICByZXR1cm4gcGF0aC5qb2luKFNvbmFtdS5hcHBSb290UGF0aCwgXCJjb250cmFjdFwiKTtcbn1cblxuY29uc3QgcHJhY3RpY2VTZXF1ZW5jZVBhdHRlcm4gPSAvXnAoWzAtOV0rKS0vO1xuXG4vLyDsnbTrpoTsnYAg7YyM7J2866qF6rO8IOyKpO2FgSDrs7jrrLjsnZgg66y47J6Q7Je0IOumrO2EsOuftOyXkCDqt7jrjIDroZwg65Ok7Ja06rCA66+A66GcLFxuLy8g6rK966GcIOq1rOu2hOyekC/sg4HsnIQg6rK966GcIOywuOyhsC/rlLDsmLTtkZwv7Jet7Iqs656Y7Iuc66W8IOybkOyynCDssKjri6jtlZjripQg66y47J6Q66eMIO2XiOyaqe2VqeuLiOuLpC5cbmNvbnN0IHByYWN0aWNlTmFtZVBhdHRlcm4gPSAvXltBLVphLXowLTldW0EtWmEtejAtOS5fLV0qJC87XG5cbmZ1bmN0aW9uIGludmFsaWRQcmFjdGljZU5hbWUobmFtZTogc3RyaW5nKTogRXJyb3Ige1xuICByZXR1cm4gT2JqZWN0LmFzc2lnbihcbiAgICBuZXcgRXJyb3IoXG4gICAgICBgSW52YWxpZCBwcmFjdGljZSBuYW1lOiAke25hbWV9LiBVc2UgbGV0dGVycywgZGlnaXRzLCBcIi5cIiwgXCItXCIsIGFuZCBcIl9cIiBvbmx5LCBzdGFydGluZyB3aXRoIGEgbGV0dGVyIG9yIGRpZ2l0LmAsXG4gICAgKSxcbiAgICB7IGNvZGU6IFwiSU5WQUxJRF9QUkFDVElDRV9OQU1FXCIsIGV4aXRDb2RlOiAyIH0sXG4gICk7XG59XG5cbmZ1bmN0aW9uIGludmFsaWRQcmFjdGljZURpcmVjdG9yeShkaXJlY3Rvcnk6IHN0cmluZyk6IEVycm9yIHtcbiAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGBQcmFjdGljZSBkaXJlY3RvcnkgZXNjYXBlcyB0aGUgQVBJIHJvb3Q6ICR7ZGlyZWN0b3J5fWApLCB7XG4gICAgY29kZTogXCJJTlZBTElEX1BSQUNUSUNFX1BBVEhcIixcbiAgICBleGl0Q29kZTogMixcbiAgfSk7XG59XG5cbi8qKlxuICogYHNyYy9wcmFjdGljZXNgIOyVhOuemOyXkCDri6TsnYwg7Iuc7YCA7IqkIOuyiO2YuOulvCDqsIDsp4QgcHJhY3RpY2Ug7Iqk7YWBIO2MjOydvOydhCDrp4zrk63ri4jri6QuXG4gKlxuICog6rWsIENMSShgc3R1YiBwcmFjdGljZWAp7J2YIO2MjOydvOuqhSDqt5zsuZnqs7wg7Iqk7YWBIOuzuOusuOydhCDqt7jrjIDroZwg7Jyg7KeA7ZWp64uI64ukLlxuICovXG5hc3luYyBmdW5jdGlvbiBzdHViUHJhY3RpY2VPcGVyYXRpb24oaW5wdXQ6IENvbW1hbmRJbnB1dCk6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBjb25zdCBuYW1lID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcIm5hbWVcIik7XG4gIGlmICghcHJhY3RpY2VOYW1lUGF0dGVybi50ZXN0KG5hbWUpKSB0aHJvdyBpbnZhbGlkUHJhY3RpY2VOYW1lKG5hbWUpO1xuICBhd2FpdCBlbnN1cmVTb25hbXUoKTtcbiAgY29uc3QgW3sgU29uYW11IH0sIHsgY29uc3RhbnRzIH0sIHsgbWtkaXIsIG9wZW4sIHJlYWRkaXIsIHJlYWxwYXRoIH0sIHBhdGhdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGltcG9ydChcIi4uL2FwaS9zb25hbXVcIiksXG4gICAgaW1wb3J0KFwibm9kZTpmc1wiKSxcbiAgICBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpLFxuICAgIGltcG9ydChcIm5vZGU6cGF0aFwiKSxcbiAgXSk7XG4gIGNvbnN0IHByYWN0aWNlRGlyZWN0b3J5ID0gcGF0aC5kZWZhdWx0LmpvaW4oU29uYW11LmFwaVJvb3RQYXRoLCBcInNyY1wiLCBcInByYWN0aWNlc1wiKTtcbiAgYXdhaXQgbWtkaXIocHJhY3RpY2VEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAvLyBjZGQtc2VydmljZeyZgCDqsJnsnbQg7Iuk7KCcIOqyveuhnOq5jOyngCDtmZXsnbjtlbQsIHN5bWxpbmvroZwg7Jew6rKw65CcIHByYWN0aWNlcyDrlJTroInthLDrpqzqsIBcbiAgLy8gYXBpIHJvb3Qg67CW7J2EIOqwgOumrO2CpOuKlCDqsr3smrDrpbwg7LCo64uo7ZWp64uI64ukLlxuICBjb25zdCBbY2Fub25pY2FsQXBpUm9vdCwgY2Fub25pY2FsRGlyZWN0b3J5XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICByZWFscGF0aChTb25hbXUuYXBpUm9vdFBhdGgpLFxuICAgIHJlYWxwYXRoKHByYWN0aWNlRGlyZWN0b3J5KSxcbiAgXSk7XG4gIGNvbnN0IGRpcmVjdG9yeVJlbGF0aXZlID0gcGF0aC5kZWZhdWx0LnJlbGF0aXZlKGNhbm9uaWNhbEFwaVJvb3QsIGNhbm9uaWNhbERpcmVjdG9yeSk7XG4gIGlmIChkaXJlY3RvcnlSZWxhdGl2ZS5zdGFydHNXaXRoKFwiLi5cIikgfHwgcGF0aC5kZWZhdWx0LmlzQWJzb2x1dGUoZGlyZWN0b3J5UmVsYXRpdmUpKSB7XG4gICAgdGhyb3cgaW52YWxpZFByYWN0aWNlRGlyZWN0b3J5KHByYWN0aWNlRGlyZWN0b3J5KTtcbiAgfVxuICBjb25zdCBmaWxlTmFtZXMgPSBhd2FpdCByZWFkZGlyKHByYWN0aWNlRGlyZWN0b3J5KTtcbiAgY29uc3QgbWF4U2VxdWVuY2UgPSBmaWxlTmFtZXNcbiAgICAuZmlsdGVyKChmaWxlTmFtZSkgPT4gZmlsZU5hbWUuc3RhcnRzV2l0aChcInBcIikgJiYgZmlsZU5hbWUuZW5kc1dpdGgoXCIudHNcIikpXG4gICAgLnJlZHVjZSgobGFyZ2VzdCwgZmlsZU5hbWUpID0+IHtcbiAgICAgIGNvbnN0IG1hdGNoZWQgPSBwcmFjdGljZVNlcXVlbmNlUGF0dGVybi5leGVjKGZpbGVOYW1lKTtcbiAgICAgIHJldHVybiBtYXRjaGVkID09PSBudWxsID8gbGFyZ2VzdCA6IE1hdGgubWF4KGxhcmdlc3QsIE51bWJlci5wYXJzZUludChtYXRjaGVkWzFdLCAxMCkpO1xuICAgIH0sIDApO1xuXG4gIGNvbnN0IGZpbGVOYW1lID0gYHAke21heFNlcXVlbmNlICsgMX0tJHtuYW1lfS50c2A7XG4gIC8vIOydtOumhCDtjKjthLTsnbQg6rK966GcIOq1rOu2hOyekOulvCDssKjri6jtlZjrr4DroZwg7YyM7J2866qF7J2AIO2VreyDgSDsnbQg65SU66CJ7YSw66as7J2YIOyngeqzhCDsnpDsi53snoXri4jri6QuXG4gIC8vIOqyveuhnOuKlCDshKTsoJXrkJwg6rCSIOq3uOuMgOuhnCDrj4zroKTso7zqs6AsIO2DiOy2nCDsl6zrtoDripQg7JyE7J2YIGNhbm9uaWNhbCDqsoDsgqzroZwg7YyQ64uo7ZWp64uI64ukLlxuICBjb25zdCBmaWxlUGF0aCA9IHBhdGguZGVmYXVsdC5yZXNvbHZlKHByYWN0aWNlRGlyZWN0b3J5LCBmaWxlTmFtZSk7XG4gIGNvbnN0IHN0dWJDb2RlID0gW1xuICAgIGBpbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwic29uYW11XCI7YCxcbiAgICBcIlwiLFxuICAgIGBjb25zb2xlLmNsZWFyKCk7YCxcbiAgICBgY29uc29sZS5sb2coXCIke2ZpbGVOYW1lfVwiKTtgLFxuICAgIFwiXCIsXG4gICAgYFNvbmFtdS5ydW5TY3JpcHQoYXN5bmMgKCkgPT4ge2AsXG4gICAgYCAvLyBUT0RPYCxcbiAgICBgfSk7YCxcbiAgICBcIlwiLFxuICBdLmpvaW4oXCJcXG5cIik7XG4gIGxldCBoYW5kbGU7XG4gIHRyeSB7XG4gICAgLy8g6riw7KG0IO2MjOydvOydhCB0cnVuY2F0Ze2VmOyngCDslYrrj4TroZ0g67Cw7YOAIOyDneyEse2VmOqzoCwg7LWc7KKFIOqyveuhnOydmCBzeW1saW5r64qUIOuUsOudvOqwgOyngCDslYrsirXri4jri6QuXG4gICAgaGFuZGxlID0gYXdhaXQgb3BlbihcbiAgICAgIGZpbGVQYXRoLFxuICAgICAgY29uc3RhbnRzLk9fV1JPTkxZIHwgY29uc3RhbnRzLk9fQ1JFQVQgfCBjb25zdGFudHMuT19FWENMIHwgY29uc3RhbnRzLk9fTk9GT0xMT1csXG4gICAgICAwbzY2NixcbiAgICApO1xuICAgIGF3YWl0IGhhbmRsZS53cml0ZUZpbGUoc3R1YkNvZGUsIFwidXRmOFwiKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBTQUZFVFk6IG5vZGU6ZnMgb3BlbiDsi6TtjKjsnZggY29kZeunjCDsnb3slrQg6riw7KG0IO2MjOydvC9zeW1saW5rIOy2qeuPjOydhCDsoJXqt5ztmZTtlanri4jri6QuXG4gICAgY29uc3QgZXJyb3JDb2RlID0gKGVycm9yIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZTtcbiAgICBpZiAoZXJyb3JDb2RlID09PSBcIkVFWElTVFwiIHx8IGVycm9yQ29kZSA9PT0gXCJFTE9PUFwiKSB7XG4gICAgICB0aHJvdyBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihgUHJhY3RpY2UgZmlsZSBhbHJlYWR5IGV4aXN0czogJHtmaWxlUGF0aH1gKSwge1xuICAgICAgICBjb2RlOiBcIlBSQUNUSUNFX0ZJTEVfRVhJU1RTXCIsXG4gICAgICAgIGV4aXRDb2RlOiAyLFxuICAgICAgICBjYXVzZTogZXJyb3IsXG4gICAgICB9KTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgaGFuZGxlPy5jbG9zZSgpO1xuICB9XG4gIC8vIOyXkOuUlO2EsCDsl7TquLAv7YG066a967O065OcIOuzteyCrCDqsJnsnYAg64yA7ZmU7ZiVIOu2gOyImO2aqOqzvOuKlCDruYTrjIDtmZTtmJUg7Iuk7ZaJ7J2EIOq5qOucqOumrOuvgOuhnCDtmLjstpzsnpDsl5Dqsowg66eh6rmB64uI64ukLlxuICByZXR1cm4geyBmaWxlTmFtZSwgcGF0aDogZmlsZVBhdGggfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZENkZFRyZWUoZGlyZWN0b3J5OiBzdHJpbmcsIHJvb3Q6IHN0cmluZyk6IFByb21pc2U8b2JqZWN0W10+IHtcbiAgY29uc3QgW3sgcmVhZGRpciB9LCBwYXRoXSA9IGF3YWl0IFByb21pc2UuYWxsKFtpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpLCBpbXBvcnQoXCJub2RlOnBhdGhcIildKTtcbiAgY29uc3QgZW50cmllcyA9IGF3YWl0IHJlYWRkaXIoZGlyZWN0b3J5LCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gIGNvbnN0IG5vZGVzID0gW107XG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGlmIChlbnRyeS5uYW1lID09PSBcInJ1bGVzXCIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGguam9pbihkaXJlY3RvcnksIGVudHJ5Lm5hbWUpO1xuICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IHBhdGgucmVsYXRpdmUocm9vdCwgYWJzb2x1dGVQYXRoKTtcbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSBhd2FpdCByZWFkQ2RkVHJlZShhYnNvbHV0ZVBhdGgsIHJvb3QpO1xuICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbm9kZXMucHVzaCh7IG5hbWU6IGVudHJ5Lm5hbWUsIHBhdGg6IHJlbGF0aXZlUGF0aCwgdHlwZTogXCJkaXJlY3RvcnlcIiwgY2hpbGRyZW4gfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChlbnRyeS5pc0ZpbGUoKSAmJiBlbnRyeS5uYW1lLmVuZHNXaXRoKFwiLmNvbnRyYWN0Lm1kXCIpKSB7XG4gICAgICBub2Rlcy5wdXNoKHsgbmFtZTogZW50cnkubmFtZSwgcGF0aDogcmVsYXRpdmVQYXRoLCB0eXBlOiBcImZpbGVcIiwgZmlsZVR5cGU6IFwiY29udHJhY3RcIiB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5vZGVzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjZGRPcGVyYXRpb24obWV0aG9kOiBzdHJpbmcsIGlucHV0OiBDb21tYW5kSW5wdXQpOiBQcm9taXNlPFRvb2xpbmdSZXN1bHQ+IHtcbiAgYXdhaXQgZW5zdXJlU29uYW11KCk7XG4gIGNvbnN0IFt7IGFjY2VzcyB9LCB7IGNyZWF0ZURlZmF1bHRDZGRUb29saW5nQWRhcHRlciB9XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpLFxuICAgIGltcG9ydChcIi4vY2RkLXNlcnZpY2VcIiksXG4gIF0pO1xuICBjb25zdCBhZGFwdGVyID0gY3JlYXRlRGVmYXVsdENkZFRvb2xpbmdBZGFwdGVyKHsgY29udHJhY3RSb290OiBhd2FpdCBjZGRSb290UGF0aCgpIH0pO1xuICBpZiAobWV0aG9kID09PSBcInRyZWVcIikge1xuICAgIGNvbnN0IHJvb3QgPSBhd2FpdCBjZGRSb290UGF0aCgpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBhY2Nlc3Mocm9vdCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4geyBleGlzdHM6IGZhbHNlLCB0cmVlOiBbXSB9O1xuICAgIH1cbiAgICByZXR1cm4geyBleGlzdHM6IHRydWUsIHRyZWU6IGF3YWl0IHJlYWRDZGRUcmVlKHJvb3QsIHJvb3QpIH07XG4gIH1cbiAgaWYgKG1ldGhvZCA9PT0gXCJyZWFkXCIpIHtcbiAgICBjb25zdCByZWxhdGl2ZVBhdGggPSByZXF1aXJlZFRleHQoaW5wdXQsIFwicGF0aFwiKTtcbiAgICByZXR1cm4gYWRhcHRlci5yZWFkKHsgcGF0aDogcmVsYXRpdmVQYXRoIH0pO1xuICB9XG4gIGlmIChtZXRob2QgPT09IFwicnVsZXNcIikgcmV0dXJuIGFkYXB0ZXIucnVsZXMoKTtcbiAgaWYgKG1ldGhvZCA9PT0gXCJzaG93UnVsZVwiKSB7XG4gICAgY29uc3QgcnVsZUlkID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcInJ1bGVJZFwiKTtcbiAgICByZXR1cm4gYWRhcHRlci5zaG93UnVsZSh7IHJ1bGVJZCB9KTtcbiAgfVxuICBpZiAobWV0aG9kID09PSBcImFkZFJ1bGVcIikge1xuICAgIGNvbnN0IHJ1bGVLZXkgPSByZXF1aXJlZFRleHQoaW5wdXQsIFwicnVsZUtleVwiKTtcbiAgICBjb25zdCBpZCA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJpZFwiKTtcbiAgICBjb25zdCB3aGVuID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcIndoZW5cIik7XG4gICAgY29uc3QgcnVsZVRleHQgPSB0ZXh0KGlucHV0LCBcImluc3RydWN0aW9uXCIpID8/IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJ0ZXh0XCIpO1xuICAgIHJldHVybiBhZGFwdGVyLmFkZFJ1bGUoe1xuICAgICAgcnVsZUtleSxcbiAgICAgIGlkLFxuICAgICAgd2hlbixcbiAgICAgIHRleHQ6IHJ1bGVUZXh0LFxuICAgICAgZXhhbXBsZXM6IHN0cmluZ3MoaW5wdXQsIFwiZXhhbXBsZXNcIiksXG4gICAgICBkcnlSdW46IGV4cGxpY2l0bHlEcnlSdW4oaW5wdXQpLFxuICAgIH0pO1xuICB9XG4gIGlmIChleHBsaWNpdGx5RHJ5UnVuKGlucHV0KSkge1xuICAgIHJldHVybiB7IG9wZXJhdGlvbjogXCJhZGRBY2NlcHRhbmNlQ3JpdGVyaW9uXCIsIGlucHV0LCBkcnlSdW46IHRydWUgfTtcbiAgfVxuICBjb25zdCBkb2N1bWVudCA9IHJlcXVpcmVkVGV4dChpbnB1dCwgXCJkb2N1bWVudFwiKTtcbiAgY29uc3QgY3JpdGVyaW9uID0gcmVxdWlyZWRUZXh0KGlucHV0LCBcInRleHRcIik7XG4gIHJldHVybiBhZGFwdGVyLmFkZEFjY2VwdGFuY2VDcml0ZXJpb24oeyBkb2N1bWVudCwgdGV4dDogY3JpdGVyaW9uLCBkcnlSdW46IGZhbHNlIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnZva2VEZWZhdWx0KFxuICBncm91cDogc3RyaW5nLFxuICBtZXRob2Q6IHN0cmluZyxcbiAgaW5wdXQ6IENvbW1hbmRJbnB1dCxcbik6IFByb21pc2U8VG9vbGluZ1Jlc3VsdD4ge1xuICBpZiAoZ3JvdXAgPT09IFwiY29yZVwiKSByZXR1cm4gc3luY09wZXJhdGlvbihpbnB1dCk7XG4gIGlmIChncm91cCA9PT0gXCJlbnRpdHlcIikgcmV0dXJuIGVudGl0eU9wZXJhdGlvbihtZXRob2QsIGlucHV0KTtcbiAgaWYgKGdyb3VwID09PSBcInNjYWZmb2xkXCIpIHJldHVybiBzY2FmZm9sZE9wZXJhdGlvbihtZXRob2QsIGlucHV0KTtcbiAgaWYgKGdyb3VwID09PSBcIm1pZ3JhdGlvblwiKSByZXR1cm4gbWlncmF0aW9uT3BlcmF0aW9uKG1ldGhvZCwgaW5wdXQpO1xuICBpZiAoZ3JvdXAgPT09IFwiZml4dHVyZVwiKSByZXR1cm4gZml4dHVyZU9wZXJhdGlvbihtZXRob2QsIGlucHV0KTtcbiAgaWYgKGdyb3VwID09PSBcImJ1aWxkXCIpIHJldHVybiBidWlsZE9wZXJhdGlvbihtZXRob2QpO1xuICBpZiAoZ3JvdXAgPT09IFwidGVzdFwiKSByZXR1cm4gdGVzdE9wZXJhdGlvbihtZXRob2QsIGlucHV0KTtcbiAgaWYgKGdyb3VwID09PSBcImF1dGhcIikgcmV0dXJuIGF1dGhPcGVyYXRpb24obWV0aG9kLCBpbnB1dCk7XG4gIGlmIChncm91cCA9PT0gXCJpMThuXCIpIHJldHVybiBpMThuT3BlcmF0aW9uKG1ldGhvZCwgaW5wdXQpO1xuICBpZiAoZ3JvdXAgPT09IFwidGFza1wiKSByZXR1cm4gdGFza09wZXJhdGlvbihtZXRob2QsIGlucHV0KTtcbiAgaWYgKGdyb3VwID09PSBcInN0dWJcIikgcmV0dXJuIHN0dWJQcmFjdGljZU9wZXJhdGlvbihpbnB1dCk7XG4gIHJldHVybiBjZGRPcGVyYXRpb24obWV0aG9kLCBpbnB1dCk7XG59XG5cbi8vIOq4sOuzuCByZWdpc3RyeeuKlCDtmLjstpwg7Iuc7KCQ6rmM7KeAIFNvbmFtdSDstIjquLDtmZTsmYAg7Jm467aAIOyekeyXheydhCDrqqjrkZAg66+466O564uI64ukLlxuZXhwb3J0IGNvbnN0IHRvb2xpbmc6IENsaVRvb2xpbmdPcGVyYXRpb25zID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICBPYmplY3QuZW50cmllcyhSRVFVSVJFRF9NRVRIT0RTKS5tYXAoKFtncm91cCwgbWV0aG9kc10pID0+IFtcbiAgICBncm91cCxcbiAgICBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICBtZXRob2RzLm1hcCgobWV0aG9kKSA9PiBbXG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgKGlucHV0OiBDb21tYW5kSW5wdXQpID0+IGludm9rZURlZmF1bHQoZ3JvdXAsIG1ldGhvZCwgaW5wdXQpLFxuICAgICAgXSksXG4gICAgKSxcbiAgXSksXG4pO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkodG9vbGluZy5taWdyYXRpb24sIFwiYXBwbHlcIiwge1xuICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgdmFsdWU6IChpbnB1dDogQ29tbWFuZElucHV0KSA9PiBpbnZva2VEZWZhdWx0KFwibWlncmF0aW9uXCIsIFwiYXBwbHlcIiwgaW5wdXQpLFxufSk7XG4iXSwibWFwcGluZ3MiOiI7O0FBSUEsTUFBTSxrQkFBa0IsRUFBRSxLQUFLO0FBVS9CLE1BQU0sb0NBQW9CLElBQUksSUFBWTtDQUN4QztDQUNBO0NBQ0E7Q0FDQTtDQUNB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