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
@@ -4,30 +4,25 @@ import { z } from "zod";
4
4
  import { EntityManager } from "../../entity/entity-manager.js";
5
5
  import { getEnumInfoFromColName, getRelationPropFromColName } from "../helpers.js";
6
6
  import { Template } from "../template.js";
7
- import { getZodTypeById, zodTypeToRenderingNode } from "../zod-converter.js";
8
7
  export class Template__view_form extends Template {
9
8
  constructor(){
10
9
  super("view_form");
11
10
  }
12
11
  getTargetAndPath(names) {
13
12
  return {
14
- target: "web/src/pages/admin",
13
+ target: "web/src/routes/admin",
15
14
  path: `${names.fsPlural}/form.tsx`
16
15
  };
17
16
  }
18
17
  wrapFC(body, label) {
19
18
  return [
20
- `<Form.Field>${label ? `\n <label>${label}</label>` : ""}`,
21
- body,
22
- `</Form.Field>`
19
+ `<div className="space-y-2">${label ? `\n <Label>${label}</Label>` : ""}`,
20
+ ` ${body}`,
21
+ `</div>`
23
22
  ].join("\n");
24
23
  }
25
24
  wrapFG(body, label) {
26
- return [
27
- `<Form.Group widths="equal">`,
28
- this.wrapFC(body, label),
29
- `</Form.Group>`
30
- ].join("\n");
25
+ return this.wrapFC(body, label);
31
26
  }
32
27
  renderColumnImport(entityId, col) {
33
28
  if (col.renderType === "enums") {
@@ -47,7 +42,7 @@ export class Template__view_form extends Template {
47
42
  throw new Error(`렌더 불가능한 임포트 ${col.name} ${col.renderType}`);
48
43
  }
49
44
  }
50
- renderColumn(entityId, col, names, parent = "") {
45
+ renderColumnOld(entityId, col, names, parent = "") {
51
46
  let regExpr = "";
52
47
  regExpr = `{...register(\`${parent}${col.name}\`)}`;
53
48
  switch(col.renderType){
@@ -55,24 +50,30 @@ export class Template__view_form extends Template {
55
50
  if (col.zodType instanceof z.ZodString && (col.zodType.maxLength ?? 0) <= 512) {
56
51
  return `<Input placeholder="${col.label}" ${regExpr} />`;
57
52
  } else {
58
- return `<TextArea rows={8} placeholder="${col.label}" ${regExpr} />`;
53
+ return `<Textarea rows={8} placeholder="${col.label}" ${regExpr} />`;
59
54
  }
60
- case "datetime":
61
- return `<Input type="datetime-local" ${regExpr} />`;
62
55
  case "string-datetime":
63
- return `<SQLDateTimeInput ${regExpr} />`;
56
+ return `<DatePicker ${regExpr} />`;
64
57
  case "string-date":
65
- return `<SQLDateInput ${regExpr} />`;
58
+ return `<DatePicker ${regExpr} />`;
66
59
  case "number-id":
67
60
  return `<input type="hidden" ${regExpr} />`;
68
61
  case "number-plain":
69
- return `<NumberInput placeholder="${col.label}" ${regExpr} />`;
62
+ return `<Input type="number" placeholder="${col.label}" ${regExpr} />`;
70
63
  case "boolean":
71
- return `<BooleanToggle ${regExpr} />`;
64
+ return `<Switch ${regExpr} />`;
72
65
  case "string-image":
73
- return `<ImageUploader multiple={false} ${regExpr} />`;
66
+ return `<ImageUploader
67
+ ${regExpr}
68
+ uploader={async (file: File) => {
69
+ const { file: uploadedFile } = await FileService.upload(file);
70
+ return uploadedFile.url;
71
+ }}
72
+ previewSize="md"
73
+ />`;
74
74
  case "array-images":
75
- return `<ImageUploader multiple={true} ${regExpr} maxSize={5} />`;
75
+ return `{/* TODO: Implement multiple image uploader */}
76
+ <Input placeholder="${col.label}" ${regExpr} />`;
76
77
  case "enums":
77
78
  try {
78
79
  let enumId;
@@ -82,9 +83,9 @@ export class Template__view_form extends Template {
82
83
  const { id } = getEnumInfoFromColName(entityId, col.name);
83
84
  enumId = `${id}Select`;
84
85
  }
85
- return `<${enumId} ${regExpr} ${col.optional || col.nullable ? "clearable" : ""} textPrefix="" />`;
86
+ return `<${enumId} ${regExpr} ${col.optional || col.nullable ? "clearable" : ""} />`;
86
87
  } catch {
87
- return `<>찾을 수 없는 Enum ${col.name}</>`;
88
+ return `<span className="text-destructive">찾을 수 없는 Enum ${col.name}</span>`;
88
89
  }
89
90
  case "number-fk_id":
90
91
  try {
@@ -95,16 +96,95 @@ export class Template__view_form extends Template {
95
96
  return `<Input ${regExpr} />`;
96
97
  }
97
98
  case "array":
98
- return `<>${col.name} array</>`;
99
+ return `<span className="text-muted-foreground">${col.name} array</span>`;
99
100
  case "object":
100
- return `<>${col.name} object</>`;
101
- case "vector":
102
- // vector 타입은 일반적으로 API를 통해 생성되므로 읽기 전용으로 표시
103
- return `<div className="p-8px text-gray-500">[Vector: ${col.name}] - 임베딩 데이터는 API를 통해 자동 생성됩니다.</div>`;
101
+ return `<span className="text-muted-foreground">${col.name} object</span>`;
104
102
  default:
105
103
  throw new Error(`대응 불가능한 렌더 타입 ${col.renderType} on ${col.name}`);
106
104
  }
107
105
  }
106
+ // New style rendering for feed-sites style form
107
+ renderColumn(entityId, col, names) {
108
+ const regExpr = `{...register("${col.name}")}`;
109
+ switch(col.renderType){
110
+ case "string-plain":
111
+ if (col.zodType instanceof z.ZodString && (col.zodType.maxLength ?? 0) <= 256) {
112
+ return `<Input className="h-8 text-xs bg-white" placeholder="${col.label}" ${regExpr} />`;
113
+ } else {
114
+ return `<Textarea className="text-xs bg-white" rows={4} placeholder="${col.label}" ${regExpr} />`;
115
+ }
116
+ case "string-datetime":
117
+ return `<DateInput
118
+ className="h-8 text-xs bg-white"
119
+ value={form.${col.name} ? new Date(form.${col.name}) : null}
120
+ onValueChange={(value) => setForm({ ...form, ${col.name}: value })}
121
+ />`;
122
+ case "string-date":
123
+ return `<DateInput
124
+ mode="date"
125
+ className="h-8 text-xs bg-white"
126
+ value={form.${col.name} ? new Date(form.${col.name}) : null}
127
+ onValueChange={(value) => setForm({ ...form, ${col.name}: value })}
128
+ />`;
129
+ case "datetime":
130
+ return `<DateInput
131
+ className="h-8 text-xs bg-white"
132
+ ${regExpr}
133
+ />`;
134
+ case "number-id":
135
+ return `<input type="hidden" ${regExpr} />`;
136
+ case "number-plain":
137
+ return `<Input type="number" className="h-8 text-xs bg-white" placeholder="${col.label}" ${regExpr} />`;
138
+ case "boolean":
139
+ return `<Switch ${regExpr} />`;
140
+ case "string-image":
141
+ return `<ImageUploader
142
+ ${regExpr}
143
+ uploader={async (file: File) => {
144
+ const { file: uploadedFile } = await FileService.upload(file);
145
+ return uploadedFile.url;
146
+ }}
147
+ previewSize="md"
148
+ />`;
149
+ case "array-images":
150
+ return `<MultiImageUploader
151
+ value={Array.isArray(form.${col.name}) ? form.${col.name} : []}
152
+ onValueChange={(urls) => setForm({ ...form, ${col.name}: urls })}
153
+ uploader={async (file: File) => {
154
+ const { file: uploadedFile } = await FileService.upload(file);
155
+ return uploadedFile.url;
156
+ }}
157
+ previewSize="md"
158
+ placeholder="${col.label}"
159
+ />`;
160
+ case "enums":
161
+ try {
162
+ let enumId;
163
+ if (col.name === "orderBy") {
164
+ enumId = `${names.capital}${inflection.camelize(col.name)}Select`;
165
+ } else {
166
+ const { id } = getEnumInfoFromColName(entityId, col.name);
167
+ enumId = `${id}Select`;
168
+ }
169
+ return `<${enumId} ${regExpr} ${col.optional || col.nullable ? "clearable" : ""} />`;
170
+ } catch {
171
+ return `<Input className="h-8 text-xs bg-white" ${regExpr} />`;
172
+ }
173
+ case "number-fk_id":
174
+ try {
175
+ const relProp = getRelationPropFromColName(entityId, col.name.replace("_id", ""));
176
+ const fkId = `${relProp.with}IdAsyncSelect`;
177
+ return `<${fkId} subset="A" ${regExpr} ${col.optional || col.nullable ? "clearable" : ""} className="h-8 text-xs" />`;
178
+ } catch {
179
+ return `<Input type="number" className="h-8 text-xs bg-white" placeholder="${col.label}" ${regExpr} />`;
180
+ }
181
+ case "array":
182
+ case "object":
183
+ return `<Input className="h-8 text-xs bg-white" placeholder="${col.name}" ${regExpr} />`;
184
+ default:
185
+ return `<Input className="h-8 text-xs bg-white" ${regExpr} />`;
186
+ }
187
+ }
108
188
  resolveDefaultValue(columns) {
109
189
  return columns.reduce((result, col)=>{
110
190
  if (col.optional) {
@@ -116,11 +196,9 @@ export class Template__view_form extends Template {
116
196
  } else if (col.zodType instanceof z.ZodNumber) {
117
197
  value = 0;
118
198
  } else if (col.zodType instanceof z.ZodEnum) {
119
- value = Object.keys(col.zodType.options)[0];
199
+ value = Object.keys(col.zodType.enum)[0];
120
200
  } else if (col.zodType instanceof z.ZodBoolean) {
121
201
  value = false;
122
- } else if (col.zodType instanceof z.ZodDate) {
123
- value = new Date();
124
202
  } else if (col.zodType instanceof z.ZodString) {
125
203
  if (col.renderType === "string-datetime") {
126
204
  value = "now()";
@@ -137,11 +215,19 @@ export class Template__view_form extends Template {
137
215
  }, {});
138
216
  }
139
217
  async render({ entityId }) {
140
- const saveParamsZodType = await getZodTypeById(`${entityId}SaveParams`);
141
- const saveParamsNode = zodTypeToRenderingNode(saveParamsZodType);
142
218
  const entity = EntityManager.get(entityId);
143
219
  const names = EntityManager.getNamesFromId(entityId);
144
- const columns = saveParamsNode.children.filter((col)=>col.name !== "id").map((col)=>{
220
+ // SaveParams 타입을 로드하여 saveParamsNode 생성
221
+ const { loadTypes } = await import("../../syncer/module-loader.js");
222
+ const loadedTypes = await loadTypes();
223
+ const SaveParamsZodType = loadedTypes[`${entityId}SaveParams`];
224
+ if (!SaveParamsZodType) {
225
+ throw new Error(`SaveParams for ${entityId} not found. Did you run 'sonamu sync'?`);
226
+ }
227
+ // Zod 타입을 RenderingNode로 변환
228
+ const { zodTypeToRenderingNode } = await import("../zod-converter.js");
229
+ const saveParamsNode = zodTypeToRenderingNode(SaveParamsZodType);
230
+ const columns = (saveParamsNode?.children ?? []).filter((col)=>col.name !== "id").map((col)=>{
145
231
  const propCandidate = entity.props.find((prop)=>prop.name === col.name);
146
232
  col.label = propCandidate?.desc ?? col.label;
147
233
  return col;
@@ -203,28 +289,37 @@ export class Template__view_form extends Template {
203
289
  return {
204
290
  ...this.getTargetAndPath(names),
205
291
  body: `
206
- import React, { useEffect, useState, Dispatch, SetStateAction, forwardRef, Ref, useImperativeHandle, useCallback } from 'react';
207
- import { useSearchParams } from 'react-router-dom';
208
292
  import {
209
293
  Button,
210
- Checkbox,
211
- Form,
212
- Header,
213
- Input,
214
- Segment,
215
- TextArea,
216
- Label,
217
- } from 'semantic-ui-react';
218
- import { DateTime } from "luxon";
219
-
220
- import { BackLink, LinkInput, NumberInput, BooleanToggle, SQLDateTimeInput, SQLDateInput, useTypeForm, useGoBack, formatDateTime } from "@sonamu-kit/react-sui";
221
- import { defaultCatch } from '@/services/sonamu.shared';
222
- // import { ImageUploader } from '@/admin-common/ImageUploader';
223
- // import { useCommonModal } from "@/admin-common/CommonModal";
224
-
225
- import { ${names.capital}SaveParams } from '@/services/${names.fs}/${names.fs}.types';
226
- import { ${names.capital}Service } from '@/services/services.generated';
227
- import { ${names.capital}SubsetA } from '@/services/sonamu.generated';
294
+ Card,
295
+ CardContent,
296
+ CardHeader,
297
+ CardTitle,
298
+ Input,${columns.some((col)=>col.renderType === "string-plain" && col.zodType instanceof z.ZodString && (col.zodType.maxLength ?? 0) > 256) ? "\n Textarea," : ""}${columns.some((col)=>col.renderType === "enums") ? "\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue," : ""}${columns.some((col)=>col.renderType === "boolean") ? "\n Switch," : ""}${columns.some((col)=>col.renderType === "string-image") ? "\n ImageUploader," : ""}${columns.some((col)=>col.renderType === "array-images") ? "\n MultiImageUploader," : ""}${columns.some((col)=>[
299
+ "string-datetime",
300
+ "string-date",
301
+ "datetime"
302
+ ].includes(col.renderType)) ? "\n DateInput," : ""}
303
+ } from "@sonamu-kit/react-components/components";
304
+ import { useTypeForm } from "@sonamu-kit/react-components/lib";
305
+ import { useQueryClient } from "@tanstack/react-query";
306
+ import { createFileRoute, useRouter } from "@tanstack/react-router";
307
+ import { useEffect } from "react";
308
+ import { z } from "zod";
309
+ import { ${names.capital}Service${columns.some((col)=>[
310
+ "string-image",
311
+ "array-images"
312
+ ].includes(col.renderType)) ? ", FileService" : ""} } from "@/services/services.generated";
313
+ import type { ${names.capital}SubsetA } from "@/services/sonamu.generated";${columns.filter((col)=>col.renderType === "enums").length > 0 ? "\nimport { " + unique(columns.filter((col)=>col.renderType === "enums").map((col)=>{
314
+ try {
315
+ const { id } = getEnumInfoFromColName(entityId, col.name);
316
+ return `${id}, ${id}Label`;
317
+ } catch {
318
+ return "";
319
+ }
320
+ })).filter(Boolean).join(", ") + ' } from "@/services/sonamu.generated";' : ""}
321
+ import { defaultCatch } from "@/services/sonamu.shared";
322
+ import { ${names.capital}SaveParams } from "@/services/${names.fs}/${names.fs}.types";
228
323
  ${unique(columns.filter((col)=>[
229
324
  "number-fk_id",
230
325
  "enums"
@@ -232,104 +327,181 @@ ${unique(columns.filter((col)=>[
232
327
  return this.renderColumnImport(entityId, col);
233
328
  })).join("\n")}
234
329
 
235
- export default function ${names.capitalPlural}FormPage() {
236
- // 라우팅 searchParams
237
- const [searchParams] = useSearchParams();
238
- const query = {
239
- id: searchParams.get('id') ?? undefined,
240
- };
330
+ import ArrowLeftIcon from "~icons/lucide/arrow-left";
331
+ import SaveIcon from "~icons/lucide/save";
332
+ import FormIcon from "~icons/mdi/form-select";
333
+
334
+ const formSearchSchema = z.object({
335
+ id: z.number().optional(),
336
+ });
337
+
338
+ export const Route = createFileRoute("/admin/${names.fsPlural}/form")({
339
+ validateSearch: formSearchSchema,
340
+ component: ${names.capitalPlural}FormPage,
341
+ });
241
342
 
242
- return <${names.capitalPlural}Form id={query?.id ? Number(query.id) : undefined} />;
343
+ function ${names.capitalPlural}FormPage() {
344
+ const { id } = Route.useSearch();
345
+ return <${names.capitalPlural}Form id={id} />;
243
346
  }
347
+
244
348
  type ${names.capitalPlural}FormProps = {
245
349
  id?: number;
246
- mode?: 'page' | 'modal';
350
+ mode?: "page" | "modal";
247
351
  };
352
+
248
353
  export function ${names.capitalPlural}Form({ id, mode }: ${names.capitalPlural}FormProps) {
249
- // 편집시 기존 row
250
- const [row, setRow] = useState<${names.capital}SubsetA | undefined>();
354
+ const router = useRouter();
355
+ const queryClient = useQueryClient();
356
+
357
+ const { form, setForm, register } = useTypeForm(${names.capital}SaveParams, ${JSON.stringify(defaultValue).replace(/"now\(\)"/g, '""')});
358
+ ${(()=>{
359
+ const hasDatetime = columns.some((col)=>col.renderType === "string-datetime");
360
+ const hasDate = columns.some((col)=>col.renderType === "string-date");
361
+ if (!hasDatetime && !hasDate) return "";
362
+ let helpers = "\n";
363
+ if (hasDatetime) {
364
+ helpers += ` // datetime-local 형식으로 변환 (YYYY-MM-DDTHH:MM)
365
+ const toDatetimeLocalString = (date: Date | string | null | undefined): string => {
366
+ if (!date) return "";
367
+ const d = typeof date === "string" ? new Date(date) : date;
368
+ return d.toISOString().slice(0, 16);
369
+ };
251
370
 
252
- // ${names.capital}SaveParams
253
- const { form, setForm, register } = useTypeForm(${names.capital}SaveParams, ${JSON.stringify(defaultValue).replace(/"now\(\)"/g, "DateTime.local().toSQL()!.slice(0, 19)")});
371
+ // datetime-local 문자열을 Date로 변환
372
+ const fromDatetimeLocalString = (value: string): Date | null => {
373
+ if (!value) return null;
374
+ return new Date(value);
375
+ };
376
+ `;
377
+ }
378
+ if (hasDate) {
379
+ helpers += ` // date 형식으로 변환 (YYYY-MM-DD)
380
+ const toDateString = (date: Date | string | null | undefined): string => {
381
+ if (!date) return "";
382
+ const d = typeof date === "string" ? new Date(date) : date;
383
+ return d.toISOString().split("T")[0];
384
+ };
254
385
 
255
- // 수정일 기존 row 콜
386
+ // date 문자열을 Date로 변환
387
+ const fromDateString = (value: string): Date | null => {
388
+ if (!value) return null;
389
+ return new Date(value);
390
+ };
391
+ `;
392
+ }
393
+ return helpers;
394
+ })()}
256
395
  useEffect(() => {
257
396
  if (id) {
258
- ${names.capital}Service.get${names.capital}('A', id).then((row) => {
259
- setRow(row);
260
- setForm({
397
+ ${names.capital}Service.get${names.capital}("A", id).then((row) => {
398
+ setForm((prevForm) => ({
399
+ ...prevForm,
261
400
  ...row,
262
- ${columns.filter((col)=>col.renderType === "number-fk_id").map((col)=>{
263
- if (col.nullable) {
264
- return `${col.name}: row.${col.name.replace("_id", "?.id")} ?? null`;
265
- } else {
266
- return `${col.name}: row.${col.name.replace("_id", ".id")}`;
267
- }
268
- }).join(",\n")}
269
- });
401
+ }));
270
402
  });
271
403
  }
272
- }, [id]);
404
+ }, [id, setForm]);
273
405
 
274
- // CommonModal
275
- // const { doneModal, closeModal } = useCommonModal();
406
+ const saveMutation = ${names.capital}Service.useSaveMutation();
407
+ const handleSubmit = () => {
408
+ saveMutation.mutate(
409
+ { spa: [form] },
410
+ {
411
+ onSuccess: () => {
412
+ queryClient.invalidateQueries({
413
+ queryKey: ["${names.capital}"],
414
+ });
276
415
 
277
- // 저장
278
- const { goBack } = useGoBack();
279
- const handleSubmit = useCallback(() => {
280
- ${names.capital}Service.save([form]).then(([id]) => {
281
- if( mode === 'modal' ) {
282
- // doneModal();
283
- } else {
284
- goBack('/admin/${names.fsPlural}');
285
- }
286
- }).catch(defaultCatch);
287
- }, [ form, mode, id ]);
416
+ if (mode === "modal") {
417
+ // modal mode
418
+ } else {
419
+ router.navigate({ to: "/admin/${names.fsPlural}" });
420
+ }
421
+ },
422
+ onError: defaultCatch,
423
+ },
424
+ );
425
+ };
288
426
 
289
- // 페이지
290
427
  const PAGE = {
291
- title: \`${entity.title ?? names.capital}\${id ? \`#\${id} 수정\` : ' 등록'}\`,
292
- }
428
+ title: \`${entity.title ?? names.capital}\${id ? \` #\${id} Edit\` : " Create"}\`,
429
+ };
293
430
 
294
431
  return (
295
- <div className="form">
296
- <Segment padded basic>
297
- <Segment padded color="grey">
298
- <div className="header-row">
299
- <Header>
300
- {PAGE.title}
301
- </Header>
302
- { mode !== 'modal' && <div className="buttons">
303
- <BackLink primary size="tiny" to="/admin/${names.fsPlural}" content="목록" icon="list" />
304
- </div>}
432
+ <div className="flex-1 overflow-auto">
433
+ <div className="max-w-[1800px] mx-auto p-8">
434
+ <div className="space-y-6 mb-8">
435
+ {/* Header */}
436
+ <div className="flex items-center justify-between">
437
+ <div className="flex items-center gap-2">
438
+ <FormIcon className="h-5 w-5" />
439
+ <span className="text-lg font-semibold h-5">{PAGE.title}</span>
440
+ </div>
441
+ {mode !== "modal" && (
442
+ <Button
443
+ variant="outline"
444
+ onClick={() => router.navigate({ to: "/admin/${names.fsPlural}" })}
445
+ icon={<ArrowLeftIcon />}
446
+ >
447
+ Back To List
448
+ </Button>
449
+ )}
305
450
  </div>
306
- <Form>
307
- ${columns.map((col)=>{
308
- if (col.name === "created_at") {
309
- return `{form.id && (${this.wrapFG(`<div className="p-8px">{formatDateTime(form.${col.name})}</div>`, "등록일시")})}`;
310
- } else {
311
- return this.wrapFG(this.renderColumn(entityId, col, names), (()=>{
312
- if (col.label.endsWith("Id")) {
313
- try {
314
- const entity = EntityManager.get(col.label.replace("Id", ""));
315
- return entity.title ?? col.label;
316
- } catch {
317
- return col.label;
318
- }
451
+
452
+ {/* Form Card */}
453
+ <Card className="border-border/40 bg-gray-50 shadow-sm">
454
+ <CardHeader className="px-4 border-b border-gray-200 flex items-center">
455
+ <CardTitle className="text-sm font-medium leading-none m-0">
456
+ {PAGE.title}
457
+ </CardTitle>
458
+ </CardHeader>
459
+ <CardContent className="p-6">
460
+ <div className="space-y-6">
461
+ ${columns.filter((col)=>col.name !== "created_at").map((col)=>{
462
+ const label = (()=>{
463
+ if (col.label.endsWith("Id")) {
464
+ try {
465
+ const entity = EntityManager.get(col.label.replace("Id", ""));
466
+ return entity.title ?? col.label;
467
+ } catch {
468
+ return col.label;
319
469
  }
320
- return col.label;
321
- })());
322
- }
323
- }).join("\n")}
324
- <Segment basic textAlign="center">
325
- <Button type="submit" primary onClick={handleSubmit} content="저장" icon="save" />
326
- </Segment>
327
- </Form>
328
- </Segment>
329
- </Segment>
470
+ }
471
+ return col.label;
472
+ })();
473
+ return ` {/* ${label} */}
474
+ <div className="space-y-2">
475
+ <label className="block text-xs mb-1 text-gray-600">${label}</label>
476
+ ${this.renderColumn(entityId, col, names)}
477
+ </div>`;
478
+ }).join("\n\n")}
479
+
480
+ {/* Save Button */}
481
+ <div className="flex items-center justify-between pt-4">
482
+ {form.id && form.created_at && (
483
+ <div className="flex items-center">
484
+ <label className="mr-2 text-xs text-gray-600">Created At:</label>
485
+ <span className="text-xs text-gray-600">
486
+ {String(form.created_at)}
487
+ </span>
488
+ </div>
489
+ )}
490
+ <Button
491
+ onClick={handleSubmit}
492
+ icon={<SaveIcon />}
493
+ >
494
+ Save
495
+ </Button>
496
+ </div>
497
+ </div>
498
+ </CardContent>
499
+ </Card>
500
+ </div>
501
+ </div>
330
502
  </div>
331
503
  );
332
- };
504
+ }
333
505
  `.trim(),
334
506
  importKeys: [],
335
507
  preTemplates
@@ -337,4 +509,4 @@ export function ${names.capitalPlural}Form({ id, mode }: ${names.capitalPlural}F
337
509
  }
338
510
  }
339
511
 
340
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZW1wbGF0ZS9pbXBsZW1lbnRhdGlvbnMvdmlld19mb3JtLnRlbXBsYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBpbmZsZWN0aW9uIGZyb20gXCJpbmZsZWN0aW9uXCI7XG5pbXBvcnQgeyB1bmlxdWUgfSBmcm9tIFwicmFkYXNoaVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIsIHR5cGUgRW50aXR5TmFtZXNSZWNvcmQgfSBmcm9tIFwiLi4vLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgdHlwZSB7IFJlbmRlcmluZ05vZGUsIFRlbXBsYXRlS2V5LCBUZW1wbGF0ZU9wdGlvbnMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IGdldEVudW1JbmZvRnJvbUNvbE5hbWUsIGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lIH0gZnJvbSBcIi4uL2hlbHBlcnNcIjtcbmltcG9ydCB0eXBlIHsgUmVuZGVyZWRUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZVwiO1xuaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tIFwiLi4vdGVtcGxhdGVcIjtcbmltcG9ydCB7IGdldFpvZFR5cGVCeUlkLCB6b2RUeXBlVG9SZW5kZXJpbmdOb2RlIH0gZnJvbSBcIi4uL3pvZC1jb252ZXJ0ZXJcIjtcblxuZXhwb3J0IGNsYXNzIFRlbXBsYXRlX192aWV3X2Zvcm0gZXh0ZW5kcyBUZW1wbGF0ZSB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwidmlld19mb3JtXCIpO1xuICB9XG5cbiAgZ2V0VGFyZ2V0QW5kUGF0aChuYW1lczogRW50aXR5TmFtZXNSZWNvcmQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGFyZ2V0OiBcIndlYi9zcmMvcGFnZXMvYWRtaW5cIixcbiAgICAgIHBhdGg6IGAke25hbWVzLmZzUGx1cmFsfS9mb3JtLnRzeGAsXG4gICAgfTtcbiAgfVxuXG4gIHdyYXBGQyhib2R5OiBzdHJpbmcsIGxhYmVsPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gW1xuICAgICAgYDxGb3JtLkZpZWxkPiR7bGFiZWwgPyBgXFxuICAgPGxhYmVsPiR7bGFiZWx9PC9sYWJlbD5gIDogXCJcIn1gLFxuICAgICAgYm9keSxcbiAgICAgIGA8L0Zvcm0uRmllbGQ+YCxcbiAgICBdLmpvaW4oXCJcXG5cIik7XG4gIH1cbiAgd3JhcEZHKGJvZHk6IHN0cmluZywgbGFiZWw/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBbYDxGb3JtLkdyb3VwIHdpZHRocz1cImVxdWFsXCI+YCwgdGhpcy53cmFwRkMoYm9keSwgbGFiZWwpLCBgPC9Gb3JtLkdyb3VwPmBdLmpvaW4oXCJcXG5cIik7XG4gIH1cblxuICByZW5kZXJDb2x1bW5JbXBvcnQoZW50aXR5SWQ6IHN0cmluZywgY29sOiBSZW5kZXJpbmdOb2RlKSB7XG4gICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgIGNvbnN0IHsgaWQsIHRhcmdldEVudGl0eU5hbWVzIH0gPSBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZSk7XG4gICAgICBjb25zdCBjb21wb25lbnRJZCA9IGAke2lkfVNlbGVjdGA7XG4gICAgICByZXR1cm4gYGltcG9ydCB7ICR7Y29tcG9uZW50SWR9IH0gZnJvbSBcIkAvY29tcG9uZW50cy8ke3RhcmdldEVudGl0eU5hbWVzLmZzfS8ke2NvbXBvbmVudElkfVwiO2A7XG4gICAgfSBlbHNlIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJudW1iZXItZmtfaWRcIikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0TmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKHJlbFByb3Aud2l0aCk7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudElkID0gYCR7cmVsUHJvcC53aXRofUlkQXN5bmNTZWxlY3RgO1xuICAgICAgICByZXR1cm4gYGltcG9ydCB7ICR7Y29tcG9uZW50SWR9IH0gZnJvbSBcIkAvY29tcG9uZW50cy8ke3RhcmdldE5hbWVzLmZzfS8ke2NvbXBvbmVudElkfVwiO2A7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihg66CM642UIOu2iOqwgOuKpe2VnCDsnoTtj6ztirggJHtjb2wubmFtZX0gJHtjb2wucmVuZGVyVHlwZX1gKTtcbiAgICB9XG4gIH1cblxuICByZW5kZXJDb2x1bW4oXG4gICAgZW50aXR5SWQ6IHN0cmluZyxcbiAgICBjb2w6IFJlbmRlcmluZ05vZGUsXG4gICAgbmFtZXM6IEVudGl0eU5hbWVzUmVjb3JkLFxuICAgIHBhcmVudDogc3RyaW5nID0gXCJcIixcbiAgKTogc3RyaW5nIHtcbiAgICBsZXQgcmVnRXhwcjogc3RyaW5nID0gXCJcIjtcbiAgICByZWdFeHByID0gYHsuLi5yZWdpc3RlcihcXGAke3BhcmVudH0ke2NvbC5uYW1lfVxcYCl9YDtcblxuICAgIHN3aXRjaCAoY29sLnJlbmRlclR5cGUpIHtcbiAgICAgIGNhc2UgXCJzdHJpbmctcGxhaW5cIjpcbiAgICAgICAgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2RTdHJpbmcgJiYgKGNvbC56b2RUeXBlLm1heExlbmd0aCA/PyAwKSA8PSA1MTIpIHtcbiAgICAgICAgICByZXR1cm4gYDxJbnB1dCBwbGFjZWhvbGRlcj1cIiR7Y29sLmxhYmVsfVwiICR7cmVnRXhwcn0gLz5gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBgPFRleHRBcmVhIHJvd3M9ezh9IHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgXCJkYXRldGltZVwiOlxuICAgICAgICByZXR1cm4gYDxJbnB1dCB0eXBlPVwiZGF0ZXRpbWUtbG9jYWxcIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgIGNhc2UgXCJzdHJpbmctZGF0ZXRpbWVcIjpcbiAgICAgICAgcmV0dXJuIGA8U1FMRGF0ZVRpbWVJbnB1dCAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgIGNhc2UgXCJzdHJpbmctZGF0ZVwiOlxuICAgICAgICByZXR1cm4gYDxTUUxEYXRlSW5wdXQgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwibnVtYmVyLWlkXCI6XG4gICAgICAgIHJldHVybiBgPGlucHV0IHR5cGU9XCJoaWRkZW5cIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgIGNhc2UgXCJudW1iZXItcGxhaW5cIjpcbiAgICAgICAgcmV0dXJuIGA8TnVtYmVySW5wdXQgcGxhY2Vob2xkZXI9XCIke2NvbC5sYWJlbH1cIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgIGNhc2UgXCJib29sZWFuXCI6XG4gICAgICAgIHJldHVybiBgPEJvb2xlYW5Ub2dnbGUgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwic3RyaW5nLWltYWdlXCI6XG4gICAgICAgIHJldHVybiBgPEltYWdlVXBsb2FkZXIgbXVsdGlwbGU9e2ZhbHNlfSAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgIGNhc2UgXCJhcnJheS1pbWFnZXNcIjpcbiAgICAgICAgcmV0dXJuIGA8SW1hZ2VVcGxvYWRlciBtdWx0aXBsZT17dHJ1ZX0gJHtyZWdFeHByfSBtYXhTaXplPXs1fSAvPmA7XG4gICAgICBjYXNlIFwiZW51bXNcIjpcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsZXQgZW51bUlkOiBzdHJpbmc7XG4gICAgICAgICAgaWYgKGNvbC5uYW1lID09PSBcIm9yZGVyQnlcIikge1xuICAgICAgICAgICAgZW51bUlkID0gYCR7bmFtZXMuY2FwaXRhbH0ke2luZmxlY3Rpb24uY2FtZWxpemUoY29sLm5hbWUpfVNlbGVjdGA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaWQgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgICAgICAgIGVudW1JZCA9IGAke2lkfVNlbGVjdGA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgPCR7ZW51bUlkfSAke3JlZ0V4cHJ9ICR7XG4gICAgICAgICAgICBjb2wub3B0aW9uYWwgfHwgY29sLm51bGxhYmxlID8gXCJjbGVhcmFibGVcIiA6IFwiXCJcbiAgICAgICAgICB9IHRleHRQcmVmaXg9XCJcIiAvPmA7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBgPD7ssL7snYQg7IiYIOyXhuuKlCBFbnVtICR7Y29sLm5hbWV9PC8+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcIm51bWJlci1ma19pZFwiOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlbFByb3AgPSBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUucmVwbGFjZShcIl9pZFwiLCBcIlwiKSk7XG4gICAgICAgICAgY29uc3QgZmtJZCA9IGAke3JlbFByb3Aud2l0aH1JZEFzeW5jU2VsZWN0YDtcbiAgICAgICAgICByZXR1cm4gYDwke2ZrSWR9IHsuLi5yZWdpc3RlcignJHtjb2wubmFtZX0nKX0gJHtcbiAgICAgICAgICAgIGNvbC5vcHRpb25hbCB8fCBjb2wubnVsbGFibGUgPyBcImNsZWFyYWJsZVwiIDogXCJcIlxuICAgICAgICAgIH0gc3Vic2V0PVwiQVwiIC8+YDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGA8SW5wdXQgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgXCJhcnJheVwiOlxuICAgICAgICByZXR1cm4gYDw+JHtjb2wubmFtZX0gYXJyYXk8Lz5gO1xuICAgICAgY2FzZSBcIm9iamVjdFwiOlxuICAgICAgICByZXR1cm4gYDw+JHtjb2wubmFtZX0gb2JqZWN0PC8+YDtcbiAgICAgIGNhc2UgXCJ2ZWN0b3JcIjpcbiAgICAgICAgLy8gdmVjdG9yIO2DgOyeheydgCDsnbzrsJjsoIHsnLzroZwgQVBJ66W8IO2Gte2VtCDsg53shLHrkJjrr4DroZwg7J296riwIOyghOyaqeycvOuhnCDtkZzsi5xcbiAgICAgICAgcmV0dXJuIGA8ZGl2IGNsYXNzTmFtZT1cInAtOHB4IHRleHQtZ3JheS01MDBcIj5bVmVjdG9yOiAke2NvbC5uYW1lfV0gLSDsnoTrsqDrlKkg642w7J207YSw64qUIEFQSeulvCDthrXtlbQg7J6Q64+ZIOyDneyEseuQqeuLiOuLpC48L2Rpdj5gO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDrjIDsnZEg67aI6rCA64ql7ZWcIOugjOuNlCDtg4DsnoUgJHtjb2wucmVuZGVyVHlwZX0gb24gJHtjb2wubmFtZX1gKTtcbiAgICB9XG4gIH1cblxuICByZXNvbHZlRGVmYXVsdFZhbHVlKGNvbHVtbnM6IFJlbmRlcmluZ05vZGVbXSk6IG9iamVjdCB7XG4gICAgcmV0dXJuIGNvbHVtbnMucmVkdWNlKFxuICAgICAgKHJlc3VsdCwgY29sKSA9PiB7XG4gICAgICAgIGlmIChjb2wub3B0aW9uYWwpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHZhbHVlOiB1bmtub3duO1xuICAgICAgICBpZiAoY29sLm51bGxhYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgdmFsdWUgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2ROdW1iZXIpIHtcbiAgICAgICAgICB2YWx1ZSA9IDA7XG4gICAgICAgIH0gZWxzZSBpZiAoY29sLnpvZFR5cGUgaW5zdGFuY2VvZiB6LlpvZEVudW0pIHtcbiAgICAgICAgICB2YWx1ZSA9IE9iamVjdC5rZXlzKGNvbC56b2RUeXBlLm9wdGlvbnMpWzBdO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2RCb29sZWFuKSB7XG4gICAgICAgICAgdmFsdWUgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIGlmIChjb2wuem9kVHlwZSBpbnN0YW5jZW9mIHouWm9kRGF0ZSkge1xuICAgICAgICAgIHZhbHVlID0gbmV3IERhdGUoKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb2wuem9kVHlwZSBpbnN0YW5jZW9mIHouWm9kU3RyaW5nKSB7XG4gICAgICAgICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcInN0cmluZy1kYXRldGltZVwiKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IFwibm93KClcIjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBcIlwiO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjb2wuem9kVHlwZSBpbnN0YW5jZW9mIHouWm9kQXJyYXkpIHtcbiAgICAgICAgICB2YWx1ZSA9IFtdO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2RPYmplY3QpIHtcbiAgICAgICAgICB2YWx1ZSA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzdWx0W2NvbC5uYW1lXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICAgIHt9IGFzIHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9LFxuICAgICk7XG4gIH1cblxuICBhc3luYyByZW5kZXIoeyBlbnRpdHlJZCB9OiBUZW1wbGF0ZU9wdGlvbnNbXCJ2aWV3X2Zvcm1cIl0pIHtcbiAgICBjb25zdCBzYXZlUGFyYW1zWm9kVHlwZSA9IGF3YWl0IGdldFpvZFR5cGVCeUlkKGAke2VudGl0eUlkfVNhdmVQYXJhbXNgKTtcbiAgICBjb25zdCBzYXZlUGFyYW1zTm9kZSA9IHpvZFR5cGVUb1JlbmRlcmluZ05vZGUoc2F2ZVBhcmFtc1pvZFR5cGUpO1xuXG4gICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuICAgIGNvbnN0IG5hbWVzID0gRW50aXR5TWFuYWdlci5nZXROYW1lc0Zyb21JZChlbnRpdHlJZCk7XG4gICAgY29uc3QgY29sdW1ucyA9IChzYXZlUGFyYW1zTm9kZS5jaGlsZHJlbiBhcyBSZW5kZXJpbmdOb2RlW10pXG4gICAgICAuZmlsdGVyKChjb2wpID0+IGNvbC5uYW1lICE9PSBcImlkXCIpXG4gICAgICAubWFwKChjb2wpID0+IHtcbiAgICAgICAgY29uc3QgcHJvcENhbmRpZGF0ZSA9IGVudGl0eS5wcm9wcy5maW5kKChwcm9wKSA9PiBwcm9wLm5hbWUgPT09IGNvbC5uYW1lKTtcbiAgICAgICAgY29sLmxhYmVsID0gcHJvcENhbmRpZGF0ZT8uZGVzYyA/PyBjb2wubGFiZWw7XG4gICAgICAgIHJldHVybiBjb2w7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IHRoaXMucmVzb2x2ZURlZmF1bHRWYWx1ZShjb2x1bW5zKTtcblxuICAgIC8vIO2UhOumrCDthZztlIzrpr9cbiAgICBjb25zdCBwcmVUZW1wbGF0ZXM6IFJlbmRlcmVkVGVtcGxhdGVbXCJwcmVUZW1wbGF0ZXNcIl0gPSAoY29sdW1ucyBhcyBSZW5kZXJpbmdOb2RlW10pXG4gICAgICAuZmlsdGVyKChjb2wpID0+IHtcbiAgICAgICAgaWYgKGNvbC5uYW1lID09PSBcImlkXCIpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAoY29sLm5hbWUuZW5kc1dpdGgoXCJfaWRcIikgfHwgY29sLnJlbmRlclR5cGUgPT09IFwibnVtYmVyLWlkXCIpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lLnJlcGxhY2UoXCJfaWRcIiwgXCJcIikpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0pXG4gICAgICAubWFwKChjb2wpID0+IHtcbiAgICAgICAgbGV0IGtleTogVGVtcGxhdGVLZXk7XG4gICAgICAgIGxldCB0YXJnZXRNZElkID0gZW50aXR5SWQ7XG4gICAgICAgIGxldCBlbnVtSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpIHtcbiAgICAgICAgICBrZXkgPSBcInZpZXdfZW51bXNfc2VsZWN0XCI7XG4gICAgICAgICAgY29uc3QgeyB0YXJnZXRFbnRpdHlOYW1lczogdGFyZ2V0TUROYW1lcywgaWQgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUoXG4gICAgICAgICAgICBlbnRpdHlJZCxcbiAgICAgICAgICAgIGNvbC5uYW1lLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGFyZ2V0TWRJZCA9IHRhcmdldE1ETmFtZXMuY2FwaXRhbDtcbiAgICAgICAgICBlbnVtSWQgPSBpZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXkgPSBcInZpZXdfaWRfYXN5bmNfc2VsZWN0XCI7XG4gICAgICAgICAgY29uc3QgcmVsUHJvcCA9IGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgICB0YXJnZXRNZElkID0gcmVsUHJvcC53aXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBrZXk6IGtleSBhcyBUZW1wbGF0ZUtleSxcbiAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICBlbnRpdHlJZDogdGFyZ2V0TWRJZCxcbiAgICAgICAgICAgIG5vZGU6IGNvbCxcbiAgICAgICAgICAgIGVudW1JZCxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIoKHByZVRlbXBsYXRlKSA9PiB7XG4gICAgICAgIGlmIChwcmVUZW1wbGF0ZS5rZXkgPT09IFwidmlld19pZF9hc3luY19zZWxlY3RcIikge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBFbnRpdHlNYW5hZ2VyLmdldChwcmVUZW1wbGF0ZS5vcHRpb25zLmVudGl0eUlkKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnRoaXMuZ2V0VGFyZ2V0QW5kUGF0aChuYW1lcyksXG4gICAgICBib2R5OiBgXG5pbXBvcnQgUmVhY3QsIHsgdXNlRWZmZWN0LCB1c2VTdGF0ZSwgRGlzcGF0Y2gsIFNldFN0YXRlQWN0aW9uLCBmb3J3YXJkUmVmLCBSZWYsIHVzZUltcGVyYXRpdmVIYW5kbGUsIHVzZUNhbGxiYWNrIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgdXNlU2VhcmNoUGFyYW1zIH0gZnJvbSAncmVhY3Qtcm91dGVyLWRvbSc7XG5pbXBvcnQge1xuICBCdXR0b24sXG4gIENoZWNrYm94LFxuICBGb3JtLFxuICBIZWFkZXIsXG4gIElucHV0LFxuICBTZWdtZW50LFxuICBUZXh0QXJlYSxcbiAgTGFiZWwsXG59IGZyb20gJ3NlbWFudGljLXVpLXJlYWN0JztcbmltcG9ydCB7IERhdGVUaW1lIH0gZnJvbSBcImx1eG9uXCI7XG5cbmltcG9ydCB7IEJhY2tMaW5rLCBMaW5rSW5wdXQsIE51bWJlcklucHV0LCBCb29sZWFuVG9nZ2xlLCBTUUxEYXRlVGltZUlucHV0LCBTUUxEYXRlSW5wdXQsIHVzZVR5cGVGb3JtLCB1c2VHb0JhY2ssIGZvcm1hdERhdGVUaW1lIH0gZnJvbSBcIkBzb25hbXUta2l0L3JlYWN0LXN1aVwiO1xuaW1wb3J0IHsgZGVmYXVsdENhdGNoIH0gZnJvbSAnQC9zZXJ2aWNlcy9zb25hbXUuc2hhcmVkJztcbi8vIGltcG9ydCB7IEltYWdlVXBsb2FkZXIgfSBmcm9tICdAL2FkbWluLWNvbW1vbi9JbWFnZVVwbG9hZGVyJztcbi8vIGltcG9ydCB7IHVzZUNvbW1vbk1vZGFsIH0gZnJvbSBcIkAvYWRtaW4tY29tbW9uL0NvbW1vbk1vZGFsXCI7XG5cbmltcG9ydCB7ICR7bmFtZXMuY2FwaXRhbH1TYXZlUGFyYW1zIH0gZnJvbSAnQC9zZXJ2aWNlcy8ke25hbWVzLmZzfS8ke25hbWVzLmZzfS50eXBlcyc7XG5pbXBvcnQgeyAke25hbWVzLmNhcGl0YWx9U2VydmljZSB9IGZyb20gJ0Avc2VydmljZXMvc2VydmljZXMuZ2VuZXJhdGVkJztcbmltcG9ydCB7ICR7bmFtZXMuY2FwaXRhbH1TdWJzZXRBIH0gZnJvbSAnQC9zZXJ2aWNlcy9zb25hbXUuZ2VuZXJhdGVkJztcbiR7dW5pcXVlKFxuICBjb2x1bW5zXG4gICAgLmZpbHRlcigoY29sKSA9PiBbXCJudW1iZXItZmtfaWRcIiwgXCJlbnVtc1wiXS5pbmNsdWRlcyhjb2wucmVuZGVyVHlwZSkpXG4gICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5yZW5kZXJDb2x1bW5JbXBvcnQoZW50aXR5SWQsIGNvbCk7XG4gICAgfSksXG4pLmpvaW4oXCJcXG5cIil9XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uICR7bmFtZXMuY2FwaXRhbFBsdXJhbH1Gb3JtUGFnZSgpIHtcbiAgLy8g65287Jqw7YyFIHNlYXJjaFBhcmFtc1xuICBjb25zdCBbc2VhcmNoUGFyYW1zXSA9IHVzZVNlYXJjaFBhcmFtcygpO1xuICBjb25zdCBxdWVyeSA9IHtcbiAgICBpZDogc2VhcmNoUGFyYW1zLmdldCgnaWQnKSA/PyB1bmRlZmluZWQsXG4gIH07XG5cbiAgcmV0dXJuIDwke25hbWVzLmNhcGl0YWxQbHVyYWx9Rm9ybSBpZD17cXVlcnk/LmlkID8gTnVtYmVyKHF1ZXJ5LmlkKSA6IHVuZGVmaW5lZH0gLz47XG59XG50eXBlICR7bmFtZXMuY2FwaXRhbFBsdXJhbH1Gb3JtUHJvcHMgPSB7XG4gIGlkPzogbnVtYmVyO1xuICBtb2RlPzogJ3BhZ2UnIHwgJ21vZGFsJztcbn07XG5leHBvcnQgZnVuY3Rpb24gJHtuYW1lcy5jYXBpdGFsUGx1cmFsfUZvcm0oeyBpZCwgbW9kZSB9OiAke25hbWVzLmNhcGl0YWxQbHVyYWx9Rm9ybVByb3BzKSB7XG4gIC8vIO2OuOynkeyLnCDquLDsobQgcm93XG4gIGNvbnN0IFtyb3csIHNldFJvd10gPSB1c2VTdGF0ZTwke25hbWVzLmNhcGl0YWx9U3Vic2V0QSB8IHVuZGVmaW5lZD4oKTtcblxuICAvLyAke25hbWVzLmNhcGl0YWx9U2F2ZVBhcmFtcyDtj7xcbiAgY29uc3QgeyBmb3JtLCBzZXRGb3JtLCByZWdpc3RlciB9ID0gdXNlVHlwZUZvcm0oJHtuYW1lcy5jYXBpdGFsfVNhdmVQYXJhbXMsICR7SlNPTi5zdHJpbmdpZnkoXG4gICAgZGVmYXVsdFZhbHVlLFxuICApLnJlcGxhY2UoL1wibm93XFwoXFwpXCIvZywgXCJEYXRlVGltZS5sb2NhbCgpLnRvU1FMKCkhLnNsaWNlKDAsIDE5KVwiKX0pO1xuXG4gIC8vIOyImOygleydvCDrlYwg6riw7KG0IHJvdyDsvZxcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaWQpIHtcbiAgICAgICR7bmFtZXMuY2FwaXRhbH1TZXJ2aWNlLmdldCR7bmFtZXMuY2FwaXRhbH0oJ0EnLCBpZCkudGhlbigocm93KSA9PiB7XG4gICAgICAgIHNldFJvdyhyb3cpO1xuICAgICAgICBzZXRGb3JtKHtcbiAgICAgICAgICAuLi5yb3csXG4gICAgICAgICAgJHtjb2x1bW5zXG4gICAgICAgICAgICAuZmlsdGVyKChjb2wpID0+IGNvbC5yZW5kZXJUeXBlID09PSBcIm51bWJlci1ma19pZFwiKVxuICAgICAgICAgICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChjb2wubnVsbGFibGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7Y29sLm5hbWV9OiByb3cuJHtjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiPy5pZFwiKX0gPz8gbnVsbGA7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke2NvbC5uYW1lfTogcm93LiR7Y29sLm5hbWUucmVwbGFjZShcIl9pZFwiLCBcIi5pZFwiKX1gO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oXCIsXFxuXCIpfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwgW2lkXSk7XG5cbiAgLy8gQ29tbW9uTW9kYWxcbiAgLy8gY29uc3QgeyBkb25lTW9kYWwsIGNsb3NlTW9kYWwgfSA9IHVzZUNvbW1vbk1vZGFsKCk7XG5cbiAgLy8g7KCA7J6lXG4gIGNvbnN0IHsgZ29CYWNrIH0gPSB1c2VHb0JhY2soKTtcbiAgY29uc3QgaGFuZGxlU3VibWl0ID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICR7bmFtZXMuY2FwaXRhbH1TZXJ2aWNlLnNhdmUoW2Zvcm1dKS50aGVuKChbaWRdKSA9PiB7XG4gICAgICBpZiggbW9kZSA9PT0gJ21vZGFsJyApIHtcbiAgICAgICAgLy8gZG9uZU1vZGFsKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnb0JhY2soJy9hZG1pbi8ke25hbWVzLmZzUGx1cmFsfScpO1xuICAgICAgfVxuICAgIH0pLmNhdGNoKGRlZmF1bHRDYXRjaCk7XG4gIH0sIFsgZm9ybSwgbW9kZSwgaWQgXSk7XG5cbiAgLy8g7Y6Y7J207KeAXG4gIGNvbnN0IFBBR0UgPSB7XG4gICAgdGl0bGU6IFxcYCR7ZW50aXR5LnRpdGxlID8/IG5hbWVzLmNhcGl0YWx9XFwke2lkID8gXFxgI1xcJHtpZH0g7IiY7KCVXFxgIDogJyDrk7HroZ0nfVxcYCxcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPGRpdiBjbGFzc05hbWU9XCJmb3JtXCI+XG4gICAgICA8U2VnbWVudCBwYWRkZWQgYmFzaWM+XG4gICAgICAgIDxTZWdtZW50IHBhZGRlZCBjb2xvcj1cImdyZXlcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImhlYWRlci1yb3dcIj5cbiAgICAgICAgICAgIDxIZWFkZXI+XG4gICAgICAgICAgICAgIHtQQUdFLnRpdGxlfVxuICAgICAgICAgICAgPC9IZWFkZXI+XG4gICAgICAgICAgICB7IG1vZGUgIT09ICdtb2RhbCcgJiYgPGRpdiBjbGFzc05hbWU9XCJidXR0b25zXCI+XG4gICAgICAgICAgICAgIDxCYWNrTGluayBwcmltYXJ5IHNpemU9XCJ0aW55XCIgdG89XCIvYWRtaW4vJHtcbiAgICAgICAgICAgICAgICBuYW1lcy5mc1BsdXJhbFxuICAgICAgICAgICAgICB9XCIgY29udGVudD1cIuuqqeuhnVwiIGljb249XCJsaXN0XCIgLz5cbiAgICAgICAgICAgIDwvZGl2Pn1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8Rm9ybT5cbiAgICAgICAgICAgICR7Y29sdW1uc1xuICAgICAgICAgICAgICAubWFwKChjb2wpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29sLm5hbWUgPT09IFwiY3JlYXRlZF9hdFwiKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gYHtmb3JtLmlkICYmICgke3RoaXMud3JhcEZHKFxuICAgICAgICAgICAgICAgICAgICBgPGRpdiBjbGFzc05hbWU9XCJwLThweFwiPntmb3JtYXREYXRlVGltZShmb3JtLiR7Y29sLm5hbWV9KX08L2Rpdj5gLFxuICAgICAgICAgICAgICAgICAgICBcIuuTseuhneydvOyLnFwiLFxuICAgICAgICAgICAgICAgICAgKX0pfWA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLndyYXBGRyhcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW4oZW50aXR5SWQsIGNvbCwgbmFtZXMpLFxuICAgICAgICAgICAgICAgICAgICAoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2wubGFiZWwuZW5kc1dpdGgoXCJJZFwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoY29sLmxhYmVsLnJlcGxhY2UoXCJJZFwiLCBcIlwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlbnRpdHkudGl0bGUgPz8gY29sLmxhYmVsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2wubGFiZWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2wubGFiZWw7XG4gICAgICAgICAgICAgICAgICAgIH0pKCksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgLmpvaW4oXCJcXG5cIil9XG4gICAgICAgICAgICA8U2VnbWVudCBiYXNpYyB0ZXh0QWxpZ249XCJjZW50ZXJcIj5cbiAgICAgICAgICAgICAgPEJ1dHRvbiB0eXBlPVwic3VibWl0XCIgcHJpbWFyeSBvbkNsaWNrPXtoYW5kbGVTdWJtaXR9IGNvbnRlbnQ9XCLsoIDsnqVcIiBpY29uPVwic2F2ZVwiIC8+XG4gICAgICAgICAgICA8L1NlZ21lbnQ+XG4gICAgICAgICAgPC9Gb3JtPlxuICAgICAgICA8L1NlZ21lbnQ+XG4gICAgICA8L1NlZ21lbnQ+XG4gICAgPC9kaXY+XG4gICk7XG59O1xuICAgICAgYC50cmltKCksXG4gICAgICBpbXBvcnRLZXlzOiBbXSxcbiAgICAgIHByZVRlbXBsYXRlcyxcbiAgICB9O1xuICB9XG59XG4iXSwibmFtZXMiOlsiaW5mbGVjdGlvbiIsInVuaXF1ZSIsInoiLCJFbnRpdHlNYW5hZ2VyIiwiZ2V0RW51bUluZm9Gcm9tQ29sTmFtZSIsImdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lIiwiVGVtcGxhdGUiLCJnZXRab2RUeXBlQnlJZCIsInpvZFR5cGVUb1JlbmRlcmluZ05vZGUiLCJUZW1wbGF0ZV9fdmlld19mb3JtIiwiZ2V0VGFyZ2V0QW5kUGF0aCIsIm5hbWVzIiwidGFyZ2V0IiwicGF0aCIsImZzUGx1cmFsIiwid3JhcEZDIiwiYm9keSIsImxhYmVsIiwiam9pbiIsIndyYXBGRyIsInJlbmRlckNvbHVtbkltcG9ydCIsImVudGl0eUlkIiwiY29sIiwicmVuZGVyVHlwZSIsImlkIiwidGFyZ2V0RW50aXR5TmFtZXMiLCJuYW1lIiwiY29tcG9uZW50SWQiLCJmcyIsInJlbFByb3AiLCJyZXBsYWNlIiwidGFyZ2V0TmFtZXMiLCJnZXROYW1lc0Zyb21JZCIsIndpdGgiLCJFcnJvciIsInJlbmRlckNvbHVtbiIsInBhcmVudCIsInJlZ0V4cHIiLCJ6b2RUeXBlIiwiWm9kU3RyaW5nIiwibWF4TGVuZ3RoIiwiZW51bUlkIiwiY2FwaXRhbCIsImNhbWVsaXplIiwib3B0aW9uYWwiLCJudWxsYWJsZSIsImZrSWQiLCJyZXNvbHZlRGVmYXVsdFZhbHVlIiwiY29sdW1ucyIsInJlZHVjZSIsInJlc3VsdCIsInZhbHVlIiwiWm9kTnVtYmVyIiwiWm9kRW51bSIsIk9iamVjdCIsImtleXMiLCJvcHRpb25zIiwiWm9kQm9vbGVhbiIsIlpvZERhdGUiLCJEYXRlIiwiWm9kQXJyYXkiLCJab2RPYmplY3QiLCJyZW5kZXIiLCJzYXZlUGFyYW1zWm9kVHlwZSIsInNhdmVQYXJhbXNOb2RlIiwiZW50aXR5IiwiZ2V0IiwiY2hpbGRyZW4iLCJmaWx0ZXIiLCJtYXAiLCJwcm9wQ2FuZGlkYXRlIiwicHJvcHMiLCJmaW5kIiwicHJvcCIsImRlc2MiLCJkZWZhdWx0VmFsdWUiLCJwcmVUZW1wbGF0ZXMiLCJlbmRzV2l0aCIsImtleSIsInRhcmdldE1kSWQiLCJ0YXJnZXRNRE5hbWVzIiwibm9kZSIsInByZVRlbXBsYXRlIiwiaW5jbHVkZXMiLCJjYXBpdGFsUGx1cmFsIiwiSlNPTiIsInN0cmluZ2lmeSIsInRpdGxlIiwidHJpbSIsImltcG9ydEtleXMiXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLGdCQUFnQixhQUFhO0FBQ3BDLFNBQVNDLE1BQU0sUUFBUSxVQUFVO0FBQ2pDLFNBQVNDLENBQUMsUUFBUSxNQUFNO0FBQ3hCLFNBQVNDLGFBQWEsUUFBZ0MsaUNBQThCO0FBRXBGLFNBQVNDLHNCQUFzQixFQUFFQywwQkFBMEIsUUFBUSxnQkFBYTtBQUVoRixTQUFTQyxRQUFRLFFBQVEsaUJBQWM7QUFDdkMsU0FBU0MsY0FBYyxFQUFFQyxzQkFBc0IsUUFBUSxzQkFBbUI7QUFFMUUsT0FBTyxNQUFNQyw0QkFBNEJIO0lBQ3ZDLGFBQWM7UUFDWixLQUFLLENBQUM7SUFDUjtJQUVBSSxpQkFBaUJDLEtBQXdCLEVBQUU7UUFDekMsT0FBTztZQUNMQyxRQUFRO1lBQ1JDLE1BQU0sR0FBR0YsTUFBTUcsUUFBUSxDQUFDLFNBQVMsQ0FBQztRQUNwQztJQUNGO0lBRUFDLE9BQU9DLElBQVksRUFBRUMsS0FBYyxFQUFVO1FBQzNDLE9BQU87WUFDTCxDQUFDLFlBQVksRUFBRUEsUUFBUSxDQUFDLFlBQVksRUFBRUEsTUFBTSxRQUFRLENB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
512
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZW1wbGF0ZS9pbXBsZW1lbnRhdGlvbnMvdmlld19mb3JtLnRlbXBsYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBpbmZsZWN0aW9uIGZyb20gXCJpbmZsZWN0aW9uXCI7XG5pbXBvcnQgeyB1bmlxdWUgfSBmcm9tIFwicmFkYXNoaVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIsIHR5cGUgRW50aXR5TmFtZXNSZWNvcmQgfSBmcm9tIFwiLi4vLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgdHlwZSB7IFJlbmRlcmluZ05vZGUsIFRlbXBsYXRlS2V5LCBUZW1wbGF0ZU9wdGlvbnMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IGdldEVudW1JbmZvRnJvbUNvbE5hbWUsIGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lIH0gZnJvbSBcIi4uL2hlbHBlcnNcIjtcbmltcG9ydCB0eXBlIHsgUmVuZGVyZWRUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZVwiO1xuaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tIFwiLi4vdGVtcGxhdGVcIjtcblxuZXhwb3J0IGNsYXNzIFRlbXBsYXRlX192aWV3X2Zvcm0gZXh0ZW5kcyBUZW1wbGF0ZSB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwidmlld19mb3JtXCIpO1xuICB9XG5cbiAgZ2V0VGFyZ2V0QW5kUGF0aChuYW1lczogRW50aXR5TmFtZXNSZWNvcmQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGFyZ2V0OiBcIndlYi9zcmMvcm91dGVzL2FkbWluXCIsXG4gICAgICBwYXRoOiBgJHtuYW1lcy5mc1BsdXJhbH0vZm9ybS50c3hgLFxuICAgIH07XG4gIH1cblxuICB3cmFwRkMoYm9keTogc3RyaW5nLCBsYWJlbD86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFtcbiAgICAgIGA8ZGl2IGNsYXNzTmFtZT1cInNwYWNlLXktMlwiPiR7bGFiZWwgPyBgXFxuICA8TGFiZWw+JHtsYWJlbH08L0xhYmVsPmAgOiBcIlwifWAsXG4gICAgICBgICAke2JvZHl9YCxcbiAgICAgIGA8L2Rpdj5gLFxuICAgIF0uam9pbihcIlxcblwiKTtcbiAgfVxuICB3cmFwRkcoYm9keTogc3RyaW5nLCBsYWJlbD86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3JhcEZDKGJvZHksIGxhYmVsKTtcbiAgfVxuXG4gIHJlbmRlckNvbHVtbkltcG9ydChlbnRpdHlJZDogc3RyaW5nLCBjb2w6IFJlbmRlcmluZ05vZGUpIHtcbiAgICBpZiAoY29sLnJlbmRlclR5cGUgPT09IFwiZW51bXNcIikge1xuICAgICAgY29uc3QgeyBpZCwgdGFyZ2V0RW50aXR5TmFtZXMgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgIGNvbnN0IGNvbXBvbmVudElkID0gYCR7aWR9U2VsZWN0YDtcbiAgICAgIHJldHVybiBgaW1wb3J0IHsgJHtjb21wb25lbnRJZH0gfSBmcm9tIFwiQC9jb21wb25lbnRzLyR7dGFyZ2V0RW50aXR5TmFtZXMuZnN9LyR7Y29tcG9uZW50SWR9XCI7YDtcbiAgICB9IGVsc2UgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcIm51bWJlci1ma19pZFwiKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZWxQcm9wID0gZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lLnJlcGxhY2UoXCJfaWRcIiwgXCJcIikpO1xuICAgICAgICBjb25zdCB0YXJnZXROYW1lcyA9IEVudGl0eU1hbmFnZXIuZ2V0TmFtZXNGcm9tSWQocmVsUHJvcC53aXRoKTtcbiAgICAgICAgY29uc3QgY29tcG9uZW50SWQgPSBgJHtyZWxQcm9wLndpdGh9SWRBc3luY1NlbGVjdGA7XG4gICAgICAgIHJldHVybiBgaW1wb3J0IHsgJHtjb21wb25lbnRJZH0gfSBmcm9tIFwiQC9jb21wb25lbnRzLyR7dGFyZ2V0TmFtZXMuZnN9LyR7Y29tcG9uZW50SWR9XCI7YDtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGDroIzrjZQg67aI6rCA64ql7ZWcIOyehO2PrO2KuCAke2NvbC5uYW1lfSAke2NvbC5yZW5kZXJUeXBlfWApO1xuICAgIH1cbiAgfVxuXG4gIHJlbmRlckNvbHVtbk9sZChcbiAgICBlbnRpdHlJZDogc3RyaW5nLFxuICAgIGNvbDogUmVuZGVyaW5nTm9kZSxcbiAgICBuYW1lczogRW50aXR5TmFtZXNSZWNvcmQsXG4gICAgcGFyZW50OiBzdHJpbmcgPSBcIlwiLFxuICApOiBzdHJpbmcge1xuICAgIGxldCByZWdFeHByOiBzdHJpbmcgPSBcIlwiO1xuICAgIHJlZ0V4cHIgPSBgey4uLnJlZ2lzdGVyKFxcYCR7cGFyZW50fSR7Y29sLm5hbWV9XFxgKX1gO1xuXG4gICAgc3dpdGNoIChjb2wucmVuZGVyVHlwZSkge1xuICAgICAgY2FzZSBcInN0cmluZy1wbGFpblwiOlxuICAgICAgICBpZiAoY29sLnpvZFR5cGUgaW5zdGFuY2VvZiB6LlpvZFN0cmluZyAmJiAoY29sLnpvZFR5cGUubWF4TGVuZ3RoID8/IDApIDw9IDUxMikge1xuICAgICAgICAgIHJldHVybiBgPElucHV0IHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGA8VGV4dGFyZWEgcm93cz17OH0gcGxhY2Vob2xkZXI9XCIke2NvbC5sYWJlbH1cIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcInN0cmluZy1kYXRldGltZVwiOlxuICAgICAgICByZXR1cm4gYDxEYXRlUGlja2VyICR7cmVnRXhwcn0gLz5gO1xuICAgICAgY2FzZSBcInN0cmluZy1kYXRlXCI6XG4gICAgICAgIHJldHVybiBgPERhdGVQaWNrZXIgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwibnVtYmVyLWlkXCI6XG4gICAgICAgIHJldHVybiBgPGlucHV0IHR5cGU9XCJoaWRkZW5cIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgIGNhc2UgXCJudW1iZXItcGxhaW5cIjpcbiAgICAgICAgcmV0dXJuIGA8SW5wdXQgdHlwZT1cIm51bWJlclwiIHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgICByZXR1cm4gYDxTd2l0Y2ggJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwic3RyaW5nLWltYWdlXCI6XG4gICAgICAgIHJldHVybiBgPEltYWdlVXBsb2FkZXJcbiAgICAgICAgICAgICAgICAgICAgJHtyZWdFeHByfVxuICAgICAgICAgICAgICAgICAgICB1cGxvYWRlcj17YXN5bmMgKGZpbGU6IEZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGZpbGU6IHVwbG9hZGVkRmlsZSB9ID0gYXdhaXQgRmlsZVNlcnZpY2UudXBsb2FkKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1cGxvYWRlZEZpbGUudXJsO1xuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICBwcmV2aWV3U2l6ZT1cIm1kXCJcbiAgICAgICAgICAgICAgICAgIC8+YDtcbiAgICAgIGNhc2UgXCJhcnJheS1pbWFnZXNcIjpcbiAgICAgICAgcmV0dXJuIGB7LyogVE9ETzogSW1wbGVtZW50IG11bHRpcGxlIGltYWdlIHVwbG9hZGVyICovfVxuICAgICAgICAgICAgICAgICAgPElucHV0IHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwiZW51bXNcIjpcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsZXQgZW51bUlkOiBzdHJpbmc7XG4gICAgICAgICAgaWYgKGNvbC5uYW1lID09PSBcIm9yZGVyQnlcIikge1xuICAgICAgICAgICAgZW51bUlkID0gYCR7bmFtZXMuY2FwaXRhbH0ke2luZmxlY3Rpb24uY2FtZWxpemUoY29sLm5hbWUpfVNlbGVjdGA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaWQgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgICAgICAgIGVudW1JZCA9IGAke2lkfVNlbGVjdGA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgPCR7ZW51bUlkfSAke3JlZ0V4cHJ9ICR7Y29sLm9wdGlvbmFsIHx8IGNvbC5udWxsYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwifSAvPmA7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC1kZXN0cnVjdGl2ZVwiPuywvuydhCDsiJgg7JeG64qUIEVudW0gJHtjb2wubmFtZX08L3NwYW4+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcIm51bWJlci1ma19pZFwiOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlbFByb3AgPSBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUucmVwbGFjZShcIl9pZFwiLCBcIlwiKSk7XG4gICAgICAgICAgY29uc3QgZmtJZCA9IGAke3JlbFByb3Aud2l0aH1JZEFzeW5jU2VsZWN0YDtcbiAgICAgICAgICByZXR1cm4gYDwke2ZrSWR9IHsuLi5yZWdpc3RlcignJHtjb2wubmFtZX0nKX0gJHtcbiAgICAgICAgICAgIGNvbC5vcHRpb25hbCB8fCBjb2wubnVsbGFibGUgPyBcImNsZWFyYWJsZVwiIDogXCJcIlxuICAgICAgICAgIH0gc3Vic2V0PVwiQVwiIC8+YDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGA8SW5wdXQgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgXCJhcnJheVwiOlxuICAgICAgICByZXR1cm4gYDxzcGFuIGNsYXNzTmFtZT1cInRleHQtbXV0ZWQtZm9yZWdyb3VuZFwiPiR7Y29sLm5hbWV9IGFycmF5PC9zcGFuPmA7XG4gICAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICAgIHJldHVybiBgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC1tdXRlZC1mb3JlZ3JvdW5kXCI+JHtjb2wubmFtZX0gb2JqZWN0PC9zcGFuPmA7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOuMgOydkSDrtojqsIDriqXtlZwg66CM642UIO2DgOyehSAke2NvbC5yZW5kZXJUeXBlfSBvbiAke2NvbC5uYW1lfWApO1xuICAgIH1cbiAgfVxuXG4gIC8vIE5ldyBzdHlsZSByZW5kZXJpbmcgZm9yIGZlZWQtc2l0ZXMgc3R5bGUgZm9ybVxuICByZW5kZXJDb2x1bW4oZW50aXR5SWQ6IHN0cmluZywgY29sOiBSZW5kZXJpbmdOb2RlLCBuYW1lczogRW50aXR5TmFtZXNSZWNvcmQpOiBzdHJpbmcge1xuICAgIGNvbnN0IHJlZ0V4cHIgPSBgey4uLnJlZ2lzdGVyKFwiJHtjb2wubmFtZX1cIil9YDtcblxuICAgIHN3aXRjaCAoY29sLnJlbmRlclR5cGUpIHtcbiAgICAgIGNhc2UgXCJzdHJpbmctcGxhaW5cIjpcbiAgICAgICAgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2RTdHJpbmcgJiYgKGNvbC56b2RUeXBlLm1heExlbmd0aCA/PyAwKSA8PSAyNTYpIHtcbiAgICAgICAgICByZXR1cm4gYDxJbnB1dCBjbGFzc05hbWU9XCJoLTggdGV4dC14cyBiZy13aGl0ZVwiIHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGA8VGV4dGFyZWEgY2xhc3NOYW1lPVwidGV4dC14cyBiZy13aGl0ZVwiIHJvd3M9ezR9IHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgXCJzdHJpbmctZGF0ZXRpbWVcIjpcbiAgICAgICAgcmV0dXJuIGA8RGF0ZUlucHV0XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cImgtOCB0ZXh0LXhzIGJnLXdoaXRlXCJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e2Zvcm0uJHtjb2wubmFtZX0gPyBuZXcgRGF0ZShmb3JtLiR7Y29sLm5hbWV9KSA6IG51bGx9XG4gICAgICAgICAgICAgICAgICAgIG9uVmFsdWVDaGFuZ2U9eyh2YWx1ZSkgPT4gc2V0Rm9ybSh7IC4uLmZvcm0sICR7Y29sLm5hbWV9OiB2YWx1ZSB9KX1cbiAgICAgICAgICAgICAgICAgIC8+YDtcbiAgICAgIGNhc2UgXCJzdHJpbmctZGF0ZVwiOlxuICAgICAgICByZXR1cm4gYDxEYXRlSW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbW9kZT1cImRhdGVcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJoLTggdGV4dC14cyBiZy13aGl0ZVwiXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlPXtmb3JtLiR7Y29sLm5hbWV9ID8gbmV3IERhdGUoZm9ybS4ke2NvbC5uYW1lfSkgOiBudWxsfVxuICAgICAgICAgICAgICAgICAgICBvblZhbHVlQ2hhbmdlPXsodmFsdWUpID0+IHNldEZvcm0oeyAuLi5mb3JtLCAke2NvbC5uYW1lfTogdmFsdWUgfSl9XG4gICAgICAgICAgICAgICAgICAvPmA7XG4gICAgICBjYXNlIFwiZGF0ZXRpbWVcIjpcbiAgICAgICAgcmV0dXJuIGA8RGF0ZUlucHV0XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cImgtOCB0ZXh0LXhzIGJnLXdoaXRlXCJcbiAgICAgICAgICAgICAgICAgICAgJHtyZWdFeHByfVxuICAgICAgICAgICAgICAgICAgLz5gO1xuICAgICAgY2FzZSBcIm51bWJlci1pZFwiOlxuICAgICAgICByZXR1cm4gYDxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwibnVtYmVyLXBsYWluXCI6XG4gICAgICAgIHJldHVybiBgPElucHV0IHR5cGU9XCJudW1iZXJcIiBjbGFzc05hbWU9XCJoLTggdGV4dC14cyBiZy13aGl0ZVwiIHBsYWNlaG9sZGVyPVwiJHtjb2wubGFiZWx9XCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgICByZXR1cm4gYDxTd2l0Y2ggJHtyZWdFeHByfSAvPmA7XG4gICAgICBjYXNlIFwic3RyaW5nLWltYWdlXCI6XG4gICAgICAgIHJldHVybiBgPEltYWdlVXBsb2FkZXJcbiAgICAgICAgICAgICAgICAgICAgICAke3JlZ0V4cHJ9XG4gICAgICAgICAgICAgICAgICAgICAgdXBsb2FkZXI9e2FzeW5jIChmaWxlOiBGaWxlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGZpbGU6IHVwbG9hZGVkRmlsZSB9ID0gYXdhaXQgRmlsZVNlcnZpY2UudXBsb2FkKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVwbG9hZGVkRmlsZS51cmw7XG4gICAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgICBwcmV2aWV3U2l6ZT1cIm1kXCJcbiAgICAgICAgICAgICAgICAgICAgLz5gO1xuICAgICAgY2FzZSBcImFycmF5LWltYWdlc1wiOlxuICAgICAgICByZXR1cm4gYDxNdWx0aUltYWdlVXBsb2FkZXJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e0FycmF5LmlzQXJyYXkoZm9ybS4ke2NvbC5uYW1lfSkgPyBmb3JtLiR7Y29sLm5hbWV9IDogW119XG4gICAgICAgICAgICAgICAgICAgIG9uVmFsdWVDaGFuZ2U9eyh1cmxzKSA9PiBzZXRGb3JtKHsgLi4uZm9ybSwgJHtjb2wubmFtZX06IHVybHMgfSl9XG4gICAgICAgICAgICAgICAgICAgIHVwbG9hZGVyPXthc3luYyAoZmlsZTogRmlsZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgZmlsZTogdXBsb2FkZWRGaWxlIH0gPSBhd2FpdCBGaWxlU2VydmljZS51cGxvYWQoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVwbG9hZGVkRmlsZS51cmw7XG4gICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgIHByZXZpZXdTaXplPVwibWRcIlxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIiR7Y29sLmxhYmVsfVwiXG4gICAgICAgICAgICAgICAgICAvPmA7XG4gICAgICBjYXNlIFwiZW51bXNcIjpcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsZXQgZW51bUlkOiBzdHJpbmc7XG4gICAgICAgICAgaWYgKGNvbC5uYW1lID09PSBcIm9yZGVyQnlcIikge1xuICAgICAgICAgICAgZW51bUlkID0gYCR7bmFtZXMuY2FwaXRhbH0ke2luZmxlY3Rpb24uY2FtZWxpemUoY29sLm5hbWUpfVNlbGVjdGA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaWQgfSA9IGdldEVudW1JbmZvRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgICAgICAgIGVudW1JZCA9IGAke2lkfVNlbGVjdGA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgPCR7ZW51bUlkfSAke3JlZ0V4cHJ9ICR7Y29sLm9wdGlvbmFsIHx8IGNvbC5udWxsYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwifSAvPmA7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBgPElucHV0IGNsYXNzTmFtZT1cImgtOCB0ZXh0LXhzIGJnLXdoaXRlXCIgJHtyZWdFeHByfSAvPmA7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgXCJudW1iZXItZmtfaWRcIjpcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZWxQcm9wID0gZ2V0UmVsYXRpb25Qcm9wRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lLnJlcGxhY2UoXCJfaWRcIiwgXCJcIikpO1xuICAgICAgICAgIGNvbnN0IGZrSWQgPSBgJHtyZWxQcm9wLndpdGh9SWRBc3luY1NlbGVjdGA7XG4gICAgICAgICAgcmV0dXJuIGA8JHtma0lkfSBzdWJzZXQ9XCJBXCIgJHtyZWdFeHByfSAke1xuICAgICAgICAgICAgY29sLm9wdGlvbmFsIHx8IGNvbC5udWxsYWJsZSA/IFwiY2xlYXJhYmxlXCIgOiBcIlwiXG4gICAgICAgICAgfSBjbGFzc05hbWU9XCJoLTggdGV4dC14c1wiIC8+YDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGA8SW5wdXQgdHlwZT1cIm51bWJlclwiIGNsYXNzTmFtZT1cImgtOCB0ZXh0LXhzIGJnLXdoaXRlXCIgcGxhY2Vob2xkZXI9XCIke2NvbC5sYWJlbH1cIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICAgICAgfVxuICAgICAgY2FzZSBcImFycmF5XCI6XG4gICAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICAgIHJldHVybiBgPElucHV0IGNsYXNzTmFtZT1cImgtOCB0ZXh0LXhzIGJnLXdoaXRlXCIgcGxhY2Vob2xkZXI9XCIke2NvbC5uYW1lfVwiICR7cmVnRXhwcn0gLz5gO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGA8SW5wdXQgY2xhc3NOYW1lPVwiaC04IHRleHQteHMgYmctd2hpdGVcIiAke3JlZ0V4cHJ9IC8+YDtcbiAgICB9XG4gIH1cblxuICByZXNvbHZlRGVmYXVsdFZhbHVlKGNvbHVtbnM6IFJlbmRlcmluZ05vZGVbXSk6IG9iamVjdCB7XG4gICAgcmV0dXJuIGNvbHVtbnMucmVkdWNlKFxuICAgICAgKHJlc3VsdCwgY29sKSA9PiB7XG4gICAgICAgIGlmIChjb2wub3B0aW9uYWwpIHtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHZhbHVlOiB1bmtub3duO1xuICAgICAgICBpZiAoY29sLm51bGxhYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgdmFsdWUgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2ROdW1iZXIpIHtcbiAgICAgICAgICB2YWx1ZSA9IDA7XG4gICAgICAgIH0gZWxzZSBpZiAoY29sLnpvZFR5cGUgaW5zdGFuY2VvZiB6LlpvZEVudW0pIHtcbiAgICAgICAgICB2YWx1ZSA9IE9iamVjdC5rZXlzKGNvbC56b2RUeXBlLmVudW0pWzBdO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2RCb29sZWFuKSB7XG4gICAgICAgICAgdmFsdWUgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIGlmIChjb2wuem9kVHlwZSBpbnN0YW5jZW9mIHouWm9kU3RyaW5nKSB7XG4gICAgICAgICAgaWYgKGNvbC5yZW5kZXJUeXBlID09PSBcInN0cmluZy1kYXRldGltZVwiKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IFwibm93KClcIjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBcIlwiO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjb2wuem9kVHlwZSBpbnN0YW5jZW9mIHouWm9kQXJyYXkpIHtcbiAgICAgICAgICB2YWx1ZSA9IFtdO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC56b2RUeXBlIGluc3RhbmNlb2Ygei5ab2RPYmplY3QpIHtcbiAgICAgICAgICB2YWx1ZSA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzdWx0W2NvbC5uYW1lXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICAgIHt9IGFzIHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9LFxuICAgICk7XG4gIH1cblxuICBhc3luYyByZW5kZXIoeyBlbnRpdHlJZCB9OiBUZW1wbGF0ZU9wdGlvbnNbXCJ2aWV3X2Zvcm1cIl0pIHtcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG4gICAgY29uc3QgbmFtZXMgPSBFbnRpdHlNYW5hZ2VyLmdldE5hbWVzRnJvbUlkKGVudGl0eUlkKTtcblxuICAgIC8vIFNhdmVQYXJhbXMg7YOA7J6F7J2EIOuhnOuTnO2VmOyXrCBzYXZlUGFyYW1zTm9kZSDsg53shLFcbiAgICBjb25zdCB7IGxvYWRUeXBlcyB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vLi4vc3luY2VyL21vZHVsZS1sb2FkZXJcIik7XG4gICAgY29uc3QgbG9hZGVkVHlwZXMgPSBhd2FpdCBsb2FkVHlwZXMoKTtcbiAgICBjb25zdCBTYXZlUGFyYW1zWm9kVHlwZSA9IGxvYWRlZFR5cGVzW2Ake2VudGl0eUlkfVNhdmVQYXJhbXNgXTtcblxuICAgIGlmICghU2F2ZVBhcmFtc1pvZFR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU2F2ZVBhcmFtcyBmb3IgJHtlbnRpdHlJZH0gbm90IGZvdW5kLiBEaWQgeW91IHJ1biAnc29uYW11IHN5bmMnP2ApO1xuICAgIH1cblxuICAgIC8vIFpvZCDtg4DsnoXsnYQgUmVuZGVyaW5nTm9kZeuhnCDrs4DtmZhcbiAgICBjb25zdCB7IHpvZFR5cGVUb1JlbmRlcmluZ05vZGUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3pvZC1jb252ZXJ0ZXJcIik7XG4gICAgY29uc3Qgc2F2ZVBhcmFtc05vZGUgPSB6b2RUeXBlVG9SZW5kZXJpbmdOb2RlKFNhdmVQYXJhbXNab2RUeXBlKTtcblxuICAgIGNvbnN0IGNvbHVtbnMgPSAoKHNhdmVQYXJhbXNOb2RlPy5jaGlsZHJlbiA/PyBbXSkgYXMgUmVuZGVyaW5nTm9kZVtdKVxuICAgICAgLmZpbHRlcigoY29sKSA9PiBjb2wubmFtZSAhPT0gXCJpZFwiKVxuICAgICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICAgIGNvbnN0IHByb3BDYW5kaWRhdGUgPSBlbnRpdHkucHJvcHMuZmluZCgocHJvcCkgPT4gcHJvcC5uYW1lID09PSBjb2wubmFtZSk7XG4gICAgICAgIGNvbC5sYWJlbCA9IHByb3BDYW5kaWRhdGU/LmRlc2MgPz8gY29sLmxhYmVsO1xuICAgICAgICByZXR1cm4gY29sO1xuICAgICAgfSk7XG5cbiAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSB0aGlzLnJlc29sdmVEZWZhdWx0VmFsdWUoY29sdW1ucyk7XG5cbiAgICAvLyDtlITrpqwg7YWc7ZSM66a/XG4gICAgY29uc3QgcHJlVGVtcGxhdGVzOiBSZW5kZXJlZFRlbXBsYXRlW1wicHJlVGVtcGxhdGVzXCJdID0gKGNvbHVtbnMgYXMgUmVuZGVyaW5nTm9kZVtdKVxuICAgICAgLmZpbHRlcigoY29sKSA9PiB7XG4gICAgICAgIGlmIChjb2wubmFtZSA9PT0gXCJpZFwiKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbC5uYW1lLmVuZHNXaXRoKFwiX2lkXCIpIHx8IGNvbC5yZW5kZXJUeXBlID09PSBcIm51bWJlci1pZFwiKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGdldFJlbGF0aW9uUHJvcEZyb21Db2xOYW1lKGVudGl0eUlkLCBjb2wubmFtZS5yZXBsYWNlKFwiX2lkXCIsIFwiXCIpKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJlbnVtc1wiKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGdldEVudW1JbmZvRnJvbUNvbE5hbWUoZW50aXR5SWQsIGNvbC5uYW1lKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9KVxuICAgICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICAgIGxldCBrZXk6IFRlbXBsYXRlS2V5O1xuICAgICAgICBsZXQgdGFyZ2V0TWRJZCA9IGVudGl0eUlkO1xuICAgICAgICBsZXQgZW51bUlkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChjb2wucmVuZGVyVHlwZSA9PT0gXCJlbnVtc1wiKSB7XG4gICAgICAgICAga2V5ID0gXCJ2aWV3X2VudW1zX3NlbGVjdFwiO1xuICAgICAgICAgIGNvbnN0IHsgdGFyZ2V0RW50aXR5TmFtZXM6IHRhcmdldE1ETmFtZXMsIGlkIH0gPSBnZXRFbnVtSW5mb0Zyb21Db2xOYW1lKFxuICAgICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgICBjb2wubmFtZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIHRhcmdldE1kSWQgPSB0YXJnZXRNRE5hbWVzLmNhcGl0YWw7XG4gICAgICAgICAgZW51bUlkID0gaWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAga2V5ID0gXCJ2aWV3X2lkX2FzeW5jX3NlbGVjdFwiO1xuICAgICAgICAgIGNvbnN0IHJlbFByb3AgPSBnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUucmVwbGFjZShcIl9pZFwiLCBcIlwiKSk7XG4gICAgICAgICAgdGFyZ2V0TWRJZCA9IHJlbFByb3Aud2l0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAga2V5OiBrZXkgYXMgVGVtcGxhdGVLZXksXG4gICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgZW50aXR5SWQ6IHRhcmdldE1kSWQsXG4gICAgICAgICAgICBub2RlOiBjb2wsXG4gICAgICAgICAgICBlbnVtSWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKChwcmVUZW1wbGF0ZSkgPT4ge1xuICAgICAgICBpZiAocHJlVGVtcGxhdGUua2V5ID09PSBcInZpZXdfaWRfYXN5bmNfc2VsZWN0XCIpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgRW50aXR5TWFuYWdlci5nZXQocHJlVGVtcGxhdGUub3B0aW9ucy5lbnRpdHlJZCk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmdldFRhcmdldEFuZFBhdGgobmFtZXMpLFxuICAgICAgYm9keTogYFxuaW1wb3J0IHtcbiAgQnV0dG9uLFxuICBDYXJkLFxuICBDYXJkQ29udGVudCxcbiAgQ2FyZEhlYWRlcixcbiAgQ2FyZFRpdGxlLFxuICBJbnB1dCwke2NvbHVtbnMuc29tZSgoY29sKSA9PiBjb2wucmVuZGVyVHlwZSA9PT0gXCJzdHJpbmctcGxhaW5cIiAmJiBjb2wuem9kVHlwZSBpbnN0YW5jZW9mIHouWm9kU3RyaW5nICYmIChjb2wuem9kVHlwZS5tYXhMZW5ndGggPz8gMCkgPiAyNTYpID8gXCJcXG4gIFRleHRhcmVhLFwiIDogXCJcIn0ke2NvbHVtbnMuc29tZSgoY29sKSA9PiBjb2wucmVuZGVyVHlwZSA9PT0gXCJlbnVtc1wiKSA/IFwiXFxuICBTZWxlY3QsXFxuICBTZWxlY3RDb250ZW50LFxcbiAgU2VsZWN0SXRlbSxcXG4gIFNlbGVjdFRyaWdnZXIsXFxuICBTZWxlY3RWYWx1ZSxcIiA6IFwiXCJ9JHtjb2x1bW5zLnNvbWUoKGNvbCkgPT4gY29sLnJlbmRlclR5cGUgPT09IFwiYm9vbGVhblwiKSA/IFwiXFxuICBTd2l0Y2gsXCIgOiBcIlwifSR7Y29sdW1ucy5zb21lKChjb2wpID0+IGNvbC5yZW5kZXJUeXBlID09PSBcInN0cmluZy1pbWFnZVwiKSA/IFwiXFxuICBJbWFnZVVwbG9hZGVyLFwiIDogXCJcIn0ke2NvbHVtbnMuc29tZSgoY29sKSA9PiBjb2wucmVuZGVyVHlwZSA9PT0gXCJhcnJheS1pbWFnZXNcIikgPyBcIlxcbiAgTXVsdGlJbWFnZVVwbG9hZGVyLFwiIDogXCJcIn0ke2NvbHVtbnMuc29tZSgoY29sKSA9PiBbXCJzdHJpbmctZGF0ZXRpbWVcIiwgXCJzdHJpbmctZGF0ZVwiLCBcImRhdGV0aW1lXCJdLmluY2x1ZGVzKGNvbC5yZW5kZXJUeXBlKSkgPyBcIlxcbiAgRGF0ZUlucHV0LFwiIDogXCJcIn1cbn0gZnJvbSBcIkBzb25hbXUta2l0L3JlYWN0LWNvbXBvbmVudHMvY29tcG9uZW50c1wiO1xuaW1wb3J0IHsgdXNlVHlwZUZvcm0gfSBmcm9tIFwiQHNvbmFtdS1raXQvcmVhY3QtY29tcG9uZW50cy9saWJcIjtcbmltcG9ydCB7IHVzZVF1ZXJ5Q2xpZW50IH0gZnJvbSBcIkB0YW5zdGFjay9yZWFjdC1xdWVyeVwiO1xuaW1wb3J0IHsgY3JlYXRlRmlsZVJvdXRlLCB1c2VSb3V0ZXIgfSBmcm9tIFwiQHRhbnN0YWNrL3JlYWN0LXJvdXRlclwiO1xuaW1wb3J0IHsgdXNlRWZmZWN0IH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfVNlcnZpY2Uke1xuICAgICAgICBjb2x1bW5zLnNvbWUoKGNvbCkgPT4gW1wic3RyaW5nLWltYWdlXCIsIFwiYXJyYXktaW1hZ2VzXCJdLmluY2x1ZGVzKGNvbC5yZW5kZXJUeXBlKSlcbiAgICAgICAgICA/IFwiLCBGaWxlU2VydmljZVwiXG4gICAgICAgICAgOiBcIlwiXG4gICAgICB9IH0gZnJvbSBcIkAvc2VydmljZXMvc2VydmljZXMuZ2VuZXJhdGVkXCI7XG5pbXBvcnQgdHlwZSB7ICR7bmFtZXMuY2FwaXRhbH1TdWJzZXRBIH0gZnJvbSBcIkAvc2VydmljZXMvc29uYW11LmdlbmVyYXRlZFwiOyR7XG4gICAgICAgIGNvbHVtbnMuZmlsdGVyKChjb2wpID0+IGNvbC5yZW5kZXJUeXBlID09PSBcImVudW1zXCIpLmxlbmd0aCA+IDBcbiAgICAgICAgICA/IFwiXFxuaW1wb3J0IHsgXCIgK1xuICAgICAgICAgICAgdW5pcXVlKFxuICAgICAgICAgICAgICBjb2x1bW5zXG4gICAgICAgICAgICAgICAgLmZpbHRlcigoY29sKSA9PiBjb2wucmVuZGVyVHlwZSA9PT0gXCJlbnVtc1wiKVxuICAgICAgICAgICAgICAgIC5tYXAoKGNvbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBpZCB9ID0gZ2V0RW51bUluZm9Gcm9tQ29sTmFtZShlbnRpdHlJZCwgY29sLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7aWR9LCAke2lkfUxhYmVsYDtcbiAgICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgICAgICAgICAuam9pbihcIiwgXCIpICtcbiAgICAgICAgICAgICcgfSBmcm9tIFwiQC9zZXJ2aWNlcy9zb25hbXUuZ2VuZXJhdGVkXCI7J1xuICAgICAgICAgIDogXCJcIlxuICAgICAgfVxuaW1wb3J0IHsgZGVmYXVsdENhdGNoIH0gZnJvbSBcIkAvc2VydmljZXMvc29uYW11LnNoYXJlZFwiO1xuaW1wb3J0IHsgJHtuYW1lcy5jYXBpdGFsfVNhdmVQYXJhbXMgfSBmcm9tIFwiQC9zZXJ2aWNlcy8ke25hbWVzLmZzfS8ke25hbWVzLmZzfS50eXBlc1wiO1xuJHt1bmlxdWUoXG4gIGNvbHVtbnNcbiAgICAuZmlsdGVyKChjb2wpID0+IFtcIm51bWJlci1ma19pZFwiLCBcImVudW1zXCJdLmluY2x1ZGVzKGNvbC5yZW5kZXJUeXBlKSlcbiAgICAubWFwKChjb2wpID0+IHtcbiAgICAgIHJldHVybiB0aGlzLnJlbmRlckNvbHVtbkltcG9ydChlbnRpdHlJZCwgY29sKTtcbiAgICB9KSxcbikuam9pbihcIlxcblwiKX1cblxuaW1wb3J0IEFycm93TGVmdEljb24gZnJvbSBcIn5pY29ucy9sdWNpZGUvYXJyb3ctbGVmdFwiO1xuaW1wb3J0IFNhdmVJY29uIGZyb20gXCJ+aWNvbnMvbHVjaWRlL3NhdmVcIjtcbmltcG9ydCBGb3JtSWNvbiBmcm9tIFwifmljb25zL21kaS9mb3JtLXNlbGVjdFwiO1xuXG5jb25zdCBmb3JtU2VhcmNoU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBSb3V0ZSA9IGNyZWF0ZUZpbGVSb3V0ZShcIi9hZG1pbi8ke25hbWVzLmZzUGx1cmFsfS9mb3JtXCIpKHtcbiAgdmFsaWRhdGVTZWFyY2g6IGZvcm1TZWFyY2hTY2hlbWEsXG4gIGNvbXBvbmVudDogJHtuYW1lcy5jYXBpdGFsUGx1cmFsfUZvcm1QYWdlLFxufSk7XG5cbmZ1bmN0aW9uICR7bmFtZXMuY2FwaXRhbFBsdXJhbH1Gb3JtUGFnZSgpIHtcbiAgY29uc3QgeyBpZCB9ID0gUm91dGUudXNlU2VhcmNoKCk7XG4gIHJldHVybiA8JHtuYW1lcy5jYXBpdGFsUGx1cmFsfUZvcm0gaWQ9e2lkfSAvPjtcbn1cblxudHlwZSAke25hbWVzLmNhcGl0YWxQbHVyYWx9Rm9ybVByb3BzID0ge1xuICBpZD86IG51bWJlcjtcbiAgbW9kZT86IFwicGFnZVwiIHwgXCJtb2RhbFwiO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uICR7bmFtZXMuY2FwaXRhbFBsdXJhbH1Gb3JtKHsgaWQsIG1vZGUgfTogJHtuYW1lcy5jYXBpdGFsUGx1cmFsfUZvcm1Qcm9wcykge1xuICBjb25zdCByb3V0ZXIgPSB1c2VSb3V0ZXIoKTtcbiAgY29uc3QgcXVlcnlDbGllbnQgPSB1c2VRdWVyeUNsaWVudCgpO1xuXG4gIGNvbnN0IHsgZm9ybSwgc2V0Rm9ybSwgcmVnaXN0ZXIgfSA9IHVzZVR5cGVGb3JtKCR7bmFtZXMuY2FwaXRhbH1TYXZlUGFyYW1zLCAke0pTT04uc3RyaW5naWZ5KGRlZmF1bHRWYWx1ZSkucmVwbGFjZSgvXCJub3dcXChcXClcIi9nLCAnXCJcIicpfSk7XG4keygoKSA9PiB7XG4gIGNvbnN0IGhhc0RhdGV0aW1lID0gY29sdW1ucy5zb21lKChjb2wpID0+IGNvbC5yZW5kZXJUeXBlID09PSBcInN0cmluZy1kYXRldGltZVwiKTtcbiAgY29uc3QgaGFzRGF0ZSA9IGNvbHVtbnMuc29tZSgoY29sKSA9PiBjb2wucmVuZGVyVHlwZSA9PT0gXCJzdHJpbmctZGF0ZVwiKTtcbiAgaWYgKCFoYXNEYXRldGltZSAmJiAhaGFzRGF0ZSkgcmV0dXJuIFwiXCI7XG5cbiAgbGV0IGhlbHBlcnMgPSBcIlxcblwiO1xuICBpZiAoaGFzRGF0ZXRpbWUpIHtcbiAgICBoZWxwZXJzICs9IGAgIC8vIGRhdGV0aW1lLWxvY2FsIO2YleyLneycvOuhnCDrs4DtmZggKFlZWVktTU0tRERUSEg6TU0pXG4gIGNvbnN0IHRvRGF0ZXRpbWVMb2NhbFN0cmluZyA9IChkYXRlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyA9PiB7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gXCJcIjtcbiAgICBjb25zdCBkID0gdHlwZW9mIGRhdGUgPT09IFwic3RyaW5nXCIgPyBuZXcgRGF0ZShkYXRlKSA6IGRhdGU7XG4gICAgcmV0dXJuIGQudG9JU09TdHJpbmcoKS5zbGljZSgwLCAxNik7XG4gIH07XG5cbiAgLy8gZGF0ZXRpbWUtbG9jYWwg66y47J6Q7Je07J2EIERhdGXroZwg67OA7ZmYXG4gIGNvbnN0IGZyb21EYXRldGltZUxvY2FsU3RyaW5nID0gKHZhbHVlOiBzdHJpbmcpOiBEYXRlIHwgbnVsbCA9PiB7XG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbiAgfTtcbmA7XG4gIH1cbiAgaWYgKGhhc0RhdGUpIHtcbiAgICBoZWxwZXJzICs9IGAgIC8vIGRhdGUg7ZiV7Iud7Jy866GcIOuzgO2ZmCAoWVlZWS1NTS1ERClcbiAgY29uc3QgdG9EYXRlU3RyaW5nID0gKGRhdGU6IERhdGUgfCBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nID0+IHtcbiAgICBpZiAoIWRhdGUpIHJldHVybiBcIlwiO1xuICAgIGNvbnN0IGQgPSB0eXBlb2YgZGF0ZSA9PT0gXCJzdHJpbmdcIiA/IG5ldyBEYXRlKGRhdGUpIDogZGF0ZTtcbiAgICByZXR1cm4gZC50b0lTT1N0cmluZygpLnNwbGl0KFwiVFwiKVswXTtcbiAgfTtcblxuICAvLyBkYXRlIOusuOyekOyXtOydhCBEYXRl66GcIOuzgO2ZmFxuICBjb25zdCBmcm9tRGF0ZVN0cmluZyA9ICh2YWx1ZTogc3RyaW5nKTogRGF0ZSB8IG51bGwgPT4ge1xuICAgIGlmICghdmFsdWUpIHJldHVybiBudWxsO1xuICAgIHJldHVybiBuZXcgRGF0ZSh2YWx1ZSk7XG4gIH07XG5gO1xuICB9XG4gIHJldHVybiBoZWxwZXJzO1xufSkoKX1cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaWQpIHtcbiAgICAgICR7bmFtZXMuY2FwaXRhbH1TZXJ2aWNlLmdldCR7bmFtZXMuY2FwaXRhbH0oXCJBXCIsIGlkKS50aGVuKChyb3cpID0+IHtcbiAgICAgICAgc2V0Rm9ybSgocHJldkZvcm0pID0+ICh7XG4gICAgICAgICAgLi4ucHJldkZvcm0sXG4gICAgICAgICAgLi4ucm93LFxuICAgICAgICB9KSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIFtpZCwgc2V0Rm9ybV0pO1xuXG4gIGNvbnN0IHNhdmVNdXRhdGlvbiA9ICR7bmFtZXMuY2FwaXRhbH1TZXJ2aWNlLnVzZVNhdmVNdXRhdGlvbigpO1xuICBjb25zdCBoYW5kbGVTdWJtaXQgPSAoKSA9PiB7XG4gICAgc2F2ZU11dGF0aW9uLm11dGF0ZShcbiAgICAgIHsgc3BhOiBbZm9ybV0gfSxcbiAgICAgIHtcbiAgICAgICAgb25TdWNjZXNzOiAoKSA9PiB7XG4gICAgICAgICAgcXVlcnlDbGllbnQuaW52YWxpZGF0ZVF1ZXJpZXMoe1xuICAgICAgICAgICAgcXVlcnlLZXk6IFtcIiR7bmFtZXMuY2FwaXRhbH1cIl0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAobW9kZSA9PT0gXCJtb2RhbFwiKSB7XG4gICAgICAgICAgICAvLyBtb2RhbCBtb2RlXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvdXRlci5uYXZpZ2F0ZSh7IHRvOiBcIi9hZG1pbi8ke25hbWVzLmZzUGx1cmFsfVwiIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgb25FcnJvcjogZGVmYXVsdENhdGNoLFxuICAgICAgfSxcbiAgICApO1xuICB9O1xuXG4gIGNvbnN0IFBBR0UgPSB7XG4gICAgdGl0bGU6IFxcYCR7ZW50aXR5LnRpdGxlID8/IG5hbWVzLmNhcGl0YWx9XFwke2lkID8gXFxgICNcXCR7aWR9IEVkaXRcXGAgOiBcIiBDcmVhdGVcIn1cXGAsXG4gIH07XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXgtMSBvdmVyZmxvdy1hdXRvXCI+XG4gICAgICA8ZGl2IGNsYXNzTmFtZT1cIm1heC13LVsxODAwcHhdIG14LWF1dG8gcC04XCI+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwic3BhY2UteS02IG1iLThcIj5cbiAgICAgICAgICB7LyogSGVhZGVyICovfVxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgICAgICAgIDxGb3JtSWNvbiBjbGFzc05hbWU9XCJoLTUgdy01XCIgLz5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC1sZyBmb250LXNlbWlib2xkIGgtNVwiPntQQUdFLnRpdGxlfTwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAge21vZGUgIT09IFwibW9kYWxcIiAmJiAoXG4gICAgICAgICAgICAgIDxCdXR0b25cbiAgICAgICAgICAgICAgICB2YXJpYW50PVwib3V0bGluZVwiXG4gICAgICAgICAgICAgICAgb25DbGljaz17KCkgPT4gcm91dGVyLm5hdmlnYXRlKHsgdG86IFwiL2FkbWluLyR7bmFtZXMuZnNQbHVyYWx9XCIgfSl9XG4gICAgICAgICAgICAgICAgaWNvbj17PEFycm93TGVmdEljb24gLz59XG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBCYWNrIFRvIExpc3RcbiAgICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgICApfVxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgey8qIEZvcm0gQ2FyZCAqL31cbiAgICAgICAgICA8Q2FyZCBjbGFzc05hbWU9XCJib3JkZXItYm9yZGVyLzQwIGJnLWdyYXktNTAgc2hhZG93LXNtXCI+XG4gICAgICAgICAgICA8Q2FyZEhlYWRlciBjbGFzc05hbWU9XCJweC00IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMCBmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICA8Q2FyZFRpdGxlIGNsYXNzTmFtZT1cInRleHQtc20gZm9udC1tZWRpdW0gbGVhZGluZy1ub25lIG0tMFwiPlxuICAgICAgICAgICAgICAgIHtQQUdFLnRpdGxlfVxuICAgICAgICAgICAgICA8L0NhcmRUaXRsZT5cbiAgICAgICAgICAgIDwvQ2FyZEhlYWRlcj5cbiAgICAgICAgICAgIDxDYXJkQ29udGVudCBjbGFzc05hbWU9XCJwLTZcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJzcGFjZS15LTZcIj5cbiR7Y29sdW1uc1xuICAuZmlsdGVyKChjb2wpID0+IGNvbC5uYW1lICE9PSBcImNyZWF0ZWRfYXRcIilcbiAgLm1hcCgoY29sKSA9PiB7XG4gICAgY29uc3QgbGFiZWwgPSAoKCkgPT4ge1xuICAgICAgaWYgKGNvbC5sYWJlbC5lbmRzV2l0aChcIklkXCIpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoY29sLmxhYmVsLnJlcGxhY2UoXCJJZFwiLCBcIlwiKSk7XG4gICAgICAgICAgcmV0dXJuIGVudGl0eS50aXRsZSA/PyBjb2wubGFiZWw7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBjb2wubGFiZWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBjb2wubGFiZWw7XG4gICAgfSkoKTtcbiAgICByZXR1cm4gYCAgICAgICAgICAgICAgICB7LyogJHtsYWJlbH0gKi99XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJzcGFjZS15LTJcIj5cbiAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzc05hbWU9XCJibG9jayB0ZXh0LXhzIG1iLTEgdGV4dC1ncmF5LTYwMFwiPiR7bGFiZWx9PC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICR7dGhpcy5yZW5kZXJDb2x1bW4oZW50aXR5SWQsIGNvbCwgbmFtZXMpfVxuICAgICAgICAgICAgICAgIDwvZGl2PmA7XG4gIH0pXG4gIC5qb2luKFwiXFxuXFxuXCIpfVxuXG4gICAgICAgICAgICAgICAgey8qIFNhdmUgQnV0dG9uICovfVxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuIHB0LTRcIj5cbiAgICAgICAgICAgICAgICAgIHtmb3JtLmlkICYmIGZvcm0uY3JlYXRlZF9hdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3NOYW1lPVwibXItMiB0ZXh0LXhzIHRleHQtZ3JheS02MDBcIj5DcmVhdGVkIEF0OjwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC14cyB0ZXh0LWdyYXktNjAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7U3RyaW5nKGZvcm0uY3JlYXRlZF9hdCl9XG4gICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgICA8QnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e2hhbmRsZVN1Ym1pdH1cbiAgICAgICAgICAgICAgICAgICAgaWNvbj17PFNhdmVJY29uIC8+fVxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICBTYXZlXG4gICAgICAgICAgICAgICAgICA8L0J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L0NhcmRDb250ZW50PlxuICAgICAgICAgIDwvQ2FyZD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiAgICAgIGAudHJpbSgpLFxuICAgICAgaW1wb3J0S2V5czogW10sXG4gICAgICBwcmVUZW1wbGF0ZXMsXG4gICAgfTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbImluZmxlY3Rpb24iLCJ1bmlxdWUiLCJ6IiwiRW50aXR5TWFuYWdlciIsImdldEVudW1JbmZvRnJvbUNvbE5hbWUiLCJnZXRSZWxhdGlvblByb3BGcm9tQ29sTmFtZSIsIlRlbXBsYXRlIiwiVGVtcGxhdGVfX3ZpZXdfZm9ybSIsImdldFRhcmdldEFuZFBhdGgiLCJuYW1lcyIsInRhcmdldCIsInBhdGgiLCJmc1BsdXJhbCIsIndyYXBGQyIsImJvZHkiLCJsYWJlbCIsImpvaW4iLCJ3cmFwRkciLCJyZW5kZXJDb2x1bW5JbXBvcnQiLCJlbnRpdHlJZCIsImNvbCIsInJlbmRlclR5cGUiLCJpZCIsInRhcmdldEVudGl0eU5hbWVzIiwibmFtZSIsImNvbXBvbmVudElkIiwiZnMiLCJyZWxQcm9wIiwicmVwbGFjZSIsInRhcmdldE5hbWVzIiwiZ2V0TmFtZXNGcm9tSWQiLCJ3aXRoIiwiRXJyb3IiLCJyZW5kZXJDb2x1bW5PbGQiLCJwYXJlbnQiLCJyZWdFeHByIiwiem9kVHlwZSIsIlpvZFN0cmluZyIsIm1heExlbmd0aCIsImVudW1JZCIsImNhcGl0YWwiLCJjYW1lbGl6ZSIsIm9wdGlvbmFsIiwibnVsbGFibGUiLCJma0lkIiwicmVuZGVyQ29sdW1uIiwicmVzb2x2ZURlZmF1bHRWYWx1ZSIsImNvbHVtbnMiLCJyZWR1Y2UiLCJyZXN1bHQiLCJ2YWx1ZSIsIlpvZE51bWJlciIsIlpvZEVudW0iLCJPYmplY3QiLCJrZXlzIiwiZW51bSIsIlpvZEJvb2xlYW4iLCJab2RBcnJheSIsIlpvZE9iamVjdCIsInJlbmRlciIsImVudGl0eSIsImdldCIsImxvYWRUeXBlcyIsImxvYWRlZFR5cGVzIiwiU2F2ZVBhcmFtc1pvZFR5cGUiLCJ6b2RUeXBlVG9SZW5kZXJpbmdOb2RlIiwic2F2ZVBhcmFtc05vZGUiLCJjaGlsZHJlbiIsImZpbHRlciIsIm1hcCIsInByb3BDYW5kaWRhdGUiLCJwcm9wcyIsImZpbmQiLCJwcm9wIiwiZGVzYyIsImRlZmF1bHRWYWx1ZSIsInByZVRlbXBsYXRlcyIsImVuZHNXaXRoIiwia2V5IiwidGFyZ2V0TWRJZCIsInRhcmdldE1ETmFtZXMiLCJvcHRpb25zIiwibm9kZSIsInByZVRlbXBsYXRlIiwic29tZSIsImluY2x1ZGVzIiwibGVuZ3RoIiwiQm9vbGVhbiIsImNhcGl0YWxQbHVyYWwiLCJKU09OIiwic3RyaW5naWZ5IiwiaGFzRGF0ZXRpbWUiLCJo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