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.
- package/dist/api/config.d.ts +10 -6
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +2 -1
- package/dist/api/sonamu.d.ts +4 -0
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +49 -5
- package/dist/bin/cli.js +118 -170
- package/dist/database/base-model.d.ts +10 -50
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +19 -84
- package/dist/database/base-model.types.d.ts +4 -4
- package/dist/database/base-model.types.d.ts.map +1 -1
- package/dist/database/base-model.types.js +1 -1
- package/dist/database/db.d.ts +1 -0
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +24 -13
- package/dist/database/puri-subset.test-d.js +1 -1
- package/dist/database/puri-subset.types.d.ts +1 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -1
- package/dist/database/puri-subset.types.js +2 -2
- package/dist/database/puri.d.ts +82 -3
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +180 -14
- package/dist/database/puri.types.d.ts +33 -6
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +1 -1
- package/dist/database/puri.types.test-d.js +1 -1
- package/dist/entity/entity-manager.d.ts +5 -4
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +8 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +33 -2
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +53 -22
- package/dist/naite/messaging-types.d.ts.map +1 -1
- package/dist/naite/messaging-types.js +1 -1
- package/dist/naite/naite.js +2 -2
- package/dist/stream/sse.d.ts +2 -6
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +9 -3
- package/dist/syncer/api-parser.d.ts.map +1 -1
- package/dist/syncer/api-parser.js +7 -2
- package/dist/syncer/file-patterns.d.ts +1 -1
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +6 -5
- package/dist/syncer/module-loader.d.ts +5 -0
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +17 -1
- package/dist/syncer/syncer.d.ts +5 -1
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +28 -19
- package/dist/tasks/decorator.d.ts +26 -0
- package/dist/tasks/decorator.d.ts.map +1 -0
- package/dist/tasks/decorator.js +28 -0
- package/dist/tasks/step-wrapper.d.ts +18 -0
- package/dist/tasks/step-wrapper.d.ts.map +1 -0
- package/dist/tasks/step-wrapper.js +38 -0
- package/dist/tasks/workflow-manager.d.ts +40 -0
- package/dist/tasks/workflow-manager.d.ts.map +1 -0
- package/dist/tasks/workflow-manager.js +193 -0
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +7 -3
- package/dist/types/types.d.ts +26 -10
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +15 -2
- package/dist/ui/ai-api.d.ts +1 -0
- package/dist/ui/ai-api.d.ts.map +1 -0
- package/dist/ui/ai-api.js +50 -0
- package/dist/ui/ai-client.d.ts +1 -0
- package/dist/ui/ai-client.d.ts.map +1 -0
- package/dist/ui/ai-client.js +438 -0
- package/dist/ui/api.d.ts +3 -0
- package/dist/ui/api.d.ts.map +1 -0
- package/dist/ui/api.js +680 -0
- package/dist/ui-web/assets/brand-icons-Cu_C0hZ4.svg +1008 -0
- package/dist/ui-web/assets/brand-icons-F3SPCeH1.woff +0 -0
- package/dist/ui-web/assets/brand-icons-XL9sxUpA.woff2 +0 -0
- package/dist/ui-web/assets/brand-icons-sqJ2Pg7a.eot +0 -0
- package/dist/ui-web/assets/brand-icons-ubhWoxly.ttf +0 -0
- package/dist/ui-web/assets/flags-DOLqOU7Y.png +0 -0
- package/dist/ui-web/assets/icons-BOCtAERH.woff +0 -0
- package/dist/ui-web/assets/icons-CHzK1VD9.eot +0 -0
- package/dist/ui-web/assets/icons-D29ZQHHw.ttf +0 -0
- package/dist/ui-web/assets/icons-Du6TOHnR.woff2 +0 -0
- package/dist/ui-web/assets/icons-RwhydX30.svg +1518 -0
- package/dist/ui-web/assets/index-CpaB9P6g.css +1 -0
- package/dist/ui-web/assets/index-J9MCfjCd.js +95 -0
- package/dist/ui-web/assets/outline-icons-BfdLr8tr.svg +366 -0
- package/dist/ui-web/assets/outline-icons-DD8jm0uy.ttf +0 -0
- package/dist/ui-web/assets/outline-icons-DInHoiqI.woff2 +0 -0
- package/dist/ui-web/assets/outline-icons-LX8adJ4n.eot +0 -0
- package/dist/ui-web/assets/outline-icons-aQ88nltS.woff +0 -0
- package/dist/ui-web/assets/provider-utils_false-BKJD46kk.js +1 -0
- package/dist/ui-web/assets/provider-utils_false-Bu5lmX18.js +1 -0
- package/dist/ui-web/index.html +13 -0
- package/dist/ui-web/vite.svg +1 -0
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +10 -2
- package/dist/utils/model.d.ts +9 -2
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/model.js +16 -1
- package/dist/utils/type-utils.d.ts.map +1 -1
- package/dist/utils/type-utils.js +3 -1
- package/dist/vector/embedding.d.ts +2 -5
- package/dist/vector/embedding.d.ts.map +1 -1
- package/dist/vector/embedding.js +9 -13
- package/dist/vector/types.d.ts.map +1 -1
- package/dist/vector/types.js +1 -1
- package/package.json +9 -5
- package/src/api/config.ts +15 -11
- package/src/api/sonamu.ts +60 -6
- package/src/bin/cli.ts +57 -119
- package/src/database/base-model.ts +21 -128
- package/src/database/base-model.types.ts +3 -4
- package/src/database/db.ts +28 -18
- package/src/database/puri-subset.test-d.ts +1 -0
- package/src/database/puri-subset.types.ts +2 -0
- package/src/database/puri.ts +238 -27
- package/src/database/puri.types.test-d.ts +1 -1
- package/src/database/puri.types.ts +49 -6
- package/src/entity/entity-manager.ts +9 -0
- package/src/index.ts +1 -1
- package/src/migration/code-generation.ts +40 -1
- package/src/migration/postgresql-schema-reader.ts +53 -22
- package/src/naite/messaging-types.ts +43 -44
- package/src/naite/naite.ts +1 -1
- package/src/shared/app.shared.ts.txt +13 -0
- package/src/shared/web.shared.ts.txt +13 -0
- package/src/stream/sse.ts +15 -3
- package/src/syncer/api-parser.ts +6 -1
- package/src/syncer/file-patterns.ts +11 -9
- package/src/syncer/module-loader.ts +35 -0
- package/src/syncer/syncer.ts +34 -21
- package/src/tasks/decorator.ts +71 -0
- package/src/tasks/step-wrapper.ts +84 -0
- package/src/tasks/workflow-manager.ts +330 -0
- package/src/template/implementations/generated.template.ts +19 -6
- package/src/types/types.ts +20 -4
- package/src/ui/ai-api.ts +60 -0
- package/src/ui/ai-client.ts +499 -0
- package/src/ui/api.ts +786 -0
- package/src/utils/formatter.ts +8 -1
- package/src/utils/model.ts +26 -2
- package/src/utils/type-utils.ts +2 -0
- package/src/vector/embedding.ts +10 -14
- package/src/vector/types.ts +1 -2
- package/dist/vector/vector-search.d.ts +0 -47
- package/dist/vector/vector-search.d.ts.map +0 -1
- package/dist/vector/vector-search.js +0 -176
- 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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
|