sonamu 0.7.21 → 0.7.23

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 (200) hide show
  1. package/dist/ai/agents/agent.d.ts +6 -1
  2. package/dist/ai/agents/agent.d.ts.map +1 -1
  3. package/dist/ai/agents/agent.js +20 -5
  4. package/dist/api/base-frame.d.ts +4 -0
  5. package/dist/api/base-frame.d.ts.map +1 -1
  6. package/dist/api/base-frame.js +9 -1
  7. package/dist/api/caster.d.ts.map +1 -1
  8. package/dist/api/caster.js +2 -2
  9. package/dist/api/config.d.ts +35 -3
  10. package/dist/api/config.d.ts.map +1 -1
  11. package/dist/api/config.js +1 -1
  12. package/dist/api/decorators.d.ts +4 -4
  13. package/dist/api/decorators.d.ts.map +1 -1
  14. package/dist/api/decorators.js +80 -18
  15. package/dist/api/index.d.ts +1 -0
  16. package/dist/api/index.d.ts.map +1 -1
  17. package/dist/api/index.js +2 -1
  18. package/dist/api/secret.d.ts +7 -0
  19. package/dist/api/secret.d.ts.map +1 -0
  20. package/dist/api/secret.js +17 -0
  21. package/dist/api/sonamu.d.ts +17 -8
  22. package/dist/api/sonamu.d.ts.map +1 -1
  23. package/dist/api/sonamu.js +265 -47
  24. package/dist/cache/cache-manager.d.ts +11 -0
  25. package/dist/cache/cache-manager.d.ts.map +1 -0
  26. package/dist/cache/cache-manager.js +22 -0
  27. package/dist/cache/decorator.d.ts +31 -0
  28. package/dist/cache/decorator.d.ts.map +1 -0
  29. package/dist/cache/decorator.js +86 -0
  30. package/dist/cache/drivers.d.ts +33 -0
  31. package/dist/cache/drivers.d.ts.map +1 -0
  32. package/dist/cache/drivers.js +36 -0
  33. package/dist/cache/index.d.ts +4 -0
  34. package/dist/cache/index.d.ts.map +1 -0
  35. package/dist/cache/index.js +8 -0
  36. package/dist/cache/types.d.ts +28 -0
  37. package/dist/cache/types.d.ts.map +1 -0
  38. package/dist/cache/types.js +6 -0
  39. package/dist/database/base-model.d.ts +4 -2
  40. package/dist/database/base-model.d.ts.map +1 -1
  41. package/dist/database/base-model.js +9 -4
  42. package/dist/database/code-generator.d.ts +3 -1
  43. package/dist/database/code-generator.d.ts.map +1 -1
  44. package/dist/database/code-generator.js +3 -2
  45. package/dist/database/db.d.ts +1 -1
  46. package/dist/database/db.d.ts.map +1 -1
  47. package/dist/database/db.js +5 -5
  48. package/dist/database/knex.d.ts +3 -0
  49. package/dist/database/knex.d.ts.map +1 -0
  50. package/dist/database/knex.js +29 -0
  51. package/dist/database/puri.types.d.ts.map +1 -1
  52. package/dist/database/puri.types.js +1 -1
  53. package/dist/database/upsert-builder.d.ts.map +1 -1
  54. package/dist/database/upsert-builder.js +49 -5
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +4 -1
  58. package/dist/logger/category.d.ts +4 -0
  59. package/dist/logger/category.d.ts.map +1 -0
  60. package/dist/logger/category.js +34 -0
  61. package/dist/logger/configure.d.ts +9 -0
  62. package/dist/logger/configure.d.ts.map +1 -0
  63. package/dist/logger/configure.js +115 -0
  64. package/dist/migration/code-generation.d.ts +5 -1
  65. package/dist/migration/code-generation.d.ts.map +1 -1
  66. package/dist/migration/code-generation.js +13 -7
  67. package/dist/migration/migrator.d.ts +1 -1
  68. package/dist/migration/migrator.d.ts.map +1 -1
  69. package/dist/migration/migrator.js +7 -7
  70. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  71. package/dist/migration/postgresql-schema-reader.js +5 -3
  72. package/dist/naite/naite.d.ts +0 -4
  73. package/dist/naite/naite.d.ts.map +1 -1
  74. package/dist/naite/naite.js +11 -19
  75. package/dist/ssr/index.d.ts +4 -0
  76. package/dist/ssr/index.d.ts.map +1 -0
  77. package/dist/ssr/index.js +4 -0
  78. package/dist/ssr/registry.d.ts +10 -0
  79. package/dist/ssr/registry.d.ts.map +1 -0
  80. package/dist/ssr/registry.js +43 -0
  81. package/dist/ssr/renderer.d.ts +6 -0
  82. package/dist/ssr/renderer.d.ts.map +1 -0
  83. package/dist/ssr/renderer.js +70 -0
  84. package/dist/ssr/types.d.ts +19 -0
  85. package/dist/ssr/types.d.ts.map +1 -0
  86. package/dist/ssr/types.js +4 -0
  87. package/dist/syncer/syncer.d.ts +1 -0
  88. package/dist/syncer/syncer.d.ts.map +1 -1
  89. package/dist/syncer/syncer.js +58 -1
  90. package/dist/tasks/decorator.d.ts +1 -0
  91. package/dist/tasks/decorator.d.ts.map +1 -1
  92. package/dist/tasks/decorator.js +9 -7
  93. package/dist/tasks/step-wrapper.d.ts +5 -0
  94. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  95. package/dist/tasks/step-wrapper.js +11 -6
  96. package/dist/tasks/workflow-manager.d.ts +2 -0
  97. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  98. package/dist/tasks/workflow-manager.js +5 -2
  99. package/dist/template/implementations/entry-server.template.d.ts +17 -0
  100. package/dist/template/implementations/entry-server.template.d.ts.map +1 -0
  101. package/dist/template/implementations/entry-server.template.js +78 -0
  102. package/dist/template/implementations/model.template.d.ts.map +1 -1
  103. package/dist/template/implementations/model.template.js +5 -3
  104. package/dist/template/implementations/queries.template.d.ts +17 -0
  105. package/dist/template/implementations/queries.template.d.ts.map +1 -0
  106. package/dist/template/implementations/queries.template.js +83 -0
  107. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
  108. package/dist/template/implementations/view_enums_select.template.js +34 -20
  109. package/dist/template/implementations/view_form.template.d.ts +2 -1
  110. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  111. package/dist/template/implementations/view_form.template.js +301 -129
  112. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
  113. package/dist/template/implementations/view_id_async_select.template.js +136 -57
  114. package/dist/template/implementations/view_list.template.d.ts +2 -0
  115. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  116. package/dist/template/implementations/view_list.template.js +392 -227
  117. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  118. package/dist/template/implementations/view_search_input.template.js +46 -30
  119. package/dist/template/zod-converter.d.ts.map +1 -1
  120. package/dist/template/zod-converter.js +2 -2
  121. package/dist/testing/bootstrap.d.ts +28 -0
  122. package/dist/testing/bootstrap.d.ts.map +1 -0
  123. package/dist/testing/bootstrap.js +120 -0
  124. package/dist/testing/fixture-loader.d.ts +21 -0
  125. package/dist/testing/fixture-loader.d.ts.map +1 -0
  126. package/dist/testing/fixture-loader.js +28 -0
  127. package/dist/testing/fixture-manager.d.ts +1 -1
  128. package/dist/testing/fixture-manager.d.ts.map +1 -1
  129. package/dist/testing/fixture-manager.js +7 -7
  130. package/dist/testing/index.d.ts +4 -0
  131. package/dist/testing/index.d.ts.map +1 -0
  132. package/dist/testing/index.js +5 -0
  133. package/dist/testing/naite-vitest-reporter.d.ts +12 -0
  134. package/dist/testing/naite-vitest-reporter.d.ts.map +1 -0
  135. package/dist/testing/naite-vitest-reporter.js +17 -0
  136. package/dist/types/types.d.ts +5 -6
  137. package/dist/types/types.d.ts.map +1 -1
  138. package/dist/types/types.js +7 -8
  139. package/dist/ui/ai-client.d.ts +3 -1
  140. package/dist/ui/ai-client.d.ts.map +1 -1
  141. package/dist/ui/ai-client.js +27 -8
  142. package/dist/ui-web/assets/index-CTYv3qL6.js +92 -0
  143. package/dist/ui-web/index.html +1 -1
  144. package/package.json +43 -20
  145. package/src/ai/agents/agent.ts +38 -19
  146. package/src/api/base-frame.ts +8 -0
  147. package/src/api/caster.ts +6 -1
  148. package/src/api/config.ts +38 -4
  149. package/src/api/decorators.ts +106 -20
  150. package/src/api/index.ts +1 -0
  151. package/src/api/secret.ts +23 -0
  152. package/src/api/sonamu.ts +334 -61
  153. package/src/cache/cache-manager.ts +23 -0
  154. package/src/cache/decorator.ts +116 -0
  155. package/src/cache/drivers.ts +42 -0
  156. package/src/cache/index.ts +16 -0
  157. package/src/cache/types.ts +32 -0
  158. package/src/database/base-model.ts +7 -3
  159. package/src/database/code-generator.ts +3 -1
  160. package/src/database/db.ts +5 -5
  161. package/src/database/knex.ts +34 -0
  162. package/src/database/puri.types.ts +2 -3
  163. package/src/database/upsert-builder.ts +58 -4
  164. package/src/index.ts +4 -0
  165. package/src/logger/category.ts +42 -0
  166. package/src/logger/configure.ts +132 -0
  167. package/src/migration/code-generation.ts +19 -6
  168. package/src/migration/migrator.ts +7 -6
  169. package/src/migration/postgresql-schema-reader.ts +7 -2
  170. package/src/naite/naite.ts +10 -18
  171. package/src/shared/web.shared.ts.txt +1 -1
  172. package/src/ssr/index.ts +13 -0
  173. package/src/ssr/registry.ts +52 -0
  174. package/src/ssr/renderer.ts +105 -0
  175. package/src/ssr/types.ts +20 -0
  176. package/src/syncer/syncer.ts +59 -0
  177. package/src/tasks/decorator.ts +20 -4
  178. package/src/tasks/step-wrapper.ts +14 -5
  179. package/src/tasks/workflow-manager.ts +9 -1
  180. package/src/template/implementations/entry-server.template.ts +81 -0
  181. package/src/template/implementations/model.template.ts +4 -2
  182. package/src/template/implementations/queries.template.ts +111 -0
  183. package/src/template/implementations/view_enums_select.template.ts +33 -19
  184. package/src/template/implementations/view_form.template.ts +324 -145
  185. package/src/template/implementations/view_id_async_select.template.ts +145 -56
  186. package/src/template/implementations/view_list.template.ts +446 -236
  187. package/src/template/implementations/view_search_input.template.ts +45 -29
  188. package/src/template/zod-converter.ts +4 -1
  189. package/src/testing/bootstrap.ts +176 -0
  190. package/src/testing/fixture-loader.ts +28 -0
  191. package/src/testing/fixture-manager.ts +7 -6
  192. package/src/testing/index.ts +3 -0
  193. package/src/testing/naite-vitest-reporter.ts +18 -0
  194. package/src/types/types.ts +4 -5
  195. package/src/ui/ai-client.ts +82 -50
  196. package/dist/template/implementations/view_enums_dropdown.template.d.ts +0 -17
  197. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +0 -1
  198. package/dist/template/implementations/view_enums_dropdown.template.js +0 -50
  199. package/dist/ui-web/assets/index-B87IyofX.js +0 -92
  200. package/src/template/implementations/view_enums_dropdown.template.ts +0 -53
@@ -1,19 +1,16 @@
1
- import assert from "assert";
2
1
  import inflection from "inflection";
3
- import { flat, unique } from "radashi";
2
+ import { flat } from "radashi";
4
3
  import { z } from "zod";
5
4
  import { EntityManager } from "../../entity/entity-manager.js";
6
- import { getColumnsNode } from "../entity-converter.js";
7
5
  import { getEnumInfoFromColName, getRelationPropFromColName } from "../helpers.js";
8
6
  import { Template } from "../template.js";
9
- import { getZodTypeById, zodTypeToRenderingNode } from "../zod-converter.js";
10
7
  export class Template__view_list extends Template {
11
8
  constructor(){
12
9
  super("view_list");
13
10
  }
14
11
  getTargetAndPath(names) {
15
12
  return {
16
- target: "web/src/pages/admin",
13
+ target: "web/src/routes/admin",
17
14
  path: `${names.fsPlural}/index.tsx`
18
15
  };
19
16
  }
@@ -21,7 +18,17 @@ export class Template__view_list extends Template {
21
18
  return `<Table.Cell key="${key}"${collapsing ? " collapsing" : ""}${className ? ` className={\`${className}\`}` : ""}>${body}</Table.Cell>`;
22
19
  }
23
20
  renderColumn(entityId, col, names, parentObj = "row", withoutName = false) {
24
- const colName = withoutName ? `${parentObj}` : `${parentObj}.${col.name}`;
21
+ // 중첩 경로 처리 (예: "user.name" -> "row.user?.name")
22
+ let colName;
23
+ if (withoutName) {
24
+ colName = parentObj;
25
+ } else if (col.name.includes(".")) {
26
+ // 중첩 경로는 optional chaining으로 변환
27
+ const parts = col.name.split(".");
28
+ colName = `${parentObj}.${parts.join("?.")}`;
29
+ } else {
30
+ colName = `${parentObj}.${col.name}`;
31
+ }
25
32
  switch(col.renderType){
26
33
  case "string-plain":
27
34
  case "string-date":
@@ -29,36 +36,45 @@ export class Template__view_list extends Template {
29
36
  return `<>{${colName}}</>`;
30
37
  case "number-fk_id":
31
38
  {
32
- const relPropFk = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
33
- return `<>${relPropFk.with}#{${colName}}</>`;
39
+ try {
40
+ const baseName = col.name.includes(".") ? (col.name.split(".").pop() ?? col.name).replace("_id", "") : col.name.replace("_id", "");
41
+ const relPropFk = getRelationPropFromColName(entityId, baseName);
42
+ return `<>${relPropFk.with}#{${colName}}</>`;
43
+ } catch {
44
+ return `<>{${colName}}</>`;
45
+ }
34
46
  }
35
47
  case "string-image":
36
- return `<>{${col.nullable ? `${colName} && ` : ""}<img src={${colName}} />}</>`;
48
+ return `<>{${col.nullable ? `${colName} && ` : ""}<img src={${colName}} alt="${col.label ?? col.name}" className="h-8 w-8 object-cover rounded" />}</>`;
37
49
  case "datetime":
38
- if (col.nullable) {
39
- return `<span className="text-tiny">{${colName} === null ? '-' : formatDateTime(${colName})}</span>`;
50
+ if (col.nullable || col.name.includes(".")) {
51
+ return `<span>{${colName} ? datetimeF(${colName}) : '-'}</span>`;
40
52
  } else {
41
- return `<span className="text-tiny">{formatDateTime(${colName})}</span>`;
53
+ return `<span>{datetimeF(${colName})}</span>`;
42
54
  }
43
55
  case "string-datetime":
44
- if (col.nullable) {
45
- return `<span className="text-tiny">{${colName} === null ? '-' : dateF(${colName})}</span>`;
56
+ if (col.nullable || col.name.includes(".")) {
57
+ return `<span>{${colName} ? dateF(${colName}) : '-'}</span>`;
46
58
  } else {
47
- return `<span className="text-tiny">{dateF(${colName})}</span>`;
59
+ return `<span>{dateF(${colName})}</span>`;
48
60
  }
49
61
  case "boolean":
50
- return `<>{${colName} ? <Label color='green' circular>O</Label> : <Label color='grey' circular>X</Label> }</>`;
62
+ return `<>{${colName} ? <Badge variant="default">O</Badge> : <Badge variant="secondary">X</Badge>}</>`;
51
63
  case "enums":
52
64
  {
53
- const { id: enumId } = getEnumInfoFromColName(entityId, col.name);
54
- return `<>{${col.nullable ? `${colName} && ` : ""}${enumId}Label[${colName}]}</>`;
65
+ try {
66
+ const { id: enumId } = getEnumInfoFromColName(entityId, col.name);
67
+ return `<>{${col.nullable ? `${colName} && ` : ""}${enumId}Label[${colName}]}</>`;
68
+ } catch {
69
+ return `<>{${colName}}</>`;
70
+ }
55
71
  }
56
72
  case "array-images":
57
- return `<>{ ${colName}.map(r => ${col.nullable ? `r && ` : ""}<img src={r} />) }</>`;
73
+ return `<div className="flex gap-1">{ ${colName}?.map((r, i) => ${col.nullable ? `r && ` : ""}<img key={i} src={r} alt={\`${col.label ?? col.name} \${i + 1}\`} className="h-8 w-8 object-cover rounded" />) }</div>`;
58
74
  case "number-plain":
59
- return `<>{${col.nullable ? `${colName} && ` : ""}numF(${colName})}</>`;
75
+ return `<>{${col.nullable || col.name.includes(".") ? `${colName} && ` : ""}numF(${colName})}</>`;
60
76
  case "object":
61
- return `<>{/* object ${colName} */}</>`;
77
+ return `<span className="text-xs">{${col.nullable ? `${colName} ? ` : ""}JSON.stringify(${colName})${col.nullable ? ` : '-'` : ""}}</span>`;
62
78
  case "object-pick":
63
79
  {
64
80
  const pickedChild = col.children?.find((child)=>child.name === col.config?.picked);
@@ -85,19 +101,21 @@ export class Template__view_list extends Template {
85
101
  } else if (col.renderType === "object") {
86
102
  try {
87
103
  const relProp = getRelationPropFromColName(entityId, col.name);
88
- const result = col.children?.map((child)=>{
104
+ const result = (col.children ?? []).map((child)=>{
89
105
  entityId = relProp.with;
90
106
  names = EntityManager.getNamesFromId(relProp.with);
91
107
  return this.renderColumnImport(entityId, child, names);
92
108
  });
93
- return flat(result ?? []);
109
+ return flat(result);
94
110
  } catch {
95
111
  return [
96
112
  null
97
113
  ];
98
114
  }
99
115
  } else if (col.renderType === "array") {
100
- assert(col.element);
116
+ if (!col.element) return [
117
+ null
118
+ ];
101
119
  return this.renderColumnImport(entityId, col.element, names);
102
120
  }
103
121
  return [
@@ -165,32 +183,41 @@ export class Template__view_list extends Template {
165
183
  }
166
184
  getDefault(columns) {
167
185
  const def = {
168
- orderBy: "id-desc",
169
- search: "title"
186
+ orderBy: "",
187
+ search: "",
188
+ hasSearch: false,
189
+ hasOrderBy: false
170
190
  };
171
191
  const orderByZodType = columns.find((col)=>col.name === "orderBy")?.zodType;
172
192
  if (orderByZodType && orderByZodType instanceof z.ZodEnum) {
173
- def.orderBy = orderByZodType.options[0].toString();
193
+ def.orderBy = Object.keys(orderByZodType.enum)[0];
194
+ def.hasOrderBy = true;
174
195
  }
175
196
  const searchZodType = columns.find((col)=>col.name === "search")?.zodType;
176
197
  if (searchZodType && searchZodType instanceof z.ZodEnum) {
177
- def.search = searchZodType.options[0].toString();
198
+ def.search = Object.keys(searchZodType.enum)[0];
199
+ def.hasSearch = true;
178
200
  }
179
201
  return def;
180
202
  }
181
203
  async render({ entityId }) {
204
+ const { getColumnsNode } = await import("../entity-converter.js");
205
+ const { getZodTypeById, zodTypeToRenderingNode } = await import("../zod-converter.js");
182
206
  const columnsNode = await getColumnsNode(entityId, "A");
183
207
  const listParamsZodType = await getZodTypeById(`${entityId}ListParams`);
184
208
  const listParamsNode = zodTypeToRenderingNode(listParamsZodType);
185
209
  const names = EntityManager.getNamesFromId(entityId);
186
210
  const entity = EntityManager.get(entityId);
187
211
  // 실제 리스트 컬럼
188
- const columns = columnsNode.children.filter((col)=>col.name !== "id").map((col)=>{
212
+ const columns = columnsNode.children.sort((a, b)=>a.name === "id" ? -1 : b.name === "id" ? 1 : 0).map((col)=>{
189
213
  const propCandidate = entity.props.find((p)=>p.name === col.name);
214
+ const rendered = this.renderColumn(entityId, col, names);
190
215
  return {
191
216
  name: col.name,
192
- label: propCandidate?.desc ?? col.label,
193
- tc: `(row) => ${this.renderColumn(entityId, col, names)}`
217
+ label: col.name === "id" ? "ID" : propCandidate?.desc ?? col.label,
218
+ tc: `(row) => ${rendered}`,
219
+ fit: col.renderType === "number-id" || col.renderType === "datetime" || col.renderType === "string-datetime",
220
+ align: col.renderType === "number-id" ? "center" : undefined
194
221
  };
195
222
  });
196
223
  // 필터 컬럼
@@ -209,17 +236,23 @@ export class Template__view_list extends Template {
209
236
  let enumId;
210
237
  if (col.renderType === "enums") {
211
238
  if (col.name === "search") {
212
- key = "view_enums_dropdown";
239
+ key = "view_enums_select";
213
240
  enumId = `${names.capital}SearchField`;
214
241
  targetEntityId = names.capital;
215
242
  } else {
216
243
  key = "view_enums_select";
217
- try {
218
- const { targetEntityNames, id } = getEnumInfoFromColName(entityId, col.name);
219
- targetEntityId = targetEntityNames.capital;
220
- enumId = id;
221
- } catch {
222
- continue;
244
+ // config.enumId 우선 사용
245
+ if (col.config && "enumId" in col.config) {
246
+ enumId = col.config.enumId;
247
+ targetEntityId = entityId;
248
+ } else {
249
+ try {
250
+ const { targetEntityNames, id } = getEnumInfoFromColName(entityId, col.name);
251
+ targetEntityId = targetEntityNames.capital;
252
+ enumId = id;
253
+ } catch {
254
+ continue;
255
+ }
223
256
  }
224
257
  }
225
258
  } else {
@@ -239,232 +272,364 @@ export class Template__view_list extends Template {
239
272
  }
240
273
  });
241
274
  }
242
- // 리스트 컬럼
243
- assert(columnsNode.children);
244
- const columnImports = unique(columnsNode.children.flatMap((col)=>{
245
- return this.renderColumnImport(entityId, col, names);
246
- }).filter((col)=>col !== null)).join("\n");
275
+ // 컬럼에서 사용하는 enum들 수집
276
+ const columnEnums = [];
277
+ (columnsNode.children ?? []).forEach((col)=>{
278
+ if (col.renderType === "enums") {
279
+ try {
280
+ const { id: enumId } = getEnumInfoFromColName(entityId, col.name);
281
+ columnEnums.push(enumId);
282
+ } catch {}
283
+ }
284
+ });
247
285
  // SearchInput
248
- assert(preTemplates);
249
- preTemplates.push({
286
+ preTemplates?.push({
250
287
  key: "view_search_input",
251
288
  options: {
252
289
  entityId
253
290
  }
254
291
  });
255
292
  // 디폴트 파라미터
256
- const def = this.getDefault(filterColumns);
293
+ // const def = this.getDefault(filterColumns);
257
294
  return {
258
295
  ...this.getTargetAndPath(names),
259
296
  body: `
260
- import React from 'react';
261
- import { Link } from 'react-router-dom';
262
- import {
263
- Breadcrumb,
264
- Checkbox,
265
- Pagination,
266
- Segment,
267
- Table,
268
- TableRow,
269
- Message,
270
- Transition,
271
- Button,
272
- Label,
273
- } from 'semantic-ui-react';
274
- import classNames from 'classnames';
275
- import { DateTime } from "luxon";
276
- import { DelButton, EditButton, AppBreadcrumbs, AddButton, useSelection, useListParams, SonamuCol, numF, formatDate, formatDateTime } from '@sonamu-kit/react-sui';
297
+ import { useState, Fragment } from "react";
298
+ import { createFileRoute, useNavigate } from "@tanstack/react-router";
299
+
300
+ import { Card, CardContent, CardHeader } from "@sonamu-kit/react-components/components";
301
+ import { Badge } from "@sonamu-kit/react-components/components";
302
+ import { Button } from "@sonamu-kit/react-components/components";
303
+ import { Pagination, Table, TableBody, TableCell, type TableCol, TableHead, TableHeader, TableRow } from "@sonamu-kit/react-components/components";
304
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@sonamu-kit/react-components/components";
305
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@sonamu-kit/react-components/components";
306
+ import { Input } from "@sonamu-kit/react-components/components";
307
+ import { Checkbox } from "@sonamu-kit/react-components/components";
277
308
 
309
+ import { useListParams, numF, dateF, datetimeF } from "@sonamu-kit/react-components/lib";
278
310
  import { ${names.capital}SubsetA } from "@/services/sonamu.generated";
279
- import { ${names.capital}Service } from '@/services/services.generated';
280
- import { ${names.capital}ListParams } from '@/services/${names.fs}/${names.fs}.types';
281
- ${columnImports}
282
- ${filterColumns.map((col)=>{
283
- return this.renderFilterImport(entityId, col, names);
284
- }).join("\n")}
311
+ import { ${names.capital}Service } from "@/services/services.generated";
312
+ import { ${names.capital}ListParams } from "@/services/${names.fs}/${names.fs}.types";
313
+ import { ${(()=>{
314
+ // 기본 enum 수집 (filterColumns에 있는 것만)
315
+ const baseEnums = [];
316
+ if (filterColumns.some((col)=>col.name === "orderBy")) {
317
+ baseEnums.push(`${names.capital}OrderBy`, `${names.capital}OrderByLabel`);
318
+ }
319
+ if (filterColumns.some((col)=>col.name === "search")) {
320
+ baseEnums.push(`${names.capital}SearchField`, `${names.capital}SearchFieldLabel`);
321
+ }
322
+ // 필터 enum 수집 (config.enumId 우선, 없으면 getEnumInfoFromColName)
323
+ const filterEnumIds = filterColumns.filter((col)=>col.renderType === "enums" && col.name !== "search" && col.name !== "orderBy").map((col)=>{
324
+ if (col.config && "enumId" in col.config) {
325
+ return col.config.enumId;
326
+ }
327
+ try {
328
+ const { id: enumId } = getEnumInfoFromColName(entityId, col.name);
329
+ return enumId;
330
+ } catch {
331
+ return null;
332
+ }
333
+ }).filter(Boolean);
334
+ // 모든 enum 합치고 중복 제거
335
+ const allEnums = [
336
+ ...new Set([
337
+ ...filterEnumIds,
338
+ ...columnEnums
339
+ ])
340
+ ];
341
+ const enumImports = allEnums.flatMap((enumId)=>[
342
+ `${enumId}`,
343
+ `${enumId}Label`
344
+ ]);
345
+ return [
346
+ ...baseEnums,
347
+ ...enumImports
348
+ ].join(", ");
349
+ })()} } from "@/services/sonamu.generated";
350
+ ${(()=>{
351
+ // FK 필드의 AsyncSelect 컴포넌트 import
352
+ const fkColumns = filterColumns.filter((col)=>col.name.endsWith("_id") && col.name !== "id");
353
+ return fkColumns.map((col)=>{
354
+ try {
355
+ const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
356
+ const targetNames = EntityManager.getNamesFromId(relProp.with);
357
+ return `import { ${relProp.with}IdAsyncSelect } from "@/components/${targetNames.fs}/${relProp.with}IdAsyncSelect";`;
358
+ } catch {
359
+ return "";
360
+ }
361
+ }).filter(Boolean).join("\n");
362
+ })()}
363
+ ${filterColumns.some((col)=>col.name === "search") ? `
364
+ import { ${names.capital}SearchFieldSelect } from "@/components/${names.fs}/${names.capital}SearchFieldSelect";` : ""}
365
+ ${filterColumns.some((col)=>col.name === "orderBy") ? `
366
+ import { ${names.capital}OrderBySelect } from "@/components/${names.fs}/${names.capital}OrderBySelect";` : ""}
367
+
368
+ import EditIcon from "~icons/lucide/square-pen";
369
+ import TrashIcon from "~icons/lucide/trash-2";
370
+ import ListIcon from "~icons/mdi/format-list-bulleted";
371
+ import SearchIcon from "~icons/mdi/magnify";
372
+
373
+ export const Route = createFileRoute("/admin/${names.fsPlural}/")({\n head: () => ({\n meta: [\n { title: "${entity.title ?? names.capital} List" },\n { name: "description", content: "${entity.title ?? names.capital} 목록 관리" },\n ],\n }),\n component: ${names.capital}List,\n});\n\ntype ${names.capital}ListProps = {};
374
+
375
+ function ${names.capital}List({}: ${names.capital}ListProps) {
376
+ const navigate = useNavigate();
377
+
378
+ // 상태 관리
379
+ const [selectedItems, setSelectedItems] = useState<Set<number>>(new Set());
380
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
381
+ const [itemToDelete, setItemToDelete] = useState<{ id: number; name?: string } | null>(null);
285
382
 
286
- type ${names.capital}ListProps = {};
287
- export default function ${names.capital}List({}: ${names.capital}ListProps) {
288
383
  // 리스트 필터
289
384
  const { listParams, register } = useListParams(${names.capital}ListParams, {
290
- num: 12,
385
+ num: 10,
291
386
  page: 1,
292
- orderBy: '${def.orderBy}',
293
- search: '${def.search}',
387
+ keyword: "",${filterColumns.some((col)=>col.name === "search") ? `
388
+ search: ${names.capital}SearchField.options[0],` : ""}${filterColumns.some((col)=>col.name === "orderBy") ? `
389
+ orderBy: ${names.capital}OrderBy.options[0],` : ""}
294
390
  });
295
391
 
296
392
  // 리스트 쿼리
297
- const { data, refetch, isLoading } = ${names.capital}Service.use${names.capitalPlural}('A', listParams);
393
+ const { data, refetch, isLoading } = ${names.capital}Service.use${names.capitalPlural}("A", listParams);
298
394
  const { rows, total } = data ?? {};
299
395
 
300
- // 삭제
301
- const confirmDel = (ids: number[]) => {
302
- const answer = confirm('삭제하시겠습니까?');
303
- if (!answer) {
304
- return;
305
- }
306
-
307
- ${names.capital}Service.del(ids).then(() => {
308
- refetch();
309
- });
396
+ // 현재 경로와 타이틀
397
+ const PAGE = {
398
+ route: "/admin/${names.fsPlural}",
399
+ title: "${entity.title ?? names.capital}",
310
400
  };
311
401
 
312
- // 일괄 삭제
313
- const confirmDelSelected = () => {
314
- const answer = confirm(\`\${selectedKeys.length}건을 일괄 삭제하시겠습니까?\`);
315
- if (!answer) {
316
- return;
402
+ // 컬럼 정의
403
+ type ${names.capital}Row = NonNullable<typeof rows>[number];
404
+ const columns: TableCol<${names.capital}Row>[] = [
405
+ ${columns.map((col)=>` {
406
+ label: "${col.label}",
407
+ tc: ${col.tc},${col.fit ? `
408
+ fit: true,` : ""}${col.align ? `
409
+ align: "${col.align}",` : ""}
410
+ }`).join(",\n")},
411
+ {
412
+ label: "Manage",
413
+ fit: true,
414
+ align: "center",
415
+ tc: (row) => (
416
+ <div className="flex items-center justify-center gap-1">
417
+ <Button
418
+ variant="yellow"
419
+ size="xs"
420
+ icon={<EditIcon />}
421
+ onClick={() => navigate({ to: \`\${PAGE.route}/form\`, search: { id: row.id } })}
422
+ />
423
+ <Button
424
+ variant="red"
425
+ size="xs"
426
+ icon={<TrashIcon />}
427
+ onClick={() => handleDeleteClick(row.id)}
428
+ />
429
+ </div>
430
+ ),
431
+ },
432
+ ];
433
+
434
+ // 선택 핸들러
435
+ const handleToggleItem = (id: number) => {
436
+ const newSelection = new Set(selectedItems);
437
+ if (newSelection.has(id)) {
438
+ newSelection.delete(id);
439
+ } else {
440
+ newSelection.add(id);
317
441
  }
442
+ setSelectedItems(newSelection);
443
+ };
318
444
 
319
- ${names.capital}Service.del(selectedKeys).then(() => {
320
- refetch();
321
- });
445
+ const isAllSelected = () => {
446
+ return (rows?.length ?? 0) > 0 && rows!.every((row) => selectedItems.has(row.id));
322
447
  };
323
448
 
324
- // 현재 경로와 타이틀
325
- const PAGE = {
326
- route: '/admin/${names.fsPlural}',
327
- title: '${entity.title ?? names.capital}',
449
+ const handleSelectAll = (checked: boolean) => {
450
+ if (checked) {
451
+ setSelectedItems(new Set(rows?.map((row) => row.id) ?? []));
452
+ } else {
453
+ setSelectedItems(new Set());
454
+ }
328
455
  };
329
456
 
330
- // 선택
331
- const {
332
- getSelected,
333
- isAllSelected,
334
- selectedKeys,
335
- toggle,
336
- selectAll,
337
- deselectAll,
338
- handleCheckboxClick,
339
- } = useSelection((rows ?? []).map((row) => row.id));
457
+ // 삭제 핸들러
458
+ const handleDeleteClick = (id: number, name?: string) => {
459
+ setItemToDelete({ id, name });
460
+ setDeleteDialogOpen(true);
461
+ };
340
462
 
341
- // 컬럼
342
- const columns:SonamuCol<${names.capital}SubsetA>[] = [${columns.map((col)=>{
343
- return [
344
- `{ label: "${col.label}",`,
345
- `tc: ${col.tc}, `,
346
- `collapsing: ${[
347
- "Title",
348
- "Name"
349
- ].includes(col.label) === false}, }`
350
- ].join("\n");
351
- }).join(",\n")}];
463
+ const handleConfirmDelete = () => {
464
+ if (itemToDelete) {
465
+ ${names.capital}Service.del([itemToDelete.id]).then(() => {
466
+ refetch();
467
+ });
468
+ }
469
+ setDeleteDialogOpen(false);
470
+ setItemToDelete(null);
471
+ };
352
472
 
353
473
  return (
354
- <div className="list ${names.fsPlural}-index">
355
- <div className="top-nav">
356
- <div className="header-row">
357
- <div className="header">{PAGE.title}</div>
358
- <AppBreadcrumbs>
359
- <Breadcrumb.Section active>{PAGE.title}</Breadcrumb.Section>
360
- </AppBreadcrumbs>
361
- <${names.capital}SearchInput
362
- input={register('keyword')}
363
- dropdown={register('search')}
364
- />
365
- </div>
366
- <div className="filters-row">
367
- ${filterColumns.map((col)=>{
368
- return this.renderFilter(entityId, col, names);
369
- }).join("&nbsp;\n")}
370
- </div>
371
- </div>
372
-
373
- <Segment basic padded className="contents-segment" loading={isLoading}>
374
- <div className="buttons-row">
375
- <div className={classNames('count', { hidden: isLoading })}>
376
- {total} 건
377
- </div>
378
- <div className="buttons">
379
- <AddButton currentRoute={PAGE.route} icon="write" label="추가" />
474
+ <div className="flex-1 overflow-auto">
475
+ <div className="max-w-[1800px] mx-auto p-8">
476
+ <div className="space-y-6 mb-8">
477
+ {/* Header */}
478
+ <div className="flex items-center gap-2">
479
+ <ListIcon className="h-5 w-5" />
480
+ <span className="text-lg font-semibold h-5">{PAGE.title}</span>
380
481
  </div>
381
- </div>
382
482
 
383
- <Table
384
- celled
385
- compact
386
- selectable
387
- className={classNames({ hidden: total === undefined || total === 0 })}
388
- >
389
- <Table.Header>
390
- <TableRow>
391
- <Table.HeaderCell collapsing>
392
- <Checkbox
393
- label="ID"
394
- checked={isAllSelected}
395
- onChange={isAllSelected ? deselectAll : selectAll}
396
- />
397
- </Table.HeaderCell>
398
- {
399
- /* Header */
400
- columns.map((col, index) => col.th ?? <Table.HeaderCell key={index} collapsing={col.collapsing}>{ col.label }</Table.HeaderCell>)
401
- }
402
- <Table.HeaderCell>관리</Table.HeaderCell>
403
- </TableRow>
404
- </Table.Header>
405
- <Table.Body>
406
- {rows &&
407
- rows.map((row, rowIndex) => (
408
- <Table.Row key={row.id}>
409
- <Table.Cell>
410
- <Checkbox
411
- label={row.id}
412
- checked={getSelected(row.id)}
413
- onChange={() => toggle(row.id)}
414
- onClick={(e) =>
415
- handleCheckboxClick(e, rowIndex)
416
- }
483
+ <Card className="shadow-sm border-border/40 overflow-hidden">
484
+ <CardHeader className="pb-0 px-0 pt-0">
485
+ {/* Filters */}
486
+ <div className="bg-gray-100 px-6 py-4 space-y-3">
487
+ <div className="flex items-center gap-3 flex-wrap">
488
+ ${filterColumns.some((col)=>col.name === "search") ? ` <${names.capital}SearchFieldSelect
489
+ {...register("search")}
490
+ placeholder="Search Type"
491
+ className="w-[200px] h-8 bg-white border-gray-300 text-xs"
492
+ />` : ""}
493
+
494
+ <div className="relative flex-1 max-w-xs">
495
+ <Input
496
+ {...register("keyword")}
497
+ placeholder="Search..."
498
+ className="h-8 pr-8 text-xs bg-white border-gray-300"
417
499
  />
418
- </Table.Cell>
419
- {
420
- /* Body */
421
- columns.map((col, colIndex) => (
422
- <Table.Cell key={colIndex} collapsing={col.collapsing} className={col.className}>
423
- {col.tc(row, rowIndex)}
424
- </Table.Cell>
425
- ))
426
- }
427
- <Table.Cell collapsing>
428
- <EditButton
429
- as={Link}
430
- to={\`\${PAGE.route}/form?id=\${row.id}\`}
431
- state={{ from: PAGE.route }}
500
+ <Button
501
+ variant="ghost"
502
+ size="sm"
503
+ icon={<SearchIcon />}
504
+ className="absolute right-0 top-0 h-8 w-8 hover:bg-transparent"
432
505
  />
433
- <DelButton onClick={() => confirmDel([row.id])} />
434
- </Table.Cell>
435
- </Table.Row>
436
- ))}
437
- </Table.Body>
438
- </Table>
439
- <div
440
- className={classNames('pagination-row', {
441
- hidden: (total ?? 0) === 0,
442
- })}
443
- >
444
- <Pagination
445
- totalPages={Math.ceil((total ?? 0) / (listParams.num ?? 24))}
446
- {...register('page')}
447
- />
448
- </div>
449
- </Segment>
506
+ </div>
507
+
508
+ <div className="ml-auto">
509
+ <Button
510
+ className="h-8 px-4 bg-primary hover:bg-primary/90 text-white"
511
+ onClick={() => navigate({ to: \`\${PAGE.route}/form\` })}
512
+ >
513
+ <span className="text-xs">Create</span>
514
+ </Button>
515
+ </div>
516
+ </div>
517
+
518
+ <div className="flex items-center gap-3 flex-wrap">
519
+ ${filterColumns.filter((col)=>col.name !== "search" && col.name !== "orderBy").map((col)=>{
520
+ if (col.renderType === "enums") {
521
+ try {
522
+ // config.enumId가 있으면 우선 사용, 없으면 getEnumInfoFromColName 시도
523
+ const enumId = col.config && "enumId" in col.config ? col.config.enumId : getEnumInfoFromColName(entityId, col.name).id;
524
+ return ` <Select key={\`${col.name}-\${listParams.${col.name}}\`} {...register("${col.name}")} clearable>
525
+ <SelectTrigger className="w-[200px] h-8 bg-white border-gray-300 text-xs">
526
+ <SelectValue placeholder="${col.label}" className="truncate" />
527
+ </SelectTrigger>
528
+ <SelectContent>
529
+ {${enumId}.options.map((key) => (
530
+ <SelectItem key={key} value={key}>
531
+ {${enumId}Label[key]}
532
+ </SelectItem>
533
+ ))}
534
+ </SelectContent>
535
+ </Select>`;
536
+ } catch {
537
+ return "";
538
+ }
539
+ }
540
+ // FK 필드 (AsyncSelect)
541
+ if (col.name.endsWith("_id") && col.name !== "id") {
542
+ try {
543
+ const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
544
+ return ` <${relProp.with}IdAsyncSelect
545
+ subset="A"
546
+ {...register("${col.name}")}
547
+ placeholder="${col.label ?? relProp.with}"
548
+ clearable
549
+ className="w-[200px] h-8 text-xs"
550
+ />`;
551
+ } catch {
552
+ return "";
553
+ }
554
+ }
555
+ return "";
556
+ }).filter(Boolean).join("\n")}
557
+ ${filterColumns.some((col)=>col.name === "orderBy") ? ` <${names.capital}OrderBySelect
558
+ {...register("orderBy")}
559
+ placeholder="Sort"
560
+ textPrefix="Sort: "
561
+ className="w-[200px] h-8 bg-white border-gray-300 text-xs"
562
+ />` : ""}
563
+ <span className="text-xs text-muted-foreground">{total ?? 0} results</span>
564
+ </div>
565
+ </div>
566
+ </CardHeader>
567
+
568
+ <CardContent className="px-6 pb-6 pt-6 bg-white">
569
+ {/* Table */}
570
+ <Table>
571
+ <TableHeader>
572
+ <TableRow className="hover:bg-transparent bg-gray-100">
573
+ <TableHead className="h-9 text-xs w-[40px]">
574
+ <Checkbox
575
+ checked={isAllSelected()}
576
+ onValueChange={handleSelectAll}
577
+ />
578
+ </TableHead>
579
+ {columns.map((col, idx) => (
580
+ <TableHead key={idx} fit={col.fit} align={col.align}>
581
+ {col.label}
582
+ </TableHead>
583
+ ))}
584
+ </TableRow>
585
+ </TableHeader>
586
+ <TableBody>
587
+ {!isLoading && rows && rows.map((row) => (
588
+ <Fragment key={row.id}>
589
+ <TableRow>
590
+ <TableCell className="py-3">
591
+ <Checkbox
592
+ checked={selectedItems.has(row.id)}
593
+ onValueChange={() => handleToggleItem(row.id)}
594
+ />
595
+ </TableCell>
596
+ {columns.map((col, idx) => (
597
+ <TableCell key={idx} fit={col.fit} align={col.align} className="py-3">
598
+ {col.tc(row)}
599
+ </TableCell>
600
+ ))}
601
+ </TableRow>
602
+ </Fragment>
603
+ ))}
604
+ </TableBody>
605
+ </Table>
450
606
 
451
- <div className="fixed-menu">
452
- <Transition
453
- visible={selectedKeys.length > 0}
454
- animation="slide left"
455
- duration={500}
456
- >
457
- <Message size="small" color="violet" className="text-center">
458
- <span className="px-4">{selectedKeys.length}개 선택됨</span>
459
- <Button size="tiny" color="violet" onClick={() => deselectAll()}>
460
- 선택 해제
461
- </Button>
462
- <Button size="tiny" color="red" onClick={confirmDelSelected}>
463
- 일괄 삭제
464
- </Button>
465
- </Message>
466
- </Transition>
607
+ {/* Pagination */}
608
+ <Pagination
609
+ {...register("page")}
610
+ total={total ?? 0}
611
+ itemsPerPage={listParams.num ?? 10}
612
+ />
613
+ </CardContent>
614
+ </Card>
615
+ </div>
467
616
  </div>
617
+
618
+ {/* Delete Dialog */}
619
+ <AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
620
+ <AlertDialogContent>
621
+ <AlertDialogHeader>
622
+ <AlertDialogTitle>Are you sure?</AlertDialogTitle>
623
+ <AlertDialogDescription>
624
+ This action cannot be undone. This will permanently delete this item.
625
+ </AlertDialogDescription>
626
+ </AlertDialogHeader>
627
+ <AlertDialogFooter>
628
+ <AlertDialogCancel>Cancel</AlertDialogCancel>
629
+ <AlertDialogAction onClick={handleConfirmDelete}>Delete</AlertDialogAction>
630
+ </AlertDialogFooter>
631
+ </AlertDialogContent>
632
+ </AlertDialog>
468
633
  </div>
469
634
  );
470
635
  }
@@ -475,4 +640,4 @@ export default function ${names.capital}List({}: ${names.capital}ListProps) {
475
640
  }
476
641
  }
477
642
 
478
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZW1wbGF0ZS9pbXBsZW1lbnRhdGlvbnMvdmlld19saXN0LnRlbXBsYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCB7IGZsYXQsIHVuaXF1ZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciwgdHlwZSBFbnRpdHlOYW1lc1JlY29yZCB9IGZyb20gXCIuLi8uLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB0eXBlIHsgUmVuZGVyaW5nTm9kZSwgVGVtcGxhdGVLZXksIFRlbXBsYXRlT3B0aW9ucyB9IGZyb20gXCIuLi8uLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgZ2V0Q29sdW1uc05vZGUgfSBmcm9tIFwiLi4vZW50aXR5LWNvbnZlcnRlclwiO1xuaW1wb3J0IHsgZ2V0RW51bUluZm9Gcm9tQ29sTmFtZSwgZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUgfSBmcm9tIFwiLi4vaGVscGVyc1wiO1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJlZFRlbXBsYXRlIH0gZnJvbSBcIi4uL3RlbXBsYXRlXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZVwiO1xuaW1wb3J0IHsgZ2V0Wm9kVHlwZUJ5SWQsIHpvZFR5cGVUb1JlbmRlcmluZ05vZGUgfSBmcm9tIFwiLi4vem9kLWNvbnZlcnRlclwiO1xuXG5leHBvcnQgY2xhc3MgVGVtcGxhdGVfX3ZpZXdfbGlzdCBleHRlbmRzIFRlbXBsYXRlIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJ2aWV3X2xpc3RcIik7XG4gIH1cblxuICBnZXRUYXJnZXRBbmRQYXRoKG5hbWVzOiBFbnRpdHlOYW1lc1JlY29yZCkge1xuICAgIHJldHVybiB7XG4gICAgICB0YXJnZXQ6IFwid2ViL3NyYy9wYWdlcy9hZG1pblwiLFxuICAgICAgcGF0aDogYCR7bmFtZXMuZnNQbHVyYWx9L2luZGV4LnRzeGAsXG4gICAgfTtcbiAgfVxuXG4gIHdyYXBUYyhib2R5OiBzdHJpbmcsIGtleTogc3RyaW5nLCBjb2xsYXBzaW5nOiBib29sZWFuID0gdHJ1ZSwgY2xhc3NOYW1lOiBzdHJpbmcgPSBcIlwiKSB7XG4gICAgcmV0dXJuIGA8VGFibGUuQ2VsbCBrZXk9XCIke2tleX1cIiR7Y29sbGFwc2luZyA/IFwiIGNvbGxhcHNpbmdcIiA6IFwiXCJ9JHtcbiAgICAgIGNsYXNzTmFtZSA/IGAgY2xhc3NOYW1lPXtcXGAke2NsYXNzTmFtZX1cXGB9YCA6IFwiXCJcbiAgICB9PiR7Ym9keX08L1RhYmxlLkNlbGw+YDtcbiAgfVxuXG4gIHJlbmRlckNvbHVtbihcbiAgICBlbnRpdHlJZDogc3RyaW5nLFxuICAgIGNvbDogUmVuZGVyaW5nTm9kZSxcbiAgICBuYW1lczogRW50aXR5TmFtZXNSZWNvcmQsXG4gICAgcGFyZW50T2JqOiBzdHJpbmcgPSBcInJvd1wiLFxuICAgIHdpdGhvdXROYW1lOiBib29sZWFuID0gZmFsc2UsXG4gICk6IHN0cmluZyB7XG4gICAgY29uc3QgY29sTmFtZSA9IHdpdGhvdXROYW1lID8gYCR7cGFyZW50T2JqfWAgOiBgJHtwYXJlbnRPYmp9LiR7Y29sLm5hbWV9YDtcblxuICAgIHN3aXRjaCAoY29sLnJlbmRlclR5cGUpIHtcbiAgICAgIGNhc2UgXCJzdHJpbmctcGxhaW5cIjpcbiAgICAgIGNhc2UgXCJzdHJpbmctZGF0ZVwiOlxuICAgICAgY2FzZSBcIm51bWJlci1pZFwiOlxuICAgICAgICByZXR1cm4gYDw+eyR7Y29sTmFtZX19PC8+YDtcbiAgICAgIGNhc2UgXCJudW1iZXItZmtfaWRcIjoge1xuICAgICAgICBjb25zdCByZWxQcm9wRmsgPSBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUucmVwbGFjZShcIl9pZFwiLCBcIlwiKSk7XG4gICAgICAgIHJldHVybiBgPD4ke3JlbFByb3BGay53aXRofSN7JHtjb2xOYW1lfX08Lz5gO1xuICAgICAgfVxuICAgICAgY2FzZSBcInN0cmluZy1pbWFnZVwiOlxuICAgICAgICByZXR1cm4gYDw+eyR7Y29sLm51bGxhYmxlID8gYCR7Y29sTmFtZX0gJiYgYCA6IFwiXCJ9PGltZyBzcmM9eyR7Y29sTmFtZX19IC8+fTwvPmA7XG4gICAgICBjYXNlIFwiZGF0ZXRpbWVcIjpcbiAgICAgICAgaWYgKGNvbC5udWxsYWJsZSkge1xuICAgICAgICAgIHJldHVybiBgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC10aW55XCI+eyR7Y29sTmFtZX0gPT09IG51bGwgPyAnLScgOiBmb3JtYXREYXRlVGltZSgke2NvbE5hbWV9KX08L3NwYW4+YDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gYDxzcGFuIGNsYXNzTmFtZT1cInRleHQtdGlueVwiPntmb3JtYXREYXRlVGltZSgke2NvbE5hbWV9KX08L3NwYW4+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcInN0cmluZy1kYXRldGltZVwiOlxuICAgICAgICBpZiAoY29sLm51bGxhYmxlKSB7XG4gICAgICAgICAgcmV0dXJuIGA8c3BhbiBjbGFzc05hbWU9XCJ0ZXh0LXRpbnlcIj57JHtjb2xOYW1lfSA9PT0gbnVsbCA/ICctJyA6IGRhdGVGKCR7Y29sTmFtZX0pfTwvc3Bhbj5gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC10aW55XCI+e2RhdGVGKCR7Y29sTmFtZX0pfTwvc3Bhbj5gO1xuICAgICAgICB9XG4gICAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgICByZXR1cm4gYDw+eyR7Y29sTmFtZX0gPyA8TGFiZWwgY29sb3I9J2dyZWVuJyBjaXJjdWxhcj5PPC9MYWJlbD4gOiA8TGFiZWwgY29sb3I9J2dyZXknIGNpcmN1bGFyPlg8L0xhYmVsPiB9PC8+YDtcbiAgICAgIGNhc2UgXCJlbnVtc1wiOiB7XG4gICAgICAgIGNvbnN0IHsgaWQ6IGVudW1JZCB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICByZXR1cm4gYDw+eyR7Y29sLm51bGxhYmxlID8gYCR7Y29sTmFtZX0gJiYgYCA6IFwiXCJ9JHtlbnVtSWR9TGFiZWxbJHtjb2xOYW1lfV19PC8+YDtcbiAgICAgIH1cbiAgICAgIGNhc2UgXCJhcnJheS1pbWFnZXNcIjpcbiAgICAgICAgcmV0dXJuIGA8PnsgJHtjb2xOYW1lfS5tYXAociA9PiAke2NvbC5udWxsYWJsZSA/IGByICYmIGAgOiBcIlwifTxpbWcgc3JjPXtyfSAvPikgfTwvPmA7XG4gICAgICBjYXNlIFwibnVtYmVyLXBsYWluXCI6XG4gICAgICAgIHJldHVybiBgPD57JHtjb2wubnVsbGFibGUgPyBgJHtjb2xOYW1lfSAmJiBgIDogXCJcIn1udW1GKCR7Y29sTmFtZX0pfTwvPmA7XG4gICAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICAgIHJldHVybiBgPD57Lyogb2JqZWN0ICR7Y29sTmFtZX0gKi99PC8+YDtcbiAgICAgIGNhc2UgXCJvYmplY3QtcGlja1wiOiB7XG4gICAgICAgIGNvbnN0IHBpY2tlZENoaWxkID0gY29sLmNoaWxkcmVuPy5maW5kKChjaGlsZCkgPT4gY2hpbGQubmFtZSA9PT0gY29sLmNvbmZpZz8ucGlja2VkKTtcbiAgICAgICAgaWYgKCFwaWNrZWRDaGlsZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgb2JqZWN0LXBpY2sg7ISg7YOdIOyLpO2MqCAo7Jik67iM7KCd7Yq4OiAke2NvbC5uYW1lfSlgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJDb2x1bW4oXG4gICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgcGlja2VkQ2hpbGQsXG4gICAgICAgICAgbmFtZXMsXG4gICAgICAgICAgYCR7Y29sTmFtZX0ke2NvbC5udWxsYWJsZSA/IFwiP1wiIDogXCJcIn1gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY2FzZSBcImFycmF5XCI6XG4gICAgICAgIHJldHVybiBgPD57IC8qIGFycmF5ICR7Y29sTmFtZX0gKi8gfTwvPmA7XG4gICAgICBjYXNlIFwidmVjdG9yXCI6XG4gICAgICAgIC8vIHZlY3RvciDtg4DsnoXsnYAg7LCo7JuQIOyImOunjCDtkZzsi5wgKOyLpOygnCDrjbDsnbTthLDripQg64SI66y0IOq5gClcbiAgICAgICAgcmV0dXJuIGA8Pnske2NvbC5udWxsYWJsZSA/IGAke2NvbE5hbWV9ID8gYCA6IFwiXCJ9W1ZlY3RvcjogeyR7Y29sTmFtZX0ke2NvbC5udWxsYWJsZSA/IFwiXCIgOiBcIiA/PyBbXVwifS5sZW5ndGh9ZF0ke2NvbC5udWxsYWJsZSA/IFwiIDogJy0nXCIgOiBcIlwifX08Lz5gO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDroIzrjZQg67aI6rCAIOy7rOufvCAke2NvbC5yZW5kZXJUeXBlfWApO1xuICAgIH1cbiAgfVxuXG4gIHJlbmRlckNvbHVtbkltcG9ydChcbiAgICBlbnRpdHlJZDogc3RyaW5nLFxuICAgIGNvbDogUmVuZGVyaW5nTm9kZSxcbiAgICBuYW1lczogRW50aXR5TmFtZXNSZWNvcmQsXG4gICk6IChzdHJpbmcgfCBudWxsKVtdIHtcbiAgICBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwiZW51bXNcIikge1xuICAgICAgY29uc3QgeyBpZDogZW51bUlkIH0gPSBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lKG5hbWVzLmNhcGl0YWwsIGNvbC5uYW1lKTtcbiAgICAgIHJldHVybiBbYGltcG9ydCB7ICR7ZW51bUlkfUxhYmVsIH0gZnJvbSAnQC9zZXJ2aWNlcy9zb25hbXUuZ2VuZXJhdGVkJztgXTtcbiAgICB9IGVsc2UgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZWxQcm9wID0gZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gY29sLmNoaWxkcmVuPy5tYXAoKGNoaWxkKSA9PiB7XG4gICAgICAgICAgZW50aXR5SWQgPSByZWxQcm9wLndpdGg7XG4gICAgICAgICAgbmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKHJlbFByb3Aud2l0aCk7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyQ29sdW1uSW1wb3J0KGVudGl0eUlkLCBjaGlsZCwgbmFtZXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGZsYXQocmVzdWx0ID8/IFtdKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gW251bGxdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwiYXJyYXlcIikge1xuICAgICAgYXNzZXJ0KGNvbC5lbGVtZW50KTtcbiAgICAgIHJldHVybiB0aGlzLnJlbmRlckNvbHVtbkltcG9ydChlbnRpdHlJZCwgY29sLmVsZW1lbnQsIG5hbWVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW251bGxdO1xuICB9XG5cbiAgcmVuZGVyRmlsdGVySW1wb3J0KGVudGl0eUlkOiBzdHJpbmcsIGNvbDogUmVuZGVyaW5nTm9kZSwgbmFtZXM6IEVudGl0eU5hbWVzUmVjb3JkKSB7XG4gICAgaWYgKGNvbC5uYW1lID09PSBcInNlYXJjaFwiKSB7XG4gICAgICByZXR1cm4gYGltcG9ydCB7ICR7bmFtZXMuY2FwaXRhbH1TZWFyY2hJbnB1dCB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHtuYW1lcy5mc30vJHtuYW1lcy5jYXBpdGFsfVNlYXJjaElucHV0XCI7YDtcbiAgICB9IGVsc2UgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgIGlmIChjb2wubmFtZSA9PT0gXCJvcmRlckJ5XCIpIHtcbiAgICAgICAgY29uc3QgY29tcG9uZW50SWQgPSBgJHtuYW1lcy5jYXBpdGFsfSR7aW5mbGVjdGlvbi5jYW1lbGl6ZShjb2wubmFtZSl9U2VsZWN0YDtcbiAgICAgICAgcmV0dXJuIGBpbXBvcnQgeyAke2NvbXBvbmVudElkfSB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHtuYW1lcy5mc30vJHtjb21wb25lbnRJZH1cIjtgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGlkLCB0YXJnZXRFbnRpdHlOYW1lczogdGFyZ2V0TUROYW1lcyB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShcbiAgICAgICAgICAgIGVudGl0eUlkLFxuICAgICAgICAgICAgY29sLm5hbWUsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjb21wb25lbnRJZCA9IGAke2lkfVNlbGVjdGA7XG4gICAgICAgICAgcmV0dXJuIGBpbXBvcnQgeyAke2NvbXBvbmVudElkfSB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHt0YXJnZXRNRE5hbWVzLmZzfS8ke2NvbXBvbmVudElkfVwiO2A7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJudW1iZXItZmtfaWRcIikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0TmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKHJlbFByb3Aud2l0aCk7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudElkID0gYCR7cmVsUHJvcC53aXRofUlkQXN5bmNTZWxlY3RgO1xuICAgICAgICByZXR1cm4gYGltcG9ydCB7ICR7Y29tcG9uZW50SWR9IH0gZnJvbSBcIkAvY29tcG9uZW50cy8ke3RhcmdldE5hbWVzLmZzfS8ke2NvbXBvbmVudElkfVwiO2A7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihg66CM642UIOu2iOqwgOuKpe2VnCDtlYTthLAg7J6E7Y+s7Yq4ICR7Y29sLm5hbWV9ICR7Y29sLnJlbmRlclR5cGV9YCk7XG4gICAgfVxuICB9XG5cbiAgcmVuZGVyRmlsdGVyKGVudGl0eUlkOiBzdHJpbmcsIGNvbDogUmVuZGVyaW5nTm9kZSwgbmFtZXM6IEVudGl0eU5hbWVzUmVjb3JkKSB7XG4gICAgaWYgKGNvbC5uYW1lID09PSBcInNlYXJjaFwiKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICBjb25zdCBpc0NsZWFyYWJsZSA9IGNvbC5vcHRpb25hbCA9PT0gdHJ1ZSAmJiBjb2wubmFtZSAhPT0gXCJvcmRlckJ5XCI7XG4gICAgbGV0IGNvbXBvbmVudElkOiBzdHJpbmc7XG4gICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgIGlmIChjb2wubmFtZSA9PT0gXCJvcmRlckJ5XCIpIHtcbiAgICAgICAgY29tcG9uZW50SWQgPSBgJHtuYW1lcy5jYXBpdGFsfSR7aW5mbGVjdGlvbi5jYW1lbGl6ZShjb2wubmFtZSl9U2VsZWN0YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBpZCB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICAgIGNvbXBvbmVudElkID0gYCR7aWR9U2VsZWN0YDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBgPCR7Y29tcG9uZW50SWR9IHsuLi5yZWdpc3RlcignJHtjb2wubmFtZX0nKX0gJHtpc0NsZWFyYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwifSAvPmA7XG4gICAgfSBlbHNlIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJudW1iZXItZmtfaWRcIikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgY29tcG9uZW50SWQgPSBgJHtyZWxQcm9wLndpdGh9SWRBc3luY1NlbGVjdGA7XG4gICAgICAgIHJldHVybiBgPCR7Y29tcG9uZW50SWR9IHsuLi5yZWdpc3RlcignJHtjb2wubmFtZX0nKX0gJHtcbiAgICAgICAgICBpc0NsZWFyYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwiXG4gICAgICAgIH0gc3Vic2V0PVwiQVwiIC8+YDtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGDroIzrjZQg67aI6rCA64ql7ZWcIO2VhO2EsCDsnoTtj6ztirggJHtjb2wubmFtZX0gJHtjb2wucmVuZGVyVHlwZX1gKTtcbiAgICB9XG4gIH1cblxuICBnZXREZWZhdWx0KGNvbHVtbnM6IFJlbmRlcmluZ05vZGVbXSk6IHtcbiAgICBvcmRlckJ5OiBzdHJpbmc7XG4gICAgc2VhcmNoOiBzdHJpbmc7XG4gIH0ge1xuICAgIGNvbnN0IGRlZiA9IHtcbiAgICAgIG9yZGVyQnk6IFwiaWQtZGVzY1wiLFxuICAgICAgc2VhcmNoOiBcInRpdGxlXCIsXG4gICAgfTtcbiAgICBjb25zdCBvcmRlckJ5Wm9kVHlwZSA9IGNvbHVtbnMuZmluZCgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJvcmRlckJ5XCIpPy56b2RUeXBlO1xuICAgIGlmIChvcmRlckJ5Wm9kVHlwZSAmJiBvcmRlckJ5Wm9kVHlwZSBpbnN0YW5jZW9mIHouWm9kRW51bSkge1xuICAgICAgZGVmLm9yZGVyQnkgPSBvcmRlckJ5Wm9kVHlwZS5vcHRpb25zWzBdLnRvU3RyaW5nKCk7XG4gICAgfVxuICAgIGNvbnN0IHNlYXJjaFpvZFR5cGUgPSBjb2x1bW5zLmZpbmQoKGNvbCkgPT4gY29sLm5hbWUgPT09IFwic2VhcmNoXCIpPy56b2RUeXBlO1xuICAgIGlmIChzZWFyY2hab2RUeXBlICYmIHNlYXJjaFpvZFR5cGUgaW5zdGFuY2VvZiB6LlpvZEVudW0pIHtcbiAgICAgIGRlZi5zZWFyY2ggPSBzZWFyY2hab2RUeXBlLm9wdGlvbnNbMF0udG9TdHJpbmcoKTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZjtcbiAgfVxuXG4gIGFzeW5jIHJlbmRlcih7IGVudGl0eUlkIH06IFRlbXBsYXRlT3B0aW9uc1tcInZpZXdfbGlzdFwiXSkge1xuICAgIGNvbnN0IGNvbHVtbnNOb2RlID0gYXdhaXQgZ2V0Q29sdW1uc05vZGUoZW50aXR5SWQsIFwiQVwiKTtcbiAgICBjb25zdCBsaXN0UGFyYW1zWm9kVHlwZSA9IGF3YWl0IGdldFpvZFR5cGVCeUlkKGAke2VudGl0eUlkfUxpc3RQYXJhbXNgKTtcbiAgICBjb25zdCBsaXN0UGFyYW1zTm9kZSA9IHpvZFR5cGVUb1JlbmRlcmluZ05vZGUobGlzdFBhcmFtc1pvZFR5cGUpO1xuXG4gICAgY29uc3QgbmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKGVudGl0eUlkKTtcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG5cbiAgICAvLyDsi6TsoJwg66as7Iqk7Yq4IOy7rOufvFxuICAgIGNvbnN0IGNvbHVtbnMgPSAoY29sdW1uc05vZGUuY2hpbGRyZW4gYXMgUmVuZGVyaW5nTm9kZVtdKVxuICAgICAgLmZpbHRlcigoY29sKSA9PiBjb2wubmFtZSAhPT0gXCJpZFwiKVxuICAgICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICAgIGNvbnN0IHByb3BDYW5kaWRhdGUgPSBlbnRpdHkucHJvcHMuZmluZCgocCkgPT4gcC5uYW1lID09PSBjb2wubmFtZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogY29sLm5hbWUsXG4gICAgICAgICAgbGFiZWw6IHByb3BDYW5kaWRhdGU/LmRlc2MgPz8gY29sLmxhYmVsLFxuICAgICAgICAgIHRjOiBgKHJvdykgPT4gJHt0aGlzLnJlbmRlckNvbHVtbihlbnRpdHlJZCwgY29sLCBuYW1lcyl9YCxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgLy8g7ZWE7YSwIOy7rOufvFxuICAgIGNvbnN0IGZpbHRlckNvbHVtbnMgPSAobGlzdFBhcmFtc05vZGUuY2hpbGRyZW4gYXMgUmVuZGVyaW5nTm9kZVtdKVxuICAgICAgLmZpbHRlcihcbiAgICAgICAgKGNvbCkgPT5cbiAgICAgICAgICBjb2wubmFtZSAhPT0gXCJpZFwiICYmXG4gICAgICAgICAgY29sLm5hbWUgIT09IFwicXVlcnlNb2RlXCIgJiZcbiAgICAgICAgICAoW1wiZW51bXNcIiwgXCJudW1iZXItaWRcIl0uaW5jbHVkZXMoY29sLnJlbmRlclR5cGUpIHx8IGNvbC5uYW1lLmVuZHNXaXRoKFwiX2lkXCIpKSxcbiAgICAgIClcbiAgICAgIC8vIG9yZGVyQnnqsIAg6rCA7J6lIOuSpOuhnCDsmKTqsowg7Iic7IScIOyhsOyglVxuICAgICAgLnNvcnQoKGEpID0+IHtcbiAgICAgICAgcmV0dXJuIGEubmFtZSA9PT0gXCJvcmRlckJ5XCIgPyAxIDogLTE7XG4gICAgICB9KTtcblxuICAgIC8vIO2VhO2EsCDsu6zrn7zsnYQg7ZSE66asIO2FnO2UjOumv+ycvOuhnCDshKTsoJVcbiAgICBjb25zdCBwcmVUZW1wbGF0ZXM6IFJlbmRlcmVkVGVtcGxhdGVbXCJwcmVUZW1wbGF0ZXNcIl0gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGNvbCBvZiBmaWx0ZXJDb2x1bW5zKSB7XG4gICAgICBsZXQga2V5OiBUZW1wbGF0ZUtleTtcbiAgICAgIGxldCB0YXJnZXRFbnRpdHlJZCA9IGVudGl0eUlkO1xuICAgICAgbGV0IGVudW1JZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgICBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwiZW51bXNcIikge1xuICAgICAgICBpZiAoY29sLm5hbWUgPT09IFwic2VhcmNoXCIpIHtcbiAgICAgICAgICBrZXkgPSBcInZpZXdfZW51bXNfZHJvcGRvd25cIjtcbiAgICAgICAgICBlbnVtSWQgPSBgJHtuYW1lcy5jYXBpdGFsfVNlYXJjaEZpZWxkYDtcbiAgICAgICAgICB0YXJnZXRFbnRpdHlJZCA9IG5hbWVzLmNhcGl0YWw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAga2V5ID0gXCJ2aWV3X2VudW1zX3NlbGVjdFwiO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB7IHRhcmdldEVudGl0eU5hbWVzLCBpZCB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICAgICAgdGFyZ2V0RW50aXR5SWQgPSB0YXJnZXRFbnRpdHlOYW1lcy5jYXBpdGFsO1xuICAgICAgICAgICAgZW51bUlkID0gaWQ7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGtleSA9IFwidmlld19pZF9hc3luY19zZWxlY3RcIjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZWxQcm9wID0gZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lLnJlcGxhY2UoXCJfaWRcIiwgXCJcIikpO1xuICAgICAgICAgIHRhcmdldEVudGl0eUlkID0gcmVsUHJvcC53aXRoO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBwcmVUZW1wbGF0ZXMucHVzaCh7XG4gICAgICAgIGtleSxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgIGVudGl0eUlkOiB0YXJnZXRFbnRpdHlJZCxcbiAgICAgICAgICBlbnVtSWQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyDrpqzsiqTtirgg7Lus65+8XG4gICAgYXNzZXJ0KGNvbHVtbnNOb2RlLmNoaWxkcmVuKTtcbiAgICBjb25zdCBjb2x1bW5JbXBvcnRzID0gdW5pcXVlKFxuICAgICAgY29sdW1uc05vZGUuY2hpbGRyZW5cbiAgICAgICAgLmZsYXRNYXAoKGNvbCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLnJlbmRlckNvbHVtbkltcG9ydChlbnRpdHlJZCwgY29sLCBuYW1lcyk7XG4gICAgICAgIH0pXG4gICAgICAgIC5maWx0ZXIoKGNvbCkgPT4gY29sICE9PSBudWxsKSxcbiAgICApLmpvaW4oXCJcXG5cIik7XG5cbiAgICAvLyBTZWFyY2hJbnB1dFxuICAgIGFzc2VydChwcmVUZW1wbGF0ZXMpO1xuICAgIHByZVRlbXBsYXRlcy5wdXNoKHtcbiAgICAgIGtleTogXCJ2aWV3X3NlYXJjaF9pbnB1dFwiLFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICBlbnRpdHlJZCxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyDrlJTtj7Ttirgg7YyM652866+47YSwXG4gICAgY29uc3QgZGVmID0gdGhpcy5nZXREZWZhdWx0KGZpbHRlckNvbHVtbnMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnRoaXMuZ2V0VGFyZ2V0QW5kUGF0aChuYW1lcyksXG4gICAgICBib2R5OiBgXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgTGluayB9IGZyb20gJ3JlYWN0LXJvdXRlci1kb20nO1xuaW1wb3J0IHtcbiAgQnJlYWRjcnVtYixcbiAgQ2hlY2tib3gsXG4gIFBhZ2luYXRpb24sXG4gIFNlZ21lbnQsXG4gIFRhYmxlLFxuICBUYWJsZVJvdyxcbiAgTWVzc2FnZSxcbiAgVHJhbnNpdGlvbixcbiAgQnV0dG9uLFxuICBMYWJlbCxcbn0gZnJvbSAnc2VtYW50aWMtdWktcmVhY3QnO1xuaW1wb3J0IGNsYXNzTmFtZXMgZnJvbSAnY2xhc3NuYW1lcyc7XG5pbXBvcnQgeyBEYXRlVGltZSB9IGZyb20gXCJsdXhvblwiO1xuaW1wb3J0IHsgRGVsQnV0dG9uLCBFZGl0QnV0dG9uLCBBcHBCcmVhZGNydW1icywgQWRkQnV0dG9uLCB1c2VTZWxlY3Rpb24sIHVzZUxpc3RQYXJhbXMsIFNvbmFtdUNvbCwgbnVtRiwgZm9ybWF0RGF0ZSwgZm9ybWF0RGF0ZVRpbWUgfSBmcm9tICdAc29uYW11LWtpdC9yZWFjdC1zdWknO1xuXG5pbXBvcnQgeyAke25hbWVzLmNhcGl0YWx9U3Vic2V0QSB9IGZyb20gXCJAL3NlcnZpY2VzL3NvbmFtdS5nZW5lcmF0ZWRcIjtcbmltcG9ydCB7ICR7bmFtZXMuY2FwaXRhbH1TZXJ2aWNlIH0gZnJvbSAnQC9zZXJ2aWNlcy9zZXJ2aWNlcy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfUxpc3RQYXJhbXMgfSBmcm9tICdAL3NlcnZpY2VzLyR7bmFtZXMuZnN9LyR7bmFtZXMuZnN9LnR5cGVzJztcbiR7Y29sdW1uSW1wb3J0c31cbiR7ZmlsdGVyQ29sdW1uc1xuICAubWFwKChjb2wpID0+IHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJGaWx0ZXJJbXBvcnQoZW50aXR5SWQsIGNvbCwgbmFtZXMpO1xuICB9KVxuICAuam9pbihcIlxcblwiKX1cblxudHlwZSAke25hbWVzLmNhcGl0YWx9TGlzdFByb3BzID0ge307XG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiAke25hbWVzLmNhcGl0YWx9TGlzdCh7fTogJHtuYW1lcy5jYXBpdGFsfUxpc3RQcm9wcykge1xuICAvLyDrpqzsiqTtirgg7ZWE7YSwXG4gIGNvbnN0IHsgbGlzdFBhcmFtcywgcmVnaXN0ZXIgfSA9IHVzZUxpc3RQYXJhbXMoJHtuYW1lcy5jYXBpdGFsfUxpc3RQYXJhbXMsIHtcbiAgICBudW06IDEyLFxuICAgIHBhZ2U6IDEsXG4gICAgb3JkZXJCeTogJyR7ZGVmLm9yZGVyQnl9JyxcbiAgICBzZWFyY2g6ICcke2RlZi5zZWFyY2h9JyxcbiAgfSk7XG5cbiAgLy8g66as7Iqk7Yq4IOy/vOumrFxuICBjb25zdCB7IGRhdGEsIHJlZmV0Y2gsIGlzTG9hZGluZyB9ID0gJHtuYW1lcy5jYXBpdGFsfVNlcnZpY2UudXNlJHtcbiAgICBuYW1lcy5jYXBpdGFsUGx1cmFsXG4gIH0oJ0EnLCBsaXN0UGFyYW1zKTtcbiAgY29uc3QgeyByb3dzLCB0b3RhbCB9ID0gZGF0YSA/PyB7fTtcblxuICAvLyDsgq3soJxcbiAgY29uc3QgY29uZmlybURlbCA9IChpZHM6IG51bWJlcltdKSA9PiB7XG4gICAgY29uc3QgYW5zd2VyID0gY29uZmlybSgn7IKt7KCc7ZWY7Iuc6rKg7Iq164uI6rmMPycpO1xuICAgIGlmICghYW5zd2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgJHtuYW1lcy5jYXBpdGFsfVNlcnZpY2UuZGVsKGlkcykudGhlbigoKSA9PiB7XG4gICAgICByZWZldGNoKCk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8g7J286rSEIOyCreygnFxuICBjb25zdCBjb25maXJtRGVsU2VsZWN0ZWQgPSAoKSA9PiB7XG4gICAgY29uc3QgYW5zd2VyID0gY29uZmlybShcXGBcXCR7c2VsZWN0ZWRLZXlzLmxlbmd0aH3qsbTsnYQg7J286rSEIOyCreygnO2VmOyLnOqyoOyKteuLiOq5jD9cXGApO1xuICAgIGlmICghYW5zd2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgJHtuYW1lcy5jYXBpdGFsfVNlcnZpY2UuZGVsKHNlbGVjdGVkS2V5cykudGhlbigoKSA9PiB7XG4gICAgICByZWZldGNoKCk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8g7ZiE7J6sIOqyveuhnOyZgCDtg4DsnbTti4BcbiAgY29uc3QgUEFHRSA9IHtcbiAgICByb3V0ZTogJy9hZG1pbi8ke25hbWVzLmZzUGx1cmFsfScsXG4gICAgdGl0bGU6ICcke2VudGl0eS50aXRsZSA/PyBuYW1lcy5jYXBpdGFsfScsXG4gIH07XG5cbiAgLy8g7ISg7YOdXG4gIGNvbnN0IHtcbiAgICBnZXRTZWxlY3RlZCxcbiAgICBpc0FsbFNlbGVjdGVkLFxuICAgIHNlbGVjdGVkS2V5cyxcbiAgICB0b2dnbGUsXG4gICAgc2VsZWN0QWxsLFxuICAgIGRlc2VsZWN0QWxsLFxuICAgIGhhbmRsZUNoZWNrYm94Q2xpY2ssXG4gIH0gPSB1c2VTZWxlY3Rpb24oKHJvd3MgPz8gW10pLm1hcCgocm93KSA9PiByb3cuaWQpKTtcblxuICAvLyDsu6zrn7xcbiAgY29uc3QgY29sdW1uczpTb25hbXVDb2w8JHtuYW1lcy5jYXBpdGFsfVN1YnNldEE+W10gPSBbJHtjb2x1bW5zXG4gICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICByZXR1cm4gW1xuICAgICAgICBgeyBsYWJlbDogXCIke2NvbC5sYWJlbH1cIixgLFxuICAgICAgICBgdGM6ICR7Y29sLnRjfSwgYCxcbiAgICAgICAgYGNvbGxhcHNpbmc6ICR7W1wiVGl0bGVcIiwgXCJOYW1lXCJdLmluY2x1ZGVzKGNvbC5sYWJlbCkgPT09IGZhbHNlfSwgfWAsXG4gICAgICBdLmpvaW4oXCJcXG5cIik7XG4gICAgfSlcbiAgICAuam9pbihcIixcXG5cIil9XTtcblxuICByZXR1cm4gKFxuICAgIDxkaXYgY2xhc3NOYW1lPVwibGlzdCAke25hbWVzLmZzUGx1cmFsfS1pbmRleFwiPlxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJ0b3AtbmF2XCI+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiaGVhZGVyLXJvd1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiaGVhZGVyXCI+e1BBR0UudGl0bGV9PC9kaXY+XG4gICAgICAgICAgPEFwcEJyZWFkY3J1bWJzPlxuICAgICAgICAgICAgPEJyZWFkY3J1bWIuU2VjdGlvbiBhY3RpdmU+e1BBR0UudGl0bGV9PC9CcmVhZGNydW1iLlNlY3Rpb24+XG4gICAgICAgICAgPC9BcHBCcmVhZGNydW1icz5cbiAgICAgICAgICA8JHtuYW1lcy5jYXBpdGFsfVNlYXJjaElucHV0XG4gICAgICAgICAgICBpbnB1dD17cmVnaXN0ZXIoJ2tleXdvcmQnKX1cbiAgICAgICAgICAgIGRyb3Bkb3duPXtyZWdpc3Rlcignc2VhcmNoJyl9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmlsdGVycy1yb3dcIj5cbiAgICAgICAgICAke2ZpbHRlckNvbHVtbnNcbiAgICAgICAgICAgIC5tYXAoKGNvbCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJGaWx0ZXIoZW50aXR5SWQsIGNvbCwgbmFtZXMpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5qb2luKFwiJm5ic3A7XFxuXCIpfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8U2VnbWVudCBiYXNpYyBwYWRkZWQgY2xhc3NOYW1lPVwiY29udGVudHMtc2VnbWVudFwiIGxvYWRpbmc9e2lzTG9hZGluZ30+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYnV0dG9ucy1yb3dcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT17Y2xhc3NOYW1lcygnY291bnQnLCB7IGhpZGRlbjogaXNMb2FkaW5nIH0pfT5cbiAgICAgICAgICAgIHt0b3RhbH0g6rG0XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJidXR0b25zXCI+XG4gICAgICAgICAgICA8QWRkQnV0dG9uIGN1cnJlbnRSb3V0ZT17UEFHRS5yb3V0ZX0gaWNvbj1cIndyaXRlXCIgbGFiZWw9XCLstpTqsIBcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8VGFibGVcbiAgICAgICAgICBjZWxsZWRcbiAgICAgICAgICBjb21wYWN0XG4gICAgICAgICAgc2VsZWN0YWJsZVxuICAgICAgICAgIGNsYXNzTmFtZT17Y2xhc3NOYW1lcyh7IGhpZGRlbjogdG90YWwgPT09IHVuZGVmaW5lZCB8fCB0b3RhbCA9PT0gMCB9KX1cbiAgICAgICAgPlxuICAgICAgICAgIDxUYWJsZS5IZWFkZXI+XG4gICAgICAgICAgICA8VGFibGVSb3c+XG4gICAgICAgICAgICAgIDxUYWJsZS5IZWFkZXJDZWxsIGNvbGxhcHNpbmc+XG4gICAgICAgICAgICAgICAgPENoZWNrYm94XG4gICAgICAgICAgICAgICAgICBsYWJlbD1cIklEXCJcbiAgICAgICAgICAgICAgICAgIGNoZWNrZWQ9e2lzQWxsU2VsZWN0ZWR9XG4gICAgICAgICAgICAgICAgICBvbkNoYW5nZT17aXNBbGxTZWxlY3RlZCA/IGRlc2VsZWN0QWxsIDogc2VsZWN0QWxsfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgIDwvVGFibGUuSGVhZGVyQ2VsbD5cbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC8qIEhlYWRlciAqL1xuICAgICAgICAgICAgICAgIGNvbHVtbnMubWFwKChjb2wsIGluZGV4KSA9PiBjb2wudGggPz8gPFRhYmxlLkhlYWRlckNlbGwga2V5PXtpbmRleH0gY29sbGFwc2luZz17Y29sLmNvbGxhcHNpbmd9PnsgY29sLmxhYmVsIH08L1RhYmxlLkhlYWRlckNlbGw+KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDxUYWJsZS5IZWFkZXJDZWxsPuq0gOumrDwvVGFibGUuSGVhZGVyQ2VsbD5cbiAgICAgICAgICAgIDwvVGFibGVSb3c+XG4gICAgICAgICAgPC9UYWJsZS5IZWFkZXI+XG4gICAgICAgICAgPFRhYmxlLkJvZHk+XG4gICAgICAgICAgICB7cm93cyAmJlxuICAgICAgICAgICAgICByb3dzLm1hcCgocm93LCByb3dJbmRleCkgPT4gKFxuICAgICAgICAgICAgICAgIDxUYWJsZS5Sb3cga2V5PXtyb3cuaWR9PlxuICAgICAgICAgICAgICAgICAgPFRhYmxlLkNlbGw+XG4gICAgICAgICAgICAgICAgICAgIDxDaGVja2JveFxuICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtyb3cuaWR9XG4gICAgICAgICAgICAgICAgICAgICAgY2hlY2tlZD17Z2V0U2VsZWN0ZWQocm93LmlkKX1cbiAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17KCkgPT4gdG9nZ2xlKHJvdy5pZCl9XG4gICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17KGUpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVDaGVja2JveENsaWNrKGUsIHJvd0luZGV4KVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgIDwvVGFibGUuQ2VsbD5cbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgLyogQm9keSAqL1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5zLm1hcCgoY29sLCBjb2xJbmRleCkgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgIDxUYWJsZS5DZWxsIGtleT17Y29sSW5kZXh9IGNvbGxhcHNpbmc9e2NvbC5jb2xsYXBzaW5nfSBjbGFzc05hbWU9e2NvbC5jbGFzc05hbWV9PlxuICAgICAgICAgICAgICAgICAgICAgICAge2NvbC50Yyhyb3csIHJvd0luZGV4KX1cbiAgICAgICAgICAgICAgICAgICAgICA8L1RhYmxlLkNlbGw+XG4gICAgICAgICAgICAgICAgICAgICkpXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8VGFibGUuQ2VsbCBjb2xsYXBzaW5nPlxuICAgICAgICAgICAgICAgICAgICA8RWRpdEJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgIGFzPXtMaW5rfVxuICAgICAgICAgICAgICAgICAgICAgIHRvPXtcXGBcXCR7UEFHRS5yb3V0ZX0vZm9ybT9pZD1cXCR7cm93LmlkfVxcYH1cbiAgICAgICAgICAgICAgICAgICAgICBzdGF0ZT17eyBmcm9tOiBQQUdFLnJvdXRlIH19XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDxEZWxCdXR0b24gb25DbGljaz17KCkgPT4gY29uZmlybURlbChbcm93LmlkXSl9IC8+XG4gICAgICAgICAgICAgICAgICA8L1RhYmxlLkNlbGw+XG4gICAgICAgICAgICAgICAgPC9UYWJsZS5Sb3c+XG4gICAgICAgICAgICAgICkpfVxuICAgICAgICAgIDwvVGFibGUuQm9keT5cbiAgICAgICAgPC9UYWJsZT5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzTmFtZT17Y2xhc3NOYW1lcygncGFnaW5hdGlvbi1yb3cnLCB7XG4gICAgICAgICAgICBoaWRkZW46ICh0b3RhbCA/PyAwKSA9PT0gMCxcbiAgICAgICAgICB9KX1cbiAgICAgICAgPlxuICAgICAgICAgIDxQYWdpbmF0aW9uXG4gICAgICAgICAgICB0b3RhbFBhZ2VzPXtNYXRoLmNlaWwoKHRvdGFsID8/IDApIC8gKGxpc3RQYXJhbXMubnVtID8/IDI0KSl9XG4gICAgICAgICAgICB7Li4ucmVnaXN0ZXIoJ3BhZ2UnKX1cbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvU2VnbWVudD5cblxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJmaXhlZC1tZW51XCI+XG4gICAgICAgIDxUcmFuc2l0aW9uXG4gICAgICAgICAgdmlzaWJsZT17c2VsZWN0ZWRLZXlzLmxlbmd0aCA+IDB9XG4gICAgICAgICAgYW5pbWF0aW9uPVwic2xpZGUgbGVmdFwiXG4gICAgICAgICAgZHVyYXRpb249ezUwMH1cbiAgICAgICAgPlxuICAgICAgICAgIDxNZXNzYWdlIHNpemU9XCJzbWFsbFwiIGNvbG9yPVwidmlvbGV0XCIgY2xhc3NOYW1lPVwidGV4dC1jZW50ZXJcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzTmFtZT1cInB4LTRcIj57c2VsZWN0ZWRLZXlzLmxlbmd0aH3qsJwg7ISg7YOd65CoPC9zcGFuPlxuICAgICAgICAgICAgPEJ1dHRvbiBzaXplPVwidGlueVwiIGNvbG9yPVwidmlvbGV0XCIgb25DbGljaz17KCkgPT4gZGVzZWxlY3RBbGwoKX0+XG4gICAgICAgICAgICAgIOyEoO2DnSDtlbTsoJxcbiAgICAgICAgICAgIDwvQnV0dG9uPlxuICAgICAgICAgICAgPEJ1dHRvbiBzaXplPVwidGlueVwiIGNvbG9yPVwicmVkXCIgb25DbGljaz17Y29uZmlybURlbFNlbGVjdGVkfT5cbiAgICAgICAgICAgICAg7J286rSEIOyCreygnFxuICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgPC9NZXNzYWdlPlxuICAgICAgICA8L1RyYW5zaXRpb24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiAgICAgIGAudHJpbSgpLFxuICAgICAgaW1wb3J0S2V5czogW10sXG4gICAgICBwcmVUZW1wbGF0ZXMsXG4gICAgfTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbImFzc2VydCIsImluZmxlY3Rpb24iLCJmbGF0IiwidW5pcXVlIiwieiIsIkVudGl0eU1hbmFnZXIiLCJnZXRDb2x1bW5zTm9kZSIsImdldEVudW1JbmZvRnJvbUNvbE5hbWUiLCJnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZSIsIlRlbXBsYXRlIiwiZ2V0Wm9kVHlwZUJ5SWQiLCJ6b2RUeXBlVG9SZW5kZXJpbmdOb2RlIiwiVGVtcGxhdGVfX3ZpZXdfbGlzdCIsImdldFRhcmdldEFuZFBhdGgiLCJuYW1lcyIsInRhcmdldCIsInBhdGgiLCJmc1BsdXJhbCIsIndyYXBUYyIsImJvZHkiLCJrZXkiLCJjb2xsYXBzaW5nIiwiY2xhc3NOYW1lIiwicmVuZGVyQ29sdW1uIiwiZW50aXR5SWQiLCJjb2wiLCJwYXJlbnRPYmoiLCJ3aXRob3V0TmFtZSIsImNvbE5hbWUiLCJuYW1lIiwicmVuZGVyVHlwZSIsInJlbFByb3BGayIsInJlcGxhY2UiLCJ3aXRoIiwibnVsbGFibGUiLCJpZCIsImVudW1JZCIsInBpY2tlZENoaWxkIiwiY2hpbGRyZW4iLCJmaW5kIiwiY2hpbGQiLCJjb25maWciLCJwaWNrZWQiLCJFcnJvciIsInJlbmRlckNvbHVtbkltcG9ydCIsImNhcGl0YWwiLCJyZWxQcm9wIiwicmVzdWx0IiwibWFwIiwiZ2V0TmFtZXNGcm9tSWQiLCJlbGVtZW50IiwicmVuZGVyRmlsdGVySW1wb3J0IiwiZnMiLCJjb21wb25lbnRJZCIsImNhbWVsaXplIiwidGFyZ2V0RW50aXR5TmFtZXMiLCJ0YXJnZXRNRE5hbWVzIiwidGFyZ2V0TmFtZXMiLCJyZW5kZXJGaWx0ZXIiLCJpc0NsZWFyYWJsZSIsIm9wdGlvbmFsIiwiZ2V0RGVmYXVsdCIsImNvbHVtbnMiLCJkZWYiLCJvcmRlckJ5Iiwic2VhcmNoIiwib3JkZXJCeVpvZFR5cGUiLCJ6b2RUeXBlIiwiWm9kRW51bSIsIm9wdGlvbnMiLCJ0b1N0cmluZyIsInNlYXJjaFpvZFR5cGUiLCJyZW5kZXIiLCJjb2x1bW5zTm9kZSIsImxpc3RQYXJhbXNab2RUeXBlIiwibGlzdFBhcmFtc05vZGUiLCJlbnRpdHkiLCJnZXQiLCJmaWx0ZXIiLCJwcm9wQ2FuZGlkYXRlIiwicHJvcHMiLCJwIiwibGFiZWwiLCJkZXNjIiwidGMiLCJmaWx0ZXJDb2x1bW5zIiwiaW5jbHVkZXMiLCJlbmRzV2l0aCIsInNvcnQiLCJhIiwicHJlVGVtcGxhdGVzIiwidGFyZ2V0RW50aXR5SWQiLCJwdXNoIiwiY29sdW1uSW1wb3J0cyIsImZsYXRNYXAiLCJqb2luIiwiY2FwaXRhbFBsdXJhbCIsInRpdGxlIiwidHJpbSIsImltcG9ydEtleXMiXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLFlBQVksU0FBUztBQUM1QixPQUFPQyxnQkFBZ0IsYUFBYTtBQUNwQyxTQUFTQyxJQUFJLEVBQUVDLE1BQU0sUUFBUSxVQUFVO0FBQ3ZDLFNBQVNDLENBQUMsUUFBUSxNQUFNO0FBQ3hCLFNBQVNDLGFBQWEsUUFBZ0MsaUNBQThCO0FBRXBGLFNBQVNDLGNBQWMsUUFBUSx5QkFBc0I7QUFDckQsU0FBU0Msc0JBQXNCLEVBQUVDLDBCQUEwQixRQUFRLGdCQUFhO0FBRWhGLFNBQVNDLFFBQVEsUUFBUSxpQkFBYztBQUN2QyxTQUFTQyxjQUFjLEVBQUVDLHNCQUFzQixRQUFRLHNCQUFtQjtBQUUxRSxPQUFPLE1BQU1DLDRCQUE0Qkg7SUFDdkMsYUFBYztRQUNaLEtBQUssQ0FBQztJQUNSO0lBRUFJLGlCQUFpQkMsS0FBd0IsRUFBRTtRQUN6QyxPQUFPO1lBQ0xDLFFBQVE7WUFDUkMsTUFBTSxHQUFHRixNQUFNRyxRQUFRLENBQUMsVUFBVSxDQUFDO1FBQ3JDO0lBQ0Y7SUFFQUMsT0FBT0MsSUFBWSxFQUFFQyxHQUFXLEVBQUVDLGFBQXNCLElBQUksRUFBRUMsWUFBb0IsRUFBRSxFQUFFO1FBQ3BGLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRUYsSUFBSSxDQUFDLEVBQUVDLGFBQWEsZ0JBQWdCLEtBQzdEQyxZQUFZLENBQUMsY0FBYyxFQUFFQSxVQUFVLEdBQUcsQ0FBQyxHQUFHLEdBQy9DLENBQUMsRUFBRUgsS0FBSyxhQUFhLENBQUM7SUFDekI7SUFFQUksYUFDRUMsUUFBZ0IsRUFDaEJDLEdBQWtCLEVBQ2xCWCxLQUF3QixFQUN4QlksWUFBb0IsS0FBSyxFQUN6QkMsY0FBdUIsS0FBSyxFQUNwQjtRQUNSLE1BQU1DLFVBQVVELGNBQWMsR0FBR0QsV0FBVyxHQUFHLEdBQUdBLFVBQVUsQ0FBQyxFQUFFRCxJQUFJSSxJQUFJLEVBQUU7UUFFekUsT0FBUUosSUFBSUssVUFBVTtZQUNwQixLQUFLO1lBQ0wsS0FBSztZQUNMLEtBQUs7Z0JBQ0gsT0FBTyxDQUFDLEdBQUcsRUFBRUYsUUFBUSxJQUFJLENBQUM7WUFDNUIsS0FBSztnQkFBZ0I7b0JBQ25CLE1BQU1HLFlBQVl2QiwyQkFBMkJnQixVQUFVQyxJQUFJSSxJQUFJLENBQUNHLE9BQU8sQ0FBQyxPQUFPO29CQUMvRSxPQUFPLENBQUMsRUFBRSxFQUFFRCxVQUFVRSxJQUFJLENBQUMsRUFBRSxFQUFFTCxRQUFRLElBQUksQ0FBQztnQkFDOUM7WUFDQSxLQUFLO2dCQUNILE9BQU8sQ0FBQyxHQUFHLEVBQUVILElBQUlTLFFBQVEsR0FBRyxHQUFHTixRQUFRLElBQUksQ0FBQyxHQUFHLEdBQUcsVUFBVSxFQUFFQSxRQUFRLFFBQVEsQ0FBQztZQUNqRixLQUFLO2dCQUNILElBQUlILElBQUlTLFFBQVEsRUFBRTtvQkFDaEIsT0FBTyxDQUFDLDZCQUE2QixFQUFFTixRQUFRLGlDQUFpQyxFQUFFQSxRQUFRLFNBQVMsQ0FBQztnQkFDdEcsT0FBTztvQkFDTCxPQUFPLENBQUMsNENBQTRDLEVBQUVBLFFBQVEsU0FBUyxDQUFDO2dCQUMxRTtZQUNGLEtBQUs7Z0JBQ0gsSUFBSUgsSUFBSVMsUUFBUSxFQUFFO29CQUNoQixPQUFPLENBQUMsNkJBQTZCLEVBQUVOLFFBQVEsd0JBQXdCLEVBQUVBLFFBQVEsU0FBUyxDQUFDO2dCQUM3RixPQUFPO29CQUNMLE9BQU8sQ0FBQyxtQ0FBbUMsRUFBRUEsUUFBUSxTQUFTLENBQUM7Z0JBQ2pFO1lBQ0YsS0FBSztnQkFDSCxPQUFPLENBQUMsR0FBRyxFQUFFQSxRQUFRLHdGQUF3RixDQUFDO1lBQ2hILEtBQUs7Z0JBQVM7b0JBQ1osTUFBTSxFQUFFTyxJQUFJQyxNQUFNLEVBQUUsR0FBRzdCLHVCQUF1QmlCLFVBQVVDLElBQUlJLElBQUk7b0JBQ2hFLE9BQU8sQ0FBQyxHQUFHLEVBQUVKLElBQUlTLFFBQVEsR0FBRyxHQUFHTixRQUFRLElBQUksQ0FBQyxHQUFHLEtBQUtRLE9BQU8sTUFBTSxFQUFFUixRQUFRLEtBQUssQ0FBQztnQkFDbkY7WUFDQSxLQUFLO2dCQUNILE9BQU8sQ0FBQyxJQUFJLEVBQUVBLFFBQVEsVUFBVSxFQUFFSCxJQUFJUyxRQUFRLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLHFCQUFxQixDQUFDO1lBQ3RGLEtBQUs7Z0JBQ0gsT0FBTyxDQUFDLEdBQUcsRUFBRVQsSUFBSVMsUUFBUSxHQUFHLEdBQUdOLFFBQVEsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLEVBQUVBLFFBQVEsS0FBSyxDQUFDO1lBQ3pFLEtBQUs7Z0JBQ0gsT0FBTyxDQUFDLGFBQWEsRUFBRUEsUUFBUSxPQUFPLENBQUM7WUFDekMsS0FBSztnQkFBZTtvQkFDbEIsTUFBTVMsY0FBY1osSUFBSWEsUUFBUSxFQUFFQyxLQUFLLENBQUNDLFFBQVVBLE1BQU1YLElBQUksS0FBS0osSUFBSWdCLE1BQU0sRUFBRUM7b0JBQzdFLElBQUksQ0FBQ0wsYUFBYTt3QkFDaEIsTUFBTSxJQUFJTSxNQUFNLENBQUMseUJBQXlCLEVBQUVsQixJQUFJSSxJQUFJLENBQUMsQ0FBQyxDQUFDO29CQUN6RDtvQkFDQSxPQUFPLElBQUksQ0FBQ04sWUFBWSxDQUN0QkMsVUFDQWEsYUFDQXZCLE9BQ0EsR0FBR2MsVUFBVUgsSUFBSVMsUUFBUSxHQUFHLE1BQU0sSUFBSTtnQkFFMUM7WUFDQSxLQUFLO2dCQUNILE9BQU8sQ0FBQyxhQUFhLEVBQUVOLFFBQVEsUUFBUSxDQUFDO1lBQzFDLEtBQUs7Z0JBQ0gscUNBQXFDO2dCQUNyQyxPQUFPLENBQUMsR0FBRyxFQUFFSCxJQUFJUyxRQUFRLEdBQUcsR0FBR04sUUFBUSxHQUFHLENBQUMsR0FBRyxHQUFHLFVBQVUsRUFBRUEsVUFBVUgsSUFBSVMsUUFBUSxHQUFHLEtBQUssU0FBUyxVQUFVLEVBQUVULElBQUlTLFFBQVEsR0FBRyxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBQ3BKO2dCQUNFLE1BQU0sSUFBSVMsTUFBTSxDQUFDLFNBQVMsRUFBRWxCLElBQUlLLFVBQVUsRUFBRTtRQUNoRDtJQUNGO0lBRUFjLG1CQUNFcEIsUUFBZ0IsRUFDaEJDLEdBQWtCLEVBQ2xCWCxLQUF3QixFQUNMO1FBQ25CLElBQUlXLElBQUlLLFVBQVUsS0FBSyxTQUFTO1lBQzlCLE1BQU0sRUFBRUssSUFBSUMsTUFBTSxFQUFFLEdBQUc3Qix1QkFBdUJPLE1BQU0rQixPQUFPLEVBQUVwQixJQUFJSSxJQUFJO1lBQ3JFLE9BQU87Z0JBQUMsQ0FBQyxTQUFTLEVBQUVPLE9BQU8sMkNBQTJDLENBQUM7YUFBQztRQUMxRSxPQUFPLElBQUlYLElBQUlLLFVBQVUsS0FBSyxVQUFVO1lBQ3RDLElBQUk7Z0JBQ0YsTUFBTWdCLFVBQVV0QywyQkFBMkJnQixVQUFVQyxJQUFJSSxJQUFJO2dCQUM3RCxNQUFNa0IsU0FBU3RCLElBQUlhLFFBQVEsRUFBRVUsSUFBSSxDQUFDUjtvQkFDaENoQixXQUFXc0IsUUFBUWIsSUFBSTtvQkFDdkJuQixRQUFRVCxjQUFjNEMsY0FBYyxDQUFDSCxRQUFRYixJQUFJO29CQUNqRCxPQUFPLElBQUksQ0FBQ1csa0JBQWtCLENBQUNwQixVQUFVZ0IsT0FBTzFCO2dCQUNsRDtnQkFDQSxPQUFPWixLQUFLNkMsVUFBVSxFQUFFO1lBQzFCLEVBQUUsT0FBTTtnQkFDTixPQUFPO29CQUFDO2lCQUFLO1lBQ2Y7UUFDRixPQUFPLElBQUl0QixJQUFJSyxVQUFVLEtBQUssU0FBUztZQUNyQzlCLE9BQU95QixJQUFJeUIsT0FBTztZQUNsQixPQUFPLElBQUksQ0FBQ04sa0JBQWtCLENBQUNwQixVQUFVQyxJQUFJeUIsT0FBTyxFQUFFcEM7UUFDeEQ7UUFFQSxPQUFPO1lBQUM7U0FBSztJQUNmO0lBRUFxQyxtQkFBbUIzQixRQUFnQixFQUFFQyxHQUFrQixFQUFFWCxLQUF3QixFQUFFO1FBQ2pGLElBQUlXLElBQUlJLElBQUksS0FBSyxVQUFVO1lBQ3pCLE9BQU8sQ0FBQyxTQUFTLEVBQUVmLE1BQU0rQixPQUFPLENBQUMsaUNBQWlDLEVBQUUvQixNQUFNc0MsRUFBRSxDQUFDLENBQUMsRUFBRXRDLE1BQU0rQixPQUFPLENBQUMsYUFBYSxDQUFDO1FBQzlHLE9BQU8sSUFBSXBCLElBQUlLLFVBQVUsS0FBSyxTQUFTO1lBQ3JDLElBQUlMLElBQUlJLElBQUksS0FBSyxXQUFXO2dCQUMxQixNQUFNd0IsY0FBYyxHQUFHdkMsTUFBTStCLE9BQU8sR0FBRzVDLFdBQVdxRCxRQUFRLENBQUM3QixJQUFJSSxJQUFJLEVBQUUsTUFBTSxDQUFDO2dCQUM1RSxPQUFPLENBQUMsU0FBUyxFQUFFd0IsWUFBWSxzQkFBc0IsRUFBRXZDLE1BQU1zQyxFQUFFLENBQUMsQ0FBQyxFQUFFQyxZQUFZLEVBQUUsQ0FBQztZQUNwRixPQUFPO2dCQUNMLElBQUk7b0JBQ0YsTUFBTSxFQUFFbEIsRUFBRSxFQUFFb0IsbUJBQW1CQyxhQUFhLEVBQUUsR0FBR2pELHVCQUMvQ2lCLFVBQ0FDLElBQUlJLElBQUk7b0JBRVYsTUFBTXdCLGNBQWMsR0FBR2xCLEdBQUcsTUFBTSxDQUFDO29CQUNqQyxPQUFPLENBQUMsU0FBUyxFQUFFa0IsWUFBWSxzQkFBc0IsRUFBRUcsY0FBY0osRUFBRSxDQUFDLENBQUMsRUFBRUMsWUFBWSxFQUFFLENBQUM7Z0JBQzVGLEVBQUUsT0FBTTtvQkFDTixPQUFPO2dCQUNUO1lBQ0Y7UUFDRixPQUFPLElBQUk1QixJQUFJSyxVQUFVLEtBQUssZ0JBQWdCO1lBQzVDLElBQUk7Z0JBQ0YsTUFBTWdCLFVBQVV0QywyQkFBMkJnQixVQUFVQyxJQUFJSSxJQUFJLENBQUNHLE9BQU8sQ0FBQyxPQUFPO2dCQUM3RSxNQUFNeUIsY0FBY3BELGNBQWM0QyxjQUFjLENBQUNILFFBQVFiLElBQUk7Z0JBQzdELE1BQU1vQixjQUFjLEdBQUdQLFFBQVFiLElBQUksQ0FBQyxhQUFhLENBQUM7Z0JBQ2xELE9BQU8sQ0FBQyxTQUFTLEVBQUVvQixZQUFZLHNCQUFzQixFQUFFSSxZQUFZTCxFQUFFLENBQUMsQ0FBQyxFQUFFQyxZQUFZLEVBQUUsQ0FBQztZQUMxRixFQUFFLE9BQU07Z0JBQ04sT0FBTztZQUNUO1FBQ0YsT0FBTztZQUNMLE1BQU0sSUFBSVYsTUFBTSxDQUFDLGVBQWUsRUFBRWxCLElBQUlJLElBQUksQ0FBQyxDQUFDLEVBQUVKLElBQUlLLFVBQVUsRUFBRTtRQUNoRTtJQUNGO0lBRUE0QixhQUFhbEMsUUFBZ0IsRUFBRUMsR0FBa0IsRUFBRVgsS0FBd0IsRUFBRTtRQUMzRSxJQUFJVyxJQUFJSSxJQUFJLEtBQUssVUFBVTtZQUN6QixPQUFPO1FBQ1Q7UUFFQSxNQUFNOEIsY0FBY2xDLElBQUltQyxRQUFRLEtBQUssUUFBUW5DLElBQUlJLElBQUksS0FBSztRQUMxRCxJQUFJd0I7UUFDSixJQUFJNUIsSUFBSUssVUFBVSxLQUFLLFNBQVM7WUFDOUIsSUFBSUwsSUFBSUksSUFBSSxLQUFLLFdBQVc7Z0JBQzFCd0IsY0FBYyxHQUFHdkMsTUFBTStCLE9BQU8sR0FBRzVDLFdBQVdxRCxRQUFRLENBQUM3QixJQUFJSSxJQUFJLEVBQUUsTUFBTSxDQUFDO1lBQ3hFLE9BQU87Z0JBQ0wsSUFBSTtvQkFDRixNQUFNLEVBQUVNLEVBQUUsRUFBRSxHQUFHNUIsdUJBQXVCaUIsVUFBVUMsSUFBSUksSUFBSTtvQkFDeER3QixjQUFjLEdBQUdsQixHQUFHLE1BQU0sQ0FBQztnQkFDN0IsRUFBRSxPQUFNO29CQUNOLE9BQU87Z0JBQ1Q7WUFDRjtZQUNBLE9BQU8sQ0FBQyxDQUFDLEVBQUVrQixZQUFZLGVBQWUsRUFBRTVCLElBQUlJLElBQUksQ0FBQyxJQUFJLEVBQUU4QixjQUFjLGNBQWMsR0FBRyxHQUFHLENBQUM7UUFDNUYsT0FBTyxJQUFJbEMsSUFBSUssVUFBVSxLQUFLLGdCQUFnQjtZQUM1QyxJQUFJO2dCQUNGLE1BQU1nQixVQUFVdEMsMkJBQTJCZ0IsVUFBVUMsSUFBSUksSUFBSSxDQUFDRyxPQUFPLENBQUMsT0FBTztnQkFDN0VxQixjQUFjLEdBQUdQLFFBQVFiLElBQUksQ0FBQyxhQUFhLENBQUM7Z0JBQzVDLE9BQU8sQ0FBQyxDQUFDLEVBQUVvQixZQUFZLGVBQWUsRUFBRTVCLElBQUlJLElBQUksQ0FBQyxJQUFJLEVBQ25EOEIsY0FBYyxjQUFjLEdBQzdCLGNBQWMsQ0FBQztZQUNsQixFQUFFLE9BQU07Z0JBQ04sT0FBTztZQUNUO1FBQ0YsT0FBTztZQUNMLE1BQU0sSUFBSWhCLE1BQU0sQ0FBQyxlQUFlLEVBQUVsQixJQUFJSSxJQUFJLENBQUMsQ0FBQyxFQUFFSixJQUFJSyxVQUFVLEVBQUU7UUFDaEU7SUFDRjtJQUVBK0IsV0FBV0MsT0FBd0IsRUFHakM7UUFDQSxNQUFNQyxNQUFNO1lBQ1ZDLFNBQVM7WUFDVEMsUUFBUTtRQUNWO1FBQ0EsTUFBTUMsaUJBQWlCSixRQUFRdkIsSUFBSSxDQUFDLENBQUNkLE1BQVFBLElBQUlJLElBQUksS0FBSyxZQUFZc0M7UUFDdEUsSUFBSUQsa0JBQWtCQSwwQkFBMEI5RCxFQUFFZ0UsT0FBTyxFQUFFO1lBQ3pETCxJQUFJQyxPQUFPLEdBQUdFLGVBQWVHLE9BQU8sQ0FBQyxFQUFFLENBQUNDLFFBQVE7UUFDbEQ7UUFDQSxNQUFNQyxnQkFBZ0JULFFBQVF2QixJQUFJLENBQUMsQ0FBQ2QsTUFBUUEsSUFBSUksSUFBSSxLQUFLLFdBQVdzQztRQUNwRSxJQUFJSSxpQkFBaUJBLHlCQUF5Qm5FLEVBQUVnRSxPQUFPLEVBQUU7WUFDdkRMLElBQUlFLE1BQU0sR0FBR00sY0FBY0YsT0FBTyxDQUFDLEVBQUUsQ0FBQ0MsUUFBUTtRQUNoRDtRQUNBLE9BQU9QO0lBQ1Q7SUFFQSxNQUFNUyxPQUFPLEVBQUVoRCxRQUFRLEVBQWdDLEVBQUU7UUFDdkQsTUFBTWlELGNBQWMsTUFBTW5FLGVBQWVrQixVQUFVO1FBQ25ELE1BQU1rRCxvQkFBb0IsTUFBTWhFLGVBQWUsR0FBR2MsU0FBUyxVQUFVLENBQUM7UUFDdEUsTUFBTW1ELGlCQUFpQmhFLHVCQUF1QitEO1FBRTlDLE1BQU01RCxRQUFRVCxjQUFjNEMsY0FBYyxDQUFDekI7UUFDM0MsTUFBTW9ELFNBQVN2RSxjQUFjd0UsR0FBRyxDQUFDckQ7UUFFakMsWUFBWTtRQUNaLE1BQU1zQyxVQUFVLEFBQUNXLFlBQVluQyxRQUFRLENBQ2xDd0MsTUFBTSxDQUFDLENBQUNyRCxNQUFRQSxJQUFJSSxJQUFJLEtBQUssTUFDN0JtQixHQUFHLENBQUMsQ0FBQ3ZCO1lBQ0osTUFBTXNELGdCQUFnQkgsT0FBT0ksS0FBSyxDQUFDekMsSUFBSSxDQUFDLENBQUMwQyxJQUFNQSxFQUFFcEQsSUFBSSxLQUFLSixJQUFJSSxJQUFJO1lBQ2xFLE9BQU87Z0JBQ0xBLE1BQU1KLElBQUlJLElBQUk7Z0JBQ2RxRCxPQUFPSCxlQUFlSSxRQUFRMUQsSUFBSXlELEtBQUs7Z0JBQ3ZDRSxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQzdELFlBQVksQ0FBQ0MsVUFBVUMsS0FBS1gsUUFBUTtZQUMzRDtRQUNGO1FBRUYsUUFBUTtRQUNSLE1BQU11RSxnQkFBZ0IsQUFBQ1YsZUFBZXJDLFFBQVEsQ0FDM0N3QyxNQUFNLENBQ0wsQ0FBQ3JELE1BQ0NBLElBQUlJLElBQUksS0FBSyxRQUNiSixJQUFJSSxJQUFJLEtBQUssZUFDWixDQUFBO2dCQUFDO2dCQUFTO2FBQVksQ0FBQ3lELFFBQVEsQ0FBQzdELElBQUlLLFVBQVUsS0FBS0wsSUFBSUksSUFBSSxDQUFDMEQsUUFBUSxDQUFDLE1BQUssRUFFL0UsMEJBQTBCO1NBQ3pCQyxJQUFJLENBQUMsQ0FBQ0M7WUFDTCxPQUFPQSxFQUFFNUQsSUFBSSxLQUFLLFlBQVksSUFBSSxDQUFDO1FBQ3JDO1FBRUYscUJBQXFCO1FBQ3JCLE1BQU02RCxlQUFpRCxFQUFFO1FBQ3pELEtBQUssTUFBTWpFLE9BQU80RCxjQUFlO1lBQy9CLElBQUlqRTtZQUNKLElBQUl1RSxpQkFBaUJuRTtZQUNyQixJQUFJWTtZQUVKLElBQUlYLElBQUlLLFVBQVUsS0FBSyxTQUFTO2dCQUM5QixJQUFJTCxJQUFJSSxJQUFJLEtBQUssVUFBVTtvQkFDekJULE1BQU07b0JBQ05nQixTQUFTLEdBQUd0QixNQUFNK0IsT0FBTyxDQUFDLFdBQVcsQ0FBQztvQkFDdEM4QyxpQkFBaUI3RSxNQUFNK0IsT0FBTztnQkFDaEMsT0FBTztvQkFDTHpCLE1BQU07b0JBQ04sSUFBSTt3QkFDRixNQUFNLEVBQUVtQyxpQkFBaUIsRUFBRXBCLEVBQUUsRUFBRSxHQUFHNUIsdUJBQXVCaUIsVUFBVUMsSUFBSUksSUFBSTt3QkFDM0U4RCxpQkFBaUJwQyxrQkFBa0JWLE9BQU87d0JBQzFDVCxTQUFTRDtvQkFDWCxFQUFFLE9BQU07d0JBQ047b0JBQ0Y7Z0JBQ0Y7WUFDRixPQUFPO2dCQUNMZixNQUFNO2dCQUNOLElBQUk7b0JBQ0YsTUFBTTBCLFVBQVV0QywyQkFBMkJnQixVQUFVQyxJQUFJSSxJQUFJLENBQUNHLE9BQU8sQ0FBQyxPQUFPO29CQUM3RTJELGlCQUFpQjdDLFFBQVFiLElBQUk7Z0JBQy9CLEVBQUUsT0FBTTtvQkFDTjtnQkFDRjtZQUNGO1lBRUF5RCxhQUFhRSxJQUFJLENBQUM7Z0JBQ2hCeEU7Z0JBQ0FpRCxTQUFTO29CQUNQN0MsVUFBVW1FO29CQUNWdkQ7Z0JBQ0Y7WUFDRjtRQUNGO1FBRUEsU0FBUztRQUNUcEMsT0FBT3lFLFlBQVluQyxRQUFRO1FBQzNCLE1BQU11RCxnQkFBZ0IxRixPQUNwQnNFLFlBQVluQyxRQUFRLENBQ2pCd0QsT0FBTyxDQUFDLENBQUNyRTtZQUNSLE9BQU8sSUFBSSxDQUFDbUIsa0JBQWtCLENBQUNwQixVQUFVQyxLQUFLWDtRQUNoRCxHQUNDZ0UsTUFBTSxDQUFDLENBQUNyRCxNQUFRQSxRQUFRLE9BQzNCc0UsSUFBSSxDQUFDO1FBRVAsY0FBYztRQUNkL0YsT0FBTzBGO1FBQ1BBLGFBQWFFLElBQUksQ0FBQztZQUNoQnhFLEtBQUs7WUFDTGlELFNBQVM7Z0JBQ1A3QztZQUNGO1FBQ0Y7UUFFQSxXQUFXO1FBQ1gsTUFBTXVDLE1BQU0sSUFBSSxDQUFDRixVQUFVLENBQUN3QjtRQUU1QixPQUFPO1lBQ0wsR0FBRyxJQUFJLENBQUN4RSxnQkFBZ0IsQ0FBQ0MsTUFBTTtZQUMvQkssTUFBTSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O1NBbUJKLEVBQUVMLE1BQU0rQixPQUFPLENBQUM7U0FDaEIsRUFBRS9CLE1BQU0rQixPQUFPLENBQUM7U0FDaEIsRUFBRS9CLE1BQU0rQixPQUFPLENBQUMsOEJBQThCLEVBQUUvQixNQUFNc0MsRUFBRSxDQUFDLENBQUMsRUFBRXRDLE1BQU1zQyxFQUFFLENBQUM7QUFDOUUsRUFBRXlDLGNBQWM7QUFDaEIsRUFBRVIsY0FDQ3JDLEdBQUcsQ0FBQyxDQUFDdkI7Z0JBQ0osT0FBTyxJQUFJLENBQUMwQixrQkFBa0IsQ0FBQzNCLFVBQVVDLEtBQUtYO1lBQ2hELEdBQ0NpRixJQUFJLENBQUMsTUFBTTs7S0FFVCxFQUFFakYsTUFBTStCLE9BQU8sQ0FBQzt3QkFDRyxFQUFFL0IsTUFBTStCLE9BQU8sQ0FBQyxTQUFTLEVBQUUvQixNQUFNK0IsT0FBTyxDQUFDOztpREFFaEIsRUFBRS9CLE1BQU0rQixPQUFPLENBQUM7OztjQUduRCxFQUFFa0IsSUFBSUMsT0FBTyxDQUFDO2FBQ2YsRUFBRUQsSUFBSUUsTUFBTSxDQUFDOzs7O3VDQUlhLEVBQUVuRCxNQUFNK0IsT0FBTyxDQUFDLFdBQVcsRUFDOUQvQixNQUFNa0YsYUFBYSxDQUNwQjs7Ozs7Ozs7OztJQVVDLEVBQUVsRixNQUFNK0IsT0FBTyxDQUFDOzs7Ozs7Ozs7Ozs7SUFZaEIsRUFBRS9CLE1BQU0rQixPQUFPLENBQUM7Ozs7Ozs7bUJBT0QsRUFBRS9CLE1BQU1HLFFBQVEsQ0FBQztZQUN4QixFQUFFMkQsT0FBT3FCLEtBQUssSUFBSW5GLE1BQU0rQixPQUFPLENBQUM7Ozs7Ozs7Ozs7Ozs7OzswQkFlbEIsRUFBRS9CLE1BQU0rQixPQUFPLENBQUMsY0FBYyxFQUFFaUIsUUFDckRkLEdBQUcsQ0FBQyxDQUFDdkI7Z0JBQ0osT0FBTztvQkFDTCxDQUFDLFVBQVUsRUFBRUEsSUFBSXlELEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQzFCLENBQUMsSUFBSSxFQUFFekQsSUFBSTJELEVBQUUsQ0FBQyxFQUFFLENBQUM7b0JBQ2pCLENBQUMsWUFBWSxFQUFFO3dCQUFDO3dCQUFTO3FCQUFPLENBQUNFLFFBQVEsQ0FBQzdELElBQUl5RCxLQUFLLE1BQU0sTUFBTSxHQUFHLENBQUM7aUJBQ3BFLENBQUNhLElBQUksQ0FBQztZQUNULEdBQ0NBLElBQUksQ0FBQyxPQUFPOzs7eUJBR1EsRUFBRWpGLE1BQU1HLFFBQVEsQ0FBQzs7Ozs7OztXQU8vQixFQUFFSCxNQUFNK0IsT0FBTyxDQUFDOzs7Ozs7VUFNakIsRUFBRXdDLGNBQ0NyQyxHQUFHLENBQUMsQ0FBQ3ZCO2dCQUNKLE9BQU8sSUFBSSxDQUFDaUMsWUFBWSxDQUFDbEMsVUFBVUMsS0FBS1g7WUFDMUMsR0FDQ2lGLElBQUksQ0FBQyxZQUFZOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7TUFzR3hCLENBQUMsQ0FBQ0csSUFBSTtZQUNOQyxZQUFZLEVBQUU7WUFDZFQ7UUFDRjtJQUNGO0FBQ0YifQ==
643
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZW1wbGF0ZS9pbXBsZW1lbnRhdGlvbnMvdmlld19saXN0LnRlbXBsYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBpbmZsZWN0aW9uIGZyb20gXCJpbmZsZWN0aW9uXCI7XG5pbXBvcnQgeyBmbGF0IH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyLCB0eXBlIEVudGl0eU5hbWVzUmVjb3JkIH0gZnJvbSBcIi4uLy4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJpbmdOb2RlLCBUZW1wbGF0ZUtleSwgVGVtcGxhdGVPcHRpb25zIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lLCBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZSB9IGZyb20gXCIuLi9oZWxwZXJzXCI7XG5pbXBvcnQgdHlwZSB7IFJlbmRlcmVkVGVtcGxhdGUgfSBmcm9tIFwiLi4vdGVtcGxhdGVcIjtcbmltcG9ydCB7IFRlbXBsYXRlIH0gZnJvbSBcIi4uL3RlbXBsYXRlXCI7XG5cbmV4cG9ydCBjbGFzcyBUZW1wbGF0ZV9fdmlld19saXN0IGV4dGVuZHMgVGVtcGxhdGUge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcInZpZXdfbGlzdFwiKTtcbiAgfVxuXG4gIGdldFRhcmdldEFuZFBhdGgobmFtZXM6IEVudGl0eU5hbWVzUmVjb3JkKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRhcmdldDogXCJ3ZWIvc3JjL3JvdXRlcy9hZG1pblwiLFxuICAgICAgcGF0aDogYCR7bmFtZXMuZnNQbHVyYWx9L2luZGV4LnRzeGAsXG4gICAgfTtcbiAgfVxuXG4gIHdyYXBUYyhib2R5OiBzdHJpbmcsIGtleTogc3RyaW5nLCBjb2xsYXBzaW5nOiBib29sZWFuID0gdHJ1ZSwgY2xhc3NOYW1lOiBzdHJpbmcgPSBcIlwiKSB7XG4gICAgcmV0dXJuIGA8VGFibGUuQ2VsbCBrZXk9XCIke2tleX1cIiR7Y29sbGFwc2luZyA/IFwiIGNvbGxhcHNpbmdcIiA6IFwiXCJ9JHtcbiAgICAgIGNsYXNzTmFtZSA/IGAgY2xhc3NOYW1lPXtcXGAke2NsYXNzTmFtZX1cXGB9YCA6IFwiXCJcbiAgICB9PiR7Ym9keX08L1RhYmxlLkNlbGw+YDtcbiAgfVxuXG4gIHJlbmRlckNvbHVtbihcbiAgICBlbnRpdHlJZDogc3RyaW5nLFxuICAgIGNvbDogUmVuZGVyaW5nTm9kZSxcbiAgICBuYW1lczogRW50aXR5TmFtZXNSZWNvcmQsXG4gICAgcGFyZW50T2JqOiBzdHJpbmcgPSBcInJvd1wiLFxuICAgIHdpdGhvdXROYW1lOiBib29sZWFuID0gZmFsc2UsXG4gICk6IHN0cmluZyB7XG4gICAgLy8g7KSR7LKpIOqyveuhnCDsspjrpqwgKOyYiDogXCJ1c2VyLm5hbWVcIiAtPiBcInJvdy51c2VyPy5uYW1lXCIpXG4gICAgbGV0IGNvbE5hbWU6IHN0cmluZztcbiAgICBpZiAod2l0aG91dE5hbWUpIHtcbiAgICAgIGNvbE5hbWUgPSBwYXJlbnRPYmo7XG4gICAgfSBlbHNlIGlmIChjb2wubmFtZS5pbmNsdWRlcyhcIi5cIikpIHtcbiAgICAgIC8vIOykkeyyqSDqsr3roZzripQgb3B0aW9uYWwgY2hhaW5pbmfsnLzroZwg67OA7ZmYXG4gICAgICBjb25zdCBwYXJ0cyA9IGNvbC5uYW1lLnNwbGl0KFwiLlwiKTtcbiAgICAgIGNvbE5hbWUgPSBgJHtwYXJlbnRPYmp9LiR7cGFydHMuam9pbihcIj8uXCIpfWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbE5hbWUgPSBgJHtwYXJlbnRPYmp9LiR7Y29sLm5hbWV9YDtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGNvbC5yZW5kZXJUeXBlKSB7XG4gICAgICBjYXNlIFwic3RyaW5nLXBsYWluXCI6XG4gICAgICBjYXNlIFwic3RyaW5nLWRhdGVcIjpcbiAgICAgIGNhc2UgXCJudW1iZXItaWRcIjpcbiAgICAgICAgcmV0dXJuIGA8Pnske2NvbE5hbWV9fTwvPmA7XG4gICAgICBjYXNlIFwibnVtYmVyLWZrX2lkXCI6IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBiYXNlTmFtZSA9IGNvbC5uYW1lLmluY2x1ZGVzKFwiLlwiKVxuICAgICAgICAgICAgPyAoY29sLm5hbWUuc3BsaXQoXCIuXCIpLnBvcCgpID8/IGNvbC5uYW1lKS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpXG4gICAgICAgICAgICA6IGNvbC5uYW1lLnJlcGxhY2UoXCJfaWRcIiwgXCJcIik7XG4gICAgICAgICAgY29uc3QgcmVsUHJvcEZrID0gZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUoZW50aXR5SWQsIGJhc2VOYW1lKTtcbiAgICAgICAgICByZXR1cm4gYDw+JHtyZWxQcm9wRmsud2l0aH0jeyR7Y29sTmFtZX19PC8+YDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGA8Pnske2NvbE5hbWV9fTwvPmA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNhc2UgXCJzdHJpbmctaW1hZ2VcIjpcbiAgICAgICAgcmV0dXJuIGA8Pnske1xuICAgICAgICAgIGNvbC5udWxsYWJsZSA/IGAke2NvbE5hbWV9ICYmIGAgOiBcIlwiXG4gICAgICAgIH08aW1nIHNyYz17JHtjb2xOYW1lfX0gYWx0PVwiJHtjb2wubGFiZWwgPz8gY29sLm5hbWV9XCIgY2xhc3NOYW1lPVwiaC04IHctOCBvYmplY3QtY292ZXIgcm91bmRlZFwiIC8+fTwvPmA7XG4gICAgICBjYXNlIFwiZGF0ZXRpbWVcIjpcbiAgICAgICAgaWYgKGNvbC5udWxsYWJsZSB8fCBjb2wubmFtZS5pbmNsdWRlcyhcIi5cIikpIHtcbiAgICAgICAgICByZXR1cm4gYDxzcGFuPnske2NvbE5hbWV9ID8gZGF0ZXRpbWVGKCR7Y29sTmFtZX0pIDogJy0nfTwvc3Bhbj5gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgPHNwYW4+e2RhdGV0aW1lRigke2NvbE5hbWV9KX08L3NwYW4+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcInN0cmluZy1kYXRldGltZVwiOlxuICAgICAgICBpZiAoY29sLm51bGxhYmxlIHx8IGNvbC5uYW1lLmluY2x1ZGVzKFwiLlwiKSkge1xuICAgICAgICAgIHJldHVybiBgPHNwYW4+eyR7Y29sTmFtZX0gPyBkYXRlRigke2NvbE5hbWV9KSA6ICctJ308L3NwYW4+YDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gYDxzcGFuPntkYXRlRigke2NvbE5hbWV9KX08L3NwYW4+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgICAgcmV0dXJuIGA8Pnske2NvbE5hbWV9ID8gPEJhZGdlIHZhcmlhbnQ9XCJkZWZhdWx0XCI+TzwvQmFkZ2U+IDogPEJhZGdlIHZhcmlhbnQ9XCJzZWNvbmRhcnlcIj5YPC9CYWRnZT59PC8+YDtcbiAgICAgIGNhc2UgXCJlbnVtc1wiOiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBpZDogZW51bUlkIH0gPSBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZSk7XG4gICAgICAgICAgcmV0dXJuIGA8Pnske2NvbC5udWxsYWJsZSA/IGAke2NvbE5hbWV9ICYmIGAgOiBcIlwifSR7ZW51bUlkfUxhYmVsWyR7Y29sTmFtZX1dfTwvPmA7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBgPD57JHtjb2xOYW1lfX08Lz5gO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjYXNlIFwiYXJyYXktaW1hZ2VzXCI6XG4gICAgICAgIHJldHVybiBgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGdhcC0xXCI+eyAke2NvbE5hbWV9Py5tYXAoKHIsIGkpID0+ICR7XG4gICAgICAgICAgY29sLm51bGxhYmxlID8gYHIgJiYgYCA6IFwiXCJcbiAgICAgICAgfTxpbWcga2V5PXtpfSBzcmM9e3J9IGFsdD17XFxgJHtjb2wubGFiZWwgPz8gY29sLm5hbWV9IFxcJHtpICsgMX1cXGB9IGNsYXNzTmFtZT1cImgtOCB3LTggb2JqZWN0LWNvdmVyIHJvdW5kZWRcIiAvPikgfTwvZGl2PmA7XG4gICAgICBjYXNlIFwibnVtYmVyLXBsYWluXCI6XG4gICAgICAgIHJldHVybiBgPD57JHtjb2wubnVsbGFibGUgfHwgY29sLm5hbWUuaW5jbHVkZXMoXCIuXCIpID8gYCR7Y29sTmFtZX0gJiYgYCA6IFwiXCJ9bnVtRigke2NvbE5hbWV9KX08Lz5gO1xuICAgICAgY2FzZSBcIm9iamVjdFwiOlxuICAgICAgICByZXR1cm4gYDxzcGFuIGNsYXNzTmFtZT1cInRleHQteHNcIj57JHtjb2wubnVsbGFibGUgPyBgJHtjb2xOYW1lfSA/IGAgOiBcIlwifUpTT04uc3RyaW5naWZ5KCR7Y29sTmFtZX0pJHtjb2wubnVsbGFibGUgPyBgIDogJy0nYCA6IFwiXCJ9fTwvc3Bhbj5gO1xuICAgICAgY2FzZSBcIm9iamVjdC1waWNrXCI6IHtcbiAgICAgICAgY29uc3QgcGlja2VkQ2hpbGQgPSBjb2wuY2hpbGRyZW4/LmZpbmQoKGNoaWxkKSA9PiBjaGlsZC5uYW1lID09PSBjb2wuY29uZmlnPy5waWNrZWQpO1xuICAgICAgICBpZiAoIXBpY2tlZENoaWxkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBvYmplY3QtcGljayDshKDtg50g7Iuk7YyoICjsmKTruIzsoJ3tirg6ICR7Y29sLm5hbWV9KWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlckNvbHVtbihcbiAgICAgICAgICBlbnRpdHlJZCxcbiAgICAgICAgICBwaWNrZWRDaGlsZCxcbiAgICAgICAgICBuYW1lcyxcbiAgICAgICAgICBgJHtjb2xOYW1lfSR7Y29sLm51bGxhYmxlID8gXCI/XCIgOiBcIlwifWAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBjYXNlIFwiYXJyYXlcIjpcbiAgICAgICAgcmV0dXJuIGA8PnsgLyogYXJyYXkgJHtjb2xOYW1lfSAqLyB9PC8+YDtcbiAgICAgIGNhc2UgXCJ2ZWN0b3JcIjpcbiAgICAgICAgLy8gdmVjdG9yIO2DgOyeheydgCDssKjsm5Ag7IiY66eMIO2RnOyLnCAo7Iuk7KCcIOuNsOydtO2EsOuKlCDrhIjrrLQg6rmAKVxuICAgICAgICByZXR1cm4gYDw+eyR7Y29sLm51bGxhYmxlID8gYCR7Y29sTmFtZX0gPyBgIDogXCJcIn1bVmVjdG9yOiB7JHtjb2xOYW1lfSR7Y29sLm51bGxhYmxlID8gXCJcIiA6IFwiID8/IFtdXCJ9Lmxlbmd0aH1kXSR7Y29sLm51bGxhYmxlID8gXCIgOiAnLSdcIiA6IFwiXCJ9fTwvPmA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOugjOuNlCDrtojqsIAg7Lus65+8ICR7Y29sLnJlbmRlclR5cGV9YCk7XG4gICAgfVxuICB9XG5cbiAgcmVuZGVyQ29sdW1uSW1wb3J0KFxuICAgIGVudGl0eUlkOiBzdHJpbmcsXG4gICAgY29sOiBSZW5kZXJpbmdOb2RlLFxuICAgIG5hbWVzOiBFbnRpdHlOYW1lc1JlY29yZCxcbiAgKTogKHN0cmluZyB8IG51bGwpW10ge1xuICAgIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJlbnVtc1wiKSB7XG4gICAgICBjb25zdCB7IGlkOiBlbnVtSWQgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUobmFtZXMuY2FwaXRhbCwgY29sLm5hbWUpO1xuICAgICAgcmV0dXJuIFtgaW1wb3J0IHsgJHtlbnVtSWR9TGFiZWwgfSBmcm9tICdAL3NlcnZpY2VzL3NvbmFtdS5nZW5lcmF0ZWQnO2BdO1xuICAgIH0gZWxzZSBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlbFByb3AgPSBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICBjb25zdCByZXN1bHQgPSAoY29sLmNoaWxkcmVuID8/IFtdKS5tYXAoKGNoaWxkKSA9PiB7XG4gICAgICAgICAgZW50aXR5SWQgPSByZWxQcm9wLndpdGg7XG4gICAgICAgICAgbmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKHJlbFByb3Aud2l0aCk7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyQ29sdW1uSW1wb3J0KGVudGl0eUlkLCBjaGlsZCwgbmFtZXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGZsYXQocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gW251bGxdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwiYXJyYXlcIikge1xuICAgICAgaWYgKCFjb2wuZWxlbWVudCkgcmV0dXJuIFtudWxsXTtcbiAgICAgIHJldHVybiB0aGlzLnJlbmRlckNvbHVtbkltcG9ydChlbnRpdHlJZCwgY29sLmVsZW1lbnQsIG5hbWVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW251bGxdO1xuICB9XG5cbiAgcmVuZGVyRmlsdGVySW1wb3J0KGVudGl0eUlkOiBzdHJpbmcsIGNvbDogUmVuZGVyaW5nTm9kZSwgbmFtZXM6IEVudGl0eU5hbWVzUmVjb3JkKSB7XG4gICAgaWYgKGNvbC5uYW1lID09PSBcInNlYXJjaFwiKSB7XG4gICAgICByZXR1cm4gYGltcG9ydCB7ICR7bmFtZXMuY2FwaXRhbH1TZWFyY2hJbnB1dCB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHtuYW1lcy5mc30vJHtuYW1lcy5jYXBpdGFsfVNlYXJjaElucHV0XCI7YDtcbiAgICB9IGVsc2UgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgIGlmIChjb2wubmFtZSA9PT0gXCJvcmRlckJ5XCIpIHtcbiAgICAgICAgY29uc3QgY29tcG9uZW50SWQgPSBgJHtuYW1lcy5jYXBpdGFsfSR7aW5mbGVjdGlvbi5jYW1lbGl6ZShjb2wubmFtZSl9U2VsZWN0YDtcbiAgICAgICAgcmV0dXJuIGBpbXBvcnQgeyAke2NvbXBvbmVudElkfSB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHtuYW1lcy5mc30vJHtjb21wb25lbnRJZH1cIjtgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB7IGlkLCB0YXJnZXRFbnRpdHlOYW1lczogdGFyZ2V0TUROYW1lcyB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShcbiAgICAgICAgICAgIGVudGl0eUlkLFxuICAgICAgICAgICAgY29sLm5hbWUsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBjb21wb25lbnRJZCA9IGAke2lkfVNlbGVjdGA7XG4gICAgICAgICAgcmV0dXJuIGBpbXBvcnQgeyAke2NvbXBvbmVudElkfSB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHt0YXJnZXRNRE5hbWVzLmZzfS8ke2NvbXBvbmVudElkfVwiO2A7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJudW1iZXItZmtfaWRcIikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0TmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKHJlbFByb3Aud2l0aCk7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudElkID0gYCR7cmVsUHJvcC53aXRofUlkQXN5bmNTZWxlY3RgO1xuICAgICAgICByZXR1cm4gYGltcG9ydCB7ICR7Y29tcG9uZW50SWR9IH0gZnJvbSBcIkAvY29tcG9uZW50cy8ke3RhcmdldE5hbWVzLmZzfS8ke2NvbXBvbmVudElkfVwiO2A7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihg66CM642UIOu2iOqwgOuKpe2VnCDtlYTthLAg7J6E7Y+s7Yq4ICR7Y29sLm5hbWV9ICR7Y29sLnJlbmRlclR5cGV9YCk7XG4gICAgfVxuICB9XG5cbiAgcmVuZGVyRmlsdGVyKGVudGl0eUlkOiBzdHJpbmcsIGNvbDogUmVuZGVyaW5nTm9kZSwgbmFtZXM6IEVudGl0eU5hbWVzUmVjb3JkKSB7XG4gICAgaWYgKGNvbC5uYW1lID09PSBcInNlYXJjaFwiKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICBjb25zdCBpc0NsZWFyYWJsZSA9IGNvbC5vcHRpb25hbCA9PT0gdHJ1ZSAmJiBjb2wubmFtZSAhPT0gXCJvcmRlckJ5XCI7XG4gICAgbGV0IGNvbXBvbmVudElkOiBzdHJpbmc7XG4gICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgIGlmIChjb2wubmFtZSA9PT0gXCJvcmRlckJ5XCIpIHtcbiAgICAgICAgY29tcG9uZW50SWQgPSBgJHtuYW1lcy5jYXBpdGFsfSR7aW5mbGVjdGlvbi5jYW1lbGl6ZShjb2wubmFtZSl9U2VsZWN0YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgeyBpZCB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICAgIGNvbXBvbmVudElkID0gYCR7aWR9U2VsZWN0YDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBgPCR7Y29tcG9uZW50SWR9IHsuLi5yZWdpc3RlcignJHtjb2wubmFtZX0nKX0gJHtpc0NsZWFyYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwifSAvPmA7XG4gICAgfSBlbHNlIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJudW1iZXItZmtfaWRcIikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgY29tcG9uZW50SWQgPSBgJHtyZWxQcm9wLndpdGh9SWRBc3luY1NlbGVjdGA7XG4gICAgICAgIHJldHVybiBgPCR7Y29tcG9uZW50SWR9IHsuLi5yZWdpc3RlcignJHtjb2wubmFtZX0nKX0gJHtcbiAgICAgICAgICBpc0NsZWFyYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwiXG4gICAgICAgIH0gc3Vic2V0PVwiQVwiIC8+YDtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGDroIzrjZQg67aI6rCA64ql7ZWcIO2VhO2EsCDsnoTtj6ztirggJHtjb2wubmFtZX0gJHtjb2wucmVuZGVyVHlwZX1gKTtcbiAgICB9XG4gIH1cblxuICBnZXREZWZhdWx0KGNvbHVtbnM6IFJlbmRlcmluZ05vZGVbXSk6IHtcbiAgICBvcmRlckJ5OiBzdHJpbmc7XG4gICAgc2VhcmNoOiBzdHJpbmc7XG4gICAgaGFzU2VhcmNoOiBib29sZWFuO1xuICAgIGhhc09yZGVyQnk6IGJvb2xlYW47XG4gIH0ge1xuICAgIGNvbnN0IGRlZiA9IHtcbiAgICAgIG9yZGVyQnk6IFwiXCIsXG4gICAgICBzZWFyY2g6IFwiXCIsXG4gICAgICBoYXNTZWFyY2g6IGZhbHNlLFxuICAgICAgaGFzT3JkZXJCeTogZmFsc2UsXG4gICAgfTtcbiAgICBjb25zdCBvcmRlckJ5Wm9kVHlwZSA9IGNvbHVtbnMuZmluZCgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJvcmRlckJ5XCIpPy56b2RUeXBlO1xuICAgIGlmIChvcmRlckJ5Wm9kVHlwZSAmJiBvcmRlckJ5Wm9kVHlwZSBpbnN0YW5jZW9mIHouWm9kRW51bSkge1xuICAgICAgZGVmLm9yZGVyQnkgPSBPYmplY3Qua2V5cyhvcmRlckJ5Wm9kVHlwZS5lbnVtKVswXTtcbiAgICAgIGRlZi5oYXNPcmRlckJ5ID0gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3Qgc2VhcmNoWm9kVHlwZSA9IGNvbHVtbnMuZmluZCgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJzZWFyY2hcIik/LnpvZFR5cGU7XG4gICAgaWYgKHNlYXJjaFpvZFR5cGUgJiYgc2VhcmNoWm9kVHlwZSBpbnN0YW5jZW9mIHouWm9kRW51bSkge1xuICAgICAgZGVmLnNlYXJjaCA9IE9iamVjdC5rZXlzKHNlYXJjaFpvZFR5cGUuZW51bSlbMF07XG4gICAgICBkZWYuaGFzU2VhcmNoID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZjtcbiAgfVxuXG4gIGFzeW5jIHJlbmRlcih7IGVudGl0eUlkIH06IFRlbXBsYXRlT3B0aW9uc1tcInZpZXdfbGlzdFwiXSkge1xuICAgIGNvbnN0IHsgZ2V0Q29sdW1uc05vZGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL2VudGl0eS1jb252ZXJ0ZXJcIik7XG4gICAgY29uc3QgeyBnZXRab2RUeXBlQnlJZCwgem9kVHlwZVRvUmVuZGVyaW5nTm9kZSB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vem9kLWNvbnZlcnRlclwiKTtcblxuICAgIGNvbnN0IGNvbHVtbnNOb2RlID0gYXdhaXQgZ2V0Q29sdW1uc05vZGUoZW50aXR5SWQsIFwiQVwiKTtcbiAgICBjb25zdCBsaXN0UGFyYW1zWm9kVHlwZSA9IGF3YWl0IGdldFpvZFR5cGVCeUlkKGAke2VudGl0eUlkfUxpc3RQYXJhbXNgKTtcbiAgICBjb25zdCBsaXN0UGFyYW1zTm9kZSA9IHpvZFR5cGVUb1JlbmRlcmluZ05vZGUobGlzdFBhcmFtc1pvZFR5cGUpO1xuXG4gICAgY29uc3QgbmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKGVudGl0eUlkKTtcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG5cbiAgICAvLyDsi6TsoJwg66as7Iqk7Yq4IOy7rOufvFxuICAgIGNvbnN0IGNvbHVtbnMgPSAoY29sdW1uc05vZGUuY2hpbGRyZW4gYXMgUmVuZGVyaW5nTm9kZVtdKVxuXG4gICAgICAuc29ydCgoYSwgYikgPT4gKGEubmFtZSA9PT0gXCJpZFwiID8gLTEgOiBiLm5hbWUgPT09IFwiaWRcIiA/IDEgOiAwKSlcbiAgICAgIC5tYXAoKGNvbCkgPT4ge1xuICAgICAgICBjb25zdCBwcm9wQ2FuZGlkYXRlID0gZW50aXR5LnByb3BzLmZpbmQoKHApID0+IHAubmFtZSA9PT0gY29sLm5hbWUpO1xuICAgICAgICBjb25zdCByZW5kZXJlZCA9IHRoaXMucmVuZGVyQ29sdW1uKGVudGl0eUlkLCBjb2wsIG5hbWVzKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBuYW1lOiBjb2wubmFtZSxcbiAgICAgICAgICBsYWJlbDogY29sLm5hbWUgPT09IFwiaWRcIiA/IFwiSURcIiA6IChwcm9wQ2FuZGlkYXRlPy5kZXNjID8/IGNvbC5sYWJlbCksXG4gICAgICAgICAgdGM6IGAocm93KSA9PiAke3JlbmRlcmVkfWAsXG4gICAgICAgICAgZml0OlxuICAgICAgICAgICAgY29sLnJlbmRlclR5cGUgPT09IFwibnVtYmVyLWlkXCIgfHxcbiAgICAgICAgICAgIGNvbC5yZW5kZXJUeXBlID09PSBcImRhdGV0aW1lXCIgfHxcbiAgICAgICAgICAgIGNvbC5yZW5kZXJUeXBlID09PSBcInN0cmluZy1kYXRldGltZVwiLFxuICAgICAgICAgIGFsaWduOiBjb2wucmVuZGVyVHlwZSA9PT0gXCJudW1iZXItaWRcIiA/IFwiY2VudGVyXCIgOiB1bmRlZmluZWQsXG4gICAgICAgIH07XG4gICAgICB9KTtcblxuICAgIC8vIO2VhO2EsCDsu6zrn7xcbiAgICBjb25zdCBmaWx0ZXJDb2x1bW5zID0gKGxpc3RQYXJhbXNOb2RlLmNoaWxkcmVuIGFzIFJlbmRlcmluZ05vZGVbXSlcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChjb2wpID0+XG4gICAgICAgICAgY29sLm5hbWUgIT09IFwiaWRcIiAmJlxuICAgICAgICAgIGNvbC5uYW1lICE9PSBcInF1ZXJ5TW9kZVwiICYmXG4gICAgICAgICAgKFtcImVudW1zXCIsIFwibnVtYmVyLWlkXCJdLmluY2x1ZGVzKGNvbC5yZW5kZXJUeXBlKSB8fCBjb2wubmFtZS5lbmRzV2l0aChcIl9pZFwiKSksXG4gICAgICApXG4gICAgICAvLyBvcmRlckJ56rCAIOqwgOyepSDrkqTroZwg7Jik6rKMIOyInOyEnCDsobDsoJVcbiAgICAgIC5zb3J0KChhKSA9PiB7XG4gICAgICAgIHJldHVybiBhLm5hbWUgPT09IFwib3JkZXJCeVwiID8gMSA6IC0xO1xuICAgICAgfSk7XG5cbiAgICAvLyDtlYTthLAg7Lus65+87J2EIO2UhOumrCDthZztlIzrpr/snLzroZwg7ISk7KCVXG4gICAgY29uc3QgcHJlVGVtcGxhdGVzOiBSZW5kZXJlZFRlbXBsYXRlW1wicHJlVGVtcGxhdGVzXCJdID0gW107XG4gICAgZm9yIChjb25zdCBjb2wgb2YgZmlsdGVyQ29sdW1ucykge1xuICAgICAgbGV0IGtleTogVGVtcGxhdGVLZXk7XG4gICAgICBsZXQgdGFyZ2V0RW50aXR5SWQgPSBlbnRpdHlJZDtcbiAgICAgIGxldCBlbnVtSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgICAgaWYgKGNvbC5uYW1lID09PSBcInNlYXJjaFwiKSB7XG4gICAgICAgICAga2V5ID0gXCJ2aWV3X2VudW1zX3NlbGVjdFwiO1xuICAgICAgICAgIGVudW1JZCA9IGAke25hbWVzLmNhcGl0YWx9U2VhcmNoRmllbGRgO1xuICAgICAgICAgIHRhcmdldEVudGl0eUlkID0gbmFtZXMuY2FwaXRhbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXkgPSBcInZpZXdfZW51bXNfc2VsZWN0XCI7XG4gICAgICAgICAgLy8gY29uZmlnLmVudW1JZCDsmrDshKAg7IKs7JqpXG4gICAgICAgICAgaWYgKGNvbC5jb25maWcgJiYgXCJlbnVtSWRcIiBpbiBjb2wuY29uZmlnKSB7XG4gICAgICAgICAgICBlbnVtSWQgPSAoY29sLmNvbmZpZyBhcyB7IGVudW1JZDogc3RyaW5nIH0pLmVudW1JZDtcbiAgICAgICAgICAgIHRhcmdldEVudGl0eUlkID0gZW50aXR5SWQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgdGFyZ2V0RW50aXR5TmFtZXMsIGlkIH0gPSBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZSk7XG4gICAgICAgICAgICAgIHRhcmdldEVudGl0eUlkID0gdGFyZ2V0RW50aXR5TmFtZXMuY2FwaXRhbDtcbiAgICAgICAgICAgICAgZW51bUlkID0gaWQ7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBrZXkgPSBcInZpZXdfaWRfYXN5bmNfc2VsZWN0XCI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgICB0YXJnZXRFbnRpdHlJZCA9IHJlbFByb3Aud2l0aDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcHJlVGVtcGxhdGVzLnB1c2goe1xuICAgICAgICBrZXksXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICBlbnRpdHlJZDogdGFyZ2V0RW50aXR5SWQsXG4gICAgICAgICAgZW51bUlkLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8g7Lus65+87JeQ7IScIOyCrOyaqe2VmOuKlCBlbnVt65OkIOyImOynkVxuICAgIGNvbnN0IGNvbHVtbkVudW1zOiBzdHJpbmdbXSA9IFtdO1xuICAgIChjb2x1bW5zTm9kZS5jaGlsZHJlbiA/PyBbXSkuZm9yRWFjaCgoY29sKSA9PiB7XG4gICAgICBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwiZW51bXNcIikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHsgaWQ6IGVudW1JZCB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICAgIGNvbHVtbkVudW1zLnB1c2goZW51bUlkKTtcbiAgICAgICAgfSBjYXRjaCB7fVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gU2VhcmNoSW5wdXRcbiAgICBwcmVUZW1wbGF0ZXM/LnB1c2goe1xuICAgICAga2V5OiBcInZpZXdfc2VhcmNoX2lucHV0XCIsXG4gICAgICBvcHRpb25zOiB7XG4gICAgICAgIGVudGl0eUlkLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIOuUlO2PtO2KuCDtjIzrnbzrr7jthLBcbiAgICAvLyBjb25zdCBkZWYgPSB0aGlzLmdldERlZmF1bHQoZmlsdGVyQ29sdW1ucyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5nZXRUYXJnZXRBbmRQYXRoKG5hbWVzKSxcbiAgICAgIGJvZHk6IGBcbmltcG9ydCB7IHVzZVN0YXRlLCBGcmFnbWVudCB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgY3JlYXRlRmlsZVJvdXRlLCB1c2VOYXZpZ2F0ZSB9IGZyb20gXCJAdGFuc3RhY2svcmVhY3Qtcm91dGVyXCI7XG5cbmltcG9ydCB7IENhcmQsIENhcmRDb250ZW50LCBDYXJkSGVhZGVyIH0gZnJvbSBcIkBzb25hbXUta2l0L3JlYWN0LWNvbXBvbmVudHMvY29tcG9uZW50c1wiO1xuaW1wb3J0IHsgQmFkZ2UgfSBmcm9tIFwiQHNvbmFtdS1raXQvcmVhY3QtY29tcG9uZW50cy9jb21wb25lbnRzXCI7XG5pbXBvcnQgeyBCdXR0b24gfSBmcm9tIFwiQHNvbmFtdS1raXQvcmVhY3QtY29tcG9uZW50cy9jb21wb25lbnRzXCI7XG5pbXBvcnQgeyBQYWdpbmF0aW9uLCBUYWJsZSwgVGFibGVCb2R5LCBUYWJsZUNlbGwsIHR5cGUgVGFibGVDb2wsIFRhYmxlSGVhZCwgVGFibGVIZWFkZXIsIFRhYmxlUm93IH0gZnJvbSBcIkBzb25hbXUta2l0L3JlYWN0LWNvbXBvbmVudHMvY29tcG9uZW50c1wiO1xuaW1wb3J0IHsgU2VsZWN0LCBTZWxlY3RDb250ZW50LCBTZWxlY3RJdGVtLCBTZWxlY3RUcmlnZ2VyLCBTZWxlY3RWYWx1ZSB9IGZyb20gXCJAc29uYW11LWtpdC9yZWFjdC1jb21wb25lbnRzL2NvbXBvbmVudHNcIjtcbmltcG9ydCB7IEFsZXJ0RGlhbG9nLCBBbGVydERpYWxvZ0FjdGlvbiwgQWxlcnREaWFsb2dDYW5jZWwsIEFsZXJ0RGlhbG9nQ29udGVudCwgQWxlcnREaWFsb2dEZXNjcmlwdGlvbiwgQWxlcnREaWFsb2dGb290ZXIsIEFsZXJ0RGlhbG9nSGVhZGVyLCBBbGVydERpYWxvZ1RpdGxlIH0gZnJvbSBcIkBzb25hbXUta2l0L3JlYWN0LWNvbXBvbmVudHMvY29tcG9uZW50c1wiO1xuaW1wb3J0IHsgSW5wdXQgfSBmcm9tIFwiQHNvbmFtdS1raXQvcmVhY3QtY29tcG9uZW50cy9jb21wb25lbnRzXCI7XG5pbXBvcnQgeyBDaGVja2JveCB9IGZyb20gXCJAc29uYW11LWtpdC9yZWFjdC1jb21wb25lbnRzL2NvbXBvbmVudHNcIjtcblxuaW1wb3J0IHsgdXNlTGlzdFBhcmFtcywgbnVtRiwgZGF0ZUYsIGRhdGV0aW1lRiB9IGZyb20gXCJAc29uYW11LWtpdC9yZWFjdC1jb21wb25lbnRzL2xpYlwiO1xuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfVN1YnNldEEgfSBmcm9tIFwiQC9zZXJ2aWNlcy9zb25hbXUuZ2VuZXJhdGVkXCI7XG5pbXBvcnQgeyAke25hbWVzLmNhcGl0YWx9U2VydmljZSB9IGZyb20gXCJAL3NlcnZpY2VzL3NlcnZpY2VzLmdlbmVyYXRlZFwiO1xuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfUxpc3RQYXJhbXMgfSBmcm9tIFwiQC9zZXJ2aWNlcy8ke25hbWVzLmZzfS8ke25hbWVzLmZzfS50eXBlc1wiO1xuaW1wb3J0IHsgJHsoKCkgPT4ge1xuICAgICAgICAvLyDquLDrs7ggZW51bSDsiJjsp5EgKGZpbHRlckNvbHVtbnPsl5Ag7J6I64qUIOqyg+unjClcbiAgICAgICAgY29uc3QgYmFzZUVudW1zOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBpZiAoZmlsdGVyQ29sdW1ucy5zb21lKChjb2wpID0+IGNvbC5uYW1lID09PSBcIm9yZGVyQnlcIikpIHtcbiAgICAgICAgICBiYXNlRW51bXMucHVzaChgJHtuYW1lcy5jYXBpdGFsfU9yZGVyQnlgLCBgJHtuYW1lcy5jYXBpdGFsfU9yZGVyQnlMYWJlbGApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaWx0ZXJDb2x1bW5zLnNvbWUoKGNvbCkgPT4gY29sLm5hbWUgPT09IFwic2VhcmNoXCIpKSB7XG4gICAgICAgICAgYmFzZUVudW1zLnB1c2goYCR7bmFtZXMuY2FwaXRhbH1TZWFyY2hGaWVsZGAsIGAke25hbWVzLmNhcGl0YWx9U2VhcmNoRmllbGRMYWJlbGApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7ZWE7YSwIGVudW0g7IiY7KeRIChjb25maWcuZW51bUlkIOyasOyEoCwg7JeG7Jy866m0IGdldEVudW1JbmZvRnJvbUNvbE5hbWUpXG4gICAgICAgIGNvbnN0IGZpbHRlckVudW1JZHMgPSBmaWx0ZXJDb2x1bW5zXG4gICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgIChjb2wpID0+IGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIgJiYgY29sLm5hbWUgIT09IFwic2VhcmNoXCIgJiYgY29sLm5hbWUgIT09IFwib3JkZXJCeVwiLFxuICAgICAgICAgIClcbiAgICAgICAgICAubWFwKChjb2wpID0+IHtcbiAgICAgICAgICAgIGlmIChjb2wuY29uZmlnICYmIFwiZW51bUlkXCIgaW4gY29sLmNvbmZpZykge1xuICAgICAgICAgICAgICByZXR1cm4gKGNvbC5jb25maWcgYXMgeyBlbnVtSWQ6IHN0cmluZyB9KS5lbnVtSWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCB7IGlkOiBlbnVtSWQgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGVudW1JZDtcbiAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICAgIC5maWx0ZXIoQm9vbGVhbikgYXMgc3RyaW5nW107XG5cbiAgICAgICAgLy8g66qo65OgIGVudW0g7ZWp7LmY6rOgIOykkeuztSDsoJzqsbBcbiAgICAgICAgY29uc3QgYWxsRW51bXMgPSBbLi4ubmV3IFNldChbLi4uZmlsdGVyRW51bUlkcywgLi4uY29sdW1uRW51bXNdKV07XG4gICAgICAgIGNvbnN0IGVudW1JbXBvcnRzID0gYWxsRW51bXMuZmxhdE1hcCgoZW51bUlkKSA9PiBbYCR7ZW51bUlkfWAsIGAke2VudW1JZH1MYWJlbGBdKTtcblxuICAgICAgICByZXR1cm4gWy4uLmJhc2VFbnVtcywgLi4uZW51bUltcG9ydHNdLmpvaW4oXCIsIFwiKTtcbiAgICAgIH0pKCl9IH0gZnJvbSBcIkAvc2VydmljZXMvc29uYW11LmdlbmVyYXRlZFwiO1xuJHsoKCkgPT4ge1xuICAvLyBGSyDtlYTrk5zsnZggQXN5bmNTZWxlY3Qg7Lu07Y+s64SM7Yq4IGltcG9ydFxuICBjb25zdCBma0NvbHVtbnMgPSBmaWx0ZXJDb2x1bW5zLmZpbHRlcigoY29sKSA9PiBjb2wubmFtZS5lbmRzV2l0aChcIl9pZFwiKSAmJiBjb2wubmFtZSAhPT0gXCJpZFwiKTtcbiAgcmV0dXJuIGZrQ29sdW1uc1xuICAgIC5tYXAoKGNvbCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0TmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKHJlbFByb3Aud2l0aCk7XG4gICAgICAgIHJldHVybiBgaW1wb3J0IHsgJHtyZWxQcm9wLndpdGh9SWRBc3luY1NlbGVjdCB9IGZyb20gXCJAL2NvbXBvbmVudHMvJHt0YXJnZXROYW1lcy5mc30vJHtyZWxQcm9wLndpdGh9SWRBc3luY1NlbGVjdFwiO2A7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9XG4gICAgfSlcbiAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgLmpvaW4oXCJcXG5cIik7XG59KSgpfVxuJHtcbiAgZmlsdGVyQ29sdW1ucy5zb21lKChjb2wpID0+IGNvbC5uYW1lID09PSBcInNlYXJjaFwiKVxuICAgID8gYFxuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfVNlYXJjaEZpZWxkU2VsZWN0IH0gZnJvbSBcIkAvY29tcG9uZW50cy8ke25hbWVzLmZzfS8ke25hbWVzLmNhcGl0YWx9U2VhcmNoRmllbGRTZWxlY3RcIjtgXG4gICAgOiBcIlwiXG59XG4ke1xuICBmaWx0ZXJDb2x1bW5zLnNvbWUoKGNvbCkgPT4gY29sLm5hbWUgPT09IFwib3JkZXJCeVwiKVxuICAgID8gYFxuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfU9yZGVyQnlTZWxlY3QgfSBmcm9tIFwiQC9jb21wb25lbnRzLyR7bmFtZXMuZnN9LyR7bmFtZXMuY2FwaXRhbH1PcmRlckJ5U2VsZWN0XCI7YFxuICAgIDogXCJcIlxufVxuXG5pbXBvcnQgRWRpdEljb24gZnJvbSBcIn5pY29ucy9sdWNpZGUvc3F1YXJlLXBlblwiO1xuaW1wb3J0IFRyYXNoSWNvbiBmcm9tIFwifmljb25zL2x1Y2lkZS90cmFzaC0yXCI7XG5pbXBvcnQgTGlzdEljb24gZnJvbSBcIn5pY29ucy9tZGkvZm9ybWF0LWxpc3QtYnVsbGV0ZWRcIjtcbmltcG9ydCBTZWFyY2hJY29uIGZyb20gXCJ+aWNvbnMvbWRpL21hZ25pZnlcIjtcblxuZXhwb3J0IGNvbnN0IFJvdXRlID0gY3JlYXRlRmlsZVJvdXRlKFwiL2FkbWluLyR7bmFtZXMuZnNQbHVyYWx9L1wiKSh7XFxuICBoZWFkOiAoKSA9PiAoe1xcbiAgICBtZXRhOiBbXFxuICAgICAgeyB0aXRsZTogXCIke2VudGl0eS50aXRsZSA/PyBuYW1lcy5jYXBpdGFsfSBMaXN0XCIgfSxcXG4gICAgICB7IG5hbWU6IFwiZGVzY3JpcHRpb25cIiwgY29udGVudDogXCIke2VudGl0eS50aXRsZSA/PyBuYW1lcy5jYXBpdGFsfSDrqqnroZ0g6rSA66asXCIgfSxcXG4gICAgXSxcXG4gIH0pLFxcbiAgY29tcG9uZW50OiAke25hbWVzLmNhcGl0YWx9TGlzdCxcXG59KTtcXG5cXG50eXBlICR7bmFtZXMuY2FwaXRhbH1MaXN0UHJvcHMgPSB7fTtcblxuZnVuY3Rpb24gJHtuYW1lcy5jYXBpdGFsfUxpc3Qoe306ICR7bmFtZXMuY2FwaXRhbH1MaXN0UHJvcHMpIHtcbiAgY29uc3QgbmF2aWdhdGUgPSB1c2VOYXZpZ2F0ZSgpO1xuXG4gIC8vIOyDge2DnCDqtIDrpqxcbiAgY29uc3QgW3NlbGVjdGVkSXRlbXMsIHNldFNlbGVjdGVkSXRlbXNdID0gdXNlU3RhdGU8U2V0PG51bWJlcj4+KG5ldyBTZXQoKSk7XG4gIGNvbnN0IFtkZWxldGVEaWFsb2dPcGVuLCBzZXREZWxldGVEaWFsb2dPcGVuXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW2l0ZW1Ub0RlbGV0ZSwgc2V0SXRlbVRvRGVsZXRlXSA9IHVzZVN0YXRlPHsgaWQ6IG51bWJlcjsgbmFtZT86IHN0cmluZyB9IHwgbnVsbD4obnVsbCk7XG5cbiAgLy8g66as7Iqk7Yq4IO2VhO2EsFxuICBjb25zdCB7IGxpc3RQYXJhbXMsIHJlZ2lzdGVyIH0gPSB1c2VMaXN0UGFyYW1zKCR7bmFtZXMuY2FwaXRhbH1MaXN0UGFyYW1zLCB7XG4gICAgbnVtOiAxMCxcbiAgICBwYWdlOiAxLFxuICAgIGtleXdvcmQ6IFwiXCIsJHtcbiAgICAgIGZpbHRlckNvbHVtbnMuc29tZSgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJzZWFyY2hcIilcbiAgICAgICAgPyBgXG4gICAgc2VhcmNoOiAke25hbWVzLmNhcGl0YWx9U2VhcmNoRmllbGQub3B0aW9uc1swXSxgXG4gICAgICAgIDogXCJcIlxuICAgIH0ke1xuICAgICAgZmlsdGVyQ29sdW1ucy5zb21lKChjb2wpID0+IGNvbC5uYW1lID09PSBcIm9yZGVyQnlcIilcbiAgICAgICAgPyBgXG4gICAgb3JkZXJCeTogJHtuYW1lcy5jYXBpdGFsfU9yZGVyQnkub3B0aW9uc1swXSxgXG4gICAgICAgIDogXCJcIlxuICAgIH1cbiAgfSk7XG5cbiAgLy8g66as7Iqk7Yq4IOy/vOumrFxuICBjb25zdCB7IGRhdGEsIHJlZmV0Y2gsIGlzTG9hZGluZyB9ID0gJHtuYW1lcy5jYXBpdGFsfVNlcnZpY2UudXNlJHtuYW1lcy5jYXBpdGFsUGx1cmFsfShcIkFcIiwgbGlzdFBhcmFtcyk7XG4gIGNvbnN0IHsgcm93cywgdG90YWwgfSA9IGRhdGEgPz8ge307XG5cbiAgLy8g7ZiE7J6sIOqyveuhnOyZgCDtg4DsnbTti4BcbiAgY29uc3QgUEFHRSA9IHtcbiAgICByb3V0ZTogXCIvYWRtaW4vJHtuYW1lcy5mc1BsdXJhbH1cIixcbiAgICB0aXRsZTogXCIke2VudGl0eS50aXRsZSA/PyBuYW1lcy5jYXBpdGFsfVwiLFxuICB9O1xuXG4gIC8vIOy7rOufvCDsoJXsnZhcbiAgdHlwZSAke25hbWVzLmNhcGl0YWx9Um93ID0gTm9uTnVsbGFibGU8dHlwZW9mIHJvd3M+W251bWJlcl07XG4gIGNvbnN0IGNvbHVtbnM6IFRhYmxlQ29sPCR7bmFtZXMuY2FwaXRhbH1Sb3c+W10gPSBbXG4ke2NvbHVtbnNcbiAgLm1hcChcbiAgICAoY29sKSA9PiBgICAgIHtcbiAgICAgIGxhYmVsOiBcIiR7Y29sLmxhYmVsfVwiLFxuICAgICAgdGM6ICR7Y29sLnRjfSwke1xuICAgICAgICBjb2wuZml0XG4gICAgICAgICAgPyBgXG4gICAgICBmaXQ6IHRydWUsYFxuICAgICAgICAgIDogXCJcIlxuICAgICAgfSR7XG4gICAgICAgIGNvbC5hbGlnblxuICAgICAgICAgID8gYFxuICAgICAgYWxpZ246IFwiJHtjb2wuYWxpZ259XCIsYFxuICAgICAgICAgIDogXCJcIlxuICAgICAgfVxuICAgIH1gLFxuICApXG4gIC5qb2luKFwiLFxcblwiKX0sXG4gICAge1xuICAgICAgbGFiZWw6IFwiTWFuYWdlXCIsXG4gICAgICBmaXQ6IHRydWUsXG4gICAgICBhbGlnbjogXCJjZW50ZXJcIixcbiAgICAgIHRjOiAocm93KSA9PiAoXG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTFcIj5cbiAgICAgICAgICA8QnV0dG9uXG4gICAgICAgICAgICB2YXJpYW50PVwieWVsbG93XCJcbiAgICAgICAgICAgIHNpemU9XCJ4c1wiXG4gICAgICAgICAgICBpY29uPXs8RWRpdEljb24gLz59XG4gICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBuYXZpZ2F0ZSh7IHRvOiBcXGBcXCR7UEFHRS5yb3V0ZX0vZm9ybVxcYCwgc2VhcmNoOiB7IGlkOiByb3cuaWQgfSB9KX1cbiAgICAgICAgICAvPlxuICAgICAgICAgIDxCdXR0b25cbiAgICAgICAgICAgIHZhcmlhbnQ9XCJyZWRcIlxuICAgICAgICAgICAgc2l6ZT1cInhzXCJcbiAgICAgICAgICAgIGljb249ezxUcmFzaEljb24gLz59XG4gICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBoYW5kbGVEZWxldGVDbGljayhyb3cuaWQpfVxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgKSxcbiAgICB9LFxuICBdO1xuXG4gIC8vIOyEoO2DnSDtlbjrk6Trn6xcbiAgY29uc3QgaGFuZGxlVG9nZ2xlSXRlbSA9IChpZDogbnVtYmVyKSA9PiB7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9uID0gbmV3IFNldChzZWxlY3RlZEl0ZW1zKTtcbiAgICBpZiAobmV3U2VsZWN0aW9uLmhhcyhpZCkpIHtcbiAgICAgIG5ld1NlbGVjdGlvbi5kZWxldGUoaWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdTZWxlY3Rpb24uYWRkKGlkKTtcbiAgICB9XG4gICAgc2V0U2VsZWN0ZWRJdGVtcyhuZXdTZWxlY3Rpb24pO1xuICB9O1xuXG4gIGNvbnN0IGlzQWxsU2VsZWN0ZWQgPSAoKSA9PiB7XG4gICAgcmV0dXJuIChyb3dzPy5sZW5ndGggPz8gMCkgPiAwICYmIHJvd3MhLmV2ZXJ5KChyb3cpID0+IHNlbGVjdGVkSXRlbXMuaGFzKHJvdy5pZCkpO1xuICB9O1xuXG4gIGNvbnN0IGhhbmRsZVNlbGVjdEFsbCA9IChjaGVja2VkOiBib29sZWFuKSA9PiB7XG4gICAgaWYgKGNoZWNrZWQpIHtcbiAgICAgIHNldFNlbGVjdGVkSXRlbXMobmV3IFNldChyb3dzPy5tYXAoKHJvdykgPT4gcm93LmlkKSA/PyBbXSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRTZWxlY3RlZEl0ZW1zKG5ldyBTZXQoKSk7XG4gICAgfVxuICB9O1xuXG4gIC8vIOyCreygnCDtlbjrk6Trn6xcbiAgY29uc3QgaGFuZGxlRGVsZXRlQ2xpY2sgPSAoaWQ6IG51bWJlciwgbmFtZT86IHN0cmluZykgPT4ge1xuICAgIHNldEl0ZW1Ub0RlbGV0ZSh7IGlkLCBuYW1lIH0pO1xuICAgIHNldERlbGV0ZURpYWxvZ09wZW4odHJ1ZSk7XG4gIH07XG5cbiAgY29uc3QgaGFuZGxlQ29uZmlybURlbGV0ZSA9ICgpID0+IHtcbiAgICBpZiAoaXRlbVRvRGVsZXRlKSB7XG4gICAgICAke25hbWVzLmNhcGl0YWx9U2VydmljZS5kZWwoW2l0ZW1Ub0RlbGV0ZS5pZF0pLnRoZW4oKCkgPT4ge1xuICAgICAgICByZWZldGNoKCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgc2V0RGVsZXRlRGlhbG9nT3BlbihmYWxzZSk7XG4gICAgc2V0SXRlbVRvRGVsZXRlKG51bGwpO1xuICB9O1xuXG4gIHJldHVybiAoXG4gICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4LTEgb3ZlcmZsb3ctYXV0b1wiPlxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJtYXgtdy1bMTgwMHB4XSBteC1hdXRvIHAtOFwiPlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cInNwYWNlLXktNiBtYi04XCI+XG4gICAgICAgICAgey8qIEhlYWRlciAqL31cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgICAgICA8TGlzdEljb24gY2xhc3NOYW1lPVwiaC01IHctNVwiIC8+XG4gICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJ0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgaC01XCI+e1BBR0UudGl0bGV9PC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPENhcmQgY2xhc3NOYW1lPVwic2hhZG93LXNtIGJvcmRlci1ib3JkZXIvNDAgb3ZlcmZsb3ctaGlkZGVuXCI+XG4gICAgICAgICAgICA8Q2FyZEhlYWRlciBjbGFzc05hbWU9XCJwYi0wIHB4LTAgcHQtMFwiPlxuICAgICAgICAgICAgICB7LyogRmlsdGVycyAqL31cbiAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJiZy1ncmF5LTEwMCBweC02IHB5LTQgc3BhY2UteS0zXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMyBmbGV4LXdyYXBcIj5cbiR7XG4gIGZpbHRlckNvbHVtbnMuc29tZSgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJzZWFyY2hcIilcbiAgICA/IGAgICAgICAgICAgICAgICAgICA8JHtuYW1lcy5jYXBpdGFsfVNlYXJjaEZpZWxkU2VsZWN0XG4gICAgICAgICAgICAgICAgICAgIHsuLi5yZWdpc3RlcihcInNlYXJjaFwiKX1cbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggVHlwZVwiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cInctWzIwMHB4XSBoLTggYmctd2hpdGUgYm9yZGVyLWdyYXktMzAwIHRleHQteHNcIlxuICAgICAgICAgICAgICAgICAgLz5gXG4gICAgOiBcIlwiXG59XG5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwicmVsYXRpdmUgZmxleC0xIG1heC13LXhzXCI+XG4gICAgICAgICAgICAgICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgIHsuLi5yZWdpc3RlcihcImtleXdvcmRcIil9XG4gICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2guLi5cIlxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cImgtOCBwci04IHRleHQteHMgYmctd2hpdGUgYm9yZGVyLWdyYXktMzAwXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPEJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgIHZhcmlhbnQ9XCJnaG9zdFwiXG4gICAgICAgICAgICAgICAgICAgICAgc2l6ZT1cInNtXCJcbiAgICAgICAgICAgICAgICAgICAgICBpY29uPXs8U2VhcmNoSWNvbiAvPn1cbiAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJhYnNvbHV0ZSByaWdodC0wIHRvcC0wIGgtOCB3LTggaG92ZXI6YmctdHJhbnNwYXJlbnRcIlxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibWwtYXV0b1wiPlxuICAgICAgICAgICAgICAgICAgICA8QnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwiaC04IHB4LTQgYmctcHJpbWFyeSBob3ZlcjpiZy1wcmltYXJ5LzkwIHRleHQtd2hpdGVcIlxuICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0+IG5hdmlnYXRlKHsgdG86IFxcYFxcJHtQQUdFLnJvdXRlfS9mb3JtXFxgIH0pfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC14c1wiPkNyZWF0ZTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTMgZmxleC13cmFwXCI+XG4ke2ZpbHRlckNvbHVtbnNcbiAgLmZpbHRlcigoY29sKSA9PiBjb2wubmFtZSAhPT0gXCJzZWFyY2hcIiAmJiBjb2wubmFtZSAhPT0gXCJvcmRlckJ5XCIpXG4gIC5tYXAoKGNvbCkgPT4ge1xuICAgIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJlbnVtc1wiKSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBjb25maWcuZW51bUlk6rCAIOyeiOycvOuptCDsmrDshKAg7IKs7JqpLCDsl4bsnLzrqbQgZ2V0RW51bUluZm9Gcm9tQ29sTmFtZSDsi5zrj4RcbiAgICAgICAgY29uc3QgZW51bUlkID1cbiAgICAgICAgICBjb2wuY29uZmlnICYmIFwiZW51bUlkXCIgaW4gY29sLmNvbmZpZ1xuICAgICAgICAgICAgPyAoY29sLmNvbmZpZyBhcyB7IGVudW1JZDogc3RyaW5nIH0pLmVudW1JZFxuICAgICAgICAgICAgOiBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZSkuaWQ7XG4gICAgICAgIHJldHVybiBgICAgICAgICAgICAgICAgICAgPFNlbGVjdCBrZXk9e1xcYCR7Y29sLm5hbWV9LVxcJHtsaXN0UGFyYW1zLiR7Y29sLm5hbWV9fVxcYH0gey4uLnJlZ2lzdGVyKFwiJHtjb2wubmFtZX1cIil9IGNsZWFyYWJsZT5cbiAgICAgICAgICAgICAgICAgICAgPFNlbGVjdFRyaWdnZXIgY2xhc3NOYW1lPVwidy1bMjAwcHhdIGgtOCBiZy13aGl0ZSBib3JkZXItZ3JheS0zMDAgdGV4dC14c1wiPlxuICAgICAgICAgICAgICAgICAgICAgIDxTZWxlY3RWYWx1ZSBwbGFjZWhvbGRlcj1cIiR7Y29sLmxhYmVsfVwiIGNsYXNzTmFtZT1cInRydW5jYXRlXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9TZWxlY3RUcmlnZ2VyPlxuICAgICAgICAgICAgICAgICAgICA8U2VsZWN0Q29udGVudD5cbiAgICAgICAgICAgICAgICAgICAgICB7JHtlbnVtSWR9Lm9wdGlvbnMubWFwKChrZXkpID0+IChcbiAgICAgICAgICAgICAgICAgICAgICAgIDxTZWxlY3RJdGVtIGtleT17a2V5fSB2YWx1ZT17a2V5fT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgeyR7ZW51bUlkfUxhYmVsW2tleV19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L1NlbGVjdEl0ZW0+XG4gICAgICAgICAgICAgICAgICAgICAgKSl9XG4gICAgICAgICAgICAgICAgICAgIDwvU2VsZWN0Q29udGVudD5cbiAgICAgICAgICAgICAgICAgIDwvU2VsZWN0PmA7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEZLIO2VhOuTnCAoQXN5bmNTZWxlY3QpXG4gICAgaWYgKGNvbC5uYW1lLmVuZHNXaXRoKFwiX2lkXCIpICYmIGNvbC5uYW1lICE9PSBcImlkXCIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlbFByb3AgPSBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUucmVwbGFjZShcIl9pZFwiLCBcIlwiKSk7XG4gICAgICAgIHJldHVybiBgICAgICAgICAgICAgICAgICAgPCR7cmVsUHJvcC53aXRofUlkQXN5bmNTZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgc3Vic2V0PVwiQVwiXG4gICAgICAgICAgICAgICAgICAgIHsuLi5yZWdpc3RlcihcIiR7Y29sLm5hbWV9XCIpfVxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIiR7Y29sLmxhYmVsID8/IHJlbFByb3Aud2l0aH1cIlxuICAgICAgICAgICAgICAgICAgICBjbGVhcmFibGVcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwidy1bMjAwcHhdIGgtOCB0ZXh0LXhzXCJcbiAgICAgICAgICAgICAgICAgIC8+YDtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFwiXCI7XG4gIH0pXG4gIC5maWx0ZXIoQm9vbGVhbilcbiAgLmpvaW4oXCJcXG5cIil9XG4ke1xuICBmaWx0ZXJDb2x1bW5zLnNvbWUoKGNvbCkgPT4gY29sLm5hbWUgPT09IFwib3JkZXJCeVwiKVxuICAgID8gYCAgICAgICAgICAgICAgICAgIDwke25hbWVzLmNhcGl0YWx9T3JkZXJCeVNlbGVjdFxuICAgICAgICAgICAgICAgICAgICB7Li4ucmVnaXN0ZXIoXCJvcmRlckJ5XCIpfVxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNvcnRcIlxuICAgICAgICAgICAgICAgICAgICB0ZXh0UHJlZml4PVwiU29ydDogXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwidy1bMjAwcHhdIGgtOCBiZy13aGl0ZSBib3JkZXItZ3JheS0zMDAgdGV4dC14c1wiXG4gICAgICAgICAgICAgICAgICAvPmBcbiAgICA6IFwiXCJcbn1cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzTmFtZT1cInRleHQteHMgdGV4dC1tdXRlZC1mb3JlZ3JvdW5kXCI+e3RvdGFsID8/IDB9IHJlc3VsdHM8L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9DYXJkSGVhZGVyPlxuXG4gICAgICAgICAgICA8Q2FyZENvbnRlbnQgY2xhc3NOYW1lPVwicHgtNiBwYi02IHB0LTYgYmctd2hpdGVcIj5cbiAgICAgICAgICAgICAgey8qIFRhYmxlICovfVxuICAgICAgICAgICAgICA8VGFibGU+XG4gICAgICAgICAgICAgICAgPFRhYmxlSGVhZGVyPlxuICAgICAgICAgICAgICAgICAgPFRhYmxlUm93IGNsYXNzTmFtZT1cImhvdmVyOmJnLXRyYW5zcGFyZW50IGJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICAgICAgICAgIDxUYWJsZUhlYWQgY2xhc3NOYW1lPVwiaC05IHRleHQteHMgdy1bNDBweF1cIj5cbiAgICAgICAgICAgICAgICAgICAgICA8Q2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWQ9e2lzQWxsU2VsZWN0ZWQoKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVmFsdWVDaGFuZ2U9e2hhbmRsZVNlbGVjdEFsbH1cbiAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICA8L1RhYmxlSGVhZD5cbiAgICAgICAgICAgICAgICAgICAge2NvbHVtbnMubWFwKChjb2wsIGlkeCkgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgIDxUYWJsZUhlYWQga2V5PXtpZHh9IGZpdD17Y29sLmZpdH0gYWxpZ249e2NvbC5hbGlnbn0+XG4gICAgICAgICAgICAgICAgICAgICAgICB7Y29sLmxhYmVsfVxuICAgICAgICAgICAgICAgICAgICAgIDwvVGFibGVIZWFkPlxuICAgICAgICAgICAgICAgICAgICApKX1cbiAgICAgICAgICAgICAgICAgIDwvVGFibGVSb3c+XG4gICAgICAgICAgICAgICAgPC9UYWJsZUhlYWRlcj5cbiAgICAgICAgICAgICAgICA8VGFibGVCb2R5PlxuICAgICAgICAgICAgICAgICAgeyFpc0xvYWRpbmcgJiYgcm93cyAmJiByb3dzLm1hcCgocm93KSA9PiAoXG4gICAgICAgICAgICAgICAgICAgIDxGcmFnbWVudCBrZXk9e3Jvdy5pZH0+XG4gICAgICAgICAgICAgICAgICAgICAgPFRhYmxlUm93PlxuICAgICAgICAgICAgICAgICAgICAgICAgPFRhYmxlQ2VsbCBjbGFzc05hbWU9XCJweS0zXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxDaGVja2JveFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWQ9e3NlbGVjdGVkSXRlbXMuaGFzKHJvdy5pZCl9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25WYWx1ZUNoYW5nZT17KCkgPT4gaGFuZGxlVG9nZ2xlSXRlbShyb3cuaWQpfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9UYWJsZUNlbGw+XG4gICAgICAgICAgICAgICAgICAgICAgICB7Y29sdW1ucy5tYXAoKGNvbCwgaWR4KSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxUYWJsZUNlbGwga2V5PXtpZHh9IGZpdD17Y29sLmZpdH0gYWxpZ249e2NvbC5hbGlnbn0gY2xhc3NOYW1lPVwicHktM1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtjb2wudGMocm93KX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9UYWJsZUNlbGw+XG4gICAgICAgICAgICAgICAgICAgICAgICApKX1cbiAgICAgICAgICAgICAgICAgICAgICA8L1RhYmxlUm93PlxuICAgICAgICAgICAgICAgICAgICA8L0ZyYWdtZW50PlxuICAgICAgICAgICAgICAgICAgKSl9XG4gICAgICAgICAgICAgICAgPC9UYWJsZUJvZHk+XG4gICAgICAgICAgICAgIDwvVGFibGU+XG5cbiAgICAgICAgICAgICAgey8qIFBhZ2luYXRpb24gKi99XG4gICAgICAgICAgICAgIDxQYWdpbmF0aW9uXG4gICAgICAgICAgICAgICAgey4uLnJlZ2lzdGVyKFwicGFnZVwiKX1cbiAgICAgICAgICAgICAgICB0b3RhbD17dG90YWwgPz8gMH1cbiAgICAgICAgICAgICAgICBpdGVtc1BlclBhZ2U9e2xpc3RQYXJhbXMubnVtID8/IDEwfVxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC9DYXJkQ29udGVudD5cbiAgICAgICAgICA8L0NhcmQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIHsvKiBEZWxldGUgRGlhbG9nICovfVxuICAgICAgPEFsZXJ0RGlhbG9nIG9wZW49e2RlbGV0ZURpYWxvZ09wZW59IG9uT3BlbkNoYW5nZT17c2V0RGVsZXRlRGlhbG9nT3Blbn0+XG4gICAgICAgIDxBbGVydERpYWxvZ0NvbnRlbnQ+XG4gICAgICAgICAgPEFsZXJ0RGlhbG9nSGVhZGVyPlxuICAgICAgICAgICAgPEFsZXJ0RGlhbG9nVGl0bGU+QXJlIHlvdSBzdXJlPzwvQWxlcnREaWFsb2dUaXRsZT5cbiAgICAgICAgICAgIDxBbGVydERpYWxvZ0Rlc2NyaXB0aW9uPlxuICAgICAgICAgICAgICBUaGlzIGFjdGlvbiBjYW5ub3QgYmUgdW5kb25lLiBUaGlzIHdpbGwgcGVybWFuZW50bHkgZGVsZXRlIHRoaXMgaXRlbS5cbiAgICAgICAgICAgIDwvQWxlcnREaWFsb2dEZXNjcmlwdGlvbj5cbiAgICAgICAgICA8L0FsZXJ0RGlhbG9nSGVhZGVyPlxuICAgICAgICAgIDxBbGVydERpYWxvZ0Zvb3Rlcj5cbiAgICAgICAgICAgIDxBbGVydERpYWxvZ0NhbmNlbD5DYW5jZWw8L0FsZXJ0RGlhbG9nQ2FuY2VsPlxuICAgICAgICAgICAgPEFsZXJ0RGlhbG9nQWN0aW9uIG9uQ2xpY2s9e2hhbmRsZUNvbmZpcm1EZWxldGV9PkRlbGV0ZTwvQWxlcnREaWFsb2dBY3Rpb24+XG4gICAgICAgICAgPC9BbGVydERpYWxvZ0Zvb3Rlcj5cbiAgICAgICAgPC9BbGVydERpYWxvZ0NvbnRlbnQ+XG4gICAgICA8L0FsZXJ0RGlhbG9nPlxuICAgIDwvZGl2PlxuICApO1xufVxuICAgICAgYC50cmltKCksXG4gICAgICBpbXBvcnRLZXlzOiBbXSxcbiAgICAgIHByZVRlbXBsYXRlcyxcbiAgICB9O1xuICB9XG59XG4iXSwibmFtZXMiOlsiaW5mbGVjdGlvbiIsImZsYXQiLCJ6IiwiRW50aXR5TWFuYWdlciIsImdldEVudW1JbmZvRnJvbUNvbE5hbWUiLCJnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZSIsIlRlbXBsYXRlIiwiVGVtcGxhdGVfX3ZpZXdfbGlzdCIsImdldFRhcmdldEFuZFBhdGgiLCJuYW1lcyIsInRhcmdldCIsInBhdGgiLCJmc1BsdXJhbCIsIndyYXBUYyIsImJvZHkiLCJrZXkiLCJjb2xsYXBzaW5nIiwiY2xhc3NOYW1lIiwicmVuZGVyQ29sdW1uIiwiZW50aXR5SWQiLCJjb2wiLCJwYXJlbnRPYmoiLCJ3aXRob3V0TmFtZSIsImNvbE5hbWUiLCJuYW1lIiwiaW5jbHVkZXMiLCJwYXJ0cyIsInNwbGl0Iiwiam9pbiIsInJlbmRlclR5cGUiLCJiYXNlTmFtZSIsInBvcCIsInJlcGxhY2UiLCJyZWxQcm9wRmsiLCJ3aXRoIiwibnVsbGFibGUiLCJsYWJlbCIsImlkIiwiZW51bUlkIiwicGlja2VkQ2hpbGQiLCJjaGlsZHJlbiIsImZpbmQiLCJjaGlsZCIsImNvbmZpZyIsInBpY2tlZCIsIkVycm9yIiwicmVuZGVyQ29sdW1uSW1wb3J0IiwiY2FwaXRhbCIsInJlbFByb3AiLCJyZXN1bHQiLCJtYXAiLCJnZXROYW1lc0Zyb21JZCIsImVsZW1lbnQiLCJyZW5kZXJGaWx0ZXJJbXBvcnQiLCJmcyIsImNvbXBvbmVudElkIiwiY2FtZWxpemUiLCJ0YXJnZXRFbnRpdHlOYW1lcyIsInRhcmdldE1ETmFtZXMiLCJ0YXJnZXROYW1lcyIsInJlbmRlckZpbHRlciIsImlzQ2xlYXJhYmxlIiwib3B0aW9uYWwiLCJnZXREZWZhdWx0IiwiY29sdW1ucyIsImRlZiIsIm9yZGVyQnkiLCJzZWFyY2giLCJoYXNTZWFyY2giLCJoYXNPcmRlckJ5Iiwib3JkZXJCeVpvZFR5cGUiLCJ6b2RUeXBlIiwiWm9kRW51bSIsIk9iamVjdCIsImtleXMiLCJlbnVtIiwic2VhcmNoWm9kVHlwZSIsInJlbmRlciIsImdldENvbHVtbnNOb2RlIiwiZ2V0Wm9kVHlwZUJ5SWQiLCJ6b2RUeXBlVG9SZW5kZXJpbmdOb2RlIiwiY29sdW1uc05vZGUiLCJsaXN0UGFyYW1zWm9kVHlwZSIsImxpc3RQYXJhbXNOb2RlIiwiZW50aXR5IiwiZ2V0Iiwic29ydCIsImEiLCJiIiwicHJvcENhbmRpZGF0ZSIsInByb3BzIiwicCIsInJlbmRlcmVkIiwiZGVzYyIsInRjIiwiZml0IiwiYWxpZ24iLCJ1bmRlZmluZWQiLCJmaWx0ZXJDb2x1bW5zIiwiZmlsdGVyIiwiZW5kc1dpdGgiLCJwcmVUZW1wbGF0ZXMiLCJ0YXJnZXRFbnRpdHlJZCIsInB1c2giLCJvcHRpb25zIiwiY29sdW1uRW51bXMiLCJmb3JFYWNoIiwiYmFzZUVudW1zIiwic29tZSIsImZpbHRlckVudW1JZHMiLCJCb29sZWFuIiwiYWxsRW51bXMiLCJTZXQiLCJlbnVtSW1wb3J0cyIsImZsYXRNYXAiLCJma0NvbHVtbnMiLCJ0aXRsZSIsImNhcGl0YWxQbHVyYWwiLCJ0cmltIiwiaW1wb3J0S2V5cyJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsZ0JBQWdCLGFBQWE7QUFDcEMsU0FBU0MsSUFBSSxRQUFRLFVBQVU7QUFDL0IsU0FBU0MsQ0FBQyxRQUFRLE1BQU07QUFDeEIsU0FBU0MsYUFBYSxRQUFnQyxpQ0FBOEI7QUFFcEYsU0FBU0Msc0JBQXNCLEVBQUVDLDBCQUEwQixRQUFRLGdCQUFhO0FBRWhGLFNBQVNDLFFB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