sonamu 0.7.11 → 0.7.13

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 (153) hide show
  1. package/dist/api/config.d.ts +10 -6
  2. package/dist/api/config.d.ts.map +1 -1
  3. package/dist/api/config.js +2 -1
  4. package/dist/api/sonamu.d.ts +4 -0
  5. package/dist/api/sonamu.d.ts.map +1 -1
  6. package/dist/api/sonamu.js +49 -5
  7. package/dist/bin/cli.js +118 -170
  8. package/dist/database/base-model.d.ts +10 -50
  9. package/dist/database/base-model.d.ts.map +1 -1
  10. package/dist/database/base-model.js +19 -84
  11. package/dist/database/base-model.types.d.ts +4 -4
  12. package/dist/database/base-model.types.d.ts.map +1 -1
  13. package/dist/database/base-model.types.js +1 -1
  14. package/dist/database/db.d.ts +1 -0
  15. package/dist/database/db.d.ts.map +1 -1
  16. package/dist/database/db.js +24 -13
  17. package/dist/database/puri-subset.test-d.js +1 -1
  18. package/dist/database/puri-subset.types.d.ts +1 -0
  19. package/dist/database/puri-subset.types.d.ts.map +1 -1
  20. package/dist/database/puri-subset.types.js +2 -2
  21. package/dist/database/puri.d.ts +82 -3
  22. package/dist/database/puri.d.ts.map +1 -1
  23. package/dist/database/puri.js +180 -14
  24. package/dist/database/puri.types.d.ts +33 -6
  25. package/dist/database/puri.types.d.ts.map +1 -1
  26. package/dist/database/puri.types.js +1 -1
  27. package/dist/database/puri.types.test-d.js +1 -1
  28. package/dist/entity/entity-manager.d.ts +5 -4
  29. package/dist/entity/entity-manager.d.ts.map +1 -1
  30. package/dist/entity/entity-manager.js +8 -1
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -3
  34. package/dist/migration/code-generation.d.ts.map +1 -1
  35. package/dist/migration/code-generation.js +33 -2
  36. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  37. package/dist/migration/postgresql-schema-reader.js +53 -22
  38. package/dist/naite/messaging-types.d.ts.map +1 -1
  39. package/dist/naite/messaging-types.js +1 -1
  40. package/dist/naite/naite.js +2 -2
  41. package/dist/stream/sse.d.ts +2 -6
  42. package/dist/stream/sse.d.ts.map +1 -1
  43. package/dist/stream/sse.js +9 -3
  44. package/dist/syncer/api-parser.d.ts.map +1 -1
  45. package/dist/syncer/api-parser.js +7 -2
  46. package/dist/syncer/file-patterns.d.ts +1 -1
  47. package/dist/syncer/file-patterns.d.ts.map +1 -1
  48. package/dist/syncer/file-patterns.js +6 -5
  49. package/dist/syncer/module-loader.d.ts +5 -0
  50. package/dist/syncer/module-loader.d.ts.map +1 -1
  51. package/dist/syncer/module-loader.js +17 -1
  52. package/dist/syncer/syncer.d.ts +5 -1
  53. package/dist/syncer/syncer.d.ts.map +1 -1
  54. package/dist/syncer/syncer.js +28 -19
  55. package/dist/tasks/decorator.d.ts +26 -0
  56. package/dist/tasks/decorator.d.ts.map +1 -0
  57. package/dist/tasks/decorator.js +28 -0
  58. package/dist/tasks/step-wrapper.d.ts +18 -0
  59. package/dist/tasks/step-wrapper.d.ts.map +1 -0
  60. package/dist/tasks/step-wrapper.js +38 -0
  61. package/dist/tasks/workflow-manager.d.ts +40 -0
  62. package/dist/tasks/workflow-manager.d.ts.map +1 -0
  63. package/dist/tasks/workflow-manager.js +193 -0
  64. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  65. package/dist/template/implementations/generated.template.js +7 -3
  66. package/dist/types/types.d.ts +26 -10
  67. package/dist/types/types.d.ts.map +1 -1
  68. package/dist/types/types.js +15 -2
  69. package/dist/ui/ai-api.d.ts +1 -0
  70. package/dist/ui/ai-api.d.ts.map +1 -0
  71. package/dist/ui/ai-api.js +50 -0
  72. package/dist/ui/ai-client.d.ts +1 -0
  73. package/dist/ui/ai-client.d.ts.map +1 -0
  74. package/dist/ui/ai-client.js +438 -0
  75. package/dist/ui/api.d.ts +3 -0
  76. package/dist/ui/api.d.ts.map +1 -0
  77. package/dist/ui/api.js +680 -0
  78. package/dist/ui-web/assets/brand-icons-Cu_C0hZ4.svg +1008 -0
  79. package/dist/ui-web/assets/brand-icons-F3SPCeH1.woff +0 -0
  80. package/dist/ui-web/assets/brand-icons-XL9sxUpA.woff2 +0 -0
  81. package/dist/ui-web/assets/brand-icons-sqJ2Pg7a.eot +0 -0
  82. package/dist/ui-web/assets/brand-icons-ubhWoxly.ttf +0 -0
  83. package/dist/ui-web/assets/flags-DOLqOU7Y.png +0 -0
  84. package/dist/ui-web/assets/icons-BOCtAERH.woff +0 -0
  85. package/dist/ui-web/assets/icons-CHzK1VD9.eot +0 -0
  86. package/dist/ui-web/assets/icons-D29ZQHHw.ttf +0 -0
  87. package/dist/ui-web/assets/icons-Du6TOHnR.woff2 +0 -0
  88. package/dist/ui-web/assets/icons-RwhydX30.svg +1518 -0
  89. package/dist/ui-web/assets/index-CpaB9P6g.css +1 -0
  90. package/dist/ui-web/assets/index-J9MCfjCd.js +95 -0
  91. package/dist/ui-web/assets/outline-icons-BfdLr8tr.svg +366 -0
  92. package/dist/ui-web/assets/outline-icons-DD8jm0uy.ttf +0 -0
  93. package/dist/ui-web/assets/outline-icons-DInHoiqI.woff2 +0 -0
  94. package/dist/ui-web/assets/outline-icons-LX8adJ4n.eot +0 -0
  95. package/dist/ui-web/assets/outline-icons-aQ88nltS.woff +0 -0
  96. package/dist/ui-web/assets/provider-utils_false-BKJD46kk.js +1 -0
  97. package/dist/ui-web/assets/provider-utils_false-Bu5lmX18.js +1 -0
  98. package/dist/ui-web/index.html +13 -0
  99. package/dist/ui-web/vite.svg +1 -0
  100. package/dist/utils/formatter.d.ts.map +1 -1
  101. package/dist/utils/formatter.js +10 -2
  102. package/dist/utils/model.d.ts +9 -2
  103. package/dist/utils/model.d.ts.map +1 -1
  104. package/dist/utils/model.js +16 -1
  105. package/dist/utils/type-utils.d.ts.map +1 -1
  106. package/dist/utils/type-utils.js +3 -1
  107. package/dist/vector/embedding.d.ts +2 -5
  108. package/dist/vector/embedding.d.ts.map +1 -1
  109. package/dist/vector/embedding.js +9 -13
  110. package/dist/vector/types.d.ts.map +1 -1
  111. package/dist/vector/types.js +1 -1
  112. package/package.json +9 -5
  113. package/src/api/config.ts +15 -11
  114. package/src/api/sonamu.ts +60 -6
  115. package/src/bin/cli.ts +57 -119
  116. package/src/database/base-model.ts +21 -128
  117. package/src/database/base-model.types.ts +3 -4
  118. package/src/database/db.ts +28 -18
  119. package/src/database/puri-subset.test-d.ts +1 -0
  120. package/src/database/puri-subset.types.ts +2 -0
  121. package/src/database/puri.ts +238 -27
  122. package/src/database/puri.types.test-d.ts +1 -1
  123. package/src/database/puri.types.ts +49 -6
  124. package/src/entity/entity-manager.ts +9 -0
  125. package/src/index.ts +1 -1
  126. package/src/migration/code-generation.ts +40 -1
  127. package/src/migration/postgresql-schema-reader.ts +53 -22
  128. package/src/naite/messaging-types.ts +43 -44
  129. package/src/naite/naite.ts +1 -1
  130. package/src/shared/app.shared.ts.txt +13 -0
  131. package/src/shared/web.shared.ts.txt +13 -0
  132. package/src/stream/sse.ts +15 -3
  133. package/src/syncer/api-parser.ts +6 -1
  134. package/src/syncer/file-patterns.ts +11 -9
  135. package/src/syncer/module-loader.ts +35 -0
  136. package/src/syncer/syncer.ts +34 -21
  137. package/src/tasks/decorator.ts +71 -0
  138. package/src/tasks/step-wrapper.ts +84 -0
  139. package/src/tasks/workflow-manager.ts +330 -0
  140. package/src/template/implementations/generated.template.ts +19 -6
  141. package/src/types/types.ts +20 -4
  142. package/src/ui/ai-api.ts +60 -0
  143. package/src/ui/ai-client.ts +499 -0
  144. package/src/ui/api.ts +786 -0
  145. package/src/utils/formatter.ts +8 -1
  146. package/src/utils/model.ts +26 -2
  147. package/src/utils/type-utils.ts +2 -0
  148. package/src/vector/embedding.ts +10 -14
  149. package/src/vector/types.ts +1 -2
  150. package/dist/vector/vector-search.d.ts +0 -47
  151. package/dist/vector/vector-search.d.ts.map +0 -1
  152. package/dist/vector/vector-search.js +0 -176
  153. package/src/vector/vector-search.ts +0 -261
package/dist/ui/api.js ADDED
@@ -0,0 +1,680 @@
1
+ import { execSync } from "child_process";
2
+ import fs from "fs";
3
+ import inflection from "inflection";
4
+ import path from "path";
5
+ import { range } from "radashi";
6
+ import { Sonamu } from "../api/sonamu.js";
7
+ import { EntityManager } from "../entity/entity-manager.js";
8
+ import { BadRequestException, isSoException, ServiceUnavailableException } from "../exceptions/so-exceptions.js";
9
+ import { Migrator } from "../migration/migrator.js";
10
+ import { FixtureManager } from "../testing/fixture-manager.js";
11
+ import { TemplateKey } from "../types/types.js";
12
+ import { nonNullable } from "../utils/utils.js";
13
+ export async function sonamuUIApiPlugin(fastify) {
14
+ fastify.register(async (server)=>{
15
+ // migrator
16
+ const migrator = new Migrator();
17
+ // waitForHMRCompleted
18
+ async function waitForHMRCompleted(fn) {
19
+ const waitPromise = new Promise((resolve)=>{
20
+ const timeout = setTimeout(()=>{
21
+ resolve();
22
+ }, 1500);
23
+ const handler = ()=>{
24
+ clearTimeout(timeout);
25
+ Sonamu.syncer.eventEmitter.off("onHMRCompleted", handler);
26
+ resolve();
27
+ };
28
+ Sonamu.syncer.eventEmitter.once("onHMRCompleted", handler);
29
+ });
30
+ const result = await fn();
31
+ await waitPromise;
32
+ return result;
33
+ }
34
+ server.get("/api/sonamu/config", async ()=>{
35
+ return Sonamu.config;
36
+ });
37
+ server.get("/api/tools/openVscode", async (request)=>{
38
+ const { entityId, preset, absPath } = request.query;
39
+ const targetPath = (()=>{
40
+ if (entityId && preset) {
41
+ const entity = EntityManager.get(entityId);
42
+ const { names } = entity;
43
+ const { apiRootPath } = Sonamu;
44
+ const filename = (()=>{
45
+ switch(preset){
46
+ case "types":
47
+ return `${names.fs}.types.ts`;
48
+ case "entity.json":
49
+ return `${names.fs}.entity.json`;
50
+ case "generated":
51
+ return `${names.fs}.generated.ts`;
52
+ }
53
+ })();
54
+ return `${apiRootPath}/src/application/${entity.names.parentFs}/${filename}`;
55
+ } else {
56
+ if (!absPath) {
57
+ throw new BadRequestException("preset or absPath must be provided");
58
+ }
59
+ return absPath;
60
+ }
61
+ })();
62
+ execSync(`code ${targetPath}`);
63
+ });
64
+ server.get("/api/tools/getSuggestion", async (request)=>{
65
+ const { origin, entityId } = request.query;
66
+ // 치환 용어집
67
+ const glossary = new Map([
68
+ [
69
+ "status",
70
+ "상태"
71
+ ],
72
+ [
73
+ "type",
74
+ "타입"
75
+ ],
76
+ [
77
+ "image",
78
+ "이미지"
79
+ ],
80
+ [
81
+ "images",
82
+ "이미지리스트"
83
+ ],
84
+ [
85
+ "url",
86
+ "URL"
87
+ ],
88
+ [
89
+ "id",
90
+ "ID"
91
+ ],
92
+ [
93
+ "name",
94
+ `{EntityID}명`
95
+ ],
96
+ [
97
+ "title",
98
+ "{EntityID}명"
99
+ ],
100
+ [
101
+ "parent",
102
+ "상위{EntityID}"
103
+ ],
104
+ [
105
+ "desc",
106
+ "설명"
107
+ ],
108
+ [
109
+ "at",
110
+ "일시"
111
+ ],
112
+ [
113
+ "created",
114
+ "등록"
115
+ ],
116
+ [
117
+ "updated",
118
+ "수정"
119
+ ],
120
+ [
121
+ "deleted",
122
+ "삭제"
123
+ ],
124
+ [
125
+ "by",
126
+ "유저"
127
+ ],
128
+ [
129
+ "date",
130
+ "일자"
131
+ ],
132
+ [
133
+ "time",
134
+ "시간"
135
+ ],
136
+ [
137
+ "ko",
138
+ "(한글)"
139
+ ],
140
+ [
141
+ "en",
142
+ "(영문)"
143
+ ],
144
+ [
145
+ "krw",
146
+ "(원)"
147
+ ],
148
+ [
149
+ "usd",
150
+ "(USD)"
151
+ ],
152
+ [
153
+ "color",
154
+ "컬러"
155
+ ],
156
+ [
157
+ "code",
158
+ "코드"
159
+ ],
160
+ [
161
+ "x",
162
+ "X좌표"
163
+ ],
164
+ [
165
+ "y",
166
+ "Y좌표"
167
+ ],
168
+ [
169
+ "current",
170
+ "현재"
171
+ ],
172
+ [
173
+ "stock",
174
+ "재고"
175
+ ],
176
+ [
177
+ "total",
178
+ "총"
179
+ ],
180
+ [
181
+ "admin",
182
+ "관리자"
183
+ ],
184
+ [
185
+ "group",
186
+ "그룹"
187
+ ],
188
+ [
189
+ "item",
190
+ "아이템"
191
+ ],
192
+ [
193
+ "cnt",
194
+ "수량"
195
+ ],
196
+ [
197
+ "price",
198
+ "가격"
199
+ ],
200
+ [
201
+ "preset",
202
+ "프리셋"
203
+ ],
204
+ [
205
+ "acct",
206
+ "계좌"
207
+ ],
208
+ [
209
+ "tel",
210
+ "전화번호"
211
+ ],
212
+ [
213
+ "no",
214
+ "번호"
215
+ ],
216
+ [
217
+ "body",
218
+ "내용"
219
+ ],
220
+ [
221
+ "content",
222
+ "내용"
223
+ ],
224
+ [
225
+ "orderno",
226
+ "정렬순서"
227
+ ],
228
+ [
229
+ "priority",
230
+ "우선순위"
231
+ ],
232
+ [
233
+ "text",
234
+ "텍스트"
235
+ ],
236
+ [
237
+ "key",
238
+ "키"
239
+ ],
240
+ [
241
+ "sum",
242
+ "합산"
243
+ ],
244
+ [
245
+ "expected",
246
+ "예상"
247
+ ],
248
+ [
249
+ "actual",
250
+ "실제"
251
+ ]
252
+ ]);
253
+ // 전체 엔티티 순회하며, 엔티티 타이틀과 프롭 설명을 치환 용어집에 추가
254
+ for (const entityId of EntityManager.getAllIds()){
255
+ const entity = EntityManager.get(entityId);
256
+ if ((entity.title ?? "") !== "") {
257
+ glossary.set(inflection.underscore(entity.id), entity.title);
258
+ glossary.set(inflection.underscore(inflection.pluralize(entity.id)), `${entity.title}리스트`);
259
+ }
260
+ entity.props.forEach((prop)=>{
261
+ if (glossary.has(prop.name)) {
262
+ return;
263
+ }
264
+ if (prop.desc) {
265
+ glossary.set(prop.name, prop.desc.replace(entity.title ?? "", "{EntityID}"));
266
+ }
267
+ });
268
+ }
269
+ const suggested = (()=>{
270
+ // 단어 분리, 가능한 조합 생성
271
+ const words = origin.split("_");
272
+ const combinations = [
273
+ ...range(words.length, 0, -1)
274
+ ].flatMap((len)=>{
275
+ return [
276
+ ...range(0, words.length - len + 1, (idx)=>{
277
+ return {
278
+ len,
279
+ w: words.slice(idx, idx + len).join("_")
280
+ };
281
+ })
282
+ ];
283
+ });
284
+ // 조합을 순회하며, 치환 용어집에 있는 단어가 포함된 경우, 치환 용어로 치환
285
+ const REPLACED_PREFIX = "#REPLACED//"; // 치환된 단어를 join 이후에도 식별하기 위해 prefix 추가
286
+ let remainArr = [
287
+ ...words
288
+ ];
289
+ for (const comb of combinations){
290
+ const remainStr = remainArr.join("_");
291
+ if (remainStr.includes(comb.w) && glossary.has(comb.w)) {
292
+ remainArr = remainStr.replace(comb.w, REPLACED_PREFIX + glossary.get(comb.w)).split("_");
293
+ }
294
+ }
295
+ return remainArr.map((r)=>{
296
+ if (r.startsWith(REPLACED_PREFIX)) {
297
+ return r.replace(REPLACED_PREFIX, "");
298
+ } else {
299
+ return r.toUpperCase();
300
+ }
301
+ }).join("").replace(/{EntityID}/g, entityId ? EntityManager.get(entityId).title : "");
302
+ })();
303
+ console.log({
304
+ entityId,
305
+ origin,
306
+ suggested
307
+ });
308
+ return {
309
+ suggested
310
+ };
311
+ });
312
+ server.get("/api/entity/findMany", async ()=>{
313
+ const entityIds = EntityManager.getAllIds();
314
+ function flattenSubsetRows(subsetRows) {
315
+ return subsetRows.flatMap((subsetRow)=>{
316
+ const { children, ...sRow } = subsetRow;
317
+ return [
318
+ sRow,
319
+ ...flattenSubsetRows(children)
320
+ ];
321
+ });
322
+ }
323
+ const entities = await Promise.all(entityIds.map((entityId)=>{
324
+ const entity = EntityManager.get(entityId);
325
+ const subsetRows = entity.getSubsetRows();
326
+ return {
327
+ ...entity,
328
+ flattenSubsetRows: flattenSubsetRows(subsetRows)
329
+ };
330
+ }));
331
+ entities.sort((a, b)=>{
332
+ const aId = a.parentId ?? a.id;
333
+ const bId = b.parentId ?? b.id;
334
+ if (aId < bId) return -1;
335
+ if (aId > bId) return 1;
336
+ if (aId === bId) {
337
+ if (a.parentId === undefined) return -1;
338
+ if (b.parentId === undefined) return 1;
339
+ return 0;
340
+ }
341
+ return 0;
342
+ });
343
+ return {
344
+ entities
345
+ };
346
+ });
347
+ server.get("/api/entity/typeIds", async (request)=>{
348
+ const { filter, reload } = request.query;
349
+ if (reload === "1") {
350
+ await Sonamu.syncer.autoloadTypes();
351
+ }
352
+ const typeIds = (()=>{
353
+ const typeIds = Object.entries(Sonamu.syncer.types).filter(([_typeId, zodType])=>zodType.def.type !== "enum").map(([typeId, _zodType])=>typeId);
354
+ if (filter === "types") {
355
+ return typeIds;
356
+ }
357
+ const enumIds = EntityManager.getAllIds().flatMap((entityId)=>{
358
+ const entity = EntityManager.get(entityId);
359
+ return Object.keys(entity.enumLabels);
360
+ });
361
+ if (filter === "enums") {
362
+ return enumIds;
363
+ } else {
364
+ return [
365
+ ...typeIds,
366
+ ...enumIds
367
+ ];
368
+ }
369
+ })();
370
+ return {
371
+ typeIds
372
+ };
373
+ });
374
+ server.post("/api/entity/create", async (request)=>{
375
+ return await waitForHMRCompleted(async ()=>{
376
+ const { form } = request.body;
377
+ await Sonamu.syncer.createEntity({
378
+ ...form,
379
+ entityId: form.id
380
+ });
381
+ return 1;
382
+ });
383
+ });
384
+ server.post("/api/entity/del", async (request)=>{
385
+ return await waitForHMRCompleted(async ()=>{
386
+ const { entityId } = request.body;
387
+ return await Sonamu.syncer.delEntity(entityId);
388
+ });
389
+ });
390
+ server.post("/api/entity/modifyEntityBase", async (request)=>{
391
+ return await waitForHMRCompleted(async ()=>{
392
+ const { entityId, newValues } = request.body;
393
+ const entity = EntityManager.get(entityId);
394
+ entity.title = newValues.title;
395
+ entity.table = newValues.table;
396
+ entity.parentId = newValues.parentId;
397
+ await entity.save();
398
+ return 1;
399
+ });
400
+ });
401
+ server.post("/api/entity/modifySubset", async (request)=>{
402
+ return await waitForHMRCompleted(async ()=>{
403
+ const { entityId, subsetKey, fields } = request.body;
404
+ const entity = EntityManager.get(entityId);
405
+ entity.subsets[subsetKey] = fields;
406
+ await entity.save();
407
+ return {
408
+ updated: fields
409
+ };
410
+ });
411
+ });
412
+ server.post("/api/entity/delSubset", async (request)=>{
413
+ return await waitForHMRCompleted(async ()=>{
414
+ const { entityId, subsetKey } = request.body;
415
+ const entity = EntityManager.get(entityId);
416
+ delete entity.subsets[subsetKey];
417
+ await entity.save();
418
+ return 1;
419
+ });
420
+ });
421
+ server.post("/api/entity/createProp", async (request)=>{
422
+ return await waitForHMRCompleted(async ()=>{
423
+ const { entityId, at, newProp } = request.body;
424
+ const entity = EntityManager.get(entityId);
425
+ await entity.createProp(newProp, at);
426
+ return true;
427
+ });
428
+ });
429
+ server.post("/api/entity/modifyProp", async (request)=>{
430
+ return await waitForHMRCompleted(async ()=>{
431
+ const { entityId, at, newProp } = request.body;
432
+ const entity = EntityManager.get(entityId);
433
+ entity.modifyProp(newProp, at);
434
+ return true;
435
+ });
436
+ });
437
+ server.post("/api/entity/delProp", async (request)=>{
438
+ return await waitForHMRCompleted(async ()=>{
439
+ const { entityId, at } = request.body;
440
+ const entity = EntityManager.get(entityId);
441
+ entity.delProp(at);
442
+ return true;
443
+ });
444
+ });
445
+ server.post("/api/entity/moveProp", async (request)=>{
446
+ return await waitForHMRCompleted(async ()=>{
447
+ const { entityId, at, to } = request.body;
448
+ const entity = EntityManager.get(entityId);
449
+ entity.moveProp(at, to);
450
+ return true;
451
+ });
452
+ });
453
+ server.post("/api/entity/modifyIndexes", async (request)=>{
454
+ return await waitForHMRCompleted(async ()=>{
455
+ const { entityId, indexes } = request.body;
456
+ const entity = EntityManager.get(entityId);
457
+ entity.indexes = indexes;
458
+ await entity.save();
459
+ return {
460
+ updated: indexes
461
+ };
462
+ });
463
+ });
464
+ server.post("/api/entity/modifyEnumLabels", async (request)=>{
465
+ return await waitForHMRCompleted(async ()=>{
466
+ const { entityId, enumLabels } = request.body;
467
+ const entity = EntityManager.get(entityId);
468
+ entity.enumLabels = enumLabels;
469
+ await entity.save();
470
+ return {
471
+ updated: enumLabels
472
+ };
473
+ });
474
+ });
475
+ server.post("/api/entity/createEnumId", async (request)=>{
476
+ return await waitForHMRCompleted(async ()=>{
477
+ const { entityId, newEnumId } = request.body;
478
+ const entity = EntityManager.get(entityId);
479
+ if (entity.enumLabels[newEnumId]) {
480
+ throw new Error(`이미 존재하는 enumId입니다: ${newEnumId}`);
481
+ }
482
+ entity.enumLabels[newEnumId] = {
483
+ ...newEnumId.endsWith("Status") ? {
484
+ active: "노출",
485
+ hidden: "숨김"
486
+ } : {
487
+ "": ""
488
+ }
489
+ };
490
+ await entity.save();
491
+ return 1;
492
+ });
493
+ });
494
+ server.post("/api/entity/modifyEnumId", async (request)=>{
495
+ return await waitForHMRCompleted(async ()=>{
496
+ const { entityId, enumId } = request.body;
497
+ const entityIds = EntityManager.getAllIds();
498
+ const isExists = entityIds.some((entityId)=>{
499
+ const entity = EntityManager.get(entityId);
500
+ return Object.keys(entity.enumLabels).includes(enumId.after);
501
+ });
502
+ if (isExists) {
503
+ throw new Error(`이미 존재하는 EnumId입니다: ${enumId.after}`);
504
+ }
505
+ const entity = EntityManager.get(entityId);
506
+ entity.enumLabels[enumId.after] = entity.enumLabels[enumId.before];
507
+ delete entity.enumLabels[enumId.before];
508
+ await entity.save();
509
+ for (const entityId of entityIds){
510
+ const entity = EntityManager.get(entityId);
511
+ for (const prop of entity.props){
512
+ if (prop.type === "enum" && prop.id === enumId.before) {
513
+ prop.id = enumId.after;
514
+ }
515
+ }
516
+ await entity.save();
517
+ }
518
+ });
519
+ });
520
+ server.post("/api/entity/deleteEnumId", async (request)=>{
521
+ return await waitForHMRCompleted(async ()=>{
522
+ const { entityId, enumId } = request.body;
523
+ const entityIds = EntityManager.getAllIds();
524
+ const isReferenced = entityIds.flatMap((entityId)=>EntityManager.get(entityId).props).some((prop)=>prop.type === "enum" && prop.id === enumId);
525
+ if (isReferenced) {
526
+ throw new Error(`${enumId}를 참조하는 프로퍼티가 존재합니다.`);
527
+ }
528
+ const entity = EntityManager.get(entityId);
529
+ delete entity.enumLabels[enumId];
530
+ await entity.save();
531
+ });
532
+ });
533
+ server.get("/api/entity/getTableColumns", async (request)=>{
534
+ const { entityId } = request.query;
535
+ const entity = EntityManager.get(entityId);
536
+ const columns = entity.getTableColumns();
537
+ return {
538
+ columns
539
+ };
540
+ });
541
+ server.get("/api/migrations/status", async ()=>{
542
+ const status = await migrator.getStatus();
543
+ return {
544
+ status
545
+ };
546
+ });
547
+ server.post("/api/migrations/runAction", async (request)=>{
548
+ const { action, targets } = request.body;
549
+ if (action === "shadow") {
550
+ return migrator.runShadowTest();
551
+ } else {
552
+ return migrator.runAction(action, targets);
553
+ }
554
+ });
555
+ server.post("/api/migrations/delCodes", async (request)=>{
556
+ const { codeNames } = request.body;
557
+ return await migrator.delCodes(codeNames);
558
+ });
559
+ server.post("/api/migrations/generatePreparedCodes", async (_requestt)=>{
560
+ return await migrator.generatePreparedCodes();
561
+ });
562
+ server.post("/api/scaffolding/getStatus", async (request)=>{
563
+ const { templateGroupName, entityIds, templateKeys: _templateKeys, enumIds } = request.body;
564
+ if ((entityIds ?? []).length === 0) {
565
+ throw new BadRequestException("entityIds must be provided");
566
+ } else if ((_templateKeys ?? []).length === 0) {
567
+ throw new BadRequestException("templateKeys must be provided");
568
+ } else if (templateGroupName === "Enums" && (enumIds ?? []).length === 0) {
569
+ throw new BadRequestException("enumIds must be provided");
570
+ }
571
+ // sorting
572
+ entityIds.sort((a, b)=>a < b ? -1 : a > b ? 1 : 0);
573
+ const templateKeys = TemplateKey.options.filter((tk)=>_templateKeys.includes(tk));
574
+ const combinations = entityIds.flatMap((entityId)=>{
575
+ if (templateGroupName === "Enums") {
576
+ const entityIds = [
577
+ entityId,
578
+ ...EntityManager.getChildrenIds(entityId)
579
+ ];
580
+ const allEnumIds = entityIds.flatMap((entityId)=>Object.keys(EntityManager.get(entityId).enumLabels));
581
+ return templateKeys.flatMap((templateKey)=>allEnumIds.filter((enumId)=>enumIds.includes(enumId)).map((enumId)=>[
582
+ entityId,
583
+ templateKey,
584
+ enumId
585
+ ]));
586
+ } else {
587
+ return templateKeys.map((templateKey)=>[
588
+ entityId,
589
+ templateKey
590
+ ]);
591
+ }
592
+ });
593
+ const statuses = await Promise.all(combinations.map(async ([entityId, templateKey, enumId])=>{
594
+ const { subPath, fullPath, isExists } = await Sonamu.syncer.checkExistsGenCode(entityId, templateKey, enumId);
595
+ return {
596
+ entityId,
597
+ templateGroupName,
598
+ templateKey,
599
+ enumId,
600
+ subPath,
601
+ fullPath,
602
+ isExists
603
+ };
604
+ }));
605
+ return {
606
+ statuses
607
+ };
608
+ });
609
+ server.post("/api/scaffolding/generate", async (request)=>{
610
+ const { options } = request.body;
611
+ if (options.length === 0) {
612
+ throw new BadRequestException("options must be provided");
613
+ }
614
+ const result = await Promise.all(options.map(async ({ entityId, templateKey, enumId, overwrite })=>{
615
+ try {
616
+ return await Sonamu.syncer.generateTemplate(templateKey, {
617
+ entityId,
618
+ enumId
619
+ }, {
620
+ overwrite
621
+ });
622
+ } catch (e) {
623
+ if (isSoException(e) && e.statusCode === 541) {
624
+ return null;
625
+ } else {
626
+ console.error(e);
627
+ throw e;
628
+ }
629
+ }
630
+ }));
631
+ console.log(result);
632
+ if (result.filter(nonNullable).length === 0) {
633
+ throw new ServiceUnavailableException("이미 모든 파일이 생성된 상태입니다.");
634
+ }
635
+ return result;
636
+ });
637
+ server.post("/api/scaffolding/preview", async (request)=>{
638
+ const { option } = request.body;
639
+ try {
640
+ const { templateKey, ...templateOptions } = option;
641
+ const pathAndCodes = await Sonamu.syncer.renderTemplate(templateKey, templateOptions);
642
+ return {
643
+ pathAndCodes
644
+ };
645
+ } catch (e) {
646
+ console.error(e);
647
+ throw e;
648
+ }
649
+ });
650
+ server.post("/api/fixture", async (request)=>{
651
+ const { sourceDB, targetDB, search, duplicateCheck } = request.body;
652
+ return FixtureManager.getFixtures(sourceDB, targetDB, search, duplicateCheck);
653
+ });
654
+ server.post("/api/fixture/import", async (request)=>{
655
+ const { db, fixtures } = request.body;
656
+ return FixtureManager.insertFixtures(db, fixtures);
657
+ });
658
+ server.post("/api/fixture/addFixtureLoader", async (request)=>{
659
+ const { code } = request.body;
660
+ return FixtureManager.addFixtureLoader(code);
661
+ });
662
+ // ui-web 빌드 파일 서빙
663
+ const uiDistPath = path.resolve(import.meta.dirname, "../ui-web");
664
+ server.register(await import("@fastify/static"), {
665
+ root: path.join(uiDistPath, "assets"),
666
+ prefix: "/assets",
667
+ decorateReply: false
668
+ });
669
+ // SPA fallback - /sonamu-ui/* 경로는 전부 index.html로
670
+ server.get("*", async (_request, reply)=>{
671
+ reply.headers({
672
+ "Content-type": "text/html"
673
+ }).send(fs.readFileSync(path.resolve(import.meta.dirname, "../ui-web/index.html")).toString().replace("{{projectName}}", Sonamu.config.projectName ?? "UnknownSonamuProject"));
674
+ });
675
+ }, {
676
+ prefix: "/sonamu-ui"
677
+ });
678
+ }
679
+
680
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91aS9hcGkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHR5cGUgeyBGYXN0aWZ5SW5zdGFuY2UgfSBmcm9tIFwiZmFzdGlmeVwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyByYW5nZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpL3NvbmFtdVwiO1xuaW1wb3J0IHR5cGUgeyBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHkgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7XG4gIEJhZFJlcXVlc3RFeGNlcHRpb24sXG4gIGlzU29FeGNlcHRpb24sXG4gIFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbixcbn0gZnJvbSBcIi4uL2V4Y2VwdGlvbnMvc28tZXhjZXB0aW9uc1wiO1xuaW1wb3J0IHsgdHlwZSBNaWdyYXRpb25SZXN1bHQsIE1pZ3JhdG9yIH0gZnJvbSBcIi4uL21pZ3JhdGlvbi9taWdyYXRvclwiO1xuaW1wb3J0IHsgdHlwZSBEdXBsaWNhdGVDaGVja09wdGlvbnMsIEZpeHR1cmVNYW5hZ2VyIH0gZnJvbSBcIi4uL3Rlc3RpbmcvZml4dHVyZS1tYW5hZ2VyXCI7XG5pbXBvcnQge1xuICB0eXBlIEVudGl0eUluZGV4LFxuICB0eXBlIEVudGl0eVByb3AsXG4gIHR5cGUgRW50aXR5U3Vic2V0Um93LFxuICB0eXBlIEZpeHR1cmVSZWNvcmQsXG4gIHR5cGUgRml4dHVyZVNlYXJjaE9wdGlvbnMsXG4gIHR5cGUgRmxhdHRlblN1YnNldFJvdyxcbiAgdHlwZSBQYXRoQW5kQ29kZSxcbiAgVGVtcGxhdGVLZXksXG59IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgbm9uTnVsbGFibGUgfSBmcm9tIFwiLi4vdXRpbHMvdXRpbHNcIjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNvbmFtdVVJQXBpUGx1Z2luKGZhc3RpZnk6IEZhc3RpZnlJbnN0YW5jZSkge1xuICBmYXN0aWZ5LnJlZ2lzdGVyKFxuICAgIGFzeW5jIChzZXJ2ZXIpID0+IHtcbiAgICAgIC8vIG1pZ3JhdG9yXG4gICAgICBjb25zdCBtaWdyYXRvciA9IG5ldyBNaWdyYXRvcigpO1xuXG4gICAgICAvLyB3YWl0Rm9ySE1SQ29tcGxldGVkXG4gICAgICBhc3luYyBmdW5jdGlvbiB3YWl0Rm9ySE1SQ29tcGxldGVkPFQ+KGZuOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgICAgIGNvbnN0IHdhaXRQcm9taXNlID0gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSwgMTUwMCk7XG5cbiAgICAgICAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgU29uYW11LnN5bmNlci5ldmVudEVtaXR0ZXIub2ZmKFwib25ITVJDb21wbGV0ZWRcIiwgaGFuZGxlcik7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIFNvbmFtdS5zeW5jZXIuZXZlbnRFbWl0dGVyLm9uY2UoXCJvbkhNUkNvbXBsZXRlZFwiLCBoYW5kbGVyKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZm4oKTtcbiAgICAgICAgYXdhaXQgd2FpdFByb21pc2U7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL3NvbmFtdS9jb25maWdcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICByZXR1cm4gU29uYW11LmNvbmZpZztcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBlbnRpdHlJZD86IHN0cmluZztcbiAgICAgICAgICBwcmVzZXQ/OiBcInR5cGVzXCIgfCBcImVudGl0eS5qc29uXCIgfCBcImdlbmVyYXRlZFwiO1xuICAgICAgICAgIGFic1BhdGg/OiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvdG9vbHMvb3BlblZzY29kZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBwcmVzZXQsIGFic1BhdGggfSA9IHJlcXVlc3QucXVlcnk7XG5cbiAgICAgICAgY29uc3QgdGFyZ2V0UGF0aCA9ICgoKSA9PiB7XG4gICAgICAgICAgaWYgKGVudGl0eUlkICYmIHByZXNldCkge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgY29uc3QgeyBuYW1lcyB9ID0gZW50aXR5O1xuXG4gICAgICAgICAgICBjb25zdCB7IGFwaVJvb3RQYXRoIH0gPSBTb25hbXU7XG4gICAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9ICgoKSA9PiB7XG4gICAgICAgICAgICAgIHN3aXRjaCAocHJlc2V0KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcInR5cGVzXCI6XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYCR7bmFtZXMuZnN9LnR5cGVzLnRzYDtcbiAgICAgICAgICAgICAgICBjYXNlIFwiZW50aXR5Lmpzb25cIjpcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgJHtuYW1lcy5mc30uZW50aXR5Lmpzb25gO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJnZW5lcmF0ZWRcIjpcbiAgICAgICAgICAgICAgICAgIHJldHVybiBgJHtuYW1lcy5mc30uZ2VuZXJhdGVkLnRzYDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIHJldHVybiBgJHthcGlSb290UGF0aH0vc3JjL2FwcGxpY2F0aW9uLyR7ZW50aXR5Lm5hbWVzLnBhcmVudEZzfS8ke2ZpbGVuYW1lfWA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghYWJzUGF0aCkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgQmFkUmVxdWVzdEV4Y2VwdGlvbihcInByZXNldCBvciBhYnNQYXRoIG11c3QgYmUgcHJvdmlkZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYWJzUGF0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCk7XG4gICAgICAgIGV4ZWNTeW5jKGBjb2RlICR7dGFyZ2V0UGF0aH1gKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBvcmlnaW46IHN0cmluZztcbiAgICAgICAgICBlbnRpdHlJZD86IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS90b29scy9nZXRTdWdnZXN0aW9uXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgb3JpZ2luLCBlbnRpdHlJZCB9ID0gcmVxdWVzdC5xdWVyeTtcblxuICAgICAgICAvLyDsuZjtmZgg7Jqp7Ja07KeRXG4gICAgICAgIGNvbnN0IGdsb3NzYXJ5ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oW1xuICAgICAgICAgIFtcInN0YXR1c1wiLCBcIuyDge2DnFwiXSxcbiAgICAgICAgICBbXCJ0eXBlXCIsIFwi7YOA7J6FXCJdLFxuICAgICAgICAgIFtcImltYWdlXCIsIFwi7J2066+47KeAXCJdLFxuICAgICAgICAgIFtcImltYWdlc1wiLCBcIuydtOuvuOyngOumrOyKpO2KuFwiXSxcbiAgICAgICAgICBbXCJ1cmxcIiwgXCJVUkxcIl0sXG4gICAgICAgICAgW1wiaWRcIiwgXCJJRFwiXSxcbiAgICAgICAgICBbXCJuYW1lXCIsIGB7RW50aXR5SUR966qFYF0sXG4gICAgICAgICAgW1widGl0bGVcIiwgXCJ7RW50aXR5SUR966qFXCJdLFxuICAgICAgICAgIFtcInBhcmVudFwiLCBcIuyDgeychHtFbnRpdHlJRH1cIl0sXG4gICAgICAgICAgW1wiZGVzY1wiLCBcIuyEpOuqhVwiXSxcbiAgICAgICAgICBbXCJhdFwiLCBcIuydvOyLnFwiXSxcbiAgICAgICAgICBbXCJjcmVhdGVkXCIsIFwi65Ox66GdXCJdLFxuICAgICAgICAgIFtcInVwZGF0ZWRcIiwgXCLsiJjsoJVcIl0sXG4gICAgICAgICAgW1wiZGVsZXRlZFwiLCBcIuyCreygnFwiXSxcbiAgICAgICAgICBbXCJieVwiLCBcIuycoOyggFwiXSxcbiAgICAgICAgICBbXCJkYXRlXCIsIFwi7J287J6QXCJdLFxuICAgICAgICAgIFtcInRpbWVcIiwgXCLsi5zqsIRcIl0sXG4gICAgICAgICAgW1wia29cIiwgXCIo7ZWc6riAKVwiXSxcbiAgICAgICAgICBbXCJlblwiLCBcIijsmIHrrLgpXCJdLFxuICAgICAgICAgIFtcImtyd1wiLCBcIijsm5ApXCJdLFxuICAgICAgICAgIFtcInVzZFwiLCBcIihVU0QpXCJdLFxuICAgICAgICAgIFtcImNvbG9yXCIsIFwi7Lus65+sXCJdLFxuICAgICAgICAgIFtcImNvZGVcIiwgXCLsvZTrk5xcIl0sXG4gICAgICAgICAgW1wieFwiLCBcIljsooztkZxcIl0sXG4gICAgICAgICAgW1wieVwiLCBcIlnsooztkZxcIl0sXG4gICAgICAgICAgW1wiY3VycmVudFwiLCBcIu2YhOyerFwiXSxcbiAgICAgICAgICBbXCJzdG9ja1wiLCBcIuyerOqzoFwiXSxcbiAgICAgICAgICBbXCJ0b3RhbFwiLCBcIuy0nVwiXSxcbiAgICAgICAgICBbXCJhZG1pblwiLCBcIuq0gOumrOyekFwiXSxcbiAgICAgICAgICBbXCJncm91cFwiLCBcIuq3uOujuVwiXSxcbiAgICAgICAgICBbXCJpdGVtXCIsIFwi7JWE7J207YWcXCJdLFxuICAgICAgICAgIFtcImNudFwiLCBcIuyImOufiVwiXSxcbiAgICAgICAgICBbXCJwcmljZVwiLCBcIuqwgOqyqVwiXSxcbiAgICAgICAgICBbXCJwcmVzZXRcIiwgXCLtlITrpqzshYtcIl0sXG4gICAgICAgICAgW1wiYWNjdFwiLCBcIuqzhOyijFwiXSxcbiAgICAgICAgICBbXCJ0ZWxcIiwgXCLsoITtmZTrsojtmLhcIl0sXG4gICAgICAgICAgW1wibm9cIiwgXCLrsojtmLhcIl0sXG4gICAgICAgICAgW1wiYm9keVwiLCBcIuuCtOyaqVwiXSxcbiAgICAgICAgICBbXCJjb250ZW50XCIsIFwi64K07JqpXCJdLFxuICAgICAgICAgIFtcIm9yZGVybm9cIiwgXCLsoJXroKzsiJzshJxcIl0sXG4gICAgICAgICAgW1wicHJpb3JpdHlcIiwgXCLsmrDshKDsiJzsnIRcIl0sXG4gICAgICAgICAgW1widGV4dFwiLCBcIu2FjeyKpO2KuFwiXSxcbiAgICAgICAgICBbXCJrZXlcIiwgXCLtgqRcIl0sXG4gICAgICAgICAgW1wic3VtXCIsIFwi7ZWp7IKwXCJdLFxuICAgICAgICAgIFtcImV4cGVjdGVkXCIsIFwi7JiI7IOBXCJdLFxuICAgICAgICAgIFtcImFjdHVhbFwiLCBcIuyLpOygnFwiXSxcbiAgICAgICAgXSk7XG4gICAgICAgIC8vIOyghOyytCDsl5Tti7Dti7Ag7Iic7ZqM7ZWY66mwLCDsl5Tti7Dti7Ag7YOA7J207YuA6rO8IO2UhOuhrSDshKTrqoXsnYQg7LmY7ZmYIOyaqeyWtOynkeyXkCDstpTqsIBcbiAgICAgICAgZm9yIChjb25zdCBlbnRpdHlJZCBvZiBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpKSB7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGlmICgoZW50aXR5LnRpdGxlID8/IFwiXCIpICE9PSBcIlwiKSB7XG4gICAgICAgICAgICBnbG9zc2FyeS5zZXQoaW5mbGVjdGlvbi51bmRlcnNjb3JlKGVudGl0eS5pZCksIGVudGl0eS50aXRsZSk7XG4gICAgICAgICAgICBnbG9zc2FyeS5zZXQoXG4gICAgICAgICAgICAgIGluZmxlY3Rpb24udW5kZXJzY29yZShpbmZsZWN0aW9uLnBsdXJhbGl6ZShlbnRpdHkuaWQpKSxcbiAgICAgICAgICAgICAgYCR7ZW50aXR5LnRpdGxlfeumrOyKpO2KuGAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVudGl0eS5wcm9wcy5mb3JFYWNoKChwcm9wKSA9PiB7XG4gICAgICAgICAgICBpZiAoZ2xvc3NhcnkuaGFzKHByb3AubmFtZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHByb3AuZGVzYykge1xuICAgICAgICAgICAgICBnbG9zc2FyeS5zZXQocHJvcC5uYW1lLCBwcm9wLmRlc2MucmVwbGFjZShlbnRpdHkudGl0bGUgPz8gXCJcIiwgXCJ7RW50aXR5SUR9XCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN1Z2dlc3RlZCA9ICgoKSA9PiB7XG4gICAgICAgICAgLy8g64uo7Ja0IOu2hOumrCwg6rCA64ql7ZWcIOyhsO2VqSDsg53shLFcbiAgICAgICAgICBjb25zdCB3b3JkcyA9IG9yaWdpbi5zcGxpdChcIl9cIik7XG4gICAgICAgICAgY29uc3QgY29tYmluYXRpb25zID0gWy4uLnJhbmdlKHdvcmRzLmxlbmd0aCwgMCwgLTEpXS5mbGF0TWFwKChsZW4pID0+IHtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgIC4uLnJhbmdlKDAsIHdvcmRzLmxlbmd0aCAtIGxlbiArIDEsIChpZHgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgbGVuLFxuICAgICAgICAgICAgICAgICAgdzogd29yZHMuc2xpY2UoaWR4LCBpZHggKyBsZW4pLmpvaW4oXCJfXCIpLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIOyhsO2VqeydhCDsiJztmoztlZjrqbAsIOy5mO2ZmCDsmqnslrTsp5Hsl5Ag7J6I64qUIOuLqOyWtOqwgCDtj6ztlajrkJwg6rK97JqwLCDsuZjtmZgg7Jqp7Ja066GcIOy5mO2ZmFxuICAgICAgICAgIGNvbnN0IFJFUExBQ0VEX1BSRUZJWCA9IFwiI1JFUExBQ0VELy9cIjsgLy8g7LmY7ZmY65CcIOuLqOyWtOulvCBqb2luIOydtO2bhOyXkOuPhCDsi53rs4TtlZjquLAg7JyE7ZW0IHByZWZpeCDstpTqsIBcbiAgICAgICAgICBsZXQgcmVtYWluQXJyOiBzdHJpbmdbXSA9IFsuLi53b3Jkc107XG4gICAgICAgICAgZm9yIChjb25zdCBjb21iIG9mIGNvbWJpbmF0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluU3RyID0gcmVtYWluQXJyLmpvaW4oXCJfXCIpO1xuICAgICAgICAgICAgaWYgKHJlbWFpblN0ci5pbmNsdWRlcyhjb21iLncpICYmIGdsb3NzYXJ5Lmhhcyhjb21iLncpKSB7XG4gICAgICAgICAgICAgIHJlbWFpbkFyciA9IHJlbWFpblN0clxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKGNvbWIudywgUkVQTEFDRURfUFJFRklYICsgZ2xvc3NhcnkuZ2V0KGNvbWIudykpXG4gICAgICAgICAgICAgICAgLnNwbGl0KFwiX1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcmVtYWluQXJyXG4gICAgICAgICAgICAubWFwKChyKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChyLnN0YXJ0c1dpdGgoUkVQTEFDRURfUFJFRklYKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByLnJlcGxhY2UoUkVQTEFDRURfUFJFRklYLCBcIlwiKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gci50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oXCJcIilcbiAgICAgICAgICAgIC5yZXBsYWNlKC97RW50aXR5SUR9L2csIGVudGl0eUlkID8gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpLnRpdGxlIDogXCJcIik7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgY29uc29sZS5sb2coeyBlbnRpdHlJZCwgb3JpZ2luLCBzdWdnZXN0ZWQgfSk7XG4gICAgICAgIHJldHVybiB7IHN1Z2dlc3RlZCB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5nZXQoXCIvYXBpL2VudGl0eS9maW5kTWFueVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVudGl0eUlkcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG5cbiAgICAgICAgZnVuY3Rpb24gZmxhdHRlblN1YnNldFJvd3Moc3Vic2V0Um93czogRW50aXR5U3Vic2V0Um93W10pOiBGbGF0dGVuU3Vic2V0Um93W10ge1xuICAgICAgICAgIHJldHVybiBzdWJzZXRSb3dzLmZsYXRNYXAoKHN1YnNldFJvdykgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBjaGlsZHJlbiwgLi4uc1JvdyB9ID0gc3Vic2V0Um93O1xuICAgICAgICAgICAgcmV0dXJuIFtzUm93LCAuLi5mbGF0dGVuU3Vic2V0Um93cyhjaGlsZHJlbildO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZW50aXRpZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICBlbnRpdHlJZHMubWFwKChlbnRpdHlJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgY29uc3Qgc3Vic2V0Um93cyA9IGVudGl0eS5nZXRTdWJzZXRSb3dzKCk7XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIC4uLmVudGl0eSxcbiAgICAgICAgICAgICAgZmxhdHRlblN1YnNldFJvd3M6IGZsYXR0ZW5TdWJzZXRSb3dzKHN1YnNldFJvd3MpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICBlbnRpdGllcy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgY29uc3QgYUlkID0gYS5wYXJlbnRJZCA/PyBhLmlkO1xuICAgICAgICAgIGNvbnN0IGJJZCA9IGIucGFyZW50SWQgPz8gYi5pZDtcbiAgICAgICAgICBpZiAoYUlkIDwgYklkKSByZXR1cm4gLTE7XG4gICAgICAgICAgaWYgKGFJZCA+IGJJZCkgcmV0dXJuIDE7XG4gICAgICAgICAgaWYgKGFJZCA9PT0gYklkKSB7XG4gICAgICAgICAgICBpZiAoYS5wYXJlbnRJZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gLTE7XG4gICAgICAgICAgICBpZiAoYi5wYXJlbnRJZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gMTtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IGVudGl0aWVzIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldDx7XG4gICAgICAgIFF1ZXJ5c3RyaW5nOiB7XG4gICAgICAgICAgZmlsdGVyPzogXCJlbnVtc1wiIHwgXCJ0eXBlc1wiO1xuICAgICAgICAgIHJlbG9hZD86IFwiMVwiO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS90eXBlSWRzXCIsIGFzeW5jIChyZXF1ZXN0KTogUHJvbWlzZTx7IHR5cGVJZHM6IHN0cmluZ1tdIH0+ID0+IHtcbiAgICAgICAgY29uc3QgeyBmaWx0ZXIsIHJlbG9hZCB9ID0gcmVxdWVzdC5xdWVyeTtcblxuICAgICAgICBpZiAocmVsb2FkID09PSBcIjFcIikge1xuICAgICAgICAgIGF3YWl0IFNvbmFtdS5zeW5jZXIuYXV0b2xvYWRUeXBlcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdHlwZUlkcyA9ICgoKSA9PiB7XG4gICAgICAgICAgY29uc3QgdHlwZUlkcyA9IE9iamVjdC5lbnRyaWVzKFNvbmFtdS5zeW5jZXIudHlwZXMpXG4gICAgICAgICAgICAuZmlsdGVyKChbX3R5cGVJZCwgem9kVHlwZV0pID0+ICh6b2RUeXBlLmRlZi50eXBlIGFzIHN0cmluZykgIT09IFwiZW51bVwiKVxuICAgICAgICAgICAgLm1hcCgoW3R5cGVJZCwgX3pvZFR5cGVdKSA9PiB0eXBlSWQpO1xuXG4gICAgICAgICAgaWYgKGZpbHRlciA9PT0gXCJ0eXBlc1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gdHlwZUlkcztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBlbnVtSWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKS5mbGF0TWFwKChlbnRpdHlJZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGVudGl0eS5lbnVtTGFiZWxzKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmIChmaWx0ZXIgPT09IFwiZW51bXNcIikge1xuICAgICAgICAgICAgcmV0dXJuIGVudW1JZHM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBbLi4udHlwZUlkcywgLi4uZW51bUlkc107XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZUlkcyxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBmb3JtOiB7XG4gICAgICAgICAgICBpZDogc3RyaW5nO1xuICAgICAgICAgICAgdGl0bGU6IHN0cmluZztcbiAgICAgICAgICAgIHRhYmxlOiBzdHJpbmc7XG4gICAgICAgICAgICBwYXJlbnRJZD86IHN0cmluZztcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9jcmVhdGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZm9ybSB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGF3YWl0IFNvbmFtdS5zeW5jZXIuY3JlYXRlRW50aXR5KHsgLi4uZm9ybSwgZW50aXR5SWQ6IGZvcm0uaWQgfSk7XG5cbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvZGVsXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IFNvbmFtdS5zeW5jZXIuZGVsRW50aXR5KGVudGl0eUlkKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBuZXdWYWx1ZXM6IHtcbiAgICAgICAgICAgIHRpdGxlOiBzdHJpbmc7XG4gICAgICAgICAgICB0YWJsZTogc3RyaW5nO1xuICAgICAgICAgICAgcGFyZW50SWQ/OiBzdHJpbmc7XG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5RW50aXR5QmFzZVwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgbmV3VmFsdWVzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS50aXRsZSA9IG5ld1ZhbHVlcy50aXRsZTtcbiAgICAgICAgICBlbnRpdHkudGFibGUgPSBuZXdWYWx1ZXMudGFibGU7XG4gICAgICAgICAgZW50aXR5LnBhcmVudElkID0gbmV3VmFsdWVzLnBhcmVudElkO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBzdWJzZXRLZXk6IHN0cmluZztcbiAgICAgICAgICBmaWVsZHM6IHN0cmluZ1tdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9tb2RpZnlTdWJzZXRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIHN1YnNldEtleSwgZmllbGRzIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5zdWJzZXRzW3N1YnNldEtleV0gPSBmaWVsZHM7XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiB7IHVwZGF0ZWQ6IGZpZWxkcyB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIHN1YnNldEtleTogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9kZWxTdWJzZXRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIHN1YnNldEtleSB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBkZWxldGUgZW50aXR5LnN1YnNldHNbc3Vic2V0S2V5XTtcbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgbmV3UHJvcDogRW50aXR5UHJvcDtcbiAgICAgICAgICBhdD86IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvY3JlYXRlUHJvcFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgYXQsIG5ld1Byb3AgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgYXdhaXQgZW50aXR5LmNyZWF0ZVByb3AobmV3UHJvcCwgYXQpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIG5ld1Byb3A6IEVudGl0eVByb3A7XG4gICAgICAgICAgYXQ6IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5UHJvcFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgYXQsIG5ld1Byb3AgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBlbnRpdHkubW9kaWZ5UHJvcChuZXdQcm9wLCBhdCk7XG5cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBhdDogbnVtYmVyO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9kZWxQcm9wXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBhdCB9ID0gcmVxdWVzdC5ib2R5O1xuXG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgIGVudGl0eS5kZWxQcm9wKGF0KTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBhdDogbnVtYmVyO1xuICAgICAgICAgIHRvOiBudW1iZXI7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L21vdmVQcm9wXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBhdCwgdG8gfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBlbnRpdHkubW92ZVByb3AoYXQsIHRvKTtcblxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICAgIGluZGV4ZXM6IEVudGl0eUluZGV4W107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L21vZGlmeUluZGV4ZXNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHdhaXRGb3JITVJDb21wbGV0ZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgZW50aXR5SWQsIGluZGV4ZXMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5LmluZGV4ZXMgPSBpbmRleGVzO1xuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICByZXR1cm4geyB1cGRhdGVkOiBpbmRleGVzIH07XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgZW51bUxhYmVsczogRW50aXR5W1wiZW51bUxhYmVsc1wiXTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5RW51bUxhYmVsc1wiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgZW51bUxhYmVscyB9ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBlbnRpdHkuZW51bUxhYmVscyA9IGVudW1MYWJlbHM7XG4gICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcblxuICAgICAgICAgIHJldHVybiB7IHVwZGF0ZWQ6IGVudW1MYWJlbHMgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3Q8e1xuICAgICAgICBCb2R5OiB7XG4gICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICBuZXdFbnVtSWQ6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvY3JlYXRlRW51bUlkXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBuZXdFbnVtSWQgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG5cbiAgICAgICAgICBpZiAoZW50aXR5LmVudW1MYWJlbHNbbmV3RW51bUlkXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDsnbTrr7gg7KG07J6s7ZWY64qUIGVudW1JZOyeheuLiOuLpDogJHtuZXdFbnVtSWR9YCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZW50aXR5LmVudW1MYWJlbHNbbmV3RW51bUlkXSA9IHtcbiAgICAgICAgICAgIC4uLihuZXdFbnVtSWQuZW5kc1dpdGgoXCJTdGF0dXNcIilcbiAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICBhY3RpdmU6IFwi64W47LacXCIsXG4gICAgICAgICAgICAgICAgICBoaWRkZW46IFwi7Iio6rmAXCIsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgIFwiXCI6IFwiXCIsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgZW51bUlkOiB7XG4gICAgICAgICAgICBiZWZvcmU6IHN0cmluZztcbiAgICAgICAgICAgIGFmdGVyOiBzdHJpbmc7XG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9lbnRpdHkvbW9kaWZ5RW51bUlkXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB3YWl0Rm9ySE1SQ29tcGxldGVkKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGVudGl0eUlkLCBlbnVtSWQgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgICBjb25zdCBlbnRpdHlJZHMgPSBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpO1xuICAgICAgICAgIGNvbnN0IGlzRXhpc3RzID0gZW50aXR5SWRzLnNvbWUoKGVudGl0eUlkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoZW50aXR5LmVudW1MYWJlbHMpLmluY2x1ZGVzKGVudW1JZC5hZnRlcik7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKGlzRXhpc3RzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOydtOuvuCDsobTsnqztlZjripQgRW51bUlk7J6F64uI64ukOiAke2VudW1JZC5hZnRlcn1gKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgICAgICAgZW50aXR5LmVudW1MYWJlbHNbZW51bUlkLmFmdGVyXSA9IGVudGl0eS5lbnVtTGFiZWxzW2VudW1JZC5iZWZvcmVdO1xuICAgICAgICAgIGRlbGV0ZSBlbnRpdHkuZW51bUxhYmVsc1tlbnVtSWQuYmVmb3JlXTtcblxuICAgICAgICAgIGF3YWl0IGVudGl0eS5zYXZlKCk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IGVudGl0eUlkIG9mIGVudGl0eUlkcykge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwcm9wIG9mIGVudGl0eS5wcm9wcykge1xuICAgICAgICAgICAgICBpZiAocHJvcC50eXBlID09PSBcImVudW1cIiAmJiBwcm9wLmlkID09PSBlbnVtSWQuYmVmb3JlKSB7XG4gICAgICAgICAgICAgICAgcHJvcC5pZCA9IGVudW1JZC5hZnRlcjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgZW50aXR5LnNhdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgZW51bUlkOiBzdHJpbmc7XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvZW50aXR5L2RlbGV0ZUVudW1JZFwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgd2FpdEZvckhNUkNvbXBsZXRlZChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBlbnRpdHlJZCwgZW51bUlkIH0gPSByZXF1ZXN0LmJvZHk7XG5cbiAgICAgICAgICBjb25zdCBlbnRpdHlJZHMgPSBFbnRpdHlNYW5hZ2VyLmdldEFsbElkcygpO1xuICAgICAgICAgIGNvbnN0IGlzUmVmZXJlbmNlZCA9IGVudGl0eUlkc1xuICAgICAgICAgICAgLmZsYXRNYXAoKGVudGl0eUlkKSA9PiBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkucHJvcHMpXG4gICAgICAgICAgICAuc29tZSgocHJvcCkgPT4gcHJvcC50eXBlID09PSBcImVudW1cIiAmJiBwcm9wLmlkID09PSBlbnVtSWQpO1xuICAgICAgICAgIGlmIChpc1JlZmVyZW5jZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtlbnVtSWR966W8IOywuOyhsO2VmOuKlCDtlITroZztjbzti7DqsIAg7KG07J6s7ZWp64uI64ukLmApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbiAgICAgICAgICBkZWxldGUgZW50aXR5LmVudW1MYWJlbHNbZW51bUlkXTtcbiAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIuZ2V0PHtcbiAgICAgICAgUXVlcnlzdHJpbmc6IHtcbiAgICAgICAgICBlbnRpdHlJZDogc3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL2VudGl0eS9nZXRUYWJsZUNvbHVtbnNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBlbnRpdHlJZCB9ID0gcmVxdWVzdC5xdWVyeTtcbiAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgICAgICBjb25zdCBjb2x1bW5zID0gZW50aXR5LmdldFRhYmxlQ29sdW1ucygpO1xuICAgICAgICByZXR1cm4geyBjb2x1bW5zIH07XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLmdldChcIi9hcGkvbWlncmF0aW9ucy9zdGF0dXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCBtaWdyYXRvci5nZXRTdGF0dXMoKTtcblxuICAgICAgICByZXR1cm4geyBzdGF0dXMgfTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBhY3Rpb246IFwiYXBwbHlcIiB8IFwicm9sbGJhY2tcIiB8IFwic2hhZG93XCI7XG4gICAgICAgICAgdGFyZ2V0czogKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL21pZ3JhdGlvbnMvcnVuQWN0aW9uXCIsIGFzeW5jIChyZXF1ZXN0KTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQ+ID0+IHtcbiAgICAgICAgY29uc3QgeyBhY3Rpb24sIHRhcmdldHMgfSA9IHJlcXVlc3QuYm9keTtcblxuICAgICAgICBpZiAoYWN0aW9uID09PSBcInNoYWRvd1wiKSB7XG4gICAgICAgICAgcmV0dXJuIG1pZ3JhdG9yLnJ1blNoYWRvd1Rlc3QoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gbWlncmF0b3IucnVuQWN0aW9uKGFjdGlvbiwgdGFyZ2V0cyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBjb2RlTmFtZXM6IHN0cmluZ1tdO1xuICAgICAgICB9O1xuICAgICAgfT4oXCIvYXBpL21pZ3JhdGlvbnMvZGVsQ29kZXNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBjb2RlTmFtZXMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG1pZ3JhdG9yLmRlbENvZGVzKGNvZGVOYW1lcyk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3QoXCIvYXBpL21pZ3JhdGlvbnMvZ2VuZXJhdGVQcmVwYXJlZENvZGVzXCIsIGFzeW5jIChfcmVxdWVzdHQpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG1pZ3JhdG9yLmdlbmVyYXRlUHJlcGFyZWRDb2RlcygpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIHRlbXBsYXRlR3JvdXBOYW1lOiBcIkVudGl0eVwiIHwgXCJFbnVtc1wiO1xuICAgICAgICAgIGVudGl0eUlkczogc3RyaW5nW107XG4gICAgICAgICAgdGVtcGxhdGVLZXlzOiBzdHJpbmdbXTtcbiAgICAgICAgICBlbnVtSWRzOiBzdHJpbmdbXTtcbiAgICAgICAgfTtcbiAgICAgIH0+KFwiL2FwaS9zY2FmZm9sZGluZy9nZXRTdGF0dXNcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyB0ZW1wbGF0ZUdyb3VwTmFtZSwgZW50aXR5SWRzLCB0ZW1wbGF0ZUtleXM6IF90ZW1wbGF0ZUtleXMsIGVudW1JZHMgfSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgaWYgKChlbnRpdHlJZHMgPz8gW10pLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFwiZW50aXR5SWRzIG11c3QgYmUgcHJvdmlkZWRcIik7XG4gICAgICAgIH0gZWxzZSBpZiAoKF90ZW1wbGF0ZUtleXMgPz8gW10pLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFwidGVtcGxhdGVLZXlzIG11c3QgYmUgcHJvdmlkZWRcIik7XG4gICAgICAgIH0gZWxzZSBpZiAodGVtcGxhdGVHcm91cE5hbWUgPT09IFwiRW51bXNcIiAmJiAoZW51bUlkcyA/PyBbXSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24oXCJlbnVtSWRzIG11c3QgYmUgcHJvdmlkZWRcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzb3J0aW5nXG4gICAgICAgIGVudGl0eUlkcy5zb3J0KChhLCBiKSA9PiAoYSA8IGIgPyAtMSA6IGEgPiBiID8gMSA6IDApKTtcbiAgICAgICAgY29uc3QgdGVtcGxhdGVLZXlzID0gVGVtcGxhdGVLZXkub3B0aW9ucy5maWx0ZXIoKHRrKSA9PiBfdGVtcGxhdGVLZXlzLmluY2x1ZGVzKHRrKSk7XG5cbiAgICAgICAgY29uc3QgY29tYmluYXRpb25zID0gZW50aXR5SWRzLmZsYXRNYXAoKGVudGl0eUlkKSA9PiB7XG4gICAgICAgICAgaWYgKHRlbXBsYXRlR3JvdXBOYW1lID09PSBcIkVudW1zXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eUlkcyA9IFtlbnRpdHlJZCwgLi4uRW50aXR5TWFuYWdlci5nZXRDaGlsZHJlbklkcyhlbnRpdHlJZCldO1xuICAgICAgICAgICAgY29uc3QgYWxsRW51bUlkcyA9IGVudGl0eUlkcy5mbGF0TWFwKChlbnRpdHlJZCkgPT5cbiAgICAgICAgICAgICAgT2JqZWN0LmtleXMoRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpLmVudW1MYWJlbHMpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZUtleXMuZmxhdE1hcCgodGVtcGxhdGVLZXkpID0+XG4gICAgICAgICAgICAgIGFsbEVudW1JZHNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKChlbnVtSWQpID0+IGVudW1JZHMuaW5jbHVkZXMoZW51bUlkKSlcbiAgICAgICAgICAgICAgICAubWFwKChlbnVtSWQpID0+IFtlbnRpdHlJZCwgdGVtcGxhdGVLZXksIGVudW1JZF0pLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlS2V5cy5tYXAoKHRlbXBsYXRlS2V5KSA9PiBbZW50aXR5SWQsIHRlbXBsYXRlS2V5XSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIGNvbWJpbmF0aW9ucy5tYXAoYXN5bmMgKFtlbnRpdHlJZCwgdGVtcGxhdGVLZXksIGVudW1JZF0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgc3ViUGF0aCwgZnVsbFBhdGgsIGlzRXhpc3RzIH0gPSBhd2FpdCBTb25hbXUuc3luY2VyLmNoZWNrRXhpc3RzR2VuQ29kZShcbiAgICAgICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgICAgIHRlbXBsYXRlS2V5IGFzIFRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgICBlbnVtSWQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgICAgIHRlbXBsYXRlR3JvdXBOYW1lLFxuICAgICAgICAgICAgICB0ZW1wbGF0ZUtleSxcbiAgICAgICAgICAgICAgZW51bUlkLFxuICAgICAgICAgICAgICBzdWJQYXRoLFxuICAgICAgICAgICAgICBmdWxsUGF0aCxcbiAgICAgICAgICAgICAgaXNFeGlzdHMsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyBzdGF0dXNlcyB9O1xuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0PHtcbiAgICAgICAgQm9keToge1xuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgICB0ZW1wbGF0ZUtleTogc3RyaW5nO1xuICAgICAgICAgICAgZW51bUlkPzogc3RyaW5nO1xuICAgICAgICAgICAgb3ZlcndyaXRlPzogYm9vbGVhbjtcbiAgICAgICAgICB9W107XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvc2NhZmZvbGRpbmcvZ2VuZXJhdGVcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBvcHRpb25zIH0gPSByZXF1ZXN0LmJvZHk7XG4gICAgICAgIGlmIChvcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBCYWRSZXF1ZXN0RXhjZXB0aW9uKFwib3B0aW9ucyBtdXN0IGJlIHByb3ZpZGVkXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgb3B0aW9ucy5tYXAoYXN5bmMgKHsgZW50aXR5SWQsIHRlbXBsYXRlS2V5LCBlbnVtSWQsIG92ZXJ3cml0ZSB9KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgU29uYW11LnN5bmNlci5nZW5lcmF0ZVRlbXBsYXRlKFxuICAgICAgICAgICAgICAgIHRlbXBsYXRlS2V5IGFzIFRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGVudGl0eUlkLFxuICAgICAgICAgICAgICAgICAgZW51bUlkLFxuICAgICAgICAgICAgICAgIH0gYXMge1xuICAgICAgICAgICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbiAgICAgICAgICAgICAgICAgIGVudW1JZD86IHN0cmluZztcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICBpZiAoaXNTb0V4Y2VwdGlvbihlKSAmJiBlLnN0YXR1c0NvZGUgPT09IDU0MSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgICBjb25zb2xlLmxvZyhyZXN1bHQpO1xuXG4gICAgICAgIGlmIChyZXN1bHQuZmlsdGVyKG5vbk51bGxhYmxlKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFwi7J2066+4IOuqqOuToCDtjIzsnbzsnbQg7IOd7ISx65CcIOyDge2DnOyeheuLiOuLpC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdDx7XG4gICAgICAgIEJvZHk6IHtcbiAgICAgICAgICBvcHRpb246IHtcbiAgICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4gICAgICAgICAgICB0ZW1wbGF0ZUtleTogc3RyaW5nO1xuICAgICAgICAgICAgZW51bUlkPzogc3RyaW5nO1xuICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICB9PihcIi9hcGkvc2NhZmZvbGRpbmcvcHJldmlld1wiLCBhc3luYyAocmVxdWVzdCk6IFByb21pc2U8eyBwYXRoQW5kQ29kZXM6IFBhdGhBbmRDb2RlW10gfT4gPT4ge1xuICAgICAgICBjb25zdCB7IG9wdGlvbiB9ID0gcmVxdWVzdC5ib2R5O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyB0ZW1wbGF0ZUtleSwgLi4udGVtcGxhdGVPcHRpb25zIH0gPSBvcHRpb247XG4gICAgICAgICAgY29uc3QgcGF0aEFuZENvZGVzID0gYXdhaXQgU29uYW11LnN5bmNlci5yZW5kZXJUZW1wbGF0ZShcbiAgICAgICAgICAgIHRlbXBsYXRlS2V5IGFzIFRlbXBsYXRlS2V5LFxuICAgICAgICAgICAgdGVtcGxhdGVPcHRpb25zLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICByZXR1cm4geyBwYXRoQW5kQ29kZXMgfTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHNlcnZlci5wb3N0KFwiL2FwaS9maXh0dXJlXCIsIGFzeW5jIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgc291cmNlREIsIHRhcmdldERCLCBzZWFyY2gsIGR1cGxpY2F0ZUNoZWNrIH0gPSByZXF1ZXN0LmJvZHkgYXMge1xuICAgICAgICAgIHNvdXJjZURCOiBrZXlvZiBTb25hbXVEQkNvbmZpZztcbiAgICAgICAgICB0YXJnZXREQjoga2V5b2YgU29uYW11REJDb25maWc7XG4gICAgICAgICAgc2VhcmNoOiBGaXh0dXJlU2VhcmNoT3B0aW9ucztcbiAgICAgICAgICBkdXBsaWNhdGVDaGVjaz86IER1cGxpY2F0ZUNoZWNrT3B0aW9ucztcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gRml4dHVyZU1hbmFnZXIuZ2V0Rml4dHVyZXMoc291cmNlREIsIHRhcmdldERCLCBzZWFyY2gsIGR1cGxpY2F0ZUNoZWNrKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZXJ2ZXIucG9zdChcIi9hcGkvZml4dHVyZS9pbXBvcnRcIiwgYXN5bmMgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgY29uc3QgeyBkYiwgZml4dHVyZXMgfSA9IHJlcXVlc3QuYm9keSBhcyB7XG4gICAgICAgICAgZGI6IGtleW9mIFNvbmFtdURCQ29uZmlnO1xuICAgICAgICAgIGZpeHR1cmVzOiBGaXh0dXJlUmVjb3JkW107XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIEZpeHR1cmVNYW5hZ2VyLmluc2VydEZpeHR1cmVzKGRiLCBmaXh0dXJlcyk7XG4gICAgICB9KTtcblxuICAgICAgc2VydmVyLnBvc3QoXCIvYXBpL2ZpeHR1cmUvYWRkRml4dHVyZUxvYWRlclwiLCBhc3luYyAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB7IGNvZGUgfSA9IHJlcXVlc3QuYm9keSBhcyB7IGNvZGU6IHN0cmluZyB9O1xuXG4gICAgICAgIHJldHVybiBGaXh0dXJlTWFuYWdlci5hZGRGaXh0dXJlTG9hZGVyKGNvZGUpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHVpLXdlYiDruYzrk5wg7YyM7J28IOyEnOu5mVxuICAgICAgY29uc3QgdWlEaXN0UGF0aCA9IHBhdGgucmVzb2x2ZShpbXBvcnQubWV0YS5kaXJuYW1lLCBcIi4uL3VpLXdlYlwiKTtcbiAgICAgIHNlcnZlci5yZWdpc3Rlcihhd2FpdCBpbXBvcnQoXCJAZmFzdGlmeS9zdGF0aWNcIiksIHtcbiAgICAgICAgcm9vdDogcGF0aC5qb2luKHVpRGlzdFBhdGgsIFwiYXNzZXRzXCIpLFxuICAgICAgICBwcmVmaXg6IFwiL2Fzc2V0c1wiLFxuICAgICAgICBkZWNvcmF0ZVJlcGx5OiBmYWxzZSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBTUEEgZmFsbGJhY2sgLSAvc29uYW11LXVpLyog6rK966Gc64qUIOyghOu2gCBpbmRleC5odG1s66GcXG4gICAgICBzZXJ2ZXIuZ2V0KFwiKlwiLCBhc3luYyAoX3JlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIHJlcGx5LmhlYWRlcnMoeyBcIkNvbnRlbnQtdHlwZVwiOiBcInRleHQvaHRtbFwiIH0pLnNlbmQoXG4gICAgICAgICAgZnNcbiAgICAgICAgICAgIC5yZWFkRmlsZVN5bmMocGF0aC5yZXNvbHZlKGltcG9ydC5tZXRhLmRpcm5hbWUsIFwiLi4vdWktd2ViL2luZGV4Lmh0bWxcIikpXG4gICAgICAgICAgICAudG9TdHJpbmcoKVxuICAgICAgICAgICAgLnJlcGxhY2UoXCJ7e3Byb2plY3ROYW1lfX1cIiwgU29uYW11LmNvbmZpZy5wcm9qZWN0TmFtZSA/PyBcIlVua25vd25Tb25hbXVQcm9qZWN0XCIpLFxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSxcbiAgICB7IHByZWZpeDogXCIvc29uYW11LXVpXCIgfSxcbiAgKTtcbn1cbiJdLCJuYW1lcyI6WyJleGVjU3luYyIsImZzIiwiaW5mbGVjdGlvbiIsInBhdGgiLCJyYW5nZSIsIlNvbmFtdSIsIkVudGl0eU1hbmFnZXIiLCJCYWRSZXF1ZXN0RXhjZXB0aW9uIiwiaXNTb0V4Y2VwdGlvbiIsIlNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiIsIk1pZ3JhdG9yIiwiRml4dHVyZU1hbmFnZXIiLCJUZW1wbGF0ZUtleSIsIm5vbk51bGxhYmxlIiwic29uYW11VUlBcGlQbHVnaW4iLCJmYXN0aWZ5IiwicmVnaXN0ZXIiLCJzZXJ2ZXIiLCJtaWdyYXRvciIsIndhaXRGb3JITVJDb21wbGV0ZWQiLCJmbiIsIndhaXRQcm9taXNlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aW1lb3V0Iiwic2V0VGltZW91dCIsImhhbmRsZXIiLCJjbGVhclRpbWVvdXQiLCJzeW5jZXIiLCJldmVudEVtaXR0ZXIiLCJvZmYiLCJvbmNlIiwicmVzdWx0IiwiZ2V0IiwiY29uZmlnIiwicmVxdWVzdCIsImVudGl0eUlkIiwicHJlc2V0IiwiYWJzUGF0aCIsInF1ZXJ5IiwidGFyZ2V0UGF0aCIsImVudGl0eSIsIm5hbWVzIiwiYXBpUm9vdFBhdGgiLCJmaWxlbmFtZSIsInBhcmVudEZzIiwib3JpZ2luIiwiZ2xvc3NhcnkiLCJNYXAiLCJnZXRBbGxJZHMiLCJ0aXRsZSIsInNldCIsInVuZGVyc2NvcmUiLCJpZCIsInBsdXJhbGl6ZSIsInByb3BzIiwiZm9yRWFjaCIsInByb3AiLCJoYXMiLCJuYW1lIiwiZGVzYyIsInJlcGxhY2UiLCJzdWdnZXN0ZWQiLCJ3b3JkcyIsInNwbGl0IiwiY29tYmluYXRpb25zIiwibGVuZ3RoIiwiZmxhdE1hcCIsImxlbiIsImlkeCIsInciLCJzbGljZSIsImpvaW4iLCJSRVBMQUNFRF9QUkVGSVgiLCJyZW1haW5BcnIiLCJjb21iIiwicmVtYWluU3RyIiwiaW5jbHVkZXMiLCJtYXAiLCJyIiwic3RhcnRzV2l0aCIsInRvVXBwZXJDYXNlIiwiY29uc29sZSIsImxvZyIsImVudGl0eUlkcyIsImZsYXR0ZW5TdWJzZXRSb3dzIiwic3Vic2V0Um93cyIsInN1YnNldFJvdyIsImNoaWxkcmVuIiwic1JvdyIsImVudGl0aWVzIiwiYWxsIiwiZ2V0U3Vic2V0Um93cyIsInNvcnQiLCJhIiwiYiIsImFJZCIsInBhcmVudElkIiwiYklkIiwidW5kZWZpbmVkIiwiZmlsdGVyIiwicmVsb2FkIiwiYXV0b2xvYWRUeXBlcyIsInR5cGVJZHMiLCJPYmplY3QiLCJlbnRyaWVzIiwidHlwZXMiLCJfdHlwZUlkIiwiem9kVHlwZSIsImRlZiIsInR5cGUiLCJ0eXBlSWQiLCJfem9kVHlwZSIsImVudW1JZHMiLCJrZXlzIiwiZW51bUxhYmVscyIsInBvc3QiLCJmb3JtIiwiYm9keSIsImNyZWF0ZUVudGl0eSIsImRlbEVudGl0eSIsIm5ld1ZhbHVlcyIsInRhYmxlIiwic2F2ZSIsInN1YnNldEtleSIsImZpZWxkcyIsInN1YnNldHMiLCJ1cGRhdGVkIiwiYXQiLCJuZXdQcm9wIiwiY3JlYXRlUHJvcCIsIm1vZGlmeVByb3AiLCJkZWxQcm9wIiwidG8iLCJtb3ZlUHJvcCIsImluZGV4ZXMiLCJuZXdFbnVtSWQiLCJFcnJvciIsImVuZHNXaXRoIiwiYWN0aXZlIiwiaGlkZGVuIiwiZW51bUlkIiwiaXNFeGlzdHMiLCJzb21lIiwiYWZ0ZXIiLCJiZWZvcmUiLCJpc1JlZmVyZW5jZWQiLCJjb2x1bW5zIiwiZ2V0VGFibGVDb2x1bW5zIiwic3RhdHVzIiwiZ2V0U3RhdHVzIiwiYWN0aW9uIiwidGFyZ2V0cyIsInJ1blNoYWRvd1Rlc3QiLCJydW5BY3Rpb24iLCJjb2RlTmFtZXMiLCJkZWxDb2RlcyIsIl9yZXF1ZXN0dCIsImdlbmVyYXRlUHJlcGFyZWRDb2RlcyIsInRlbXBsYXRlR3JvdXBOYW1lIiwidGVtcGxhdGVLZXlzIiwiX3RlbXBsYXRlS2V5cyIsIm9wdGlvbnMiLCJ0ayIsImdldENoaWxkcmVuSWRzIiwiYWxsRW51bUlkcyIsInRlbXBsYXRlS2V5Iiwic3RhdHVzZXMiLCJzdWJQYXRoIiwiZnVsbFBhdGgiLCJjaGVja0V4aXN0c0dlbkNvZGUiLCJvdmVyd3JpdGUiLCJnZW5lcmF0ZVRlbXBsYXRlIiwiZSIsInN0YXR1c0NvZGUiLCJlcnJvciIsIm9wdGlvbiIsInRlbXBsYXRlT3B0aW9ucyIsInBhdGhBbmRDb2RlcyIsInJlbmRlclRlbXBsYXRlIiwic291cmNlREIiLCJ0YXJnZXREQiIsInNlYXJjaCIsImR1cGxpY2F0ZUNoZWNrIiwiZ2V0Rml4dHVyZXMiLCJkYiIsImZpeHR1cmVzIiwiaW5zZXJ0Rml4dHVyZXMiLCJjb2RlIiwiYWRkRml4dHVyZUxvYWRlciIsInVpRGlzdFBhdGgiLCJkaXJuYW1lIiwicm9vdCIsInByZWZpeCIsImRlY29yYXRlUmVwbHkiLCJfcmVxdWVzdCIsInJlcGx5IiwiaGVhZGVycyIsInNlbmQiLCJyZWFkRmlsZVN5bmMiLCJ0b1N0cmluZyIsInByb2plY3ROYW1lIl0s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