sonamu 0.8.26 → 0.9.0

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 (684) hide show
  1. package/bin/cli.js +60 -13
  2. package/dist/_virtual/rolldown_runtime.js +39 -0
  3. package/dist/ai/agents/agent.d.ts +3 -3
  4. package/dist/ai/agents/agent.d.ts.map +1 -1
  5. package/dist/ai/agents/agent.js +76 -73
  6. package/dist/ai/agents/index.js +3 -3
  7. package/dist/ai/agents/types.d.ts +3 -3
  8. package/dist/ai/agents/types.d.ts.map +1 -1
  9. package/dist/ai/agents/types.js +1 -3
  10. package/dist/ai/index.js +3 -2
  11. package/dist/ai/providers/rtzr/api.js +25 -25
  12. package/dist/ai/providers/rtzr/error.js +25 -26
  13. package/dist/ai/providers/rtzr/index.js +5 -5
  14. package/dist/ai/providers/rtzr/model.d.ts +1 -1
  15. package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
  16. package/dist/ai/providers/rtzr/model.js +117 -133
  17. package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
  18. package/dist/ai/providers/rtzr/options.js +35 -41
  19. package/dist/ai/providers/rtzr/provider.d.ts +1 -1
  20. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
  21. package/dist/ai/providers/rtzr/provider.js +53 -51
  22. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
  23. package/dist/ai/providers/rtzr/utils.js +84 -84
  24. package/dist/api/base-frame.d.ts +2 -2
  25. package/dist/api/base-frame.d.ts.map +1 -1
  26. package/dist/api/base-frame.js +29 -19
  27. package/dist/api/caster.d.ts +1 -1
  28. package/dist/api/caster.d.ts.map +1 -1
  29. package/dist/api/caster.js +51 -61
  30. package/dist/api/code-converters.d.ts +4 -3
  31. package/dist/api/code-converters.d.ts.map +1 -1
  32. package/dist/api/code-converters.js +226 -249
  33. package/dist/api/config.d.ts +17 -17
  34. package/dist/api/config.d.ts.map +1 -1
  35. package/dist/api/config.js +37 -30
  36. package/dist/api/context.d.ts +10 -10
  37. package/dist/api/context.d.ts.map +1 -1
  38. package/dist/api/context.js +8 -2
  39. package/dist/api/decorators.d.ts +8 -8
  40. package/dist/api/decorators.d.ts.map +1 -1
  41. package/dist/api/decorators.js +245 -268
  42. package/dist/api/index.js +39 -7
  43. package/dist/api/secret.js +22 -15
  44. package/dist/api/sonamu.d.ts +15 -15
  45. package/dist/api/sonamu.d.ts.map +1 -1
  46. package/dist/api/sonamu.js +1012 -1131
  47. package/dist/api/validator.js +88 -79
  48. package/dist/auth/auth-generator.d.ts.map +1 -1
  49. package/dist/auth/auth-generator.js +203 -200
  50. package/dist/auth/better-auth-entities.d.ts +2 -2
  51. package/dist/auth/better-auth-entities.d.ts.map +1 -1
  52. package/dist/auth/better-auth-entities.js +369 -429
  53. package/dist/auth/index.js +21 -6
  54. package/dist/auth/knex-adapter.d.ts +2 -2
  55. package/dist/auth/knex-adapter.d.ts.map +1 -1
  56. package/dist/auth/knex-adapter.js +153 -157
  57. package/dist/auth/plugins/entity-definitions/admin.d.ts +1 -1
  58. package/dist/auth/plugins/entity-definitions/admin.d.ts.map +1 -1
  59. package/dist/auth/plugins/entity-definitions/admin.js +58 -56
  60. package/dist/auth/plugins/entity-definitions/anonymous.d.ts +1 -1
  61. package/dist/auth/plugins/entity-definitions/anonymous.d.ts.map +1 -1
  62. package/dist/auth/plugins/entity-definitions/anonymous.js +20 -20
  63. package/dist/auth/plugins/entity-definitions/api-key.d.ts +1 -1
  64. package/dist/auth/plugins/entity-definitions/api-key.d.ts.map +1 -1
  65. package/dist/auth/plugins/entity-definitions/api-key.js +185 -196
  66. package/dist/auth/plugins/entity-definitions/index.d.ts +1 -1
  67. package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
  68. package/dist/auth/plugins/entity-definitions/index.js +26 -29
  69. package/dist/auth/plugins/entity-definitions/jwt.d.ts +1 -1
  70. package/dist/auth/plugins/entity-definitions/jwt.d.ts.map +1 -1
  71. package/dist/auth/plugins/entity-definitions/jwt.js +62 -64
  72. package/dist/auth/plugins/entity-definitions/organization.d.ts +1 -1
  73. package/dist/auth/plugins/entity-definitions/organization.d.ts.map +1 -1
  74. package/dist/auth/plugins/entity-definitions/organization.js +362 -421
  75. package/dist/auth/plugins/entity-definitions/passkey.d.ts +1 -1
  76. package/dist/auth/plugins/entity-definitions/passkey.d.ts.map +1 -1
  77. package/dist/auth/plugins/entity-definitions/passkey.js +115 -126
  78. package/dist/auth/plugins/entity-definitions/phone-number.d.ts +1 -1
  79. package/dist/auth/plugins/entity-definitions/phone-number.d.ts.map +1 -1
  80. package/dist/auth/plugins/entity-definitions/phone-number.js +31 -40
  81. package/dist/auth/plugins/entity-definitions/sso.d.ts +1 -1
  82. package/dist/auth/plugins/entity-definitions/sso.d.ts.map +1 -1
  83. package/dist/auth/plugins/entity-definitions/sso.js +94 -107
  84. package/dist/auth/plugins/entity-definitions/two-factor.d.ts +1 -1
  85. package/dist/auth/plugins/entity-definitions/two-factor.d.ts.map +1 -1
  86. package/dist/auth/plugins/entity-definitions/two-factor.js +78 -92
  87. package/dist/auth/plugins/entity-definitions/types.d.ts +1 -1
  88. package/dist/auth/plugins/entity-definitions/types.d.ts.map +1 -1
  89. package/dist/auth/plugins/entity-definitions/types.js +1 -10
  90. package/dist/auth/plugins/entity-definitions/username.d.ts +1 -1
  91. package/dist/auth/plugins/entity-definitions/username.d.ts.map +1 -1
  92. package/dist/auth/plugins/entity-definitions/username.js +31 -40
  93. package/dist/auth/plugins/index.js +12 -3
  94. package/dist/auth/plugins/wrappers/admin.d.ts +2 -2
  95. package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
  96. package/dist/auth/plugins/wrappers/admin.js +28 -29
  97. package/dist/auth/plugins/wrappers/anonymous.d.ts +2 -1
  98. package/dist/auth/plugins/wrappers/anonymous.d.ts.map +1 -1
  99. package/dist/auth/plugins/wrappers/anonymous.js +23 -22
  100. package/dist/auth/plugins/wrappers/api-key.d.ts +2 -1
  101. package/dist/auth/plugins/wrappers/api-key.d.ts.map +1 -1
  102. package/dist/auth/plugins/wrappers/api-key.js +39 -34
  103. package/dist/auth/plugins/wrappers/index.js +11 -11
  104. package/dist/auth/plugins/wrappers/jwt.d.ts +2 -1
  105. package/dist/auth/plugins/wrappers/jwt.d.ts.map +1 -1
  106. package/dist/auth/plugins/wrappers/jwt.js +31 -26
  107. package/dist/auth/plugins/wrappers/organization.d.ts +2 -1
  108. package/dist/auth/plugins/wrappers/organization.d.ts.map +1 -1
  109. package/dist/auth/plugins/wrappers/organization.js +65 -62
  110. package/dist/auth/plugins/wrappers/passkey.d.ts +2 -1
  111. package/dist/auth/plugins/wrappers/passkey.d.ts.map +1 -1
  112. package/dist/auth/plugins/wrappers/passkey.js +33 -28
  113. package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
  114. package/dist/auth/plugins/wrappers/phone-number.js +26 -23
  115. package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -1
  116. package/dist/auth/plugins/wrappers/sso.js +37 -31
  117. package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
  118. package/dist/auth/plugins/wrappers/two-factor.js +31 -28
  119. package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
  120. package/dist/auth/plugins/wrappers/username.js +23 -23
  121. package/dist/bin/build-config.js +31 -31
  122. package/dist/bin/cli.js +1063 -1204
  123. package/dist/bin/fixture.d.ts.map +1 -1
  124. package/dist/bin/fixture.js +266 -259
  125. package/dist/bin/hmr-hook-register.d.ts.map +1 -1
  126. package/dist/bin/hmr-hook-register.js +19 -18
  127. package/dist/bin/test-command.d.ts.map +1 -1
  128. package/dist/bin/test-command.js +180 -177
  129. package/dist/bin/ts-loader-register.js +13 -6
  130. package/dist/bin/ts-loader-registration.d.ts.map +1 -1
  131. package/dist/bin/ts-loader-registration.js +28 -38
  132. package/dist/cache/cache-manager.d.ts +1 -1
  133. package/dist/cache/cache-manager.d.ts.map +1 -1
  134. package/dist/cache/cache-manager.js +20 -15
  135. package/dist/cache/decorator.d.ts +1 -1
  136. package/dist/cache/decorator.d.ts.map +1 -1
  137. package/dist/cache/decorator.js +84 -76
  138. package/dist/cache/drivers.js +21 -34
  139. package/dist/cache/index.js +10 -7
  140. package/dist/cache/types.d.ts +2 -2
  141. package/dist/cache/types.d.ts.map +1 -1
  142. package/dist/cache/types.js +1 -6
  143. package/dist/cache-control/cache-control.d.ts +2 -2
  144. package/dist/cache-control/cache-control.d.ts.map +1 -1
  145. package/dist/cache-control/cache-control.js +106 -122
  146. package/dist/cache-control/types.d.ts +2 -2
  147. package/dist/cache-control/types.d.ts.map +1 -1
  148. package/dist/cache-control/types.js +1 -19
  149. package/dist/compress/compress.d.ts +1 -1
  150. package/dist/compress/compress.d.ts.map +1 -1
  151. package/dist/compress/compress.js +58 -56
  152. package/dist/compress/index.js +7 -2
  153. package/dist/compress/types.js +1 -11
  154. package/dist/cone/cone-generator.d.ts +1 -1
  155. package/dist/cone/cone-generator.d.ts.map +1 -1
  156. package/dist/cone/cone-generator.js +216 -219
  157. package/dist/database/_batch_update.d.ts +1 -1
  158. package/dist/database/_batch_update.d.ts.map +1 -1
  159. package/dist/database/_batch_update.js +107 -102
  160. package/dist/database/base-model.d.ts +8 -9
  161. package/dist/database/base-model.d.ts.map +1 -1
  162. package/dist/database/base-model.js +371 -392
  163. package/dist/database/base-model.types.d.ts +5 -5
  164. package/dist/database/base-model.types.d.ts.map +1 -1
  165. package/dist/database/base-model.types.js +1 -20
  166. package/dist/database/db.d.ts +5 -2
  167. package/dist/database/db.d.ts.map +1 -1
  168. package/dist/database/db.js +185 -171
  169. package/dist/database/knex.d.ts +1 -1
  170. package/dist/database/knex.d.ts.map +1 -1
  171. package/dist/database/knex.js +48 -42
  172. package/dist/database/puri-subset.types.d.ts +6 -7
  173. package/dist/database/puri-subset.types.d.ts.map +1 -1
  174. package/dist/database/puri-subset.types.js +1 -16
  175. package/dist/database/puri-wrapper.d.ts +6 -6
  176. package/dist/database/puri-wrapper.d.ts.map +1 -1
  177. package/dist/database/puri-wrapper.js +99 -101
  178. package/dist/database/puri.d.ts +4 -5
  179. package/dist/database/puri.d.ts.map +1 -1
  180. package/dist/database/puri.js +1021 -1227
  181. package/dist/database/puri.types.d.ts +6 -6
  182. package/dist/database/puri.types.d.ts.map +1 -1
  183. package/dist/database/puri.types.js +15 -6
  184. package/dist/database/transaction-context.d.ts +2 -2
  185. package/dist/database/transaction-context.d.ts.map +1 -1
  186. package/dist/database/transaction-context.js +22 -13
  187. package/dist/database/upsert-builder.d.ts +3 -3
  188. package/dist/database/upsert-builder.d.ts.map +1 -1
  189. package/dist/database/upsert-builder.js +405 -465
  190. package/dist/dict/en.js +72 -74
  191. package/dist/dict/index.js +13 -13
  192. package/dist/dict/ko.js +72 -74
  193. package/dist/dict/rc-keys.js +150 -168
  194. package/dist/dict/sd.d.ts +3 -1
  195. package/dist/dict/sd.d.ts.map +1 -1
  196. package/dist/dict/sd.js +54 -40
  197. package/dist/dict/sonamu-dictionary.d.ts +1 -1
  198. package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
  199. package/dist/dict/sonamu-dictionary.js +887 -955
  200. package/dist/dict/types.js +1 -7
  201. package/dist/dict/utils.js +26 -24
  202. package/dist/entity/entity-manager.d.ts +9 -9
  203. package/dist/entity/entity-manager.d.ts.map +1 -1
  204. package/dist/entity/entity-manager.js +226 -223
  205. package/dist/entity/entity-template-cone.d.ts +1 -1
  206. package/dist/entity/entity-template-cone.d.ts.map +1 -1
  207. package/dist/entity/entity-template-cone.js +152 -151
  208. package/dist/entity/entity.d.ts.map +1 -1
  209. package/dist/entity/entity.js +952 -1089
  210. package/dist/exceptions/error-handler.d.ts +1 -1
  211. package/dist/exceptions/error-handler.d.ts.map +1 -1
  212. package/dist/exceptions/error-handler.js +32 -27
  213. package/dist/exceptions/so-exceptions.d.ts +1 -1
  214. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  215. package/dist/exceptions/so-exceptions.js +61 -68
  216. package/dist/filter/index.js +9 -3
  217. package/dist/filter/types.js +92 -88
  218. package/dist/filter/utils.d.ts +1 -1
  219. package/dist/filter/utils.d.ts.map +1 -1
  220. package/dist/filter/utils.js +147 -161
  221. package/dist/index.js +87 -40
  222. package/dist/logger/category.d.ts.map +1 -1
  223. package/dist/logger/category.js +30 -29
  224. package/dist/logger/configure.d.ts.map +1 -1
  225. package/dist/logger/configure.js +83 -107
  226. package/dist/migration/code-generation.d.ts +2 -2
  227. package/dist/migration/code-generation.d.ts.map +1 -1
  228. package/dist/migration/code-generation.js +1385 -1578
  229. package/dist/migration/migration-set.d.ts +1 -1
  230. package/dist/migration/migration-set.d.ts.map +1 -1
  231. package/dist/migration/migration-set.js +177 -227
  232. package/dist/migration/migrator.d.ts +4 -3
  233. package/dist/migration/migrator.d.ts.map +1 -1
  234. package/dist/migration/migrator.js +340 -345
  235. package/dist/migration/postgresql-schema-reader.d.ts +2 -2
  236. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
  237. package/dist/migration/postgresql-schema-reader.js +506 -564
  238. package/dist/migration/slack-confirm.d.ts +2 -2
  239. package/dist/migration/slack-confirm.d.ts.map +1 -1
  240. package/dist/migration/slack-confirm.js +205 -193
  241. package/dist/migration/types.d.ts +2 -2
  242. package/dist/migration/types.d.ts.map +1 -1
  243. package/dist/migration/types.js +1 -3
  244. package/dist/naite/messaging-types.d.ts +1 -0
  245. package/dist/naite/messaging-types.d.ts.map +1 -1
  246. package/dist/naite/messaging-types.js +1 -7
  247. package/dist/naite/naite-reporter.d.ts +2 -2
  248. package/dist/naite/naite-reporter.d.ts.map +1 -1
  249. package/dist/naite/naite-reporter.js +127 -120
  250. package/dist/naite/naite.d.ts +3 -2
  251. package/dist/naite/naite.d.ts.map +1 -1
  252. package/dist/naite/naite.js +266 -300
  253. package/dist/ssr/index.d.ts +2 -2
  254. package/dist/ssr/index.d.ts.map +1 -1
  255. package/dist/ssr/index.js +13 -3
  256. package/dist/ssr/registry.d.ts +1 -1
  257. package/dist/ssr/registry.d.ts.map +1 -1
  258. package/dist/ssr/registry.js +45 -37
  259. package/dist/ssr/renderer.d.ts +4 -4
  260. package/dist/ssr/renderer.d.ts.map +1 -1
  261. package/dist/ssr/renderer.js +84 -91
  262. package/dist/ssr/types.d.ts +2 -2
  263. package/dist/ssr/types.d.ts.map +1 -1
  264. package/dist/ssr/types.js +1 -3
  265. package/dist/storage/base-file.js +54 -41
  266. package/dist/storage/buffered-file.d.ts +2 -2
  267. package/dist/storage/buffered-file.d.ts.map +1 -1
  268. package/dist/storage/buffered-file.js +51 -44
  269. package/dist/storage/drivers.d.ts +2 -2
  270. package/dist/storage/drivers.d.ts.map +1 -1
  271. package/dist/storage/drivers.js +12 -7
  272. package/dist/storage/index.js +14 -7
  273. package/dist/storage/s3-driver.d.ts +2 -2
  274. package/dist/storage/s3-driver.d.ts.map +1 -1
  275. package/dist/storage/s3-driver.js +52 -48
  276. package/dist/storage/storage-manager.d.ts +2 -2
  277. package/dist/storage/storage-manager.d.ts.map +1 -1
  278. package/dist/storage/storage-manager.js +33 -25
  279. package/dist/storage/types.d.ts +2 -2
  280. package/dist/storage/types.d.ts.map +1 -1
  281. package/dist/storage/types.js +1 -5
  282. package/dist/storage/uploaded-file.d.ts +1 -1
  283. package/dist/storage/uploaded-file.d.ts.map +1 -1
  284. package/dist/storage/uploaded-file.js +45 -35
  285. package/dist/stream/index.js +7 -2
  286. package/dist/stream/sse.d.ts +2 -2
  287. package/dist/stream/sse.d.ts.map +1 -1
  288. package/dist/stream/sse.js +72 -67
  289. package/dist/syncer/api-parser.d.ts +1 -1
  290. package/dist/syncer/api-parser.d.ts.map +1 -1
  291. package/dist/syncer/api-parser.js +224 -245
  292. package/dist/syncer/checksum.d.ts +1 -1
  293. package/dist/syncer/checksum.d.ts.map +1 -1
  294. package/dist/syncer/checksum.js +86 -72
  295. package/dist/syncer/code-generator.d.ts +2 -2
  296. package/dist/syncer/code-generator.d.ts.map +1 -1
  297. package/dist/syncer/code-generator.js +154 -160
  298. package/dist/syncer/entity-operations.d.ts +1 -1
  299. package/dist/syncer/entity-operations.d.ts.map +1 -1
  300. package/dist/syncer/entity-operations.js +63 -54
  301. package/dist/syncer/file-patterns.d.ts +1 -1
  302. package/dist/syncer/file-patterns.d.ts.map +1 -1
  303. package/dist/syncer/file-patterns.js +38 -38
  304. package/dist/syncer/index.js +19 -8
  305. package/dist/syncer/module-loader.d.ts +5 -5
  306. package/dist/syncer/module-loader.d.ts.map +1 -1
  307. package/dist/syncer/module-loader.js +83 -78
  308. package/dist/syncer/syncer-actions.d.ts +2 -2
  309. package/dist/syncer/syncer-actions.d.ts.map +1 -1
  310. package/dist/syncer/syncer-actions.js +76 -91
  311. package/dist/syncer/syncer.d.ts +7 -6
  312. package/dist/syncer/syncer.d.ts.map +1 -1
  313. package/dist/syncer/syncer.js +426 -492
  314. package/dist/tasks/decorator.d.ts +3 -3
  315. package/dist/tasks/decorator.d.ts.map +1 -1
  316. package/dist/tasks/decorator.js +32 -28
  317. package/dist/tasks/step-wrapper.d.ts +1 -1
  318. package/dist/tasks/step-wrapper.d.ts.map +1 -1
  319. package/dist/tasks/step-wrapper.js +42 -41
  320. package/dist/tasks/workflow-manager.d.ts +2 -2
  321. package/dist/tasks/workflow-manager.d.ts.map +1 -1
  322. package/dist/tasks/workflow-manager.js +192 -221
  323. package/dist/template/entity-converter.d.ts +1 -1
  324. package/dist/template/entity-converter.d.ts.map +1 -1
  325. package/dist/template/entity-converter.js +103 -103
  326. package/dist/template/helpers.d.ts.map +1 -1
  327. package/dist/template/helpers.js +163 -163
  328. package/dist/template/implementations/entity.template.d.ts +1 -1
  329. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  330. package/dist/template/implementations/entity.template.js +76 -85
  331. package/dist/template/implementations/entry-server.template.d.ts +1 -1
  332. package/dist/template/implementations/entry-server.template.d.ts.map +1 -1
  333. package/dist/template/implementations/entry-server.template.js +32 -27
  334. package/dist/template/implementations/generated.template.d.ts +1 -1
  335. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  336. package/dist/template/implementations/generated.template.js +254 -275
  337. package/dist/template/implementations/generated_http.template.d.ts +2 -2
  338. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  339. package/dist/template/implementations/generated_http.template.js +114 -133
  340. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  341. package/dist/template/implementations/generated_sso.template.js +249 -275
  342. package/dist/template/implementations/init_types.template.d.ts +1 -1
  343. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  344. package/dist/template/implementations/init_types.template.js +40 -34
  345. package/dist/template/implementations/model.template.d.ts +1 -1
  346. package/dist/template/implementations/model.template.d.ts.map +1 -1
  347. package/dist/template/implementations/model.template.js +56 -53
  348. package/dist/template/implementations/model_test.template.d.ts +1 -1
  349. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  350. package/dist/template/implementations/model_test.template.js +32 -24
  351. package/dist/template/implementations/queries.template.d.ts +1 -1
  352. package/dist/template/implementations/queries.template.d.ts.map +1 -1
  353. package/dist/template/implementations/queries.template.js +84 -89
  354. package/dist/template/implementations/sd.template.d.ts +1 -1
  355. package/dist/template/implementations/sd.template.d.ts.map +1 -1
  356. package/dist/template/implementations/sd.template.js +137 -144
  357. package/dist/template/implementations/services.template.d.ts +1 -1
  358. package/dist/template/implementations/services.template.d.ts.map +1 -1
  359. package/dist/template/implementations/services.template.js +164 -189
  360. package/dist/template/implementations/view_form.template.d.ts +1 -1
  361. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  362. package/dist/template/implementations/view_form.template.js +258 -285
  363. package/dist/template/implementations/view_id_all_select.template.d.ts +1 -1
  364. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  365. package/dist/template/implementations/view_id_all_select.template.js +31 -25
  366. package/dist/template/implementations/view_list.template.d.ts +1 -1
  367. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  368. package/dist/template/implementations/view_list.template.js +304 -355
  369. package/dist/template/implementations/view_search_input.template.d.ts +1 -1
  370. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  371. package/dist/template/implementations/view_search_input.template.js +31 -27
  372. package/dist/template/index.js +21 -7
  373. package/dist/template/template-manager.d.ts +1 -1
  374. package/dist/template/template-manager.d.ts.map +1 -1
  375. package/dist/template/template-manager.js +132 -123
  376. package/dist/template/template-types.js +8 -6
  377. package/dist/template/template.d.ts +2 -2
  378. package/dist/template/template.d.ts.map +1 -1
  379. package/dist/template/template.js +73 -68
  380. package/dist/template/zod-converter.d.ts.map +1 -1
  381. package/dist/template/zod-converter.js +603 -657
  382. package/dist/testing/_relation-graph.d.ts +1 -1
  383. package/dist/testing/_relation-graph.d.ts.map +1 -1
  384. package/dist/testing/_relation-graph.js +93 -88
  385. package/dist/testing/bootstrap.d.ts +22 -13
  386. package/dist/testing/bootstrap.d.ts.map +1 -1
  387. package/dist/testing/bootstrap.js +114 -114
  388. package/dist/testing/data-explorer.d.ts +3 -3
  389. package/dist/testing/data-explorer.d.ts.map +1 -1
  390. package/dist/testing/data-explorer.js +237 -265
  391. package/dist/testing/dev-test-routes.d.ts +2 -2
  392. package/dist/testing/dev-test-routes.d.ts.map +1 -1
  393. package/dist/testing/dev-test-routes.js +258 -249
  394. package/dist/testing/dev-vitest-manager.d.ts +1 -1
  395. package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
  396. package/dist/testing/dev-vitest-manager.js +514 -539
  397. package/dist/testing/faker-mappings.js +422 -420
  398. package/dist/testing/fixture-generator.d.ts +3 -3
  399. package/dist/testing/fixture-generator.d.ts.map +1 -1
  400. package/dist/testing/fixture-generator.js +1216 -1346
  401. package/dist/testing/fixture-loader.js +26 -25
  402. package/dist/testing/fixture-manager.d.ts +3 -3
  403. package/dist/testing/fixture-manager.d.ts.map +1 -1
  404. package/dist/testing/fixture-manager.js +706 -776
  405. package/dist/testing/global-setup.js +53 -49
  406. package/dist/testing/index.js +19 -11
  407. package/dist/testing/naite-vitest-reporter.js +18 -13
  408. package/dist/testing/parallel-db-manager.d.ts +1 -1
  409. package/dist/testing/parallel-db-manager.d.ts.map +1 -1
  410. package/dist/testing/parallel-db-manager.js +63 -78
  411. package/dist/testing/vitest-helpers.d.ts +1 -1
  412. package/dist/testing/vitest-helpers.d.ts.map +1 -1
  413. package/dist/testing/vitest-helpers.js +37 -33
  414. package/dist/types/types.d.ts +28 -28
  415. package/dist/types/types.d.ts.map +1 -1
  416. package/dist/types/types.js +764 -890
  417. package/dist/ui/ai-api.d.ts +1 -1
  418. package/dist/ui/ai-api.d.ts.map +1 -1
  419. package/dist/ui/ai-api.js +52 -42
  420. package/dist/ui/ai-client.d.ts +1 -2
  421. package/dist/ui/ai-client.d.ts.map +1 -1
  422. package/dist/ui/ai-client.js +353 -388
  423. package/dist/ui/api.d.ts +1 -1
  424. package/dist/ui/api.d.ts.map +1 -1
  425. package/dist/ui/api.js +903 -1145
  426. package/dist/ui/cdd-service.d.ts +1 -1
  427. package/dist/ui/cdd-service.d.ts.map +1 -1
  428. package/dist/ui/cdd-service.js +406 -407
  429. package/dist/ui/cdd-types.js +1 -3
  430. package/dist/ui-web/assets/index-C-Zz-wYg.css +1 -0
  431. package/dist/ui-web/assets/index-DejDON8K.js +238 -0
  432. package/dist/ui-web/index.html +3 -3
  433. package/dist/utils/async-utils.js +57 -45
  434. package/dist/utils/console-util.d.ts.map +1 -1
  435. package/dist/utils/console-util.js +104 -87
  436. package/dist/utils/controller.js +26 -19
  437. package/dist/utils/esm-utils.js +49 -38
  438. package/dist/utils/formatter.d.ts +1 -2
  439. package/dist/utils/formatter.d.ts.map +1 -1
  440. package/dist/utils/formatter.js +89 -115
  441. package/dist/utils/fs-utils.d.ts.map +1 -1
  442. package/dist/utils/fs-utils.js +68 -65
  443. package/dist/utils/lodash-able.js +11 -4
  444. package/dist/utils/model.d.ts +1 -1
  445. package/dist/utils/model.d.ts.map +1 -1
  446. package/dist/utils/model.js +21 -19
  447. package/dist/utils/object-utils.js +148 -186
  448. package/dist/utils/path-utils.js +67 -57
  449. package/dist/utils/process-utils.d.ts.map +1 -1
  450. package/dist/utils/process-utils.js +37 -31
  451. package/dist/utils/sql-parser.d.ts +1 -1
  452. package/dist/utils/sql-parser.d.ts.map +1 -1
  453. package/dist/utils/sql-parser.js +40 -40
  454. package/dist/utils/type-utils.js +44 -43
  455. package/dist/utils/utils.d.ts +2 -3
  456. package/dist/utils/utils.d.ts.map +1 -1
  457. package/dist/utils/utils.js +81 -93
  458. package/dist/utils/zod-error.d.ts +1 -1
  459. package/dist/utils/zod-error.d.ts.map +1 -1
  460. package/dist/utils/zod-error.js +24 -17
  461. package/dist/vector/chunking.d.ts +1 -1
  462. package/dist/vector/chunking.d.ts.map +1 -1
  463. package/dist/vector/chunking.js +100 -94
  464. package/dist/vector/config.d.ts +1 -1
  465. package/dist/vector/config.d.ts.map +1 -1
  466. package/dist/vector/config.js +76 -78
  467. package/dist/vector/embedding.d.ts +1 -1
  468. package/dist/vector/embedding.d.ts.map +1 -1
  469. package/dist/vector/embedding.js +128 -125
  470. package/dist/vector/index.js +5 -5
  471. package/dist/vector/types.js +1 -5
  472. package/package.json +31 -36
  473. package/src/ai/agents/agent.ts +12 -5
  474. package/src/ai/agents/types.ts +5 -5
  475. package/src/ai/providers/rtzr/model.ts +8 -10
  476. package/src/ai/providers/rtzr/options.ts +2 -1
  477. package/src/ai/providers/rtzr/provider.ts +5 -3
  478. package/src/ai/providers/rtzr/utils.ts +2 -7
  479. package/src/api/__tests__/config.test.ts +15 -8
  480. package/src/api/base-frame.ts +5 -3
  481. package/src/api/caster.ts +7 -6
  482. package/src/api/code-converters.ts +23 -26
  483. package/src/api/config.ts +23 -17
  484. package/src/api/context.ts +18 -11
  485. package/src/api/decorators.ts +17 -18
  486. package/src/api/sonamu.ts +44 -49
  487. package/src/auth/auth-generator.ts +4 -6
  488. package/src/auth/better-auth-entities.ts +3 -2
  489. package/src/auth/knex-adapter.ts +6 -5
  490. package/src/auth/plugins/entity-definitions/admin.ts +1 -1
  491. package/src/auth/plugins/entity-definitions/anonymous.ts +1 -1
  492. package/src/auth/plugins/entity-definitions/api-key.ts +1 -1
  493. package/src/auth/plugins/entity-definitions/index.ts +1 -1
  494. package/src/auth/plugins/entity-definitions/jwt.ts +1 -1
  495. package/src/auth/plugins/entity-definitions/organization.ts +1 -1
  496. package/src/auth/plugins/entity-definitions/passkey.ts +1 -1
  497. package/src/auth/plugins/entity-definitions/phone-number.ts +1 -1
  498. package/src/auth/plugins/entity-definitions/sso.ts +1 -1
  499. package/src/auth/plugins/entity-definitions/two-factor.ts +1 -1
  500. package/src/auth/plugins/entity-definitions/types.ts +1 -1
  501. package/src/auth/plugins/entity-definitions/username.ts +1 -1
  502. package/src/auth/plugins/wrappers/admin.ts +3 -1
  503. package/src/auth/plugins/wrappers/anonymous.ts +3 -1
  504. package/src/auth/plugins/wrappers/api-key.ts +3 -1
  505. package/src/auth/plugins/wrappers/jwt.ts +3 -1
  506. package/src/auth/plugins/wrappers/organization.ts +3 -1
  507. package/src/auth/plugins/wrappers/passkey.ts +3 -1
  508. package/src/auth/plugins/wrappers/phone-number.ts +3 -1
  509. package/src/auth/plugins/wrappers/sso.ts +2 -1
  510. package/src/auth/plugins/wrappers/two-factor.ts +3 -1
  511. package/src/auth/plugins/wrappers/username.ts +3 -1
  512. package/src/bin/__tests__/ts-loader-register.test.ts +7 -12
  513. package/src/bin/build-config.ts +3 -3
  514. package/src/bin/cli.ts +27 -25
  515. package/src/bin/fixture.ts +4 -2
  516. package/src/bin/hmr-hook-register.ts +1 -0
  517. package/src/bin/test-command.ts +4 -2
  518. package/src/bin/ts-loader-registration.ts +6 -22
  519. package/src/cache/cache-manager.ts +2 -1
  520. package/src/cache/decorator.ts +2 -2
  521. package/src/cache/types.ts +3 -3
  522. package/src/cache-control/cache-control.ts +3 -2
  523. package/src/cache-control/types.ts +2 -2
  524. package/src/compress/compress.ts +1 -1
  525. package/src/cone/cone-generator.ts +5 -3
  526. package/src/database/_batch_update.ts +1 -1
  527. package/src/database/base-model.ts +20 -14
  528. package/src/database/base-model.types.ts +12 -11
  529. package/src/database/db.ts +56 -21
  530. package/src/database/knex.ts +2 -2
  531. package/src/database/puri-subset.test-d.ts +33 -32
  532. package/src/database/puri-subset.types.ts +6 -7
  533. package/src/database/puri-wrapper.ts +29 -26
  534. package/src/database/puri.ts +36 -34
  535. package/src/database/puri.types.test-d.ts +6 -5
  536. package/src/database/puri.types.ts +9 -12
  537. package/src/database/transaction-context.ts +2 -2
  538. package/src/database/upsert-builder.ts +17 -10
  539. package/src/dict/sd.ts +17 -4
  540. package/src/dict/sonamu-dictionary.ts +23 -17
  541. package/src/entity/entity-manager.ts +9 -7
  542. package/src/entity/entity-template-cone.ts +10 -3
  543. package/src/entity/entity.ts +20 -16
  544. package/src/exceptions/error-handler.ts +2 -1
  545. package/src/exceptions/so-exceptions.ts +1 -1
  546. package/src/filter/utils.ts +3 -2
  547. package/src/logger/category.ts +1 -0
  548. package/src/logger/configure.ts +5 -5
  549. package/src/migration/__tests__/code-generation.search-text.test.ts +2 -3
  550. package/src/migration/code-generation.ts +26 -25
  551. package/src/migration/migration-set.ts +16 -18
  552. package/src/migration/migrator.ts +38 -33
  553. package/src/migration/postgresql-schema-reader.ts +12 -12
  554. package/src/migration/slack-confirm.ts +5 -4
  555. package/src/migration/types.ts +2 -2
  556. package/src/naite/messaging-types.ts +1 -1
  557. package/src/naite/naite-reporter.ts +5 -3
  558. package/src/naite/naite.ts +12 -7
  559. package/src/shared/app.shared.ts.txt +2 -2
  560. package/src/shared/web.shared.ts.txt +2 -2
  561. package/src/skills/AGENTS.md +19 -18
  562. package/src/skills/commands/sonamu-skills.md +9 -9
  563. package/src/skills/sonamu/SKILL.md +111 -104
  564. package/src/skills/sonamu/ai-agents.md +27 -26
  565. package/src/skills/sonamu/api.md +81 -69
  566. package/src/skills/sonamu/auth-migration.md +13 -27
  567. package/src/skills/sonamu/auth-plugins.md +41 -31
  568. package/src/skills/sonamu/auth.md +30 -24
  569. package/src/skills/sonamu/cdd.md +26 -17
  570. package/src/skills/sonamu/cone.md +50 -50
  571. package/src/skills/sonamu/config.md +74 -51
  572. package/src/skills/sonamu/create-sonamu.md +31 -19
  573. package/src/skills/sonamu/database.md +43 -26
  574. package/src/skills/sonamu/entity-basic.md +61 -61
  575. package/src/skills/sonamu/entity-relations.md +84 -80
  576. package/src/skills/sonamu/entity-validation-checklist.md +19 -15
  577. package/src/skills/sonamu/fixture-cli.md +52 -30
  578. package/src/skills/sonamu/framework-change.md +9 -7
  579. package/src/skills/sonamu/frontend.md +64 -82
  580. package/src/skills/sonamu/i18n.md +45 -37
  581. package/src/skills/sonamu/migration.md +54 -31
  582. package/src/skills/sonamu/model.md +98 -66
  583. package/src/skills/sonamu/naite.md +34 -32
  584. package/src/skills/sonamu/project-init.md +28 -8
  585. package/src/skills/sonamu/puri.md +82 -91
  586. package/src/skills/sonamu/scaffolding.md +44 -32
  587. package/src/skills/sonamu/skill-contribution.md +50 -45
  588. package/src/skills/sonamu/subset.md +13 -13
  589. package/src/skills/sonamu/tasks.md +73 -58
  590. package/src/skills/sonamu/testing-devrunner.md +56 -36
  591. package/src/skills/sonamu/testing.md +23 -58
  592. package/src/skills/sonamu/upsert.md +32 -31
  593. package/src/skills/sonamu/vector.md +37 -36
  594. package/src/ssr/index.ts +2 -12
  595. package/src/ssr/registry.ts +1 -1
  596. package/src/ssr/renderer.ts +7 -5
  597. package/src/ssr/types.ts +2 -2
  598. package/src/storage/buffered-file.ts +4 -2
  599. package/src/storage/drivers.ts +3 -2
  600. package/src/storage/s3-driver.ts +7 -4
  601. package/src/storage/storage-manager.ts +3 -2
  602. package/src/storage/types.ts +3 -2
  603. package/src/storage/uploaded-file.ts +1 -1
  604. package/src/stream/sse.ts +2 -2
  605. package/src/syncer/api-parser.ts +8 -5
  606. package/src/syncer/checksum.ts +9 -5
  607. package/src/syncer/code-generator.ts +16 -8
  608. package/src/syncer/entity-operations.ts +5 -3
  609. package/src/syncer/file-patterns.ts +2 -1
  610. package/src/syncer/module-loader.ts +9 -6
  611. package/src/syncer/syncer-actions.ts +5 -3
  612. package/src/syncer/syncer.ts +18 -24
  613. package/src/tasks/decorator.ts +10 -8
  614. package/src/tasks/step-wrapper.ts +1 -1
  615. package/src/tasks/workflow-manager.ts +18 -15
  616. package/src/template/__tests__/generated.template.search-text.test.ts +1 -0
  617. package/src/template/entity-converter.ts +4 -2
  618. package/src/template/generated.template.test-d.ts +2 -1
  619. package/src/template/helpers.ts +5 -2
  620. package/src/template/implementations/entity.template.ts +9 -8
  621. package/src/template/implementations/entry-server.template.ts +1 -1
  622. package/src/template/implementations/generated.template.ts +21 -29
  623. package/src/template/implementations/generated_http.template.ts +9 -6
  624. package/src/template/implementations/generated_sso.template.ts +6 -4
  625. package/src/template/implementations/init_types.template.ts +3 -2
  626. package/src/template/implementations/model.template.ts +4 -2
  627. package/src/template/implementations/model_test.template.ts +3 -2
  628. package/src/template/implementations/queries.template.ts +6 -14
  629. package/src/template/implementations/sd.template.ts +4 -2
  630. package/src/template/implementations/services.template.ts +7 -11
  631. package/src/template/implementations/view_form.template.ts +5 -3
  632. package/src/template/implementations/view_id_all_select.template.ts +3 -2
  633. package/src/template/implementations/view_list.template.ts +7 -5
  634. package/src/template/implementations/view_search_input.template.ts +3 -2
  635. package/src/template/template-manager.ts +4 -3
  636. package/src/template/template.ts +4 -3
  637. package/src/template/zod-converter.ts +10 -7
  638. package/src/testing/__tests__/dev-test-routes.test.ts +3 -2
  639. package/src/testing/__tests__/dev-vitest-manager.test.ts +1 -0
  640. package/src/testing/_relation-graph.ts +2 -2
  641. package/src/testing/bootstrap.ts +55 -27
  642. package/src/testing/data-explorer.ts +5 -4
  643. package/src/testing/dev-test-routes.ts +8 -5
  644. package/src/testing/dev-vitest-manager.ts +13 -12
  645. package/src/testing/fixture-generator.ts +11 -17
  646. package/src/testing/fixture-manager.ts +21 -17
  647. package/src/testing/parallel-db-manager.ts +2 -1
  648. package/src/testing/vitest-helpers.ts +2 -1
  649. package/src/types/__tests__/entity-json-schema-search-text.test.ts +1 -0
  650. package/src/types/types.ts +8 -8
  651. package/src/typings/knex.d.ts +4 -4
  652. package/src/ui/ai-api.ts +5 -3
  653. package/src/ui/ai-client.ts +6 -5
  654. package/src/ui/api.ts +25 -23
  655. package/src/ui/cdd-service.ts +12 -11
  656. package/src/utils/console-util.ts +3 -1
  657. package/src/utils/formatter.ts +94 -102
  658. package/src/utils/fs-utils.ts +2 -1
  659. package/src/utils/model.ts +2 -2
  660. package/src/utils/object-utils.ts +3 -3
  661. package/src/utils/process-utils.ts +2 -1
  662. package/src/utils/sql-parser.ts +10 -1
  663. package/src/utils/type-utils.ts +3 -3
  664. package/src/utils/utils.ts +9 -7
  665. package/src/utils/zod-error.ts +1 -1
  666. package/src/vector/chunking.ts +1 -1
  667. package/src/vector/config.ts +1 -1
  668. package/src/vector/embedding.ts +11 -9
  669. package/tsdown.api.config.ts +50 -0
  670. package/.swcrc.project-default +0 -18
  671. package/dist/api/__tests__/config.test.js +0 -189
  672. package/dist/bin/__tests__/test-command.test.js +0 -112
  673. package/dist/bin/__tests__/ts-loader-register.test.js +0 -45
  674. package/dist/database/puri-subset.test-d.js +0 -89
  675. package/dist/database/puri.types.test-d.js +0 -129
  676. package/dist/migration/__tests__/code-generation.search-text.test.js +0 -435
  677. package/dist/template/__tests__/generated.template.search-text.test.js +0 -99
  678. package/dist/template/generated.template.test-d.js +0 -24
  679. package/dist/testing/__tests__/dev-test-routes.test.js +0 -144
  680. package/dist/testing/__tests__/dev-vitest-manager.test.js +0 -152
  681. package/dist/types/__tests__/entity-json-schema-search-text.test.js +0 -256
  682. package/dist/typings/knex.d.js +0 -3
  683. package/dist/ui-web/assets/index-CKo0Z2Iu.css +0 -1
  684. package/dist/ui-web/assets/index-DK-2aacv.js +0 -257
@@ -1,145 +1,130 @@
1
- import assert from "assert";
1
+ import { __esmMin } from "../_virtual/rolldown_runtime.js";
2
2
  import { group } from "radashi";
3
- class PostgreSQLSchemaReaderClass {
4
- genericIndexTypes = new Set([
5
- "btree",
6
- "hash",
7
- "gin",
8
- "gist",
9
- "pgroonga"
10
- ]);
11
- /**
12
- * DB에서 테이블 정보를 읽어서 MigrationSet을 만들어옵니다.
13
- * @param compareDB Knex 인스턴스
14
- * @param table 테이블 이름
15
- * @returns MigrationSet 객체
16
- */ async getMigrationSetFromDB(compareDB, table) {
17
- let dbColumns, dbIndexes, dbForeigns;
18
- try {
19
- [dbColumns, dbIndexes, dbForeigns] = await this.readTable(compareDB, table);
20
- } catch (e) {
21
- if (e instanceof Error && e.message.includes("Table not found")) {
22
- return null;
23
- }
24
- console.error(e);
25
- return null;
26
- }
27
- // vector 컬럼의 dimensions 조회
28
- const vectorDimensions = await this.getVectorDimensions(compareDB, table);
29
- const columns = dbColumns.map((dbColumn)=>{
30
- const dbColType = this.resolveDBColType(dbColumn);
31
- // vector 타입인 경우 dimensions 설정
32
- if (dbColType.type === "vector") {
33
- dbColType.dimensions = vectorDimensions[dbColumn.column_name] ?? 0;
34
- }
35
- return {
36
- name: dbColumn.column_name,
37
- nullable: dbColumn.is_nullable === "YES",
38
- ...dbColType,
39
- // Generated Column 처리
40
- ...(()=>{
41
- if (dbColumn.is_generated === "s" || dbColumn.is_generated === "v") {
42
- return {
43
- generated: {
44
- type: dbColumn.is_generated === "s" ? "STORED" : "VIRTUAL",
45
- expression: dbColumn.generation_expression ?? ""
46
- }
47
- };
48
- }
49
- return {};
50
- })(),
51
- // Default 값 처리 (Generated Column이 아닌 경우만)
52
- ...(()=>{
53
- // Generated Column은 default 값이 없음
54
- if (dbColumn.is_generated === "s" || dbColumn.is_generated === "v") {
55
- return {};
56
- }
57
- if (dbColumn.column_default !== null) {
58
- // PostgreSQL default 값 정리 (nextval, CURRENT_TIMESTAMP 등)
59
- let defaultValue = dbColumn.column_default;
60
- // nextval 제거 (SERIAL 타입)
61
- if (defaultValue.startsWith("nextval(")) {
62
- return {};
63
- }
64
- // 타입 캐스팅 제거 (예: '1'::integer → 1)
65
- defaultValue = defaultValue.replace(/::[\w\s]+$/g, "");
66
- // 따옴표가 single quote인 경우 double quote로 변환
67
- if (defaultValue.startsWith("'") && defaultValue.endsWith("'")) {
68
- defaultValue = defaultValue.replaceAll("'", '"');
69
- }
70
- return {
71
- defaultTo: defaultValue
72
- };
73
- }
74
- return {};
75
- })()
76
- };
77
- });
78
- // PRIMARY KEY와 foreign key용 인덱스 제외
79
- const dbIndexesGroup = group(dbIndexes.filter((dbIndex)=>!dbIndex.is_primary && !dbForeigns.find((dbForeign)=>dbIndex.index_name.includes(dbForeign.constraint_name))), (dbIndex)=>dbIndex.index_name);
80
- // indexes 처리
81
- const indexes = Object.keys(dbIndexesGroup).map((indexName)=>{
82
- const currentIndexes = dbIndexesGroup[indexName]?.toSorted((left, right)=>left.column_order - right.column_order);
83
- assert(currentIndexes);
84
- const firstIndex = currentIndexes[0];
85
- const parsedIndexDefinition = this.parseIndexDefinition(firstIndex.index_definition);
86
- const restoredIndexType = this.restoreMigrationIndexType(firstIndex, parsedIndexDefinition.accessMethod);
87
- const using = this.restoreGenericUsing(parsedIndexDefinition.accessMethod ?? firstIndex.index_type);
88
- return {
89
- type: restoredIndexType,
90
- name: indexName,
91
- columns: currentIndexes.map((idx)=>({
92
- name: idx.column_name,
93
- ...this.extractIndexColumnOpclass(parsedIndexDefinition.columnDefinitions[idx.column_order - 1]) ? {
94
- opclass: this.extractIndexColumnOpclass(parsedIndexDefinition.columnDefinitions[idx.column_order - 1])
95
- } : {},
96
- ...using === "btree" ? {
97
- sortOrder: idx.sort_order,
98
- nullsFirst: idx.nulls_first
99
- } : {}
100
- })),
101
- nullsNotDistinct: firstIndex.nulls_not_distinct,
102
- ...using ? {
103
- using
104
- } : {},
105
- ...this.parseVectorIndexOptions(restoredIndexType, parsedIndexDefinition.withOptions)
106
- };
107
- });
108
- // foreigns 처리
109
- const foreigns = dbForeigns.map((dbForeign)=>{
110
- return {
111
- columns: [
112
- dbForeign.column_name
113
- ],
114
- to: `${dbForeign.foreign_table_name}.${dbForeign.foreign_column_name}`,
115
- onUpdate: this.mapConstraintAction(dbForeign.update_rule),
116
- onDelete: this.mapConstraintAction(dbForeign.delete_rule)
117
- };
118
- });
119
- return {
120
- table,
121
- columns,
122
- indexes,
123
- foreigns
124
- };
125
- }
126
- /**
127
- * PostgreSQL의 constraint action을 Knex 형식으로 변환
128
- */ mapConstraintAction(action) {
129
- const actionMap = {
130
- "NO ACTION": "NO ACTION",
131
- RESTRICT: "RESTRICT",
132
- CASCADE: "CASCADE",
133
- "SET NULL": "SET NULL",
134
- "SET DEFAULT": "SET DEFAULT"
135
- };
136
- return actionMap[action] ?? "NO ACTION";
137
- }
138
- /**
139
- * 기존 테이블 읽어서 cols, indexes, foreigns 반환
140
- */ async readTable(compareDB, tableName) {
141
- // Columns 조회 (Generated Column 정보 포함)
142
- const columnsQuery = `
3
+ import assert from "assert";
4
+
5
+ //#region src/migration/postgresql-schema-reader.ts
6
+ var PostgreSQLSchemaReaderClass, PostgreSQLSchemaReader;
7
+ var init_postgresql_schema_reader = __esmMin((() => {
8
+ PostgreSQLSchemaReaderClass = class {
9
+ genericIndexTypes = new Set([
10
+ "btree",
11
+ "hash",
12
+ "gin",
13
+ "gist",
14
+ "pgroonga"
15
+ ]);
16
+ /**
17
+ * DB에서 테이블 정보를 읽어서 MigrationSet을 만들어옵니다.
18
+ * @param compareDB Knex 인스턴스
19
+ * @param table 테이블 이름
20
+ * @returns MigrationSet 객체
21
+ */
22
+ async getMigrationSetFromDB(compareDB, table) {
23
+ let dbColumns, dbIndexes, dbForeigns;
24
+ try {
25
+ [dbColumns, dbIndexes, dbForeigns] = await this.readTable(compareDB, table);
26
+ } catch (e) {
27
+ if (e instanceof Error && e.message.includes("Table not found")) {
28
+ return null;
29
+ }
30
+ console.error(e);
31
+ return null;
32
+ }
33
+ const vectorDimensions = await this.getVectorDimensions(compareDB, table);
34
+ const columns = dbColumns.map((dbColumn) => {
35
+ const dbColType = this.resolveDBColType(dbColumn);
36
+ if (dbColType.type === "vector") {
37
+ dbColType.dimensions = vectorDimensions[dbColumn.column_name] ?? 0;
38
+ }
39
+ return {
40
+ name: dbColumn.column_name,
41
+ nullable: dbColumn.is_nullable === "YES",
42
+ ...dbColType,
43
+ ...(() => {
44
+ if (dbColumn.is_generated === "s" || dbColumn.is_generated === "v") {
45
+ return { generated: {
46
+ type: dbColumn.is_generated === "s" ? "STORED" : "VIRTUAL",
47
+ expression: dbColumn.generation_expression ?? ""
48
+ } };
49
+ }
50
+ return {};
51
+ })(),
52
+ ...(() => {
53
+ if (dbColumn.is_generated === "s" || dbColumn.is_generated === "v") {
54
+ return {};
55
+ }
56
+ if (dbColumn.column_default !== null) {
57
+ let defaultValue = dbColumn.column_default;
58
+ if (defaultValue.startsWith("nextval(")) {
59
+ return {};
60
+ }
61
+ defaultValue = defaultValue.replace(/::[\w\s]+$/g, "");
62
+ if (defaultValue.startsWith("'") && defaultValue.endsWith("'")) {
63
+ defaultValue = defaultValue.replaceAll("'", "\"");
64
+ }
65
+ return { defaultTo: defaultValue };
66
+ }
67
+ return {};
68
+ })()
69
+ };
70
+ });
71
+ const dbIndexesGroup = group(dbIndexes.filter((dbIndex) => !dbIndex.is_primary && !dbForeigns.find((dbForeign) => dbIndex.index_name.includes(dbForeign.constraint_name))), (dbIndex) => dbIndex.index_name);
72
+ const indexes = Object.keys(dbIndexesGroup).map((indexName) => {
73
+ const currentIndexes = dbIndexesGroup[indexName]?.toSorted((left, right) => left.column_order - right.column_order);
74
+ assert(currentIndexes);
75
+ const firstIndex = currentIndexes[0];
76
+ const parsedIndexDefinition = this.parseIndexDefinition(firstIndex.index_definition);
77
+ const restoredIndexType = this.restoreMigrationIndexType(firstIndex, parsedIndexDefinition.accessMethod);
78
+ const using = this.restoreGenericUsing(parsedIndexDefinition.accessMethod ?? firstIndex.index_type);
79
+ return {
80
+ type: restoredIndexType,
81
+ name: indexName,
82
+ columns: currentIndexes.map((idx) => ({
83
+ name: idx.column_name,
84
+ ...this.extractIndexColumnOpclass(parsedIndexDefinition.columnDefinitions[idx.column_order - 1]) ? { opclass: this.extractIndexColumnOpclass(parsedIndexDefinition.columnDefinitions[idx.column_order - 1]) } : {},
85
+ ...using === "btree" ? {
86
+ sortOrder: idx.sort_order,
87
+ nullsFirst: idx.nulls_first
88
+ } : {}
89
+ })),
90
+ nullsNotDistinct: firstIndex.nulls_not_distinct,
91
+ ...using ? { using } : {},
92
+ ...this.parseVectorIndexOptions(restoredIndexType, parsedIndexDefinition.withOptions)
93
+ };
94
+ });
95
+ const foreigns = dbForeigns.map((dbForeign) => {
96
+ return {
97
+ columns: [dbForeign.column_name],
98
+ to: `${dbForeign.foreign_table_name}.${dbForeign.foreign_column_name}`,
99
+ onUpdate: this.mapConstraintAction(dbForeign.update_rule),
100
+ onDelete: this.mapConstraintAction(dbForeign.delete_rule)
101
+ };
102
+ });
103
+ return {
104
+ table,
105
+ columns,
106
+ indexes,
107
+ foreigns
108
+ };
109
+ }
110
+ /**
111
+ * PostgreSQL의 constraint action을 Knex 형식으로 변환
112
+ */
113
+ mapConstraintAction(action) {
114
+ const actionMap = {
115
+ "NO ACTION": "NO ACTION",
116
+ RESTRICT: "RESTRICT",
117
+ CASCADE: "CASCADE",
118
+ "SET NULL": "SET NULL",
119
+ "SET DEFAULT": "SET DEFAULT"
120
+ };
121
+ return actionMap[action] ?? "NO ACTION";
122
+ }
123
+ /**
124
+ * 기존 테이블 읽어서 cols, indexes, foreigns 반환
125
+ */
126
+ async readTable(compareDB, tableName) {
127
+ const columnsQuery = `
143
128
  SELECT
144
129
  c.column_name,
145
130
  c.data_type,
@@ -167,14 +152,11 @@ class PostgreSQLSchemaReaderClass {
167
152
  AND c.table_schema = 'public'
168
153
  ORDER BY c.ordinal_position
169
154
  `;
170
- const columns = (await compareDB.raw(columnsQuery, [
171
- tableName
172
- ])).rows;
173
- if (columns.length === 0) {
174
- throw new Error(`Table not found: ${tableName}`);
175
- }
176
- // Indexes 조회 (PGroonga 표현식 인덱스 포함)
177
- const indexesQuery = `
155
+ const columns = (await compareDB.raw(columnsQuery, [tableName])).rows;
156
+ if (columns.length === 0) {
157
+ throw new Error(`Table not found: ${tableName}`);
158
+ }
159
+ const indexesQuery = `
178
160
  SELECT
179
161
  i.relname AS index_name,
180
162
  CASE
@@ -234,11 +216,8 @@ class PostgreSQLSchemaReaderClass {
234
216
  AND (u.attnum > 0 OR (am.amname = 'pgroonga' AND u.attnum = 0))
235
217
  ORDER BY i.relname, u.ord;
236
218
  `;
237
- const indexes = (await compareDB.raw(indexesQuery, [
238
- tableName
239
- ])).rows;
240
- // Foreign Keys 조회
241
- const foreignsQuery = `
219
+ const indexes = (await compareDB.raw(indexesQuery, [tableName])).rows;
220
+ const foreignsQuery = `
242
221
  SELECT
243
222
  tc.constraint_name,
244
223
  kcu.column_name,
@@ -259,277 +238,268 @@ class PostgreSQLSchemaReaderClass {
259
238
  WHERE tc.constraint_type = 'FOREIGN KEY'
260
239
  AND tc.table_name = ?
261
240
  `;
262
- const foreigns = (await compareDB.raw(foreignsQuery, [
263
- tableName
264
- ])).rows;
265
- return [
266
- columns,
267
- indexes,
268
- foreigns
269
- ];
270
- }
271
- restoreMigrationIndexType(index, accessMethod) {
272
- const resolvedAccessMethod = (accessMethod ?? index.index_type).toLowerCase();
273
- if (resolvedAccessMethod === "hnsw" || resolvedAccessMethod === "ivfflat") {
274
- return resolvedAccessMethod;
275
- }
276
- return index.is_unique ? "unique" : "index";
277
- }
278
- restoreGenericUsing(accessMethod) {
279
- if (!accessMethod) {
280
- return undefined;
281
- }
282
- const normalized = accessMethod.toLowerCase();
283
- if (!this.genericIndexTypes.has(normalized)) {
284
- return undefined;
285
- }
286
- return normalized;
287
- }
288
- parseVectorIndexOptions(type, withOptions) {
289
- if (type === "hnsw") {
290
- return {
291
- ...this.parseIntegerOption(withOptions.m) !== undefined ? {
292
- m: this.parseIntegerOption(withOptions.m)
293
- } : {},
294
- ...this.parseIntegerOption(withOptions.ef_construction) !== undefined ? {
295
- efConstruction: this.parseIntegerOption(withOptions.ef_construction)
296
- } : {}
297
- };
298
- }
299
- if (type === "ivfflat") {
300
- return {
301
- ...this.parseIntegerOption(withOptions.lists) !== undefined ? {
302
- lists: this.parseIntegerOption(withOptions.lists)
303
- } : {}
304
- };
305
- }
306
- return {};
307
- }
308
- parseIntegerOption(value) {
309
- if (!value) {
310
- return undefined;
311
- }
312
- const parsed = Number.parseInt(value, 10);
313
- return Number.isNaN(parsed) ? undefined : parsed;
314
- }
315
- extractIndexColumnOpclass(columnDefinition) {
316
- if (!columnDefinition) {
317
- return undefined;
318
- }
319
- const trimmed = columnDefinition.replace(/\s+NULLS\s+(FIRST|LAST)\s*$/i, "").replace(/\s+(ASC|DESC)\s*$/i, "").trim();
320
- const tokens = this.tokenizeTopLevel(trimmed);
321
- if (tokens.length < 2) {
322
- return undefined;
323
- }
324
- if (tokens[tokens.length - 2]?.toUpperCase() === "COLLATE") {
325
- return undefined;
326
- }
327
- return tokens.at(-1);
328
- }
329
- parseIndexDefinition(indexDefinition) {
330
- const accessMethod = indexDefinition.match(/\bUSING\s+([a-z_][\w]*)/i)?.[1]?.toLowerCase();
331
- const usingMatchIndex = indexDefinition.search(/\bUSING\b/i);
332
- const columnsStart = usingMatchIndex >= 0 ? indexDefinition.indexOf("(", usingMatchIndex) : -1;
333
- const columnsEnd = columnsStart >= 0 ? this.findMatchingParenthesis(indexDefinition, columnsStart) : -1;
334
- const columnDefinitions = columnsStart >= 0 && columnsEnd > columnsStart ? this.splitTopLevel(indexDefinition.slice(columnsStart + 1, columnsEnd), ",") : [];
335
- const withMatch = /\bWITH\s*\(/i.exec(indexDefinition);
336
- const withStart = withMatch ? indexDefinition.indexOf("(", withMatch.index) : -1;
337
- const withEnd = withStart >= 0 ? this.findMatchingParenthesis(indexDefinition, withStart) : -1;
338
- const withOptions = withStart >= 0 && withEnd > withStart ? this.parseIndexOptionEntries(indexDefinition.slice(withStart + 1, withEnd)) : {};
339
- return {
340
- accessMethod,
341
- columnDefinitions,
342
- withOptions
343
- };
344
- }
345
- parseIndexOptionEntries(optionSource) {
346
- return this.splitTopLevel(optionSource, ",").reduce((result, entry)=>{
347
- const matched = entry.trim().match(/^([a-z_][\w]*)\s*=\s*(.+)$/i);
348
- if (!matched) {
349
- return result;
350
- }
351
- const [, key, rawValue] = matched;
352
- result[key.toLowerCase()] = rawValue.trim().replace(/^['"]|['"]$/g, "");
353
- return result;
354
- }, {});
355
- }
356
- splitTopLevel(source, delimiter) {
357
- const items = [];
358
- let start = 0;
359
- let parenDepth = 0;
360
- let bracketDepth = 0;
361
- let inSingleQuote = false;
362
- let inDoubleQuote = false;
363
- for(let index = 0; index < source.length; index += 1){
364
- const char = source[index];
365
- const nextChar = source[index + 1];
366
- if (char === "'" && !inDoubleQuote) {
367
- if (inSingleQuote && nextChar === "'") {
368
- index += 1;
369
- continue;
370
- }
371
- inSingleQuote = !inSingleQuote;
372
- continue;
373
- }
374
- if (char === '"' && !inSingleQuote) {
375
- if (inDoubleQuote && nextChar === '"') {
376
- index += 1;
377
- continue;
378
- }
379
- inDoubleQuote = !inDoubleQuote;
380
- continue;
381
- }
382
- if (inSingleQuote || inDoubleQuote) {
383
- continue;
384
- }
385
- if (char === "(") {
386
- parenDepth += 1;
387
- continue;
388
- }
389
- if (char === ")") {
390
- parenDepth -= 1;
391
- continue;
392
- }
393
- if (char === "[") {
394
- bracketDepth += 1;
395
- continue;
396
- }
397
- if (char === "]") {
398
- bracketDepth -= 1;
399
- continue;
400
- }
401
- if (char === delimiter && parenDepth === 0 && bracketDepth === 0) {
402
- items.push(source.slice(start, index).trim());
403
- start = index + 1;
404
- }
405
- }
406
- const tail = source.slice(start).trim();
407
- if (tail.length > 0) {
408
- items.push(tail);
409
- }
410
- return items;
411
- }
412
- tokenizeTopLevel(source) {
413
- const tokens = [];
414
- let start = -1;
415
- let parenDepth = 0;
416
- let bracketDepth = 0;
417
- let inSingleQuote = false;
418
- let inDoubleQuote = false;
419
- const pushToken = (endIndex)=>{
420
- if (start < 0) {
421
- return;
422
- }
423
- const token = source.slice(start, endIndex).trim();
424
- if (token.length > 0) {
425
- tokens.push(token);
426
- }
427
- start = -1;
428
- };
429
- for(let index = 0; index < source.length; index += 1){
430
- const char = source[index];
431
- const nextChar = source[index + 1];
432
- if (char === "'" && !inDoubleQuote) {
433
- if (start < 0) {
434
- start = index;
435
- }
436
- if (inSingleQuote && nextChar === "'") {
437
- index += 1;
438
- continue;
439
- }
440
- inSingleQuote = !inSingleQuote;
441
- continue;
442
- }
443
- if (char === '"' && !inSingleQuote) {
444
- if (start < 0) {
445
- start = index;
446
- }
447
- if (inDoubleQuote && nextChar === '"') {
448
- index += 1;
449
- continue;
450
- }
451
- inDoubleQuote = !inDoubleQuote;
452
- continue;
453
- }
454
- if (!inSingleQuote && !inDoubleQuote) {
455
- if (char === "(") {
456
- if (start < 0) {
457
- start = index;
458
- }
459
- parenDepth += 1;
460
- continue;
461
- }
462
- if (char === ")") {
463
- parenDepth -= 1;
464
- continue;
465
- }
466
- if (char === "[") {
467
- if (start < 0) {
468
- start = index;
469
- }
470
- bracketDepth += 1;
471
- continue;
472
- }
473
- if (char === "]") {
474
- bracketDepth -= 1;
475
- continue;
476
- }
477
- if (/\s/.test(char) && parenDepth === 0 && bracketDepth === 0) {
478
- pushToken(index);
479
- continue;
480
- }
481
- }
482
- if (start < 0) {
483
- start = index;
484
- }
485
- }
486
- pushToken(source.length);
487
- return tokens;
488
- }
489
- findMatchingParenthesis(source, openIndex) {
490
- let depth = 0;
491
- let inSingleQuote = false;
492
- let inDoubleQuote = false;
493
- for(let index = openIndex; index < source.length; index += 1){
494
- const char = source[index];
495
- const nextChar = source[index + 1];
496
- if (char === "'" && !inDoubleQuote) {
497
- if (inSingleQuote && nextChar === "'") {
498
- index += 1;
499
- continue;
500
- }
501
- inSingleQuote = !inSingleQuote;
502
- continue;
503
- }
504
- if (char === '"' && !inSingleQuote) {
505
- if (inDoubleQuote && nextChar === '"') {
506
- index += 1;
507
- continue;
508
- }
509
- inDoubleQuote = !inDoubleQuote;
510
- continue;
511
- }
512
- if (inSingleQuote || inDoubleQuote) {
513
- continue;
514
- }
515
- if (char === "(") {
516
- depth += 1;
517
- continue;
518
- }
519
- if (char === ")") {
520
- depth -= 1;
521
- if (depth === 0) {
522
- return index;
523
- }
524
- }
525
- }
526
- return -1;
527
- }
528
- /**
529
- * 특정 테이블의 PK를 참조하는 다른 테이블의 FK 목록을 조회합니다.
530
- * PK 타입 변경 시 관련 FK 제약조건을 삭제/복구하기 위해 사용됩니다.
531
- */ async getReferencingForeignKeys(db, tableName) {
532
- const query = `
241
+ const foreigns = (await compareDB.raw(foreignsQuery, [tableName])).rows;
242
+ return [
243
+ columns,
244
+ indexes,
245
+ foreigns
246
+ ];
247
+ }
248
+ restoreMigrationIndexType(index, accessMethod) {
249
+ const resolvedAccessMethod = (accessMethod ?? index.index_type).toLowerCase();
250
+ if (resolvedAccessMethod === "hnsw" || resolvedAccessMethod === "ivfflat") {
251
+ return resolvedAccessMethod;
252
+ }
253
+ return index.is_unique ? "unique" : "index";
254
+ }
255
+ restoreGenericUsing(accessMethod) {
256
+ if (!accessMethod) {
257
+ return undefined;
258
+ }
259
+ const normalized = accessMethod.toLowerCase();
260
+ if (!this.genericIndexTypes.has(normalized)) {
261
+ return undefined;
262
+ }
263
+ return normalized;
264
+ }
265
+ parseVectorIndexOptions(type, withOptions) {
266
+ if (type === "hnsw") {
267
+ return {
268
+ ...this.parseIntegerOption(withOptions.m) !== undefined ? { m: this.parseIntegerOption(withOptions.m) } : {},
269
+ ...this.parseIntegerOption(withOptions.ef_construction) !== undefined ? { efConstruction: this.parseIntegerOption(withOptions.ef_construction) } : {}
270
+ };
271
+ }
272
+ if (type === "ivfflat") {
273
+ return this.parseIntegerOption(withOptions.lists) !== undefined ? { lists: this.parseIntegerOption(withOptions.lists) } : {};
274
+ }
275
+ return {};
276
+ }
277
+ parseIntegerOption(value) {
278
+ if (!value) {
279
+ return undefined;
280
+ }
281
+ const parsed = Number.parseInt(value, 10);
282
+ return Number.isNaN(parsed) ? undefined : parsed;
283
+ }
284
+ extractIndexColumnOpclass(columnDefinition) {
285
+ if (!columnDefinition) {
286
+ return undefined;
287
+ }
288
+ const trimmed = columnDefinition.replace(/\s+NULLS\s+(FIRST|LAST)\s*$/i, "").replace(/\s+(ASC|DESC)\s*$/i, "").trim();
289
+ const tokens = this.tokenizeTopLevel(trimmed);
290
+ if (tokens.length < 2) {
291
+ return undefined;
292
+ }
293
+ if (tokens[tokens.length - 2]?.toUpperCase() === "COLLATE") {
294
+ return undefined;
295
+ }
296
+ return tokens.at(-1);
297
+ }
298
+ parseIndexDefinition(indexDefinition) {
299
+ const accessMethod = indexDefinition.match(/\bUSING\s+([a-z_][\w]*)/i)?.[1]?.toLowerCase();
300
+ const usingMatchIndex = indexDefinition.search(/\bUSING\b/i);
301
+ const columnsStart = usingMatchIndex >= 0 ? indexDefinition.indexOf("(", usingMatchIndex) : -1;
302
+ const columnsEnd = columnsStart >= 0 ? this.findMatchingParenthesis(indexDefinition, columnsStart) : -1;
303
+ const columnDefinitions = columnsStart >= 0 && columnsEnd > columnsStart ? this.splitTopLevel(indexDefinition.slice(columnsStart + 1, columnsEnd), ",") : [];
304
+ const withMatch = /\bWITH\s*\(/i.exec(indexDefinition);
305
+ const withStart = withMatch ? indexDefinition.indexOf("(", withMatch.index) : -1;
306
+ const withEnd = withStart >= 0 ? this.findMatchingParenthesis(indexDefinition, withStart) : -1;
307
+ const withOptions = withStart >= 0 && withEnd > withStart ? this.parseIndexOptionEntries(indexDefinition.slice(withStart + 1, withEnd)) : {};
308
+ return {
309
+ accessMethod,
310
+ columnDefinitions,
311
+ withOptions
312
+ };
313
+ }
314
+ parseIndexOptionEntries(optionSource) {
315
+ return this.splitTopLevel(optionSource, ",").reduce((result, entry) => {
316
+ const matched = entry.trim().match(/^([a-z_][\w]*)\s*=\s*(.+)$/i);
317
+ if (!matched) {
318
+ return result;
319
+ }
320
+ const [, key, rawValue] = matched;
321
+ result[key.toLowerCase()] = rawValue.trim().replace(/^['"]|['"]$/g, "");
322
+ return result;
323
+ }, {});
324
+ }
325
+ splitTopLevel(source, delimiter) {
326
+ const items = [];
327
+ let start = 0;
328
+ let parenDepth = 0;
329
+ let bracketDepth = 0;
330
+ let inSingleQuote = false;
331
+ let inDoubleQuote = false;
332
+ for (let index = 0; index < source.length; index += 1) {
333
+ const char = source[index];
334
+ const nextChar = source[index + 1];
335
+ if (char === "'" && !inDoubleQuote) {
336
+ if (inSingleQuote && nextChar === "'") {
337
+ index += 1;
338
+ continue;
339
+ }
340
+ inSingleQuote = !inSingleQuote;
341
+ continue;
342
+ }
343
+ if (char === "\"" && !inSingleQuote) {
344
+ if (inDoubleQuote && nextChar === "\"") {
345
+ index += 1;
346
+ continue;
347
+ }
348
+ inDoubleQuote = !inDoubleQuote;
349
+ continue;
350
+ }
351
+ if (inSingleQuote || inDoubleQuote) {
352
+ continue;
353
+ }
354
+ if (char === "(") {
355
+ parenDepth += 1;
356
+ continue;
357
+ }
358
+ if (char === ")") {
359
+ parenDepth -= 1;
360
+ continue;
361
+ }
362
+ if (char === "[") {
363
+ bracketDepth += 1;
364
+ continue;
365
+ }
366
+ if (char === "]") {
367
+ bracketDepth -= 1;
368
+ continue;
369
+ }
370
+ if (char === delimiter && parenDepth === 0 && bracketDepth === 0) {
371
+ items.push(source.slice(start, index).trim());
372
+ start = index + 1;
373
+ }
374
+ }
375
+ const tail = source.slice(start).trim();
376
+ if (tail.length > 0) {
377
+ items.push(tail);
378
+ }
379
+ return items;
380
+ }
381
+ tokenizeTopLevel(source) {
382
+ const tokens = [];
383
+ let start = -1;
384
+ let parenDepth = 0;
385
+ let bracketDepth = 0;
386
+ let inSingleQuote = false;
387
+ let inDoubleQuote = false;
388
+ const pushToken = (endIndex) => {
389
+ if (start < 0) {
390
+ return;
391
+ }
392
+ const token = source.slice(start, endIndex).trim();
393
+ if (token.length > 0) {
394
+ tokens.push(token);
395
+ }
396
+ start = -1;
397
+ };
398
+ for (let index = 0; index < source.length; index += 1) {
399
+ const char = source[index];
400
+ const nextChar = source[index + 1];
401
+ if (char === "'" && !inDoubleQuote) {
402
+ if (start < 0) {
403
+ start = index;
404
+ }
405
+ if (inSingleQuote && nextChar === "'") {
406
+ index += 1;
407
+ continue;
408
+ }
409
+ inSingleQuote = !inSingleQuote;
410
+ continue;
411
+ }
412
+ if (char === "\"" && !inSingleQuote) {
413
+ if (start < 0) {
414
+ start = index;
415
+ }
416
+ if (inDoubleQuote && nextChar === "\"") {
417
+ index += 1;
418
+ continue;
419
+ }
420
+ inDoubleQuote = !inDoubleQuote;
421
+ continue;
422
+ }
423
+ if (!inSingleQuote && !inDoubleQuote) {
424
+ if (char === "(") {
425
+ if (start < 0) {
426
+ start = index;
427
+ }
428
+ parenDepth += 1;
429
+ continue;
430
+ }
431
+ if (char === ")") {
432
+ parenDepth -= 1;
433
+ continue;
434
+ }
435
+ if (char === "[") {
436
+ if (start < 0) {
437
+ start = index;
438
+ }
439
+ bracketDepth += 1;
440
+ continue;
441
+ }
442
+ if (char === "]") {
443
+ bracketDepth -= 1;
444
+ continue;
445
+ }
446
+ if (/\s/.test(char) && parenDepth === 0 && bracketDepth === 0) {
447
+ pushToken(index);
448
+ continue;
449
+ }
450
+ }
451
+ if (start < 0) {
452
+ start = index;
453
+ }
454
+ }
455
+ pushToken(source.length);
456
+ return tokens;
457
+ }
458
+ findMatchingParenthesis(source, openIndex) {
459
+ let depth = 0;
460
+ let inSingleQuote = false;
461
+ let inDoubleQuote = false;
462
+ for (let index = openIndex; index < source.length; index += 1) {
463
+ const char = source[index];
464
+ const nextChar = source[index + 1];
465
+ if (char === "'" && !inDoubleQuote) {
466
+ if (inSingleQuote && nextChar === "'") {
467
+ index += 1;
468
+ continue;
469
+ }
470
+ inSingleQuote = !inSingleQuote;
471
+ continue;
472
+ }
473
+ if (char === "\"" && !inSingleQuote) {
474
+ if (inDoubleQuote && nextChar === "\"") {
475
+ index += 1;
476
+ continue;
477
+ }
478
+ inDoubleQuote = !inDoubleQuote;
479
+ continue;
480
+ }
481
+ if (inSingleQuote || inDoubleQuote) {
482
+ continue;
483
+ }
484
+ if (char === "(") {
485
+ depth += 1;
486
+ continue;
487
+ }
488
+ if (char === ")") {
489
+ depth -= 1;
490
+ if (depth === 0) {
491
+ return index;
492
+ }
493
+ }
494
+ }
495
+ return -1;
496
+ }
497
+ /**
498
+ * 특정 테이블의 PK를 참조하는 다른 테이블의 FK 목록을 조회합니다.
499
+ * PK 타입 변경 시 관련 FK 제약조건을 삭제/복구하기 위해 사용됩니다.
500
+ */
501
+ async getReferencingForeignKeys(db, tableName) {
502
+ const query = `
533
503
  SELECT
534
504
  tc.table_name,
535
505
  tc.constraint_name,
@@ -552,24 +522,23 @@ class PostgreSQLSchemaReaderClass {
552
522
  AND ccu.table_name = ?
553
523
  AND tc.table_schema = 'public'
554
524
  `;
555
- const result = await db.raw(query, [
556
- tableName
557
- ]);
558
- return result.rows.map((row)=>({
559
- tableName: row.table_name,
560
- constraintName: row.constraint_name,
561
- columnName: row.column_name,
562
- referencedTableName: row.referenced_table_name,
563
- referencedColumnName: row.referenced_column_name,
564
- onUpdate: this.mapConstraintAction(row.update_rule),
565
- onDelete: this.mapConstraintAction(row.delete_rule)
566
- }));
567
- }
568
- /**
569
- * vector 컬럼의 dimensions를 조회합니다.
570
- * pg_attribute의 atttypmod에서 차원 수를 추출합니다.
571
- */ async getVectorDimensions(compareDB, tableName) {
572
- const query = `
525
+ const result = await db.raw(query, [tableName]);
526
+ return result.rows.map((row) => ({
527
+ tableName: row.table_name,
528
+ constraintName: row.constraint_name,
529
+ columnName: row.column_name,
530
+ referencedTableName: row.referenced_table_name,
531
+ referencedColumnName: row.referenced_column_name,
532
+ onUpdate: this.mapConstraintAction(row.update_rule),
533
+ onDelete: this.mapConstraintAction(row.delete_rule)
534
+ }));
535
+ }
536
+ /**
537
+ * vector 컬럼의 dimensions를 조회합니다.
538
+ * pg_attribute의 atttypmod에서 차원 수를 추출합니다.
539
+ */
540
+ async getVectorDimensions(compareDB, tableName) {
541
+ const query = `
573
542
  SELECT
574
543
  a.attname as column_name,
575
544
  a.atttypmod as dimensions
@@ -580,125 +549,98 @@ class PostgreSQLSchemaReaderClass {
580
549
  AND t.typname = 'vector'
581
550
  AND a.attnum > 0
582
551
  `;
583
- const result = await compareDB.raw(query, [
584
- tableName
585
- ]);
586
- const dimensions = {};
587
- for (const row of result.rows){
588
- // atttypmod에서 실제 dimensions 값 추출
589
- dimensions[row.column_name] = row.dimensions > 0 ? row.dimensions : 0;
590
- }
591
- return dimensions;
592
- }
593
- /**
594
- * PostgreSQL 컬럼 타입을 분석하여 MigrationColumn 객체로 변환합니다.
595
- */ resolveDBColType(dbColumn) {
596
- const { udt_name: _udt_name, character_maximum_length, precision, numeric_scale } = dbColumn;
597
- const { udt_name, singleOrArray } = (()=>{
598
- if (_udt_name.startsWith("_")) {
599
- return {
600
- udt_name: _udt_name.substring(1),
601
- singleOrArray: "[]"
602
- };
603
- }
604
- return {
605
- udt_name: _udt_name,
606
- singleOrArray: ""
607
- };
608
- })();
609
- // UUID
610
- if (udt_name === "uuid") {
611
- return {
612
- type: `uuid${singleOrArray}`
613
- };
614
- }
615
- // Integer types
616
- if (udt_name === "int4") {
617
- return {
618
- type: `integer${singleOrArray}`
619
- };
620
- }
621
- if (udt_name === "int8") {
622
- return {
623
- type: `bigInteger${singleOrArray}`
624
- };
625
- }
626
- // String types
627
- if (udt_name === "varchar") {
628
- return {
629
- type: `string${singleOrArray}`,
630
- ...character_maximum_length && {
631
- length: character_maximum_length
632
- }
633
- };
634
- }
635
- if (udt_name === "text") {
636
- return {
637
- type: `string${singleOrArray}`
638
- }; // StringProp without length
639
- }
640
- // NumberOrNumeric types
641
- if (udt_name === "numeric") {
642
- return {
643
- type: `numberOrNumeric${singleOrArray}`,
644
- numberType: "numeric",
645
- ...precision !== null && numeric_scale !== null && {
646
- precision: precision,
647
- scale: numeric_scale
648
- }
649
- };
650
- }
651
- if (udt_name === "float4") {
652
- return {
653
- type: `numberOrNumeric${singleOrArray}`,
654
- numberType: "real"
655
- };
656
- }
657
- if (udt_name === "float8") {
658
- return {
659
- type: `numberOrNumeric${singleOrArray}`,
660
- numberType: "double precision"
661
- };
662
- }
663
- // Boolean
664
- if (udt_name === "bool") {
665
- return {
666
- type: `boolean${singleOrArray}`
667
- };
668
- }
669
- // Timestampz types
670
- if (udt_name === "timestamptz") {
671
- return {
672
- type: `date${singleOrArray}`,
673
- ...precision !== null && {
674
- precision: precision
675
- }
676
- }; // DateProp → timestamptz
677
- }
678
- // JSON
679
- if (udt_name === "json" || udt_name === "jsonb") {
680
- return {
681
- type: "json"
682
- };
683
- }
684
- // Vector (pgvector)
685
- if (udt_name === "vector") {
686
- // vector 타입의 차원 수는 column_default나 별도 쿼리로 확인해야 함
687
- // 현재는 기본값 0으로 설정 (실제 dimensions는 getMigrationSetFromDB에서 별도 쿼리로 확인)
688
- return {
689
- type: `vector${singleOrArray}`,
690
- dimensions: 0
691
- };
692
- }
693
- // tsvector (PostgreSQL 전문 검색용 타입)
694
- if (udt_name === "tsvector") {
695
- return {
696
- type: "tsvector"
697
- };
698
- }
699
- throw new Error(`resolve 불가능한 PostgreSQL 컬럼 타입: ${udt_name}`);
700
- }
701
- }
702
- export const PostgreSQLSchemaReader = new PostgreSQLSchemaReaderClass();
552
+ const result = await compareDB.raw(query, [tableName]);
553
+ const dimensions = {};
554
+ for (const row of result.rows) {
555
+ dimensions[row.column_name] = row.dimensions > 0 ? row.dimensions : 0;
556
+ }
557
+ return dimensions;
558
+ }
559
+ /**
560
+ * PostgreSQL 컬럼 타입을 분석하여 MigrationColumn 객체로 변환합니다.
561
+ */
562
+ resolveDBColType(dbColumn) {
563
+ const { udt_name: _udt_name, character_maximum_length, precision, numeric_scale } = dbColumn;
564
+ const { udt_name, singleOrArray } = (() => {
565
+ if (_udt_name.startsWith("_")) {
566
+ return {
567
+ udt_name: _udt_name.substring(1),
568
+ singleOrArray: "[]"
569
+ };
570
+ }
571
+ return {
572
+ udt_name: _udt_name,
573
+ singleOrArray: ""
574
+ };
575
+ })();
576
+ if (udt_name === "uuid") {
577
+ return { type: `uuid${singleOrArray}` };
578
+ }
579
+ if (udt_name === "int4") {
580
+ return { type: `integer${singleOrArray}` };
581
+ }
582
+ if (udt_name === "int8") {
583
+ return { type: `bigInteger${singleOrArray}` };
584
+ }
585
+ if (udt_name === "varchar") {
586
+ return {
587
+ type: `string${singleOrArray}`,
588
+ ...character_maximum_length && { length: character_maximum_length }
589
+ };
590
+ }
591
+ if (udt_name === "text") {
592
+ return { type: `string${singleOrArray}` };
593
+ }
594
+ if (udt_name === "numeric") {
595
+ return {
596
+ type: `numberOrNumeric${singleOrArray}`,
597
+ numberType: "numeric",
598
+ ...precision !== null && numeric_scale !== null && {
599
+ precision,
600
+ scale: numeric_scale
601
+ }
602
+ };
603
+ }
604
+ if (udt_name === "float4") {
605
+ return {
606
+ type: `numberOrNumeric${singleOrArray}`,
607
+ numberType: "real"
608
+ };
609
+ }
610
+ if (udt_name === "float8") {
611
+ return {
612
+ type: `numberOrNumeric${singleOrArray}`,
613
+ numberType: "double precision"
614
+ };
615
+ }
616
+ if (udt_name === "bool") {
617
+ return { type: `boolean${singleOrArray}` };
618
+ }
619
+ if (udt_name === "timestamptz") {
620
+ return {
621
+ type: `date${singleOrArray}`,
622
+ ...precision !== null && { precision }
623
+ };
624
+ }
625
+ if (udt_name === "json" || udt_name === "jsonb") {
626
+ return { type: "json" };
627
+ }
628
+ if (udt_name === "vector") {
629
+ return {
630
+ type: `vector${singleOrArray}`,
631
+ dimensions: 0
632
+ };
633
+ }
634
+ if (udt_name === "tsvector") {
635
+ return { type: "tsvector" };
636
+ }
637
+ throw new Error(`resolve 불가능한 PostgreSQL 컬럼 타입: ${udt_name}`);
638
+ }
639
+ };
640
+ PostgreSQLSchemaReader = new PostgreSQLSchemaReaderClass();
641
+ }));
703
642
 
704
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb24vcG9zdGdyZXNxbC1zY2hlbWEtcmVhZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHR5cGUgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGdyb3VwIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB0eXBlIHtcbiAgTWlncmF0aW9uQ29sdW1uLFxuICBNaWdyYXRpb25Gb3JlaWduLFxuICBNaWdyYXRpb25JbmRleCxcbiAgTWlncmF0aW9uU2V0LFxuICBSZWxhdGlvbk9uLFxufSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcblxuLyoqXG4gKiDtirnsoJUg7YWM7J2067iU7J2YIFBL66W8IOywuOyhsO2VmOuKlCDri6Trpbgg7YWM7J2067iU7J2YIEZLIOygleuztOyeheuLiOuLpC5cbiAqIFBLIO2DgOyehSDrs4Dqsr0g7IucIOq0gOugqCBGSyDsoJzslb3sobDqsbTsnYQg7LKY66as7ZWY6riwIOychO2VtCDsgqzsmqnrkKnri4jri6QuXG4gKi9cbmV4cG9ydCB0eXBlIFJlZmVyZW5jaW5nRm9yZWlnbktleSA9IHtcbiAgLyoqIEZL6rCAIOygleydmOuQnCDthYzsnbTruJTrqoUgKi9cbiAgdGFibGVOYW1lOiBzdHJpbmc7XG4gIC8qKiBGSyDsoJzslb3sobDqsbQg7J2066aEICovXG4gIGNvbnN0cmFpbnROYW1lOiBzdHJpbmc7XG4gIC8qKiBGSyDsu6zrn7zrqoUgKi9cbiAgY29sdW1uTmFtZTogc3RyaW5nO1xuICAvKiog7LC47KGw7ZWY64qUIO2FjOydtOu4lOuqhSAoUEvqsIAg7J6I64qUIO2FjOydtOu4lCkgKi9cbiAgcmVmZXJlbmNlZFRhYmxlTmFtZTogc3RyaW5nO1xuICAvKiog7LC47KGw7ZWY64qUIOy7rOufvOuqhSAo67O07Ya1ICdpZCcpICovXG4gIHJlZmVyZW5jZWRDb2x1bW5OYW1lOiBzdHJpbmc7XG4gIC8qKiBPTiBVUERBVEUg7JWh7IWYICovXG4gIG9uVXBkYXRlOiBSZWxhdGlvbk9uO1xuICAvKiogT04gREVMRVRFIOyVoeyFmCAqL1xuICBvbkRlbGV0ZTogUmVsYXRpb25Pbjtcbn07XG5cbmV4cG9ydCB0eXBlIFBnQ29sdW1uID0ge1xuICBjb2x1bW5fbmFtZTogc3RyaW5nO1xuICBkYXRhX3R5cGU6IHN0cmluZztcbiAgdWR0X25hbWU6IHN0cmluZztcbiAgY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoOiBudW1iZXIgfCBudWxsO1xuICBwcmVjaXNpb246IG51bWJlciB8IG51bGw7XG4gIG51bWVyaWNfc2NhbGU6IG51bWJlciB8IG51bGw7XG4gIGlzX251bGxhYmxlOiBzdHJpbmc7XG4gIGNvbHVtbl9kZWZhdWx0OiBzdHJpbmcgfCBudWxsO1xuICBpc19nZW5lcmF0ZWQ6IHN0cmluZzsgLy8gJ3MnID0gU1RPUkVELCAndicgPSBWSVJUVUFMLCAnJyA9IG5vbmVcbiAgZ2VuZXJhdGlvbl9leHByZXNzaW9uOiBzdHJpbmcgfCBudWxsO1xufTtcblxudHlwZSBQZ0luZGV4ID0ge1xuICBpbmRleF9uYW1lOiBzdHJpbmc7XG4gIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIGlzX3VuaXF1ZTogYm9vbGVhbjtcbiAgaXNfcHJpbWFyeTogYm9vbGVhbjtcbiAgaW5kZXhfdHlwZTogc3RyaW5nO1xuICBudWxsc19maXJzdDogYm9vbGVhbjtcbiAgc29ydF9vcmRlcjogXCJBU0NcIiB8IFwiREVTQ1wiO1xuICBudWxsc19ub3RfZGlzdGluY3Q6IGJvb2xlYW47XG4gIGNvbHVtbl9vcmRlcjogbnVtYmVyO1xuICBpbmRleF9kZWZpbml0aW9uOiBzdHJpbmc7XG59O1xuXG50eXBlIFBnRm9yZWlnbiA9IHtcbiAgY29uc3RyYWludF9uYW1lOiBzdHJpbmc7XG4gIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIGZvcmVpZ25fdGFibGVfbmFtZTogc3RyaW5nO1xuICBmb3JlaWduX2NvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIHVwZGF0ZV9ydWxlOiBzdHJpbmc7XG4gIGRlbGV0ZV9ydWxlOiBzdHJpbmc7XG59O1xuXG50eXBlIFJhd0NhcGFibGVLbmV4ID0gUGljazxLbmV4LCBcInJhd1wiPjtcblxuY2xhc3MgUG9zdGdyZVNRTFNjaGVtYVJlYWRlckNsYXNzIHtcbiAgcHJpdmF0ZSByZWFkb25seSBnZW5lcmljSW5kZXhUeXBlcyA9IG5ldyBTZXQoW1wiYnRyZWVcIiwgXCJoYXNoXCIsIFwiZ2luXCIsIFwiZ2lzdFwiLCBcInBncm9vbmdhXCJdKTtcblxuICAvKipcbiAgICogRELsl5DshJwg7YWM7J2067iUIOygleuztOulvCDsnb3slrTshJwgTWlncmF0aW9uU2V07J2EIOunjOuTpOyWtOyYteuLiOuLpC5cbiAgICogQHBhcmFtIGNvbXBhcmVEQiBLbmV4IOyduOyKpO2EtOyKpFxuICAgKiBAcGFyYW0gdGFibGUg7YWM7J2067iUIOydtOumhFxuICAgKiBAcmV0dXJucyBNaWdyYXRpb25TZXQg6rCd7LK0XG4gICAqL1xuICBhc3luYyBnZXRNaWdyYXRpb25TZXRGcm9tREIoXG4gICAgY29tcGFyZURCOiBSYXdDYXBhYmxlS25leCxcbiAgICB0YWJsZTogc3RyaW5nLFxuICApOiBQcm9taXNlPE1pZ3JhdGlvblNldCB8IG51bGw+IHtcbiAgICBsZXQgZGJDb2x1bW5zOiBQZ0NvbHVtbltdLCBkYkluZGV4ZXM6IFBnSW5kZXhbXSwgZGJGb3JlaWduczogUGdGb3JlaWduW107XG4gICAgdHJ5IHtcbiAgICAgIFtkYkNvbHVtbnMsIGRiSW5kZXhlcywgZGJGb3JlaWduc10gPSBhd2FpdCB0aGlzLnJlYWRUYWJsZShjb21wYXJlREIsIHRhYmxlKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIEVycm9yICYmIGUubWVzc2FnZS5pbmNsdWRlcyhcIlRhYmxlIG5vdCBmb3VuZFwiKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyB2ZWN0b3Ig7Lus65+87J2YIGRpbWVuc2lvbnMg7KGw7ZqMXG4gICAgY29uc3QgdmVjdG9yRGltZW5zaW9ucyA9IGF3YWl0IHRoaXMuZ2V0VmVjdG9yRGltZW5zaW9ucyhjb21wYXJlREIsIHRhYmxlKTtcblxuICAgIGNvbnN0IGNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdID0gZGJDb2x1bW5zLm1hcCgoZGJDb2x1bW4pID0+IHtcbiAgICAgIGNvbnN0IGRiQ29sVHlwZSA9IHRoaXMucmVzb2x2ZURCQ29sVHlwZShkYkNvbHVtbik7XG5cbiAgICAgIC8vIHZlY3RvciDtg4DsnoXsnbgg6rK97JqwIGRpbWVuc2lvbnMg7ISk7KCVXG4gICAgICBpZiAoZGJDb2xUeXBlLnR5cGUgPT09IFwidmVjdG9yXCIpIHtcbiAgICAgICAgZGJDb2xUeXBlLmRpbWVuc2lvbnMgPSB2ZWN0b3JEaW1lbnNpb25zW2RiQ29sdW1uLmNvbHVtbl9uYW1lXSA/PyAwO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBkYkNvbHVtbi5jb2x1bW5fbmFtZSxcbiAgICAgICAgbnVsbGFibGU6IGRiQ29sdW1uLmlzX251bGxhYmxlID09PSBcIllFU1wiLFxuICAgICAgICAuLi5kYkNvbFR5cGUsXG4gICAgICAgIC8vIEdlbmVyYXRlZCBDb2x1bW4g7LKY66asXG4gICAgICAgIC4uLigoKSA9PiB7XG4gICAgICAgICAgaWYgKGRiQ29sdW1uLmlzX2dlbmVyYXRlZCA9PT0gXCJzXCIgfHwgZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInZcIikge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZ2VuZXJhdGVkOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInNcIiA/IFwiU1RPUkVEXCIgOiBcIlZJUlRVQUxcIixcbiAgICAgICAgICAgICAgICBleHByZXNzaW9uOiBkYkNvbHVtbi5nZW5lcmF0aW9uX2V4cHJlc3Npb24gPz8gXCJcIixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfSkoKSxcbiAgICAgICAgLy8gRGVmYXVsdCDqsJIg7LKY66asIChHZW5lcmF0ZWQgQ29sdW1u7J20IOyVhOuLjCDqsr3smrDrp4wpXG4gICAgICAgIC4uLigoKSA9PiB7XG4gICAgICAgICAgLy8gR2VuZXJhdGVkIENvbHVtbuydgCBkZWZhdWx0IOqwkuydtCDsl4bsnYxcbiAgICAgICAgICBpZiAoZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInNcIiB8fCBkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwidlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGRiQ29sdW1uLmNvbHVtbl9kZWZhdWx0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBQb3N0Z3JlU1FMIGRlZmF1bHQg6rCSIOygleumrCAobmV4dHZhbCwgQ1VSUkVOVF9USU1FU1RBTVAg65OxKVxuICAgICAgICAgICAgbGV0IGRlZmF1bHRWYWx1ZSA9IGRiQ29sdW1uLmNvbHVtbl9kZWZhdWx0O1xuXG4gICAgICAgICAgICAvLyBuZXh0dmFsIOygnOqxsCAoU0VSSUFMIO2DgOyehSlcbiAgICAgICAgICAgIGlmIChkZWZhdWx0VmFsdWUuc3RhcnRzV2l0aChcIm5leHR2YWwoXCIpKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8g7YOA7J6FIOy6kOyKpO2MhSDsoJzqsbAgKOyYiDogJzEnOjppbnRlZ2VyIOKGkiAxKVxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlID0gZGVmYXVsdFZhbHVlLnJlcGxhY2UoLzo6W1xcd1xcc10rJC9nLCBcIlwiKTtcblxuICAgICAgICAgICAgLy8g65Sw7Ji07ZGc6rCAIHNpbmdsZSBxdW90ZeyduCDqsr3smrAgZG91YmxlIHF1b3Rl66GcIOuzgO2ZmFxuICAgICAgICAgICAgaWYgKGRlZmF1bHRWYWx1ZS5zdGFydHNXaXRoKFwiJ1wiKSAmJiBkZWZhdWx0VmFsdWUuZW5kc1dpdGgoXCInXCIpKSB7XG4gICAgICAgICAgICAgIGRlZmF1bHRWYWx1ZSA9IGRlZmF1bHRWYWx1ZS5yZXBsYWNlQWxsKFwiJ1wiLCAnXCInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZGVmYXVsdFRvOiBkZWZhdWx0VmFsdWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH0pKCksXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gUFJJTUFSWSBLRVnsmYAgZm9yZWlnbiBrZXnsmqkg7J24642x7IqkIOygnOyZuFxuICAgIGNvbnN0IGRiSW5kZXhlc0dyb3VwID0gZ3JvdXAoXG4gICAgICBkYkluZGV4ZXMuZmlsdGVyKFxuICAgICAgICAoZGJJbmRleCkgPT5cbiAgICAgICAgICAhZGJJbmRleC5pc19wcmltYXJ5ICYmXG4gICAgICAgICAgIWRiRm9yZWlnbnMuZmluZCgoZGJGb3JlaWduKSA9PiBkYkluZGV4LmluZGV4X25hbWUuaW5jbHVkZXMoZGJGb3JlaWduLmNvbnN0cmFpbnRfbmFtZSkpLFxuICAgICAgKSxcbiAgICAgIChkYkluZGV4KSA9PiBkYkluZGV4LmluZGV4X25hbWUsXG4gICAgKTtcblxuICAgIC8vIGluZGV4ZXMg7LKY66asXG4gICAgY29uc3QgaW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSA9IE9iamVjdC5rZXlzKGRiSW5kZXhlc0dyb3VwKS5tYXAoKGluZGV4TmFtZSkgPT4ge1xuICAgICAgY29uc3QgY3VycmVudEluZGV4ZXMgPSBkYkluZGV4ZXNHcm91cFtpbmRleE5hbWVdPy50b1NvcnRlZChcbiAgICAgICAgKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LmNvbHVtbl9vcmRlciAtIHJpZ2h0LmNvbHVtbl9vcmRlcixcbiAgICAgICk7XG4gICAgICBhc3NlcnQoY3VycmVudEluZGV4ZXMpO1xuXG4gICAgICBjb25zdCBmaXJzdEluZGV4ID0gY3VycmVudEluZGV4ZXNbMF07XG4gICAgICBjb25zdCBwYXJzZWRJbmRleERlZmluaXRpb24gPSB0aGlzLnBhcnNlSW5kZXhEZWZpbml0aW9uKGZpcnN0SW5kZXguaW5kZXhfZGVmaW5pdGlvbik7XG4gICAgICBjb25zdCByZXN0b3JlZEluZGV4VHlwZSA9IHRoaXMucmVzdG9yZU1pZ3JhdGlvbkluZGV4VHlwZShcbiAgICAgICAgZmlyc3RJbmRleCxcbiAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmFjY2Vzc01ldGhvZCxcbiAgICAgICk7XG4gICAgICBjb25zdCB1c2luZyA9IHRoaXMucmVzdG9yZUdlbmVyaWNVc2luZyhcbiAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmFjY2Vzc01ldGhvZCA/PyBmaXJzdEluZGV4LmluZGV4X3R5cGUsXG4gICAgICApO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiByZXN0b3JlZEluZGV4VHlwZSxcbiAgICAgICAgbmFtZTogaW5kZXhOYW1lLFxuICAgICAgICBjb2x1bW5zOiBjdXJyZW50SW5kZXhlcy5tYXAoKGlkeCkgPT4gKHtcbiAgICAgICAgICBuYW1lOiBpZHguY29sdW1uX25hbWUsXG4gICAgICAgICAgLi4uKHRoaXMuZXh0cmFjdEluZGV4Q29sdW1uT3BjbGFzcyhcbiAgICAgICAgICAgIHBhcnNlZEluZGV4RGVmaW5pdGlvbi5jb2x1bW5EZWZpbml0aW9uc1tpZHguY29sdW1uX29yZGVyIC0gMV0sXG4gICAgICAgICAgKVxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgb3BjbGFzczogdGhpcy5leHRyYWN0SW5kZXhDb2x1bW5PcGNsYXNzKFxuICAgICAgICAgICAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmNvbHVtbkRlZmluaXRpb25zW2lkeC5jb2x1bW5fb3JkZXIgLSAxXSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAuLi4odXNpbmcgPT09IFwiYnRyZWVcIlxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgc29ydE9yZGVyOiBpZHguc29ydF9vcmRlcixcbiAgICAgICAgICAgICAgICBudWxsc0ZpcnN0OiBpZHgubnVsbHNfZmlyc3QsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KSksXG5cbiAgICAgICAgbnVsbHNOb3REaXN0aW5jdDogZmlyc3RJbmRleC5udWxsc19ub3RfZGlzdGluY3QsXG4gICAgICAgIC4uLih1c2luZyA/IHsgdXNpbmcgfSA6IHt9KSxcbiAgICAgICAgLi4udGhpcy5wYXJzZVZlY3RvckluZGV4T3B0aW9ucyhyZXN0b3JlZEluZGV4VHlwZSwgcGFyc2VkSW5kZXhEZWZpbml0aW9uLndpdGhPcHRpb25zKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBmb3JlaWducyDsspjrpqxcbiAgICBjb25zdCBmb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdID0gZGJGb3JlaWducy5tYXAoKGRiRm9yZWlnbikgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29sdW1uczogW2RiRm9yZWlnbi5jb2x1bW5fbmFtZV0sXG4gICAgICAgIHRvOiBgJHtkYkZvcmVpZ24uZm9yZWlnbl90YWJsZV9uYW1lfS4ke2RiRm9yZWlnbi5mb3JlaWduX2NvbHVtbl9uYW1lfWAsXG4gICAgICAgIG9uVXBkYXRlOiB0aGlzLm1hcENvbnN0cmFpbnRBY3Rpb24oZGJGb3JlaWduLnVwZGF0ZV9ydWxlKSxcbiAgICAgICAgb25EZWxldGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihkYkZvcmVpZ24uZGVsZXRlX3J1bGUpLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0YWJsZSxcbiAgICAgIGNvbHVtbnMsXG4gICAgICBpbmRleGVzLFxuICAgICAgZm9yZWlnbnMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3N0Z3JlU1FM7J2YIGNvbnN0cmFpbnQgYWN0aW9u7J2EIEtuZXgg7ZiV7Iud7Jy866GcIOuzgO2ZmFxuICAgKi9cbiAgcHJpdmF0ZSBtYXBDb25zdHJhaW50QWN0aW9uKGFjdGlvbjogc3RyaW5nKTogUmVsYXRpb25PbiB7XG4gICAgY29uc3QgYWN0aW9uTWFwOiBSZWNvcmQ8c3RyaW5nLCBSZWxhdGlvbk9uPiA9IHtcbiAgICAgIFwiTk8gQUNUSU9OXCI6IFwiTk8gQUNUSU9OXCIsXG4gICAgICBSRVNUUklDVDogXCJSRVNUUklDVFwiLFxuICAgICAgQ0FTQ0FERTogXCJDQVNDQURFXCIsXG4gICAgICBcIlNFVCBOVUxMXCI6IFwiU0VUIE5VTExcIixcbiAgICAgIFwiU0VUIERFRkFVTFRcIjogXCJTRVQgREVGQVVMVFwiLFxuICAgIH07XG4gICAgcmV0dXJuIGFjdGlvbk1hcFthY3Rpb25dID8/IFwiTk8gQUNUSU9OXCI7XG4gIH1cblxuICAvKipcbiAgICog6riw7KG0IO2FjOydtOu4lCDsnb3slrTshJwgY29scywgaW5kZXhlcywgZm9yZWlnbnMg67CY7ZmYXG4gICAqL1xuICBhc3luYyByZWFkVGFibGUoXG4gICAgY29tcGFyZURCOiBSYXdDYXBhYmxlS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTxbUGdDb2x1bW5bXSwgUGdJbmRleFtdLCBQZ0ZvcmVpZ25bXV0+IHtcbiAgICAvLyBDb2x1bW5zIOyhsO2ajCAoR2VuZXJhdGVkIENvbHVtbiDsoJXrs7Qg7Y+s7ZWoKVxuICAgIGNvbnN0IGNvbHVtbnNRdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICBjLmNvbHVtbl9uYW1lLFxuICAgICAgICBjLmRhdGFfdHlwZSxcbiAgICAgICAgYy51ZHRfbmFtZSxcbiAgICAgICAgQ09BTEVTQ0UoXG4gICAgICAgICAgYy5jaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGgsXG4gICAgICAgICAgQ0FTRSBXSEVOIGMuZGF0YV90eXBlID0gJ0FSUkFZJyBBTkQgYS5hdHR0eXBtb2QgPiAwXG4gICAgICAgICAgICBUSEVOIGEuYXR0dHlwbW9kIC0gNFxuICAgICAgICAgICAgRUxTRSBOVUxMXG4gICAgICAgICAgRU5EXG4gICAgICAgICkgQVMgY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoLFxuICAgICAgICBDT0FMRVNDRShjLmRhdGV0aW1lX3ByZWNpc2lvbiwgYy5udW1lcmljX3ByZWNpc2lvbikgQVMgcHJlY2lzaW9uLFxuICAgICAgICBjLm51bWVyaWNfc2NhbGUsXG4gICAgICAgIGMuaXNfbnVsbGFibGUsXG4gICAgICAgIGMuY29sdW1uX2RlZmF1bHQsXG4gICAgICAgIENPQUxFU0NFKGEuYXR0Z2VuZXJhdGVkLCAnJykgYXMgaXNfZ2VuZXJhdGVkLFxuICAgICAgICBjLmdlbmVyYXRpb25fZXhwcmVzc2lvblxuICAgICAgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEuY29sdW1ucyBjXG4gICAgICBMRUZUIEpPSU4gcGdfYXR0cmlidXRlIGEgT04gYS5hdHRuYW1lID0gYy5jb2x1bW5fbmFtZVxuICAgICAgICBBTkQgYS5hdHRyZWxpZCA9IChcbiAgICAgICAgICBTRUxFQ1Qgb2lkIEZST00gcGdfY2xhc3MgV0hFUkUgcmVsbmFtZSA9IGMudGFibGVfbmFtZVxuICAgICAgICAgIEFORCByZWxuYW1lc3BhY2UgPSAoU0VMRUNUIG9pZCBGUk9NIHBnX25hbWVzcGFjZSBXSEVSRSBuc3BuYW1lID0gYy50YWJsZV9zY2hlbWEpXG4gICAgICAgIClcbiAgICAgIFdIRVJFIGMudGFibGVfbmFtZSA9ID9cbiAgICAgICAgQU5EIGMudGFibGVfc2NoZW1hID0gJ3B1YmxpYydcbiAgICAgIE9SREVSIEJZIGMub3JkaW5hbF9wb3NpdGlvblxuICAgIGA7XG4gICAgY29uc3QgY29sdW1ucyA9IChhd2FpdCBjb21wYXJlREIucmF3KGNvbHVtbnNRdWVyeSwgW3RhYmxlTmFtZV0pKS5yb3dzIGFzIFBnQ29sdW1uW107XG4gICAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlIG5vdCBmb3VuZDogJHt0YWJsZU5hbWV9YCk7XG4gICAgfVxuXG4gICAgLy8gSW5kZXhlcyDsobDtmowgKFBHcm9vbmdhIO2RnO2YhOyLnSDsnbjrjbHsiqQg7Y+s7ZWoKVxuICAgIGNvbnN0IGluZGV4ZXNRdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICAgIGkucmVsbmFtZSBBUyBpbmRleF9uYW1lLFxuICAgICAgICAgIENBU0VcbiAgICAgICAgICAgICAgV0hFTiBhbS5hbW5hbWUgPSAncGdyb29uZ2EnIEFORCB1LmF0dG51bSA9IDAgVEhFTlxuICAgICAgICAgICAgICAgICAgcmVnZXhwX3JlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAgICAgcmVnZXhwX3JlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFRSSU0ocGdyb29uZ2FfY29sLmNvbHVtbl9leHByKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJzo6dGV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnZydcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICdbKCldJyxcbiAgICAgICAgICAgICAgICAgICAgICAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAnZydcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgRUxTRSBhLmF0dG5hbWVcbiAgICAgICAgICBFTkQgQVMgY29sdW1uX25hbWUsXG4gICAgICAgICAgaXguaW5kaXN1bmlxdWUgQVMgaXNfdW5pcXVlLFxuICAgICAgICAgIGl4LmluZGlzcHJpbWFyeSBBUyBpc19wcmltYXJ5LFxuICAgICAgICAgIGFtLmFtbmFtZSBBUyBpbmRleF90eXBlLFxuICAgICAgICAgIENPQUxFU0NFKCh1Lm9wdCAmIDIpID0gMiwgRkFMU0UpIEFTIG51bGxzX2ZpcnN0LFxuICAgICAgICAgIENBU0UgXG4gICAgICAgICAgICAgIFdIRU4gKHUub3B0ICYgMSkgPSAxIFRIRU4gJ0RFU0MnXG4gICAgICAgICAgICAgIEVMU0UgJ0FTQydcbiAgICAgICAgICBFTkQgQVMgc29ydF9vcmRlcixcbiAgICAgICAgICBpeC5pbmRudWxsc25vdGRpc3RpbmN0IEFTIG51bGxzX25vdF9kaXN0aW5jdCxcbiAgICAgICAgICB1Lm9yZCBBUyBjb2x1bW5fb3JkZXIsXG4gICAgICAgICAgcGdfZ2V0X2luZGV4ZGVmKGl4LmluZGV4cmVsaWQpIEFTIGluZGV4X2RlZmluaXRpb25cbiAgICAgIEZST00gcGdfY2xhc3MgdFxuICAgICAgSk9JTiBwZ19pbmRleCBpeCBPTiB0Lm9pZCA9IGl4LmluZHJlbGlkXG4gICAgICBKT0lOIHBnX2NsYXNzIGkgT04gaS5vaWQgPSBpeC5pbmRleHJlbGlkXG4gICAgICBKT0lOIHBnX2FtIGFtIE9OIGkucmVsYW0gPSBhbS5vaWRcbiAgICAgIEpPSU4gTEFURVJBTCB1bm5lc3QoaXguaW5ka2V5LCBpeC5pbmRvcHRpb24pXG4gICAgICAgICAgV0lUSCBPUkRJTkFMSVRZIEFTIHUoYXR0bnVtLCBvcHQsIG9yZCkgT04gdHJ1ZVxuICAgICAgTEVGVCBKT0lOIHBnX2F0dHJpYnV0ZSBhIE9OIGEuYXR0cmVsaWQgPSB0Lm9pZCBcbiAgICAgICAgICBBTkQgYS5hdHRudW0gPSB1LmF0dG51bSBcbiAgICAgICAgICBBTkQgdS5hdHRudW0gPiAwXG4gICAgICBMRUZUIEpPSU4gTEFURVJBTCAoXG4gICAgICAgICAgU0VMRUNUIFxuICAgICAgICAgICAgICB1bm5lc3QoXG4gICAgICAgICAgICAgICAgICBDQVNFIFxuICAgICAgICAgICAgICAgICAgICAgIFdIRU4gcGdfZ2V0X2V4cHIoaXguaW5kZXhwcnMsIGl4LmluZHJlbGlkKSB+ICdeQVJSQVlcXFxcWycgVEhFTlxuICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdfdG9fYXJyYXkoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdleHBfcmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZ19nZXRfZXhwcihpeC5pbmRleHBycywgaXguaW5kcmVsaWQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdeQVJSQVlcXFxcWyguKilcXFxcXSQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdcXFxcMSdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLCAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICBFTFNFXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEFSUkFZW3BnX2dldF9leHByKGl4LmluZGV4cHJzLCBpeC5pbmRyZWxpZCldXG4gICAgICAgICAgICAgICAgICBFTkRcbiAgICAgICAgICAgICAgKSBhcyBjb2x1bW5fZXhwclxuICAgICAgKSBwZ3Jvb25nYV9jb2wgT04gYW0uYW1uYW1lID0gJ3Bncm9vbmdhJyBBTkQgdS5hdHRudW0gPSAwXG4gICAgICBXSEVSRSB0LnJlbG5hbWUgPSA/XG4gICAgICAgICAgQU5EICh1LmF0dG51bSA+IDAgT1IgKGFtLmFtbmFtZSA9ICdwZ3Jvb25nYScgQU5EIHUuYXR0bnVtID0gMCkpXG4gICAgICBPUkRFUiBCWSBpLnJlbG5hbWUsIHUub3JkO1xuYDtcbiAgICBjb25zdCBpbmRleGVzID0gKGF3YWl0IGNvbXBhcmVEQi5yYXcoaW5kZXhlc1F1ZXJ5LCBbdGFibGVOYW1lXSkpLnJvd3M7XG5cbiAgICAvLyBGb3JlaWduIEtleXMg7KGw7ZqMXG4gICAgY29uc3QgZm9yZWlnbnNRdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICB0Yy5jb25zdHJhaW50X25hbWUsXG4gICAgICAgIGtjdS5jb2x1bW5fbmFtZSxcbiAgICAgICAgY2N1LnRhYmxlX25hbWUgQVMgZm9yZWlnbl90YWJsZV9uYW1lLFxuICAgICAgICBjY3UuY29sdW1uX25hbWUgQVMgZm9yZWlnbl9jb2x1bW5fbmFtZSxcbiAgICAgICAgcmMudXBkYXRlX3J1bGUsXG4gICAgICAgIHJjLmRlbGV0ZV9ydWxlXG4gICAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZV9jb25zdHJhaW50cyBBUyB0Y1xuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEua2V5X2NvbHVtbl91c2FnZSBBUyBrY3VcbiAgICAgICAgT04gdGMuY29uc3RyYWludF9uYW1lID0ga2N1LmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgdGMudGFibGVfc2NoZW1hID0ga2N1LnRhYmxlX3NjaGVtYVxuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEuY29uc3RyYWludF9jb2x1bW5fdXNhZ2UgQVMgY2N1XG4gICAgICAgIE9OIGNjdS5jb25zdHJhaW50X25hbWUgPSB0Yy5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIGNjdS50YWJsZV9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLnJlZmVyZW50aWFsX2NvbnN0cmFpbnRzIEFTIHJjXG4gICAgICAgIE9OIHJjLmNvbnN0cmFpbnRfbmFtZSA9IHRjLmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgcmMuY29uc3RyYWludF9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIFdIRVJFIHRjLmNvbnN0cmFpbnRfdHlwZSA9ICdGT1JFSUdOIEtFWSdcbiAgICAgICAgQU5EIHRjLnRhYmxlX25hbWUgPSA/XG4gICAgYDtcbiAgICBjb25zdCBmb3JlaWducyA9IChhd2FpdCBjb21wYXJlREIucmF3KGZvcmVpZ25zUXVlcnksIFt0YWJsZU5hbWVdKSkucm93cztcblxuICAgIHJldHVybiBbY29sdW1ucywgaW5kZXhlcywgZm9yZWlnbnNdO1xuICB9XG5cbiAgcHJpdmF0ZSByZXN0b3JlTWlncmF0aW9uSW5kZXhUeXBlKFxuICAgIGluZGV4OiBQaWNrPFBnSW5kZXgsIFwiaXNfdW5pcXVlXCIgfCBcImluZGV4X3R5cGVcIj4sXG4gICAgYWNjZXNzTWV0aG9kPzogc3RyaW5nLFxuICApOiBNaWdyYXRpb25JbmRleFtcInR5cGVcIl0ge1xuICAgIGNvbnN0IHJlc29sdmVkQWNjZXNzTWV0aG9kID0gKGFjY2Vzc01ldGhvZCA/PyBpbmRleC5pbmRleF90eXBlKS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgaWYgKHJlc29sdmVkQWNjZXNzTWV0aG9kID09PSBcImhuc3dcIiB8fCByZXNvbHZlZEFjY2Vzc01ldGhvZCA9PT0gXCJpdmZmbGF0XCIpIHtcbiAgICAgIHJldHVybiByZXNvbHZlZEFjY2Vzc01ldGhvZDtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5kZXguaXNfdW5pcXVlID8gXCJ1bmlxdWVcIiA6IFwiaW5kZXhcIjtcbiAgfVxuXG4gIHByaXZhdGUgcmVzdG9yZUdlbmVyaWNVc2luZyhcbiAgICBhY2Nlc3NNZXRob2Q6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgKTogTWlncmF0aW9uSW5kZXhbXCJ1c2luZ1wiXSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFhY2Nlc3NNZXRob2QpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IGFjY2Vzc01ldGhvZC50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICghdGhpcy5nZW5lcmljSW5kZXhUeXBlcy5oYXMobm9ybWFsaXplZCkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZWQgYXMgTWlncmF0aW9uSW5kZXhbXCJ1c2luZ1wiXTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VWZWN0b3JJbmRleE9wdGlvbnMoXG4gICAgdHlwZTogTWlncmF0aW9uSW5kZXhbXCJ0eXBlXCJdLFxuICAgIHdpdGhPcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICApOiBQaWNrPE1pZ3JhdGlvbkluZGV4LCBcIm1cIiB8IFwiZWZDb25zdHJ1Y3Rpb25cIiB8IFwibGlzdHNcIj4ge1xuICAgIGlmICh0eXBlID09PSBcImhuc3dcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLm0pICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgbTogdGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMubSkgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgICAuLi4odGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMuZWZfY29uc3RydWN0aW9uKSAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyB7IGVmQ29uc3RydWN0aW9uOiB0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5lZl9jb25zdHJ1Y3Rpb24pIH1cbiAgICAgICAgICA6IHt9KSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGUgPT09IFwiaXZmZmxhdFwiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi4odGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMubGlzdHMpICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgbGlzdHM6IHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLmxpc3RzKSB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VJbnRlZ2VyT3B0aW9uKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyc2VkID0gTnVtYmVyLnBhcnNlSW50KHZhbHVlLCAxMCk7XG4gICAgcmV0dXJuIE51bWJlci5pc05hTihwYXJzZWQpID8gdW5kZWZpbmVkIDogcGFyc2VkO1xuICB9XG5cbiAgcHJpdmF0ZSBleHRyYWN0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbHVtbkRlZmluaXRpb246IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFjb2x1bW5EZWZpbml0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHRyaW1tZWQgPSBjb2x1bW5EZWZpbml0aW9uXG4gICAgICAucmVwbGFjZSgvXFxzK05VTExTXFxzKyhGSVJTVHxMQVNUKVxccyokL2ksIFwiXCIpXG4gICAgICAucmVwbGFjZSgvXFxzKyhBU0N8REVTQylcXHMqJC9pLCBcIlwiKVxuICAgICAgLnRyaW0oKTtcbiAgICBjb25zdCB0b2tlbnMgPSB0aGlzLnRva2VuaXplVG9wTGV2ZWwodHJpbW1lZCk7XG5cbiAgICBpZiAodG9rZW5zLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKHRva2Vuc1t0b2tlbnMubGVuZ3RoIC0gMl0/LnRvVXBwZXJDYXNlKCkgPT09IFwiQ09MTEFURVwiKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0b2tlbnMuYXQoLTEpO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUluZGV4RGVmaW5pdGlvbihpbmRleERlZmluaXRpb246IHN0cmluZyk6IHtcbiAgICBhY2Nlc3NNZXRob2Q/OiBzdHJpbmc7XG4gICAgY29sdW1uRGVmaW5pdGlvbnM6IHN0cmluZ1tdO1xuICAgIHdpdGhPcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICB9IHtcbiAgICBjb25zdCBhY2Nlc3NNZXRob2QgPSBpbmRleERlZmluaXRpb24ubWF0Y2goL1xcYlVTSU5HXFxzKyhbYS16X11bXFx3XSopL2kpPy5bMV0/LnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgdXNpbmdNYXRjaEluZGV4ID0gaW5kZXhEZWZpbml0aW9uLnNlYXJjaCgvXFxiVVNJTkdcXGIvaSk7XG4gICAgY29uc3QgY29sdW1uc1N0YXJ0ID0gdXNpbmdNYXRjaEluZGV4ID49IDAgPyBpbmRleERlZmluaXRpb24uaW5kZXhPZihcIihcIiwgdXNpbmdNYXRjaEluZGV4KSA6IC0xO1xuICAgIGNvbnN0IGNvbHVtbnNFbmQgPVxuICAgICAgY29sdW1uc1N0YXJ0ID49IDAgPyB0aGlzLmZpbmRNYXRjaGluZ1BhcmVudGhlc2lzKGluZGV4RGVmaW5pdGlvbiwgY29sdW1uc1N0YXJ0KSA6IC0xO1xuICAgIGNvbnN0IGNvbHVtbkRlZmluaXRpb25zID1cbiAgICAgIGNvbHVtbnNTdGFydCA+PSAwICYmIGNvbHVtbnNFbmQgPiBjb2x1bW5zU3RhcnRcbiAgICAgICAgPyB0aGlzLnNwbGl0VG9wTGV2ZWwoaW5kZXhEZWZpbml0aW9uLnNsaWNlKGNvbHVtbnNTdGFydCArIDEsIGNvbHVtbnNFbmQpLCBcIixcIilcbiAgICAgICAgOiBbXTtcblxuICAgIGNvbnN0IHdpdGhNYXRjaCA9IC9cXGJXSVRIXFxzKlxcKC9pLmV4ZWMoaW5kZXhEZWZpbml0aW9uKTtcbiAgICBjb25zdCB3aXRoU3RhcnQgPSB3aXRoTWF0Y2ggPyBpbmRleERlZmluaXRpb24uaW5kZXhPZihcIihcIiwgd2l0aE1hdGNoLmluZGV4KSA6IC0xO1xuICAgIGNvbnN0IHdpdGhFbmQgPSB3aXRoU3RhcnQgPj0gMCA/IHRoaXMuZmluZE1hdGNoaW5nUGFyZW50aGVzaXMoaW5kZXhEZWZpbml0aW9uLCB3aXRoU3RhcnQpIDogLTE7XG4gICAgY29uc3Qgd2l0aE9wdGlvbnMgPVxuICAgICAgd2l0aFN0YXJ0ID49IDAgJiYgd2l0aEVuZCA+IHdpdGhTdGFydFxuICAgICAgICA/IHRoaXMucGFyc2VJbmRleE9wdGlvbkVudHJpZXMoaW5kZXhEZWZpbml0aW9uLnNsaWNlKHdpdGhTdGFydCArIDEsIHdpdGhFbmQpKVxuICAgICAgICA6IHt9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY2Vzc01ldGhvZCxcbiAgICAgIGNvbHVtbkRlZmluaXRpb25zLFxuICAgICAgd2l0aE9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VJbmRleE9wdGlvbkVudHJpZXMob3B0aW9uU291cmNlOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5zcGxpdFRvcExldmVsKG9wdGlvblNvdXJjZSwgXCIsXCIpLnJlZHVjZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PigocmVzdWx0LCBlbnRyeSkgPT4ge1xuICAgICAgY29uc3QgbWF0Y2hlZCA9IGVudHJ5LnRyaW0oKS5tYXRjaCgvXihbYS16X11bXFx3XSopXFxzKj1cXHMqKC4rKSQvaSk7XG4gICAgICBpZiAoIW1hdGNoZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgWywga2V5LCByYXdWYWx1ZV0gPSBtYXRjaGVkO1xuICAgICAgcmVzdWx0W2tleS50b0xvd2VyQ2FzZSgpXSA9IHJhd1ZhbHVlLnRyaW0oKS5yZXBsYWNlKC9eWydcIl18WydcIl0kL2csIFwiXCIpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LCB7fSk7XG4gIH1cblxuICBwcml2YXRlIHNwbGl0VG9wTGV2ZWwoc291cmNlOiBzdHJpbmcsIGRlbGltaXRlcjogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGl0ZW1zOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IHBhcmVuRGVwdGggPSAwO1xuICAgIGxldCBicmFja2V0RGVwdGggPSAwO1xuICAgIGxldCBpblNpbmdsZVF1b3RlID0gZmFsc2U7XG4gICAgbGV0IGluRG91YmxlUXVvdGUgPSBmYWxzZTtcblxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBzb3VyY2UubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICBjb25zdCBjaGFyID0gc291cmNlW2luZGV4XTtcbiAgICAgIGNvbnN0IG5leHRDaGFyID0gc291cmNlW2luZGV4ICsgMV07XG5cbiAgICAgIGlmIChjaGFyID09PSBcIidcIiAmJiAhaW5Eb3VibGVRdW90ZSkge1xuICAgICAgICBpZiAoaW5TaW5nbGVRdW90ZSAmJiBuZXh0Q2hhciA9PT0gXCInXCIpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluU2luZ2xlUXVvdGUgPSAhaW5TaW5nbGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSAnXCInICYmICFpblNpbmdsZVF1b3RlKSB7XG4gICAgICAgIGlmIChpbkRvdWJsZVF1b3RlICYmIG5leHRDaGFyID09PSAnXCInKSB7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpbkRvdWJsZVF1b3RlID0gIWluRG91YmxlUXVvdGU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5TaW5nbGVRdW90ZSB8fCBpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gXCIoXCIpIHtcbiAgICAgICAgcGFyZW5EZXB0aCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGFyID09PSBcIilcIikge1xuICAgICAgICBwYXJlbkRlcHRoIC09IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09IFwiW1wiKSB7XG4gICAgICAgIGJyYWNrZXREZXB0aCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGFyID09PSBcIl1cIikge1xuICAgICAgICBicmFja2V0RGVwdGggLT0gMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSBkZWxpbWl0ZXIgJiYgcGFyZW5EZXB0aCA9PT0gMCAmJiBicmFja2V0RGVwdGggPT09IDApIHtcbiAgICAgICAgaXRlbXMucHVzaChzb3VyY2Uuc2xpY2Uoc3RhcnQsIGluZGV4KS50cmltKCkpO1xuICAgICAgICBzdGFydCA9IGluZGV4ICsgMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB0YWlsID0gc291cmNlLnNsaWNlKHN0YXJ0KS50cmltKCk7XG4gICAgaWYgKHRhaWwubGVuZ3RoID4gMCkge1xuICAgICAgaXRlbXMucHVzaCh0YWlsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cblxuICBwcml2YXRlIHRva2VuaXplVG9wTGV2ZWwoc291cmNlOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgdG9rZW5zOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBzdGFydCA9IC0xO1xuICAgIGxldCBwYXJlbkRlcHRoID0gMDtcbiAgICBsZXQgYnJhY2tldERlcHRoID0gMDtcbiAgICBsZXQgaW5TaW5nbGVRdW90ZSA9IGZhbHNlO1xuICAgIGxldCBpbkRvdWJsZVF1b3RlID0gZmFsc2U7XG5cbiAgICBjb25zdCBwdXNoVG9rZW4gPSAoZW5kSW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRva2VuID0gc291cmNlLnNsaWNlKHN0YXJ0LCBlbmRJbmRleCkudHJpbSgpO1xuICAgICAgaWYgKHRva2VuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdG9rZW5zLnB1c2godG9rZW4pO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSAtMTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgY29uc3QgbmV4dENoYXIgPSBzb3VyY2VbaW5kZXggKyAxXTtcblxuICAgICAgaWYgKGNoYXIgPT09IFwiJ1wiICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgICBzdGFydCA9IGluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChpblNpbmdsZVF1b3RlICYmIG5leHRDaGFyID09PSBcIidcIikge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5TaW5nbGVRdW90ZSA9ICFpblNpbmdsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09ICdcIicgJiYgIWluU2luZ2xlUXVvdGUpIHtcbiAgICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluRG91YmxlUXVvdGUgJiYgbmV4dENoYXIgPT09ICdcIicpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluRG91YmxlUXVvdGUgPSAhaW5Eb3VibGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghaW5TaW5nbGVRdW90ZSAmJiAhaW5Eb3VibGVRdW90ZSkge1xuICAgICAgICBpZiAoY2hhciA9PT0gXCIoXCIpIHtcbiAgICAgICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgICAgICBzdGFydCA9IGluZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgICBwYXJlbkRlcHRoICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09IFwiKVwiKSB7XG4gICAgICAgICAgcGFyZW5EZXB0aCAtPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFyID09PSBcIltcIikge1xuICAgICAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyYWNrZXREZXB0aCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFyID09PSBcIl1cIikge1xuICAgICAgICAgIGJyYWNrZXREZXB0aCAtPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKC9cXHMvLnRlc3QoY2hhcikgJiYgcGFyZW5EZXB0aCA9PT0gMCAmJiBicmFja2V0RGVwdGggPT09IDApIHtcbiAgICAgICAgICBwdXNoVG9rZW4oaW5kZXgpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgc3RhcnQgPSBpbmRleDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwdXNoVG9rZW4oc291cmNlLmxlbmd0aCk7XG4gICAgcmV0dXJuIHRva2VucztcbiAgfVxuXG4gIHByaXZhdGUgZmluZE1hdGNoaW5nUGFyZW50aGVzaXMoc291cmNlOiBzdHJpbmcsIG9wZW5JbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgZGVwdGggPSAwO1xuICAgIGxldCBpblNpbmdsZVF1b3RlID0gZmFsc2U7XG4gICAgbGV0IGluRG91YmxlUXVvdGUgPSBmYWxzZTtcblxuICAgIGZvciAobGV0IGluZGV4ID0gb3BlbkluZGV4OyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgY29uc3QgbmV4dENoYXIgPSBzb3VyY2VbaW5kZXggKyAxXTtcblxuICAgICAgaWYgKGNoYXIgPT09IFwiJ1wiICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChpblNpbmdsZVF1b3RlICYmIG5leHRDaGFyID09PSBcIidcIikge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5TaW5nbGVRdW90ZSA9ICFpblNpbmdsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09ICdcIicgJiYgIWluU2luZ2xlUXVvdGUpIHtcbiAgICAgICAgaWYgKGluRG91YmxlUXVvdGUgJiYgbmV4dENoYXIgPT09ICdcIicpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluRG91YmxlUXVvdGUgPSAhaW5Eb3VibGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpblNpbmdsZVF1b3RlIHx8IGluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSBcIihcIikge1xuICAgICAgICBkZXB0aCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09IFwiKVwiKSB7XG4gICAgICAgIGRlcHRoIC09IDE7XG4gICAgICAgIGlmIChkZXB0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiDtirnsoJUg7YWM7J2067iU7J2YIFBL66W8IOywuOyhsO2VmOuKlCDri6Trpbgg7YWM7J2067iU7J2YIEZLIOuqqeuhneydhCDsobDtmoztlanri4jri6QuXG4gICAqIFBLIO2DgOyehSDrs4Dqsr0g7IucIOq0gOugqCBGSyDsoJzslb3sobDqsbTsnYQg7IKt7KCcL+uzteq1rO2VmOq4sCDsnITtlbQg7IKs7Jqp65Cp64uI64ukLlxuICAgKi9cbiAgYXN5bmMgZ2V0UmVmZXJlbmNpbmdGb3JlaWduS2V5cyhkYjogS25leCwgdGFibGVOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFJlZmVyZW5jaW5nRm9yZWlnbktleVtdPiB7XG4gICAgY29uc3QgcXVlcnkgPSBgXG4gICAgICBTRUxFQ1RcbiAgICAgICAgdGMudGFibGVfbmFtZSxcbiAgICAgICAgdGMuY29uc3RyYWludF9uYW1lLFxuICAgICAgICBrY3UuY29sdW1uX25hbWUsXG4gICAgICAgIGNjdS50YWJsZV9uYW1lIEFTIHJlZmVyZW5jZWRfdGFibGVfbmFtZSxcbiAgICAgICAgY2N1LmNvbHVtbl9uYW1lIEFTIHJlZmVyZW5jZWRfY29sdW1uX25hbWUsXG4gICAgICAgIHJjLnVwZGF0ZV9ydWxlLFxuICAgICAgICByYy5kZWxldGVfcnVsZVxuICAgICAgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVfY29uc3RyYWludHMgQVMgdGNcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLmtleV9jb2x1bW5fdXNhZ2UgQVMga2N1XG4gICAgICAgIE9OIHRjLmNvbnN0cmFpbnRfbmFtZSA9IGtjdS5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIHRjLnRhYmxlX3NjaGVtYSA9IGtjdS50YWJsZV9zY2hlbWFcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLmNvbnN0cmFpbnRfY29sdW1uX3VzYWdlIEFTIGNjdVxuICAgICAgICBPTiBjY3UuY29uc3RyYWludF9uYW1lID0gdGMuY29uc3RyYWludF9uYW1lXG4gICAgICAgIEFORCBjY3UudGFibGVfc2NoZW1hID0gdGMudGFibGVfc2NoZW1hXG4gICAgICBKT0lOIGluZm9ybWF0aW9uX3NjaGVtYS5yZWZlcmVudGlhbF9jb25zdHJhaW50cyBBUyByY1xuICAgICAgICBPTiByYy5jb25zdHJhaW50X25hbWUgPSB0Yy5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIHJjLmNvbnN0cmFpbnRfc2NoZW1hID0gdGMudGFibGVfc2NoZW1hXG4gICAgICBXSEVSRSB0Yy5jb25zdHJhaW50X3R5cGUgPSAnRk9SRUlHTiBLRVknXG4gICAgICAgIEFORCBjY3UudGFibGVfbmFtZSA9ID9cbiAgICAgICAgQU5EIHRjLnRhYmxlX3NjaGVtYSA9ICdwdWJsaWMnXG4gICAgYDtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRiLnJhdyhxdWVyeSwgW3RhYmxlTmFtZV0pO1xuICAgIHJldHVybiByZXN1bHQucm93cy5tYXAoXG4gICAgICAocm93OiB7XG4gICAgICAgIHRhYmxlX25hbWU6IHN0cmluZztcbiAgICAgICAgY29uc3RyYWludF9uYW1lOiBzdHJpbmc7XG4gICAgICAgIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gICAgICAgIHJlZmVyZW5jZWRfdGFibGVfbmFtZTogc3RyaW5nO1xuICAgICAgICByZWZlcmVuY2VkX2NvbHVtbl9uYW1lOiBzdHJpbmc7XG4gICAgICAgIHVwZGF0ZV9ydWxlOiBzdHJpbmc7XG4gICAgICAgIGRlbGV0ZV9ydWxlOiBzdHJpbmc7XG4gICAgICB9KSA9PiAoe1xuICAgICAgICB0YWJsZU5hbWU6IHJvdy50YWJsZV9uYW1lLFxuICAgICAgICBjb25zdHJhaW50TmFtZTogcm93LmNvbnN0cmFpbnRfbmFtZSxcbiAgICAgICAgY29sdW1uTmFtZTogcm93LmNvbHVtbl9uYW1lLFxuICAgICAgICByZWZlcmVuY2VkVGFibGVOYW1lOiByb3cucmVmZXJlbmNlZF90YWJsZV9uYW1lLFxuICAgICAgICByZWZlcmVuY2VkQ29sdW1uTmFtZTogcm93LnJlZmVyZW5jZWRfY29sdW1uX25hbWUsXG4gICAgICAgIG9uVXBkYXRlOiB0aGlzLm1hcENvbnN0cmFpbnRBY3Rpb24ocm93LnVwZGF0ZV9ydWxlKSxcbiAgICAgICAgb25EZWxldGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihyb3cuZGVsZXRlX3J1bGUpLFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiB2ZWN0b3Ig7Lus65+87J2YIGRpbWVuc2lvbnPrpbwg7KGw7ZqM7ZWp64uI64ukLlxuICAgKiBwZ19hdHRyaWJ1dGXsnZggYXR0dHlwbW9k7JeQ7IScIOywqOybkCDsiJjrpbwg7LaU7Lac7ZWp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRWZWN0b3JEaW1lbnNpb25zKFxuICAgIGNvbXBhcmVEQjogUmF3Q2FwYWJsZUtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgbnVtYmVyPj4ge1xuICAgIGNvbnN0IHF1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgIGEuYXR0bmFtZSBhcyBjb2x1bW5fbmFtZSxcbiAgICAgICAgYS5hdHR0eXBtb2QgYXMgZGltZW5zaW9uc1xuICAgICAgRlJPTSBwZ19hdHRyaWJ1dGUgYVxuICAgICAgSk9JTiBwZ19jbGFzcyBjIE9OIGEuYXR0cmVsaWQgPSBjLm9pZFxuICAgICAgSk9JTiBwZ190eXBlIHQgT04gYS5hdHR0eXBpZCA9IHQub2lkXG4gICAgICBXSEVSRSBjLnJlbG5hbWUgPSA/XG4gICAgICAgIEFORCB0LnR5cG5hbWUgPSAndmVjdG9yJ1xuICAgICAgICBBTkQgYS5hdHRudW0gPiAwXG4gICAgYDtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb21wYXJlREIucmF3KHF1ZXJ5LCBbdGFibGVOYW1lXSk7XG4gICAgY29uc3QgZGltZW5zaW9uczogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgIGZvciAoY29uc3Qgcm93IG9mIHJlc3VsdC5yb3dzKSB7XG4gICAgICAvLyBhdHR0eXBtb2Tsl5DshJwg7Iuk7KCcIGRpbWVuc2lvbnMg6rCSIOy2lOy2nFxuICAgICAgZGltZW5zaW9uc1tyb3cuY29sdW1uX25hbWVdID0gcm93LmRpbWVuc2lvbnMgPiAwID8gcm93LmRpbWVuc2lvbnMgOiAwO1xuICAgIH1cbiAgICByZXR1cm4gZGltZW5zaW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3N0Z3JlU1FMIOy7rOufvCDtg4DsnoXsnYQg67aE7ISd7ZWY7JesIE1pZ3JhdGlvbkNvbHVtbiDqsJ3ssrTroZwg67OA7ZmY7ZWp64uI64ukLlxuICAgKi9cbiAgcmVzb2x2ZURCQ29sVHlwZShcbiAgICBkYkNvbHVtbjogUGdDb2x1bW4sXG4gICk6IFBpY2s8XG4gICAgTWlncmF0aW9uQ29sdW1uLFxuICAgIFwidHlwZVwiIHwgXCJsZW5ndGhcIiB8IFwicHJlY2lzaW9uXCIgfCBcInNjYWxlXCIgfCBcIm51bWJlclR5cGVcIiB8IFwiZGltZW5zaW9uc1wiXG4gID4ge1xuICAgIGNvbnN0IHsgdWR0X25hbWU6IF91ZHRfbmFtZSwgY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoLCBwcmVjaXNpb24sIG51bWVyaWNfc2NhbGUgfSA9IGRiQ29sdW1uO1xuXG4gICAgY29uc3QgeyB1ZHRfbmFtZSwgc2luZ2xlT3JBcnJheSB9ID0gKCgpID0+IHtcbiAgICAgIGlmIChfdWR0X25hbWUuc3RhcnRzV2l0aChcIl9cIikpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB1ZHRfbmFtZTogX3VkdF9uYW1lLnN1YnN0cmluZygxKSxcbiAgICAgICAgICBzaW5nbGVPckFycmF5OiBcIltdXCIgYXMgY29uc3QsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB1ZHRfbmFtZTogX3VkdF9uYW1lLFxuICAgICAgICBzaW5nbGVPckFycmF5OiBcIlwiIGFzIGNvbnN0LFxuICAgICAgfTtcbiAgICB9KSgpO1xuXG4gICAgLy8gVVVJRFxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ1dWlkXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGB1dWlkJHtzaW5nbGVPckFycmF5fWAgfTtcbiAgICB9XG5cbiAgICAvLyBJbnRlZ2VyIHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcImludDRcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYGludGVnZXIke3NpbmdsZU9yQXJyYXl9YCB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwiaW50OFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgYmlnSW50ZWdlciR7c2luZ2xlT3JBcnJheX1gIH07XG4gICAgfVxuXG4gICAgLy8gU3RyaW5nIHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInZhcmNoYXJcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogYHN0cmluZyR7c2luZ2xlT3JBcnJheX1gLFxuICAgICAgICAuLi4oY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoICYmIHtcbiAgICAgICAgICBsZW5ndGg6IGNoYXJhY3Rlcl9tYXhpbXVtX2xlbmd0aCxcbiAgICAgICAgfSksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwidGV4dFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgc3RyaW5nJHtzaW5nbGVPckFycmF5fWAgfTsgLy8gU3RyaW5nUHJvcCB3aXRob3V0IGxlbmd0aFxuICAgIH1cblxuICAgIC8vIE51bWJlck9yTnVtZXJpYyB0eXBlc1xuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJudW1lcmljXCIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IGBudW1iZXJPck51bWVyaWMke3NpbmdsZU9yQXJyYXl9YCxcbiAgICAgICAgbnVtYmVyVHlwZTogXCJudW1lcmljXCIsXG4gICAgICAgIC4uLihwcmVjaXNpb24gIT09IG51bGwgJiZcbiAgICAgICAgICBudW1lcmljX3NjYWxlICE9PSBudWxsICYmIHtcbiAgICAgICAgICAgIHByZWNpc2lvbjogcHJlY2lzaW9uLFxuICAgICAgICAgICAgc2NhbGU6IG51bWVyaWNfc2NhbGUsXG4gICAgICAgICAgfSksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwiZmxvYXQ0XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBudW1iZXJPck51bWVyaWMke3NpbmdsZU9yQXJyYXl9YCwgbnVtYmVyVHlwZTogXCJyZWFsXCIgfTtcbiAgICB9XG4gICAgaWYgKHVkdF9uYW1lID09PSBcImZsb2F0OFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgbnVtYmVyT3JOdW1lcmljJHtzaW5nbGVPckFycmF5fWAsIG51bWJlclR5cGU6IFwiZG91YmxlIHByZWNpc2lvblwiIH07XG4gICAgfVxuXG4gICAgLy8gQm9vbGVhblxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJib29sXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBib29sZWFuJHtzaW5nbGVPckFycmF5fWAgfTtcbiAgICB9XG5cbiAgICAvLyBUaW1lc3RhbXB6IHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInRpbWVzdGFtcHR6XCIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IGBkYXRlJHtzaW5nbGVPckFycmF5fWAsXG4gICAgICAgIC4uLihwcmVjaXNpb24gIT09IG51bGwgJiYge1xuICAgICAgICAgIHByZWNpc2lvbjogcHJlY2lzaW9uLFxuICAgICAgICB9KSxcbiAgICAgIH07IC8vIERhdGVQcm9wIOKGkiB0aW1lc3RhbXB0elxuICAgIH1cblxuICAgIC8vIEpTT05cbiAgICBpZiAodWR0X25hbWUgPT09IFwianNvblwiIHx8IHVkdF9uYW1lID09PSBcImpzb25iXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwianNvblwiIH07XG4gICAgfVxuXG4gICAgLy8gVmVjdG9yIChwZ3ZlY3RvcilcbiAgICBpZiAodWR0X25hbWUgPT09IFwidmVjdG9yXCIpIHtcbiAgICAgIC8vIHZlY3RvciDtg4DsnoXsnZgg7LCo7JuQIOyImOuKlCBjb2x1bW5fZGVmYXVsdOuCmCDrs4Trj4Qg7L+866as66GcIO2ZleyduO2VtOyVvCDtlahcbiAgICAgIC8vIO2YhOyerOuKlCDquLDrs7jqsJIgMOycvOuhnCDshKTsoJUgKOyLpOygnCBkaW1lbnNpb25z64qUIGdldE1pZ3JhdGlvblNldEZyb21EQuyXkOyEnCDrs4Trj4Qg7L+866as66GcIO2ZleyduClcbiAgICAgIHJldHVybiB7IHR5cGU6IGB2ZWN0b3Ike3NpbmdsZU9yQXJyYXl9YCwgZGltZW5zaW9uczogMCB9O1xuICAgIH1cblxuICAgIC8vIHRzdmVjdG9yIChQb3N0Z3JlU1FMIOyghOusuCDqsoDsg4nsmqkg7YOA7J6FKVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ0c3ZlY3RvclwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBcInRzdmVjdG9yXCIgfTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJlc29sdmUg67aI6rCA64ql7ZWcIFBvc3RncmVTUUwg7Lus65+8IO2DgOyehTogJHt1ZHRfbmFtZX1gKTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgUG9zdGdyZVNRTFNjaGVtYVJlYWRlciA9IG5ldyBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyQ2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJhc3NlcnQiLCJncm91cCIsIlBvc3RncmVTUUxTY2hlbWFSZWFkZXJDbGFzcyIsImdlbmVyaWNJbmRleFR5cGVzIiwiU2V0IiwiZ2V0TWlncmF0aW9uU2V0RnJvbURCIiwiY29tcGFyZURCIiwidGFibGUiLCJkYkNvbHVtbnMiLCJkYkluZGV4ZXMiLCJkYkZvcmVpZ25zIiwicmVhZFRhYmxlIiwiZSIsIkVycm9yIiwibWVzc2FnZSIsImluY2x1ZGVzIiwiY29uc29sZSIsImVycm9yIiwidmVjdG9yRGltZW5zaW9ucyIsImdldFZlY3RvckRpbWVuc2lvbnMiLCJjb2x1bW5zIiwibWFwIiwiZGJDb2x1bW4iLCJkYkNvbFR5cGUiLCJyZXNvbHZlREJDb2xUeXBlIiwidHlwZSIsImRpbWVuc2lvbnMiLCJjb2x1bW5fbmFtZSIsIm5hbWUiLCJudWxsYWJsZSIsImlzX251bGxhYmxlIiwiaXNfZ2VuZXJhdGVkIiwiZ2VuZXJhdGVkIiwiZXhwcmVzc2lvbiIsImdlbmVyYXRpb25fZXhwcmVzc2lvbiIsImNvbHVtbl9kZWZhdWx0IiwiZGVmYXVsdFZhbHVlIiwic3RhcnRzV2l0aCIsInJlcGxhY2UiLCJlbmRzV2l0aCIsInJlcGxhY2VBbGwiLCJkZWZhdWx0VG8iLCJkYkluZGV4ZXNHcm91cCIsImZpbHRlciIsImRiSW5kZXgiLCJpc19wcmltYXJ5IiwiZmluZCIsImRiRm9yZWlnbiIsImluZGV4X25hbWUiLCJjb25zdHJhaW50X25hbWUiLCJpbmRleGVzIiwiT2JqZWN0Iiwia2V5cyIsImluZGV4TmFtZSIsImN1cnJlbnRJbmRleGVzIiwidG9Tb3J0ZWQiLCJsZWZ0IiwicmlnaHQiLCJjb2x1bW5fb3JkZXIiLCJmaXJzdEluZGV4IiwicGFyc2VkSW5kZXhEZWZpbml0aW9uIiwicGFyc2VJbmRleERlZmluaXRpb24iLCJpbmRleF9kZWZpbml0aW9uIiwicmVzdG9yZWRJbmRleFR5cGUiLCJyZXN0b3JlTWlncmF0aW9uSW5kZXhUeXBlIiwiYWNjZXNzTWV0aG9kIiwidXNpbmciLCJyZXN0b3JlR2VuZXJpY1VzaW5nIiwiaW5kZXhfdHlwZSIsImlkeCIsImV4dHJhY3RJbmRleENvbHVtbk9wY2xhc3MiLCJjb2x1bW5EZWZpbml0aW9ucyIsIm9wY2xhc3MiLCJzb3J0T3JkZXIiLCJzb3J0X29yZGVyIiwibnVsbHNGaXJzdCIsIm51bGxzX2ZpcnN0IiwibnVsbHNOb3REaXN0aW5jdCIsIm51bGxzX25vdF9kaXN0aW5jdCIsInBhcnNlVmVjdG9ySW5kZXhPcHRpb25zIiwid2l0aE9wdGlvbnMiLCJmb3JlaWducyIsInRvIiwiZm9yZWlnbl90YWJsZV9uYW1lIiwiZm9yZWlnbl9jb2x1bW5fbmFtZSIsIm9uVXBkYXRlIiwibWFwQ29uc3RyYWludEFjdGlvbiIsInVwZGF0ZV9ydWxlIiwib25EZWxldGUiLCJkZWxldGVfcnVsZSIsImFjdGlvbiIsImFjdGlvbk1hcCIsIlJFU1RSSUNUIiwiQ0FTQ0FERSIsInRhYmxlTmFtZSIsImNvbHVtbnNRdWVyeSIsInJhdyIsInJvd3MiLCJsZW5ndGgiLCJpbmRleGVzUXVlcnkiLCJmb3JlaWduc1F1ZXJ5IiwiaW5kZXgiLCJyZXNvbHZlZEFjY2Vzc01ldGhvZCIsInRvTG93ZXJDYXNlIiwiaXNfdW5pcXVlIiwidW5kZWZpbmVkIiwibm9ybWFsaXplZCIsImhhcyIsInBhcnNlSW50ZWdlck9wdGlvbiIsIm0iLCJlZl9jb25zdHJ1Y3Rpb24iLCJlZkNvbnN0cnVjdGlvbiIsImxpc3RzIiwidmFsdWUiLCJwYXJzZWQiLCJOdW1iZXIiLCJwYXJzZUludCIsImlzTmFOIiwiY29sdW1uRGVmaW5pdGlvbiIsInRyaW1tZWQiLCJ0cmltIiwidG9rZW5zIiwidG9rZW5pemVUb3BMZXZlbCIsInRvVXBwZXJDYXNlIiwiYXQiLCJpbmRleERlZmluaXRpb24iLCJtYXRjaCIsInVzaW5nTWF0Y2hJbmRleCIsInNlYXJjaCIsImNvbHVtbnNTdGFydCIsImluZGV4T2YiLCJjb2x1bW5zRW5kIiwiZmluZE1hdGNoaW5nUGFyZW50aGVzaXMiLCJzcGxpdFRvcExldmVsIiwic2xpY2UiLCJ3aXRoTWF0Y2giLCJleGVjIiwid2l0aFN0YXJ0Iiwid2l0aEVuZCIsInBhcnNlSW5kZXhPcHRpb25FbnRyaWVzIiwib3B0aW9uU291cmNlIiwicmVkdWNlIiwicmVzdWx0IiwiZW50cnkiLCJtYXRjaGVkIiwia2V5IiwicmF3VmFsdWUiLCJzb3VyY2UiLCJkZWxpbWl0ZXIiLCJpdGVtcyIsInN0YXJ0IiwicGFyZW5EZXB0aCIsImJyYWNrZXREZXB0aCIsImluU2luZ2xlUXVvdGUiLCJpbkRvdWJsZVF1b3RlIiwiY2hhciIsIm5leHRDaGFyIiwicHVzaCIsInRhaWwiLCJwdXNoVG9rZW4iLCJlbmRJbmRleCIsInRva2VuIiwidGVzdCIsIm9wZW5JbmRleCIsImRlcHRoIiwiZ2V0UmVmZXJlbmNpbmdGb3JlaWduS2V5cyIsImRiIiwicXVlcnkiLCJyb3ciLCJ0YWJsZV9uYW1lIiwiY29uc3RyYWludE5hbWUiLCJjb2x1bW5OYW1lIiwicmVmZXJlbmNlZFRhYmxlTmFtZSIsInJlZmVyZW5jZWRfdGFibGVfbmFtZSIsInJlZmVyZW5jZWRDb2x1bW5OYW1lIiwicmVmZXJlbmNlZF9jb2x1bW5fbmFtZSIsInVkdF9uYW1lIiwiX3VkdF9uYW1lIiwiY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoIiwicHJlY2lzaW9uIiwibnVtZXJpY19zY2FsZSIsInNpbmdsZU9yQXJyYXkiLCJzdWJzdHJpbmciLCJudW1iZXJUeXBlIiwic2NhbGUiLCJQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFFNUIsU0FBU0MsS0FBSyxRQUFRLFVBQVU7QUFtRWhDLE1BQU1DO0lBQ2FDLG9CQUFvQixJQUFJQyxJQUFJO1FBQUM7UUFBUztRQUFRO1FBQU87UUFBUTtLQUFXLEVBQUU7SUFFM0Y7Ozs7O0dBS0MsR0FDRCxNQUFNQyxzQkFDSkMsU0FBeUIsRUFDekJDLEtBQWEsRUFDaUI7UUFDOUIsSUFBSUMsV0FBdUJDLFdBQXNCQztRQUNqRCxJQUFJO1lBQ0YsQ0FBQ0YsV0FBV0MsV0FBV0MsV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDQyxTQUFTLENBQUNMLFdBQVdDO1FBQ3ZFLEVBQUUsT0FBT0ssR0FBWTtZQUNuQixJQUFJQSxhQUFhQyxTQUFTRCxFQUFFRSxPQUFPLENBQUNDLFFBQVEsQ0FBQyxvQkFBb0I7Z0JBQy9ELE9BQU87WUFDVDtZQUNBQyxRQUFRQyxLQUFLLENBQUNMO1lBQ2QsT0FBTztRQUNUO1FBRUEsMkJBQTJCO1FBQzNCLE1BQU1NLG1CQUFtQixNQUFNLElBQUksQ0FBQ0MsbUJBQW1CLENBQUNiLFdBQVdDO1FBRW5FLE1BQU1hLFVBQTZCWixVQUFVYSxHQUFHLENBQUMsQ0FBQ0M7WUFDaEQsTUFBTUMsWUFBWSxJQUFJLENBQUNDLGdCQUFnQixDQUFDRjtZQUV4Qyw4QkFBOEI7WUFDOUIsSUFBSUMsVUFBVUUsSUFBSSxLQUFLLFVBQVU7Z0JBQy9CRixVQUFVRyxVQUFVLEdBQUdSLGdCQUFnQixDQUFDSSxTQUFTSyxXQUFXLENBQUMsSUFBSTtZQUNuRTtZQUVBLE9BQU87Z0JBQ0xDLE1BQU1OLFNBQVNLLFdBQVc7Z0JBQzFCRSxVQUFVUCxTQUFTUSxXQUFXLEtBQUs7Z0JBQ25DLEdBQUdQLFNBQVM7Z0JBQ1osc0JBQXNCO2dCQUN0QixHQUFHLEFBQUMsQ0FBQTtvQkFDRixJQUFJRCxTQUFTUyxZQUFZLEtBQUssT0FBT1QsU0FBU1MsWUFBWSxLQUFLLEtBQUs7d0JBQ2xFLE9BQU87NEJBQ0xDLFdBQVc7Z0NBQ1RQLE1BQU1ILFNBQVNTLFlBQVksS0FBSyxNQUFNLFdBQVc7Z0NBQ2pERSxZQUFZWCxTQUFTWSxxQkFBcUIsSUFBSTs0QkFDaEQ7d0JBQ0Y7b0JBQ0Y7b0JBQ0EsT0FBTyxDQUFDO2dCQUNWLENBQUEsR0FBSTtnQkFDSiwwQ0FBMEM7Z0JBQzFDLEdBQUcsQUFBQyxDQUFBO29CQUNGLGtDQUFrQztvQkFDbEMsSUFBSVosU0FBU1MsWUFBWSxLQUFLLE9BQU9ULFNBQVNTLFlBQVksS0FBSyxLQUFLO3dCQUNsRSxPQUFPLENBQUM7b0JBQ1Y7b0JBRUEsSUFBSVQsU0FBU2EsY0FBYyxLQUFLLE1BQU07d0JBQ3BDLHlEQUF5RDt3QkFDekQsSUFBSUMsZUFBZWQsU0FBU2EsY0FBYzt3QkFFMUMseUJBQXlCO3dCQUN6QixJQUFJQyxhQUFhQyxVQUFVLENBQUMsYUFBYTs0QkFDdkMsT0FBTyxDQUFDO3dCQUNWO3dCQUVBLGtDQUFrQzt3QkFDbENELGVBQWVBLGFBQWFFLE9BQU8sQ0FBQyxlQUFlO3dCQUVuRCx5Q0FBeUM7d0JBQ3pDLElBQUlGLGFBQWFDLFVBQVUsQ0FBQyxRQUFRRCxhQUFhRyxRQUFRLENBQUMsTUFBTTs0QkFDOURILGVBQWVBLGFBQWFJLFVBQVUsQ0FBQyxLQUFLO3dCQUM5Qzt3QkFFQSxPQUFPOzRCQUNMQyxXQUFXTDt3QkFDYjtvQkFDRjtvQkFDQSxPQUFPLENBQUM7Z0JBQ1YsQ0FBQSxHQUFJO1lBQ047UUFDRjtRQUVBLG1DQUFtQztRQUNuQyxNQUFNTSxpQkFBaUJ6QyxNQUNyQlEsVUFBVWtDLE1BQU0sQ0FDZCxDQUFDQyxVQUNDLENBQUNBLFFBQVFDLFVBQVUsSUFDbkIsQ0FBQ25DLFdBQVdvQyxJQUFJLENBQUMsQ0FBQ0MsWUFBY0gsUUFBUUksVUFBVSxDQUFDakMsUUFBUSxDQUFDZ0MsVUFBVUUsZUFBZSxLQUV6RixDQUFDTCxVQUFZQSxRQUFRSSxVQUFVO1FBR2pDLGFBQWE7UUFDYixNQUFNRSxVQUE0QkMsT0FBT0MsSUFBSSxDQUFDVixnQkFBZ0JyQixHQUFHLENBQUMsQ0FBQ2dDO1lBQ2pFLE1BQU1DLGlCQUFpQlosY0FBYyxDQUFDVyxVQUFVLEVBQUVFLFNBQ2hELENBQUNDLE1BQU1DLFFBQVVELEtBQUtFLFlBQVksR0FBR0QsTUFBTUMsWUFBWTtZQUV6RDFELE9BQU9zRDtZQUVQLE1BQU1LLGFBQWFMLGNBQWMsQ0FBQyxFQUFFO1lBQ3BDLE1BQU1NLHdCQUF3QixJQUFJLENBQUNDLG9CQUFvQixDQUFDRixXQUFXRyxnQkFBZ0I7WUFDbkYsTUFBTUMsb0JBQW9CLElBQUksQ0FBQ0MseUJBQXlCLENBQ3RETCxZQUNBQyxzQkFBc0JLLFlBQVk7WUFFcEMsTUFBTUMsUUFBUSxJQUFJLENBQUNDLG1CQUFtQixDQUNwQ1Asc0JBQXNCSyxZQUFZLElBQUlOLFdBQVdTLFVBQVU7WUFHN0QsT0FBTztnQkFDTDNDLE1BQU1zQztnQkFDTm5DLE1BQU15QjtnQkFDTmpDLFNBQVNrQyxlQUFlakMsR0FBRyxDQUFDLENBQUNnRCxNQUFTLENBQUE7d0JBQ3BDekMsTUFBTXlDLElBQUkxQyxXQUFXO3dCQUNyQixHQUFJLElBQUksQ0FBQzJDLHlCQUF5QixDQUNoQ1Ysc0JBQXNCVyxpQkFBaUIsQ0FBQ0YsSUFBSVgsWUFBWSxHQUFHLEVBQUUsSUFFM0Q7NEJBQ0VjLFNBQVMsSUFBSSxDQUFDRix5QkFBeUIsQ0FDckNWLHNCQUFzQlcsaUJBQWlCLENBQUNGLElBQUlYLFlBQVksR0FBRyxFQUFFO3dCQUVqRSxJQUNBLENBQUMsQ0FBQzt3QkFDTixHQUFJUSxVQUFVLFVBQ1Y7NEJBQ0VPLFdBQVdKLElBQUlLLFVBQVU7NEJBQ3pCQyxZQUFZTixJQUFJTyxXQUFXO3dCQUM3QixJQUNBLENBQUMsQ0FBQztvQkFDUixDQUFBO2dCQUVBQyxrQkFBa0JsQixXQUFXbUIsa0JBQWtCO2dCQUMvQyxHQUFJWixRQUFRO29CQUFFQTtnQkFBTSxJQUFJLENBQUMsQ0FBQztnQkFDMUIsR0FBRyxJQUFJLENBQUNhLHVCQUF1QixDQUFDaEIsbUJBQW1CSCxzQkFBc0JvQixXQUFXLENBQUM7WUFDdkY7UUFDRjtRQUVBLGNBQWM7UUFDZCxNQUFNQyxXQUErQnZFLFdBQVdXLEdBQUcsQ0FBQyxDQUFDMEI7WUFDbkQsT0FBTztnQkFDTDNCLFNBQVM7b0JBQUMyQixVQUFVcEIsV0FBVztpQkFBQztnQkFDaEN1RCxJQUFJLEdBQUduQyxVQUFVb0Msa0JBQWtCLENBQUMsQ0FBQyxFQUFFcEMsVUFBVXFDLG1CQUFtQixFQUFFO2dCQUN0RUMsVUFBVSxJQUFJLENBQUNDLG1CQUFtQixDQUFDdkMsVUFBVXdDLFdBQVc7Z0JBQ3hEQyxVQUFVLElBQUksQ0FBQ0YsbUJBQW1CLENBQUN2QyxVQUFVMEMsV0FBVztZQUMxRDtRQUNGO1FBRUEsT0FBTztZQUNMbEY7WUFDQWE7WUFDQThCO1lBQ0ErQjtRQUNGO0lBQ0Y7SUFFQTs7R0FFQyxHQUNELEFBQVFLLG9CQUFvQkksTUFBYyxFQUFjO1FBQ3RELE1BQU1DLFlBQXdDO1lBQzVDLGFBQWE7WUFDYkMsVUFBVTtZQUNWQyxTQUFTO1lBQ1QsWUFBWTtZQUNaLGVBQWU7UUFDakI7UUFDQSxPQUFPRixTQUFTLENBQUNELE9BQU8sSUFBSTtJQUM5QjtJQUVBOztHQUVDLEdBQ0QsTUFBTS9FLFVBQ0pMLFNBQXlCLEVBQ3pCd0YsU0FBaUIsRUFDOEI7UUFDL0Msc0NBQXNDO1FBQ3RDLE1BQU1DLGVBQWUsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBMkJ0QixDQUFDO1FBQ0QsTUFBTTNFLFVBQVUsQUFBQyxDQUFBLE1BQU1kLFVBQVUwRixHQUFHLENBQUNELGNBQWM7WUFBQ0Q7U0FBVSxDQUFBLEVBQUdHLElBQUk7UUFDckUsSUFBSTdFLFFBQVE4RSxNQUFNLEtBQUssR0FBRztZQUN4QixNQUFNLElBQUlyRixNQUFNLENBQUMsaUJBQWlCLEVBQUVpRixXQUFXO1FBQ2pEO1FBRUEsbUNBQW1DO1FBQ25DLE1BQU1LLGVBQWUsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUEyRDFCLENBQUM7UUFDRyxNQUFNakQsVUFBVSxBQUFDLENBQUEsTUFBTTVDLFVBQVUwRixHQUFHLENBQUNHLGNBQWM7WUFBQ0w7U0FBVSxDQUFBLEVBQUdHLElBQUk7UUFFckUsa0JBQWtCO1FBQ2xCLE1BQU1HLGdCQUFnQixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztJQW9CdkIsQ0FBQztRQUNELE1BQU1uQixXQUFXLEFBQUMsQ0FBQSxNQUFNM0UsVUFBVTBGLEdBQUcsQ0FBQ0ksZUFBZTtZQUFDTjtTQUFVLENBQUEsRUFBR0csSUFBSTtRQUV2RSxPQUFPO1lBQUM3RTtZQUFTOEI7WUFBUytCO1NBQVM7SUFDckM7SUFFUWpCLDBCQUNOcUMsS0FBZ0QsRUFDaERwQyxZQUFxQixFQUNHO1FBQ3hCLE1BQU1xQyx1QkFBdUIsQUFBQ3JDLENBQUFBLGdCQUFnQm9DLE1BQU1qQyxVQUFVLEFBQUQsRUFBR21DLFdBQVc7UUFFM0UsSUFBSUQseUJBQXlCLFVBQVVBLHlCQUF5QixXQUFXO1lBQ3pFLE9BQU9BO1FBQ1Q7UUFFQSxPQUFPRCxNQUFNRyxTQUFTLEdBQUcsV0FBVztJQUN0QztJQUVRckMsb0JBQ05GLFlBQWdDLEVBQ0s7UUFDckMsSUFBSSxDQUFDQSxjQUFjO1lBQ2pCLE9BQU93QztRQUNUO1FBRUEsTUFBTUMsYUFBYXpDLGFBQWFzQyxXQUFXO1FBQzNDLElBQUksQ0FBQyxJQUFJLENBQUNwRyxpQkFBaUIsQ0FBQ3dHLEdBQUcsQ0FBQ0QsYUFBYTtZQUMzQyxPQUFPRDtRQUNUO1FBRUEsT0FBT0M7SUFDVDtJQUVRM0Isd0JBQ050RCxJQUE0QixFQUM1QnVELFdBQW1DLEVBQ3FCO1FBQ3hELElBQUl2RCxTQUFTLFFBQVE7WUFDbkIsT0FBTztnQkFDTCxHQUFJLElBQUksQ0FBQ21GLGtCQUFrQixDQUFDNUIsWUFBWTZCLENBQUMsTUFBTUosWUFDM0M7b0JBQUVJLEdBQUcsSUFBSSxDQUFDRCxrQkFBa0IsQ0FBQzVCLFlBQVk2QixDQUFDO2dCQUFFLElBQzVDLENBQUMsQ0FBQztnQkFDTixHQUFJLElBQUksQ0FBQ0Qsa0JBQWtCLENBQUM1QixZQUFZOEIsZUFBZSxNQUFNTCxZQUN6RDtvQkFBRU0sZ0JBQWdCLElBQUksQ0FBQ0gsa0JBQWtCLENBQUM1QixZQUFZOEIsZUFBZTtnQkFBRSxJQUN2RSxDQUFDLENBQUM7WUFDUjtRQUNGO1FBRUEsSUFBSXJGLFNBQVMsV0FBVztZQUN0QixPQUFPO2dCQUNMLEdBQUksSUFBSSxDQUFDbUYsa0JBQWtCLENBQUM1QixZQUFZZ0MsS0FBSyxNQUFNUCxZQUMvQztvQkFBRU8sT0FBTyxJQUFJLENBQUNKLGtCQUFrQixDQUFDNUIsWUFBWWdDLEtBQUs7Z0JBQUUsSUFDcEQsQ0FBQyxDQUFDO1lBQ1I7UUFDRjtRQUVBLE9BQU8sQ0FBQztJQUNWO0lBRVFKLG1CQUFtQkssS0FBeUIsRUFBc0I7UUFDeEUsSUFBSSxDQUFDQSxPQUFPO1lBQ1YsT0FBT1I7UUFDVDtRQUVBLE1BQU1TLFNBQVNDLE9BQU9DLFFBQVEsQ0FBQ0gsT0FBTztRQUN0QyxPQUFPRSxPQUFPRSxLQUFLLENBQUNILFVBQVVULFlBQVlTO0lBQzVDO0lBRVE1QywwQkFBMEJnRCxnQkFBb0MsRUFBc0I7UUFDMUYsSUFBSSxDQUFDQSxrQkFBa0I7WUFDckIsT0FBT2I7UUFDVDtRQUVBLE1BQU1jLFVBQVVELGlCQUNiaEYsT0FBTyxDQUFDLGdDQUFnQyxJQUN4Q0EsT0FBTyxDQUFDLHNCQUFzQixJQUM5QmtGLElBQUk7UUFDUCxNQUFNQyxTQUFTLElBQUksQ0FBQ0MsZ0JBQWdCLENBQUNIO1FBRXJDLElBQUlFLE9BQU92QixNQUFNLEdBQUcsR0FBRztZQUNyQixPQUFPTztRQUNUO1FBRUEsSUFBSWdCLE1BQU0sQ0FBQ0EsT0FBT3ZCLE1BQU0sR0FBRyxFQUFFLEVBQUV5QixrQkFBa0IsV0FBVztZQUMxRCxPQUFPbEI7UUFDVDtRQUVBLE9BQU9nQixPQUFPRyxFQUFFLENBQUMsQ0FBQztJQUNwQjtJQUVRL0QscUJBQXFCZ0UsZUFBdUIsRUFJbEQ7UUFDQSxNQUFNNUQsZUFBZTRELGdCQUFnQkMsS0FBSyxDQUFDLDZCQUE2QixDQUFDLEVBQUUsRUFBRXZCO1FBQzdFLE1BQU13QixrQkFBa0JGLGdCQUFnQkcsTUFBTSxDQUFDO1FBQy9DLE1BQU1DLGVBQWVGLG1CQUFtQixJQUFJRixnQkFBZ0JLLE9BQU8sQ0FBQyxLQUFLSCxtQkFBbUIsQ0FBQztRQUM3RixNQUFNSSxhQUNKRixnQkFBZ0IsSUFBSSxJQUFJLENBQUNHLHVCQUF1QixDQUFDUCxpQkFBaUJJLGdCQUFnQixDQUFDO1FBQ3JGLE1BQU0xRCxvQkFDSjBELGdCQUFnQixLQUFLRSxhQUFhRixlQUM5QixJQUFJLENBQUNJLGFBQWEsQ0FBQ1IsZ0JBQWdCUyxLQUFLLENBQUNMLGVBQWUsR0FBR0UsYUFBYSxPQUN4RSxFQUFFO1FBRVIsTUFBTUksWUFBWSxlQUFlQyxJQUFJLENBQUNYO1FBQ3RDLE1BQU1ZLFlBQVlGLFlBQVlWLGdCQUFnQkssT0FBTyxDQUFDLEtBQUtLLFVBQVVsQyxLQUFLLElBQUksQ0FBQztRQUMvRSxNQUFNcUMsVUFBVUQsYUFBYSxJQUFJLElBQUksQ0FBQ0wsdUJBQXVCLENBQUNQLGlCQUFpQlksYUFBYSxDQUFDO1FBQzdGLE1BQU16RCxjQUNKeUQsYUFBYSxLQUFLQyxVQUFVRCxZQUN4QixJQUFJLENBQUNFLHVCQUF1QixDQUFDZCxnQkFBZ0JTLEtBQUssQ0FBQ0csWUFBWSxHQUFHQyxZQUNsRSxDQUFDO1FBRVAsT0FBTztZQUNMekU7WUFDQU07WUFDQVM7UUFDRjtJQUNGO0lBRVEyRCx3QkFBd0JDLFlBQW9CLEVBQTBCO1FBQzVFLE9BQU8sSUFBSSxDQUFDUCxhQUFhLENBQUNPLGNBQWMsS0FBS0MsTUFBTSxDQUF5QixDQUFDQyxRQUFRQztZQUNuRixNQUFNQyxVQUFVRCxNQUFNdkIsSUFBSSxHQUFHTSxLQUFLLENBQUM7WUFDbkMsSUFBSSxDQUFDa0IsU0FBUztnQkFDWixPQUFPRjtZQUNUO1lBRUEsTUFBTSxHQUFHRyxLQUFLQyxTQUFTLEdBQUdGO1lBQzFCRixNQUFNLENBQUNHLElBQUkxQyxXQUFXLEdBQUcsR0FBRzJDLFNBQVMxQixJQUFJLEdBQUdsRixPQUFPLENBQUMsZ0JBQWdCO1lBQ3BFLE9BQU93RztRQUNULEdBQUcsQ0FBQztJQUNOO0lBRVFULGNBQWNjLE1BQWMsRUFBRUMsU0FBaUIsRUFBWTtRQUNqRSxNQUFNQyxRQUFrQixFQUFFO1FBQzFCLElBQUlDLFFBQVE7UUFDWixJQUFJQyxhQUFhO1FBQ2pCLElBQUlDLGVBQWU7UUFDbkIsSUFBSUMsZ0JBQWdCO1FBQ3BCLElBQUlDLGdCQUFnQjtRQUVwQixJQUFLLElBQUlyRCxRQUFRLEdBQUdBLFFBQVE4QyxPQUFPakQsTUFBTSxFQUFFRyxTQUFTLEVBQUc7WUFDckQsTUFBTXNELE9BQU9SLE1BQU0sQ0FBQzlDLE1BQU07WUFDMUIsTUFBTXVELFdBQVdULE1BQU0sQ0FBQzlDLFFBQVEsRUFBRTtZQUVsQyxJQUFJc0QsU0FBUyxPQUFPLENBQUNELGVBQWU7Z0JBQ2xDLElBQUlELGlCQUFpQkcsYUFBYSxLQUFLO29CQUNyQ3ZELFNBQVM7b0JBQ1Q7Z0JBQ0Y7Z0JBQ0FvRCxnQkFBZ0IsQ0FBQ0E7Z0JBQ2pCO1lBQ0Y7WUFFQSxJQUFJRSxTQUFTLE9BQU8sQ0FBQ0YsZUFBZTtnQkFDbEMsSUFBSUMsaUJBQWlCRSxhQUFhLEtBQUs7b0JBQ3JDdkQsU0FBUztvQkFDVDtnQkFDRjtnQkFDQXFELGdCQUFnQixDQUFDQTtnQkFDakI7WUFDRjtZQUVBLElBQUlELGlCQUFpQkMsZUFBZTtnQkFDbEM7WUFDRjtZQUVBLElBQUlDLFNBQVMsS0FBSztnQkFDaEJKLGNBQWM7Z0JBQ2Q7WUFDRjtZQUNBLElBQUlJLFNBQVMsS0FBSztnQkFDaEJKLGNBQWM7Z0JBQ2Q7WUFDRjtZQUNBLElBQUlJLFNBQVMsS0FBSztnQkFDaEJILGdCQUFnQjtnQkFDaEI7WUFDRjtZQUNBLElBQUlHLFNBQVMsS0FBSztnQkFDaEJILGdCQUFnQjtnQkFDaEI7WUFDRjtZQUVBLElBQUlHLFNBQVNQLGFBQWFHLGVBQWUsS0FBS0MsaUJBQWlCLEdBQUc7Z0JBQ2hFSCxNQUFNUSxJQUFJLENBQUNWLE9BQU9iLEtBQUssQ0FBQ2dCLE9BQU9qRCxPQUFPbUIsSUFBSTtnQkFDMUM4QixRQUFRakQsUUFBUTtZQUNsQjtRQUNGO1FBRUEsTUFBTXlELE9BQU9YLE9BQU9iLEtBQUssQ0FBQ2dCLE9BQU85QixJQUFJO1FBQ3JDLElBQUlzQyxLQUFLNUQsTUFBTSxHQUFHLEdBQUc7WUFDbkJtRCxNQUFNUSxJQUFJLENBQUNDO1FBQ2I7UUFFQSxPQUFPVDtJQUNUO0lBRVEzQixpQkFBaUJ5QixNQUFjLEVBQVk7UUFDakQsTUFBTTFCLFNBQW1CLEVBQUU7UUFDM0IsSUFBSTZCLFFBQVEsQ0FBQztRQUNiLElBQUlDLGFBQWE7UUFDakIsSUFBSUMsZUFBZTtRQUNuQixJQUFJQyxnQkFBZ0I7UUFDcEIsSUFBSUMsZ0JBQWdCO1FBRXBCLE1BQU1LLFlBQVksQ0FBQ0M7WUFDakIsSUFBSVYsUUFBUSxHQUFHO2dCQUNiO1lBQ0Y7WUFFQSxNQUFNVyxRQUFRZCxPQUFPYixLQUFLLENBQUNnQixPQUFPVSxVQUFVeEMsSUFBSTtZQUNoRCxJQUFJeUMsTUFBTS9ELE1BQU0sR0FBRyxHQUFHO2dCQUNwQnVCLE9BQU9vQyxJQUFJLENBQUNJO1lBQ2Q7WUFDQVgsUUFBUSxDQUFDO1FBQ1g7UUFFQSxJQUFLLElBQUlqRCxRQUFRLEdBQUdBLFFBQVE4QyxPQUFPakQsTUFBTSxFQUFFRyxTQUFTLEVBQUc7WUFDckQsTUFBTXNELE9BQU9SLE1BQU0sQ0FBQzlDLE1BQU07WUFDMUIsTUFBTXVELFdBQVdULE1BQU0sQ0FBQzlDLFFBQVEsRUFBRTtZQUVsQyxJQUFJc0QsU0FBUyxPQUFPLENBQUNELGVBQWU7Z0JBQ2xDLElBQUlKLFFBQVEsR0FBRztvQkFDYkEsUUFBUWpEO2dCQUNWO2dCQUNBLElBQUlvRCxpQkFBaUJHLGFBQWEsS0FBSztvQkFDckN2RCxTQUFTO29CQUNUO2dCQUNGO2dCQUNBb0QsZ0JBQWdCLENBQUNBO2dCQUNqQjtZQUNGO1lBRUEsSUFBSUUsU0FBUyxPQUFPLENBQUNGLGVBQWU7Z0JBQ2xDLElBQUlILFFBQVEsR0FBRztvQkFDYkEsUUFBUWpEO2dCQUNWO2dCQUNBLElBQUlxRCxpQkFBaUJFLGFBQWEsS0FBSztvQkFDckN2RCxTQUFTO29CQUNUO2dCQUNGO2dCQUNBcUQsZ0JBQWdCLENBQUNBO2dCQUNqQjtZQUNGO1lBRUEsSUFBSSxDQUFDRCxpQkFBaUIsQ0FBQ0MsZUFBZTtnQkFDcEMsSUFBSUMsU0FBUyxLQUFLO29CQUNoQixJQUFJTCxRQUFRLEdBQUc7d0JBQ2JBLFFBQVFqRDtvQkFDVjtvQkFDQWtELGNBQWM7b0JBQ2Q7Z0JBQ0Y7Z0JBQ0EsSUFBSUksU0FBUyxLQUFLO29CQUNoQkosY0FBYztvQkFDZDtnQkFDRjtnQkFDQSxJQUFJSSxTQUFTLEtBQUs7b0JBQ2hCLElBQUlMLFFBQVEsR0FBRzt3QkFDYkEsUUFBUWpEO29CQUNWO29CQUNBbUQsZ0JBQWdCO29CQUNoQjtnQkFDRjtnQkFDQSxJQUFJRyxTQUFTLEtBQUs7b0JBQ2hCSCxnQkFBZ0I7b0JBQ2hCO2dCQUNGO2dCQUVBLElBQUksS0FBS1UsSUFBSSxDQUFDUCxTQUFTSixlQUFlLEtBQUtDLGlCQUFpQixHQUFHO29CQUM3RE8sVUFBVTFEO29CQUNWO2dCQUNGO1lBQ0Y7WUFFQSxJQUFJaUQsUUFBUSxHQUFHO2dCQUNiQSxRQUFRakQ7WUFDVjtRQUNGO1FBRUEwRCxVQUFVWixPQUFPakQsTUFBTTtRQUN2QixPQUFPdUI7SUFDVDtJQUVRVyx3QkFBd0JlLE1BQWMsRUFBRWdCLFNBQWlCLEVBQVU7UUFDekUsSUFBSUMsUUFBUTtRQUNaLElBQUlYLGdCQUFnQjtRQUNwQixJQUFJQyxnQkFBZ0I7UUFFcEIsSUFBSyxJQUFJckQsUUFBUThELFdBQVc5RCxRQUFROEMsT0FBT2pELE1BQU0sRUFBRUcsU0FBUyxFQUFHO1lBQzdELE1BQU1zRCxPQUFPUixNQUFNLENBQUM5QyxNQUFNO1lBQzFCLE1BQU11RCxXQUFXVCxNQUFNLENBQUM5QyxRQUFRLEVBQUU7WUFFbEMsSUFBSXNELFNBQVMsT0FBTyxDQUFDRCxlQUFlO2dCQUNsQyxJQUFJRCxpQkFBaUJHLGFBQWEsS0FBSztvQkFDckN2RCxTQUFTO29CQUNUO2dCQUNGO2dCQUNBb0QsZ0JBQWdCLENBQUNBO2dCQUNqQjtZQUNGO1lBRUEsSUFBSUUsU0FBUyxPQUFPLENBQUNGLGVBQWU7Z0JBQ2xDLElBQUlDLGlCQUFpQkUsYUFBYSxLQUFLO29CQUNyQ3ZELFNBQVM7b0JBQ1Q7Z0JBQ0Y7Z0JBQ0FxRCxnQkFBZ0IsQ0FBQ0E7Z0JBQ2pCO1lBQ0Y7WUFFQSxJQUFJRCxpQkFBaUJDLGVBQWU7Z0JBQ2xDO1lBQ0Y7WUFFQSxJQUFJQyxTQUFTLEtBQUs7Z0JBQ2hCUyxTQUFTO2dCQUNUO1lBQ0Y7WUFFQSxJQUFJVCxTQUFTLEtBQUs7Z0JBQ2hCUyxTQUFTO2dCQUNULElBQUlBLFVBQVUsR0FBRztvQkFDZixPQUFPL0Q7Z0JBQ1Q7WUFDRjtRQUNGO1FBRUEsT0FBTyxDQUFDO0lBQ1Y7SUFFQTs7O0dBR0MsR0FDRCxNQUFNZ0UsMEJBQTBCQyxFQUFRLEVBQUV4RSxTQUFpQixFQUFvQztRQUM3RixNQUFNeUUsUUFBUSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBc0JmLENBQUM7UUFFRCxNQUFNekIsU0FBUyxNQUFNd0IsR0FBR3RFLEdBQUcsQ0FBQ3VFLE9BQU87WUFBQ3pFO1NBQVU7UUFDOUMsT0FBT2dELE9BQU83QyxJQUFJLENBQUM1RSxHQUFHLENBQ3BCLENBQUNtSixNQVFNLENBQUE7Z0JBQ0wxRSxXQUFXMEUsSUFBSUMsVUFBVTtnQkFDekJDLGdCQUFnQkYsSUFBSXZILGVBQWU7Z0JBQ25DMEgsWUFBWUgsSUFBSTdJLFdBQVc7Z0JBQzNCaUoscUJBQXFCSixJQUFJSyxxQkFBcUI7Z0JBQzlDQyxzQkFBc0JOLElBQUlPLHNCQUFzQjtnQkFDaEQxRixVQUFVLElBQUksQ0FBQ0MsbUJBQW1CLENBQUNrRixJQUFJakYsV0FBVztnQkFDbERDLFVBQVUsSUFBSSxDQUFDRixtQkFBbUIsQ0FBQ2tGLElBQUkvRSxXQUFXO1lBQ3BELENBQUE7SUFFSjtJQUVBOzs7R0FHQyxHQUNELE1BQWN0RSxvQkFDWmIsU0FBeUIsRUFDekJ3RixTQUFpQixFQUNnQjtRQUNqQyxNQUFNeUUsUUFBUSxDQUFDOzs7Ozs7Ozs7O0lBVWYsQ0FBQztRQUNELE1BQU16QixTQUFTLE1BQU14SSxVQUFVMEYsR0FBRyxDQUFDdUUsT0FBTztZQUFDekU7U0FBVTtRQUNyRCxNQUFNcEUsYUFBcUMsQ0FBQztRQUM1QyxLQUFLLE1BQU04SSxPQUFPMUIsT0FBTzdDLElBQUksQ0FBRTtZQUM3QixpQ0FBaUM7WUFDakN2RSxVQUFVLENBQUM4SSxJQUFJN0ksV0FBVyxDQUFDLEdBQUc2SSxJQUFJOUksVUFBVSxHQUFHLElBQUk4SSxJQUFJOUksVUFBVSxHQUFHO1FBQ3RFO1FBQ0EsT0FBT0E7SUFDVDtJQUVBOztHQUVDLEdBQ0RGLGlCQUNFRixRQUFrQixFQUlsQjtRQUNBLE1BQU0sRUFBRTBKLFVBQVVDLFNBQVMsRUFBRUMsd0JBQXdCLEVBQUVDLFNBQVMsRUFBRUMsYUFBYSxFQUFFLEdBQUc5SjtRQUVwRixNQUFNLEVBQUUwSixRQUFRLEVBQUVLLGFBQWEsRUFBRSxHQUFHLEFBQUMsQ0FBQTtZQUNuQyxJQUFJSixVQUFVNUksVUFBVSxDQUFDLE1BQU07Z0JBQzdCLE9BQU87b0JBQ0wySSxVQUFVQyxVQUFVSyxTQUFTLENBQUM7b0JBQzlCRCxlQUFlO2dCQUNqQjtZQUNGO1lBQ0EsT0FBTztnQkFDTEwsVUFBVUM7Z0JBQ1ZJLGVBQWU7WUFDakI7UUFDRixDQUFBO1FBRUEsT0FBTztRQUNQLElBQUlMLGFBQWEsUUFBUTtZQUN2QixPQUFPO2dCQUFFdkosTUFBTSxDQUFDLElBQUksRUFBRTRKLGVBQWU7WUFBQztRQUN4QztRQUVBLGdCQUFnQjtRQUNoQixJQUFJTCxhQUFhLFFBQVE7WUFDdkIsT0FBTztnQkFBRXZKLE1BQU0sQ0FBQyxPQUFPLEVBQUU0SixlQUFlO1lBQUM7UUFDM0M7UUFDQSxJQUFJTCxhQUFhLFFBQVE7WUFDdkIsT0FBTztnQkFBRXZKLE1BQU0sQ0FBQyxVQUFVLEVBQUU0SixlQUFlO1lBQUM7UUFDOUM7UUFFQSxlQUFlO1FBQ2YsSUFBSUwsYUFBYSxXQUFXO1lBQzFCLE9BQU87Z0JBQ0x2SixNQUFNLENBQUMsTUFBTSxFQUFFNEosZUFBZTtnQkFDOUIsR0FBSUgsNEJBQTRCO29CQUM5QmhGLFFBQVFnRjtnQkFDVixDQUFDO1lBQ0g7UUFDRjtRQUNBLElBQUlGLGFBQWEsUUFBUTtZQUN2QixPQUFPO2dCQUFFdkosTUFBTSxDQUFDLE1BQU0sRUFBRTRKLGVBQWU7WUFBQyxHQUFHLDRCQUE0QjtRQUN6RTtRQUVBLHdCQUF3QjtRQUN4QixJQUFJTCxhQUFhLFdBQVc7WUFDMUIsT0FBTztnQkFDTHZKLE1BQU0sQ0FBQyxlQUFlLEVBQUU0SixlQUFlO2dCQUN2Q0UsWUFBWTtnQkFDWixHQUFJSixjQUFjLFFBQ2hCQyxrQkFBa0IsUUFBUTtvQkFDeEJELFdBQVdBO29CQUNYSyxPQUFPSjtnQkFDVCxDQUFDO1lBQ0w7UUFDRjtRQUNBLElBQUlKLGFBQWEsVUFBVTtZQUN6QixPQUFPO2dCQUFFdkosTUFBTSxDQUFDLGVBQWUsRUFBRTRKLGVBQWU7Z0JBQUVFLFlBQVk7WUFBTztRQUN2RTtRQUNBLElBQUlQLGFBQWEsVUFBVTtZQUN6QixPQUFPO2dCQUFFdkosTUFBTSxDQUFDLGVBQWUsRUFBRTRKLGVBQWU7Z0JBQUVFLFlBQVk7WUFBbUI7UUFDbkY7UUFFQSxVQUFVO1FBQ1YsSUFBSVAsYUFBYSxRQUFRO1lBQ3ZCLE9BQU87Z0JBQUV2SixNQUFNLENBQUMsT0FBTyxFQUFFNEosZUFBZTtZQUFDO1FBQzNDO1FBRUEsbUJBQW1CO1FBQ25CLElBQUlMLGFBQWEsZUFBZTtZQUM5QixPQUFPO2dCQUNMdkosTUFBTSxDQUFDLElBQUksRUFBRTRKLGVBQWU7Z0JBQzVCLEdBQUlGLGNBQWMsUUFBUTtvQkFDeEJBLFdBQVdBO2dCQUNiLENBQUM7WUFDSCxHQUFHLHlCQUF5QjtRQUM5QjtRQUVBLE9BQU87UUFDUCxJQUFJSCxhQUFhLFVBQVVBLGFBQWEsU0FBUztZQUMvQyxPQUFPO2dCQUFFdkosTUFBTTtZQUFPO1FBQ3hCO1FBRUEsb0JBQW9CO1FBQ3BCLElBQUl1SixhQUFhLFVBQVU7WUFDekIsaURBQWlEO1lBQ2pELG9FQUFvRTtZQUNwRSxPQUFPO2dCQUFFdkosTUFBTSxDQUFDLE1BQU0sRUFBRTRKLGVBQWU7Z0JBQUUzSixZQUFZO1lBQUU7UUFDekQ7UUFFQSxrQ0FBa0M7UUFDbEMsSUFBSXNKLGFBQWEsWUFBWTtZQUMzQixPQUFPO2dCQUFFdkosTUFBTTtZQUFXO1FBQzVCO1FBRUEsTUFBTSxJQUFJWixNQUFNLENBQUMsK0JBQStCLEVBQUVtSyxVQUFVO0lBQzlEO0FBQ0Y7QUFFQSxPQUFPLE1BQU1TLHlCQUF5QixJQUFJdkwsOEJBQThCIn0=
643
+ //#endregion
644
+ init_postgresql_schema_reader();
645
+ export { PostgreSQLSchemaReader, init_postgresql_schema_reader };
646
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXNxbC1zY2hlbWEtcmVhZGVyLmpzIiwibmFtZXMiOlsiZGJDb2x1bW5zOiBQZ0NvbHVtbltdIiwiZGJJbmRleGVzOiBQZ0luZGV4W10iLCJkYkZvcmVpZ25zOiBQZ0ZvcmVpZ25bXSIsImU6IHVua25vd24iLCJjb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSIsImluZGV4ZXM6IE1pZ3JhdGlvbkluZGV4W10iLCJmb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdIiwiYWN0aW9uTWFwOiBSZWNvcmQ8c3RyaW5nLCBSZWxhdGlvbk9uPiIsIml0ZW1zOiBzdHJpbmdbXSIsInRva2Vuczogc3RyaW5nW10iLCJkaW1lbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21pZ3JhdGlvbi9wb3N0Z3Jlc3FsLXNjaGVtYS1yZWFkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5cbmltcG9ydCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBncm91cCB9IGZyb20gXCJyYWRhc2hpXCI7XG5cbmltcG9ydCB7XG4gIHR5cGUgTWlncmF0aW9uQ29sdW1uLFxuICB0eXBlIE1pZ3JhdGlvbkZvcmVpZ24sXG4gIHR5cGUgTWlncmF0aW9uSW5kZXgsXG4gIHR5cGUgTWlncmF0aW9uU2V0LFxuICB0eXBlIFJlbGF0aW9uT24sXG59IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuXG4vKipcbiAqIO2KueyglSDthYzsnbTruJTsnZggUEvrpbwg7LC47KGw7ZWY64qUIOuLpOuluCDthYzsnbTruJTsnZggRksg7KCV67O07J6F64uI64ukLlxuICogUEsg7YOA7J6FIOuzgOqyvSDsi5wg6rSA66CoIEZLIOygnOyVveyhsOqxtOydhCDsspjrpqztlZjquLAg7JyE7ZW0IOyCrOyaqeuQqeuLiOuLpC5cbiAqL1xuZXhwb3J0IHR5cGUgUmVmZXJlbmNpbmdGb3JlaWduS2V5ID0ge1xuICAvKiogRkvqsIAg7KCV7J2Y65CcIO2FjOydtOu4lOuqhSAqL1xuICB0YWJsZU5hbWU6IHN0cmluZztcbiAgLyoqIEZLIOygnOyVveyhsOqxtCDsnbTrpoQgKi9cbiAgY29uc3RyYWludE5hbWU6IHN0cmluZztcbiAgLyoqIEZLIOy7rOufvOuqhSAqL1xuICBjb2x1bW5OYW1lOiBzdHJpbmc7XG4gIC8qKiDssLjsobDtlZjripQg7YWM7J2067iU66qFIChQS+qwgCDsnojripQg7YWM7J2067iUKSAqL1xuICByZWZlcmVuY2VkVGFibGVOYW1lOiBzdHJpbmc7XG4gIC8qKiDssLjsobDtlZjripQg7Lus65+866qFICjrs7TthrUgJ2lkJykgKi9cbiAgcmVmZXJlbmNlZENvbHVtbk5hbWU6IHN0cmluZztcbiAgLyoqIE9OIFVQREFURSDslaHshZggKi9cbiAgb25VcGRhdGU6IFJlbGF0aW9uT247XG4gIC8qKiBPTiBERUxFVEUg7JWh7IWYICovXG4gIG9uRGVsZXRlOiBSZWxhdGlvbk9uO1xufTtcblxuZXhwb3J0IHR5cGUgUGdDb2x1bW4gPSB7XG4gIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIGRhdGFfdHlwZTogc3RyaW5nO1xuICB1ZHRfbmFtZTogc3RyaW5nO1xuICBjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGg6IG51bWJlciB8IG51bGw7XG4gIHByZWNpc2lvbjogbnVtYmVyIHwgbnVsbDtcbiAgbnVtZXJpY19zY2FsZTogbnVtYmVyIHwgbnVsbDtcbiAgaXNfbnVsbGFibGU6IHN0cmluZztcbiAgY29sdW1uX2RlZmF1bHQ6IHN0cmluZyB8IG51bGw7XG4gIGlzX2dlbmVyYXRlZDogc3RyaW5nOyAvLyAncycgPSBTVE9SRUQsICd2JyA9IFZJUlRVQUwsICcnID0gbm9uZVxuICBnZW5lcmF0aW9uX2V4cHJlc3Npb246IHN0cmluZyB8IG51bGw7XG59O1xuXG50eXBlIFBnSW5kZXggPSB7XG4gIGluZGV4X25hbWU6IHN0cmluZztcbiAgY29sdW1uX25hbWU6IHN0cmluZztcbiAgaXNfdW5pcXVlOiBib29sZWFuO1xuICBpc19wcmltYXJ5OiBib29sZWFuO1xuICBpbmRleF90eXBlOiBzdHJpbmc7XG4gIG51bGxzX2ZpcnN0OiBib29sZWFuO1xuICBzb3J0X29yZGVyOiBcIkFTQ1wiIHwgXCJERVNDXCI7XG4gIG51bGxzX25vdF9kaXN0aW5jdDogYm9vbGVhbjtcbiAgY29sdW1uX29yZGVyOiBudW1iZXI7XG4gIGluZGV4X2RlZmluaXRpb246IHN0cmluZztcbn07XG5cbnR5cGUgUGdGb3JlaWduID0ge1xuICBjb25zdHJhaW50X25hbWU6IHN0cmluZztcbiAgY29sdW1uX25hbWU6IHN0cmluZztcbiAgZm9yZWlnbl90YWJsZV9uYW1lOiBzdHJpbmc7XG4gIGZvcmVpZ25fY29sdW1uX25hbWU6IHN0cmluZztcbiAgdXBkYXRlX3J1bGU6IHN0cmluZztcbiAgZGVsZXRlX3J1bGU6IHN0cmluZztcbn07XG5cbnR5cGUgUmF3Q2FwYWJsZUtuZXggPSBQaWNrPEtuZXgsIFwicmF3XCI+O1xuXG5jbGFzcyBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyQ2xhc3Mge1xuICBwcml2YXRlIHJlYWRvbmx5IGdlbmVyaWNJbmRleFR5cGVzID0gbmV3IFNldChbXCJidHJlZVwiLCBcImhhc2hcIiwgXCJnaW5cIiwgXCJnaXN0XCIsIFwicGdyb29uZ2FcIl0pO1xuXG4gIC8qKlxuICAgKiBEQuyXkOyEnCDthYzsnbTruJQg7KCV67O066W8IOydveyWtOyEnCBNaWdyYXRpb25TZXTsnYQg66eM65Ok7Ja07Ji164uI64ukLlxuICAgKiBAcGFyYW0gY29tcGFyZURCIEtuZXgg7J247Iqk7YS07IqkXG4gICAqIEBwYXJhbSB0YWJsZSDthYzsnbTruJQg7J2066aEXG4gICAqIEByZXR1cm5zIE1pZ3JhdGlvblNldCDqsJ3ssrRcbiAgICovXG4gIGFzeW5jIGdldE1pZ3JhdGlvblNldEZyb21EQihcbiAgICBjb21wYXJlREI6IFJhd0NhcGFibGVLbmV4LFxuICAgIHRhYmxlOiBzdHJpbmcsXG4gICk6IFByb21pc2U8TWlncmF0aW9uU2V0IHwgbnVsbD4ge1xuICAgIGxldCBkYkNvbHVtbnM6IFBnQ29sdW1uW10sIGRiSW5kZXhlczogUGdJbmRleFtdLCBkYkZvcmVpZ25zOiBQZ0ZvcmVpZ25bXTtcbiAgICB0cnkge1xuICAgICAgW2RiQ29sdW1ucywgZGJJbmRleGVzLCBkYkZvcmVpZ25zXSA9IGF3YWl0IHRoaXMucmVhZFRhYmxlKGNvbXBhcmVEQiwgdGFibGUpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgRXJyb3IgJiYgZS5tZXNzYWdlLmluY2x1ZGVzKFwiVGFibGUgbm90IGZvdW5kXCIpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIHZlY3RvciDsu6zrn7zsnZggZGltZW5zaW9ucyDsobDtmoxcbiAgICBjb25zdCB2ZWN0b3JEaW1lbnNpb25zID0gYXdhaXQgdGhpcy5nZXRWZWN0b3JEaW1lbnNpb25zKGNvbXBhcmVEQiwgdGFibGUpO1xuXG4gICAgY29uc3QgY29sdW1uczogTWlncmF0aW9uQ29sdW1uW10gPSBkYkNvbHVtbnMubWFwKChkYkNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgZGJDb2xUeXBlID0gdGhpcy5yZXNvbHZlREJDb2xUeXBlKGRiQ29sdW1uKTtcblxuICAgICAgLy8gdmVjdG9yIO2DgOyeheyduCDqsr3smrAgZGltZW5zaW9ucyDshKTsoJVcbiAgICAgIGlmIChkYkNvbFR5cGUudHlwZSA9PT0gXCJ2ZWN0b3JcIikge1xuICAgICAgICBkYkNvbFR5cGUuZGltZW5zaW9ucyA9IHZlY3RvckRpbWVuc2lvbnNbZGJDb2x1bW4uY29sdW1uX25hbWVdID8/IDA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWU6IGRiQ29sdW1uLmNvbHVtbl9uYW1lLFxuICAgICAgICBudWxsYWJsZTogZGJDb2x1bW4uaXNfbnVsbGFibGUgPT09IFwiWUVTXCIsXG4gICAgICAgIC4uLmRiQ29sVHlwZSxcbiAgICAgICAgLy8gR2VuZXJhdGVkIENvbHVtbiDsspjrpqxcbiAgICAgICAgLi4uKCgpID0+IHtcbiAgICAgICAgICBpZiAoZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInNcIiB8fCBkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwidlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBnZW5lcmF0ZWQ6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwic1wiID8gXCJTVE9SRURcIiA6IFwiVklSVFVBTFwiLFxuICAgICAgICAgICAgICAgIGV4cHJlc3Npb246IGRiQ29sdW1uLmdlbmVyYXRpb25fZXhwcmVzc2lvbiA/PyBcIlwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9KSgpLFxuICAgICAgICAvLyBEZWZhdWx0IOqwkiDsspjrpqwgKEdlbmVyYXRlZCBDb2x1bW7snbQg7JWE64uMIOqyveyasOunjClcbiAgICAgICAgLi4uKCgpID0+IHtcbiAgICAgICAgICAvLyBHZW5lcmF0ZWQgQ29sdW1u7J2AIGRlZmF1bHQg6rCS7J20IOyXhuydjFxuICAgICAgICAgIGlmIChkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwic1wiIHx8IGRiQ29sdW1uLmlzX2dlbmVyYXRlZCA9PT0gXCJ2XCIpIHtcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZGJDb2x1bW4uY29sdW1uX2RlZmF1bHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFBvc3RncmVTUUwgZGVmYXVsdCDqsJIg7KCV66asIChuZXh0dmFsLCBDVVJSRU5UX1RJTUVTVEFNUCDrk7EpXG4gICAgICAgICAgICBsZXQgZGVmYXVsdFZhbHVlID0gZGJDb2x1bW4uY29sdW1uX2RlZmF1bHQ7XG5cbiAgICAgICAgICAgIC8vIG5leHR2YWwg7KCc6rGwIChTRVJJQUwg7YOA7J6FKVxuICAgICAgICAgICAgaWYgKGRlZmF1bHRWYWx1ZS5zdGFydHNXaXRoKFwibmV4dHZhbChcIikpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyDtg4DsnoUg7LqQ7Iqk7YyFIOygnOqxsCAo7JiIOiAnMSc6OmludGVnZXIg4oaSIDEpXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWUgPSBkZWZhdWx0VmFsdWUucmVwbGFjZSgvOjpbXFx3XFxzXSskL2csIFwiXCIpO1xuXG4gICAgICAgICAgICAvLyDrlLDsmLTtkZzqsIAgc2luZ2xlIHF1b3Rl7J24IOqyveyasCBkb3VibGUgcXVvdGXroZwg67OA7ZmYXG4gICAgICAgICAgICBpZiAoZGVmYXVsdFZhbHVlLnN0YXJ0c1dpdGgoXCInXCIpICYmIGRlZmF1bHRWYWx1ZS5lbmRzV2l0aChcIidcIikpIHtcbiAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlID0gZGVmYXVsdFZhbHVlLnJlcGxhY2VBbGwoXCInXCIsICdcIicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBkZWZhdWx0VG86IGRlZmF1bHRWYWx1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfSkoKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBQUklNQVJZIEtFWeyZgCBmb3JlaWduIGtleeyaqSDsnbjrjbHsiqQg7KCc7Jm4XG4gICAgY29uc3QgZGJJbmRleGVzR3JvdXAgPSBncm91cChcbiAgICAgIGRiSW5kZXhlcy5maWx0ZXIoXG4gICAgICAgIChkYkluZGV4KSA9PlxuICAgICAgICAgICFkYkluZGV4LmlzX3ByaW1hcnkgJiZcbiAgICAgICAgICAhZGJGb3JlaWducy5maW5kKChkYkZvcmVpZ24pID0+IGRiSW5kZXguaW5kZXhfbmFtZS5pbmNsdWRlcyhkYkZvcmVpZ24uY29uc3RyYWludF9uYW1lKSksXG4gICAgICApLFxuICAgICAgKGRiSW5kZXgpID0+IGRiSW5kZXguaW5kZXhfbmFtZSxcbiAgICApO1xuXG4gICAgLy8gaW5kZXhlcyDsspjrpqxcbiAgICBjb25zdCBpbmRleGVzOiBNaWdyYXRpb25JbmRleFtdID0gT2JqZWN0LmtleXMoZGJJbmRleGVzR3JvdXApLm1hcCgoaW5kZXhOYW1lKSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50SW5kZXhlcyA9IGRiSW5kZXhlc0dyb3VwW2luZGV4TmFtZV0/LnRvU29ydGVkKFxuICAgICAgICAobGVmdCwgcmlnaHQpID0+IGxlZnQuY29sdW1uX29yZGVyIC0gcmlnaHQuY29sdW1uX29yZGVyLFxuICAgICAgKTtcbiAgICAgIGFzc2VydChjdXJyZW50SW5kZXhlcyk7XG5cbiAgICAgIGNvbnN0IGZpcnN0SW5kZXggPSBjdXJyZW50SW5kZXhlc1swXTtcbiAgICAgIGNvbnN0IHBhcnNlZEluZGV4RGVmaW5pdGlvbiA9IHRoaXMucGFyc2VJbmRleERlZmluaXRpb24oZmlyc3RJbmRleC5pbmRleF9kZWZpbml0aW9uKTtcbiAgICAgIGNvbnN0IHJlc3RvcmVkSW5kZXhUeXBlID0gdGhpcy5yZXN0b3JlTWlncmF0aW9uSW5kZXhUeXBlKFxuICAgICAgICBmaXJzdEluZGV4LFxuICAgICAgICBwYXJzZWRJbmRleERlZmluaXRpb24uYWNjZXNzTWV0aG9kLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHVzaW5nID0gdGhpcy5yZXN0b3JlR2VuZXJpY1VzaW5nKFxuICAgICAgICBwYXJzZWRJbmRleERlZmluaXRpb24uYWNjZXNzTWV0aG9kID8/IGZpcnN0SW5kZXguaW5kZXhfdHlwZSxcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IHJlc3RvcmVkSW5kZXhUeXBlLFxuICAgICAgICBuYW1lOiBpbmRleE5hbWUsXG4gICAgICAgIGNvbHVtbnM6IGN1cnJlbnRJbmRleGVzLm1hcCgoaWR4KSA9PiAoe1xuICAgICAgICAgIG5hbWU6IGlkeC5jb2x1bW5fbmFtZSxcbiAgICAgICAgICAuLi4odGhpcy5leHRyYWN0SW5kZXhDb2x1bW5PcGNsYXNzKFxuICAgICAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmNvbHVtbkRlZmluaXRpb25zW2lkeC5jb2x1bW5fb3JkZXIgLSAxXSxcbiAgICAgICAgICApXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBvcGNsYXNzOiB0aGlzLmV4dHJhY3RJbmRleENvbHVtbk9wY2xhc3MoXG4gICAgICAgICAgICAgICAgICBwYXJzZWRJbmRleERlZmluaXRpb24uY29sdW1uRGVmaW5pdGlvbnNbaWR4LmNvbHVtbl9vcmRlciAtIDFdLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgIC4uLih1c2luZyA9PT0gXCJidHJlZVwiXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBzb3J0T3JkZXI6IGlkeC5zb3J0X29yZGVyLFxuICAgICAgICAgICAgICAgIG51bGxzRmlyc3Q6IGlkeC5udWxsc19maXJzdCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0pKSxcblxuICAgICAgICBudWxsc05vdERpc3RpbmN0OiBmaXJzdEluZGV4Lm51bGxzX25vdF9kaXN0aW5jdCxcbiAgICAgICAgLi4uKHVzaW5nID8geyB1c2luZyB9IDoge30pLFxuICAgICAgICAuLi50aGlzLnBhcnNlVmVjdG9ySW5kZXhPcHRpb25zKHJlc3RvcmVkSW5kZXhUeXBlLCBwYXJzZWRJbmRleERlZmluaXRpb24ud2l0aE9wdGlvbnMpLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIGZvcmVpZ25zIOyymOumrFxuICAgIGNvbnN0IGZvcmVpZ25zOiBNaWdyYXRpb25Gb3JlaWduW10gPSBkYkZvcmVpZ25zLm1hcCgoZGJGb3JlaWduKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2x1bW5zOiBbZGJGb3JlaWduLmNvbHVtbl9uYW1lXSxcbiAgICAgICAgdG86IGAke2RiRm9yZWlnbi5mb3JlaWduX3RhYmxlX25hbWV9LiR7ZGJGb3JlaWduLmZvcmVpZ25fY29sdW1uX25hbWV9YCxcbiAgICAgICAgb25VcGRhdGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihkYkZvcmVpZ24udXBkYXRlX3J1bGUpLFxuICAgICAgICBvbkRlbGV0ZTogdGhpcy5tYXBDb25zdHJhaW50QWN0aW9uKGRiRm9yZWlnbi5kZWxldGVfcnVsZSksXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRhYmxlLFxuICAgICAgY29sdW1ucyxcbiAgICAgIGluZGV4ZXMsXG4gICAgICBmb3JlaWducyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFBvc3RncmVTUUzsnZggY29uc3RyYWludCBhY3Rpb27snYQgS25leCDtmJXsi53snLzroZwg67OA7ZmYXG4gICAqL1xuICBwcml2YXRlIG1hcENvbnN0cmFpbnRBY3Rpb24oYWN0aW9uOiBzdHJpbmcpOiBSZWxhdGlvbk9uIHtcbiAgICBjb25zdCBhY3Rpb25NYXA6IFJlY29yZDxzdHJpbmcsIFJlbGF0aW9uT24+ID0ge1xuICAgICAgXCJOTyBBQ1RJT05cIjogXCJOTyBBQ1RJT05cIixcbiAgICAgIFJFU1RSSUNUOiBcIlJFU1RSSUNUXCIsXG4gICAgICBDQVNDQURFOiBcIkNBU0NBREVcIixcbiAgICAgIFwiU0VUIE5VTExcIjogXCJTRVQgTlVMTFwiLFxuICAgICAgXCJTRVQgREVGQVVMVFwiOiBcIlNFVCBERUZBVUxUXCIsXG4gICAgfTtcbiAgICByZXR1cm4gYWN0aW9uTWFwW2FjdGlvbl0gPz8gXCJOTyBBQ1RJT05cIjtcbiAgfVxuXG4gIC8qKlxuICAgKiDquLDsobQg7YWM7J2067iUIOydveyWtOyEnCBjb2xzLCBpbmRleGVzLCBmb3JlaWducyDrsJjtmZhcbiAgICovXG4gIGFzeW5jIHJlYWRUYWJsZShcbiAgICBjb21wYXJlREI6IFJhd0NhcGFibGVLbmV4LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICApOiBQcm9taXNlPFtQZ0NvbHVtbltdLCBQZ0luZGV4W10sIFBnRm9yZWlnbltdXT4ge1xuICAgIC8vIENvbHVtbnMg7KGw7ZqMIChHZW5lcmF0ZWQgQ29sdW1uIOygleuztCDtj6ztlagpXG4gICAgY29uc3QgY29sdW1uc1F1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgIGMuY29sdW1uX25hbWUsXG4gICAgICAgIGMuZGF0YV90eXBlLFxuICAgICAgICBjLnVkdF9uYW1lLFxuICAgICAgICBDT0FMRVNDRShcbiAgICAgICAgICBjLmNoYXJhY3Rlcl9tYXhpbXVtX2xlbmd0aCxcbiAgICAgICAgICBDQVNFIFdIRU4gYy5kYXRhX3R5cGUgPSAnQVJSQVknIEFORCBhLmF0dHR5cG1vZCA+IDBcbiAgICAgICAgICAgIFRIRU4gYS5hdHR0eXBtb2QgLSA0XG4gICAgICAgICAgICBFTFNFIE5VTExcbiAgICAgICAgICBFTkRcbiAgICAgICAgKSBBUyBjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGgsXG4gICAgICAgIENPQUxFU0NFKGMuZGF0ZXRpbWVfcHJlY2lzaW9uLCBjLm51bWVyaWNfcHJlY2lzaW9uKSBBUyBwcmVjaXNpb24sXG4gICAgICAgIGMubnVtZXJpY19zY2FsZSxcbiAgICAgICAgYy5pc19udWxsYWJsZSxcbiAgICAgICAgYy5jb2x1bW5fZGVmYXVsdCxcbiAgICAgICAgQ09BTEVTQ0UoYS5hdHRnZW5lcmF0ZWQsICcnKSBhcyBpc19nZW5lcmF0ZWQsXG4gICAgICAgIGMuZ2VuZXJhdGlvbl9leHByZXNzaW9uXG4gICAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIGNcbiAgICAgIExFRlQgSk9JTiBwZ19hdHRyaWJ1dGUgYSBPTiBhLmF0dG5hbWUgPSBjLmNvbHVtbl9uYW1lXG4gICAgICAgIEFORCBhLmF0dHJlbGlkID0gKFxuICAgICAgICAgIFNFTEVDVCBvaWQgRlJPTSBwZ19jbGFzcyBXSEVSRSByZWxuYW1lID0gYy50YWJsZV9uYW1lXG4gICAgICAgICAgQU5EIHJlbG5hbWVzcGFjZSA9IChTRUxFQ1Qgb2lkIEZST00gcGdfbmFtZXNwYWNlIFdIRVJFIG5zcG5hbWUgPSBjLnRhYmxlX3NjaGVtYSlcbiAgICAgICAgKVxuICAgICAgV0hFUkUgYy50YWJsZV9uYW1lID0gP1xuICAgICAgICBBTkQgYy50YWJsZV9zY2hlbWEgPSAncHVibGljJ1xuICAgICAgT1JERVIgQlkgYy5vcmRpbmFsX3Bvc2l0aW9uXG4gICAgYDtcbiAgICBjb25zdCBjb2x1bW5zID0gKGF3YWl0IGNvbXBhcmVEQi5yYXcoY29sdW1uc1F1ZXJ5LCBbdGFibGVOYW1lXSkpLnJvd3MgYXMgUGdDb2x1bW5bXTtcbiAgICBpZiAoY29sdW1ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgbm90IGZvdW5kOiAke3RhYmxlTmFtZX1gKTtcbiAgICB9XG5cbiAgICAvLyBJbmRleGVzIOyhsO2ajCAoUEdyb29uZ2Eg7ZGc7ZiE7IudIOyduOuNseyKpCDtj6ztlagpXG4gICAgY29uc3QgaW5kZXhlc1F1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgICAgaS5yZWxuYW1lIEFTIGluZGV4X25hbWUsXG4gICAgICAgICAgQ0FTRVxuICAgICAgICAgICAgICBXSEVOIGFtLmFtbmFtZSA9ICdwZ3Jvb25nYScgQU5EIHUuYXR0bnVtID0gMCBUSEVOXG4gICAgICAgICAgICAgICAgICByZWdleHBfcmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgICByZWdleHBfcmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJJTShwZ3Jvb25nYV9jb2wuY29sdW1uX2V4cHIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnOjp0ZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnJ1xuICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgJ1soKV0nLFxuICAgICAgICAgICAgICAgICAgICAgICcnLFxuICAgICAgICAgICAgICAgICAgICAgICdnJ1xuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICBFTFNFIGEuYXR0bmFtZVxuICAgICAgICAgIEVORCBBUyBjb2x1bW5fbmFtZSxcbiAgICAgICAgICBpeC5pbmRpc3VuaXF1ZSBBUyBpc191bmlxdWUsXG4gICAgICAgICAgaXguaW5kaXNwcmltYXJ5IEFTIGlzX3ByaW1hcnksXG4gICAgICAgICAgYW0uYW1uYW1lIEFTIGluZGV4X3R5cGUsXG4gICAgICAgICAgQ09BTEVTQ0UoKHUub3B0ICYgMikgPSAyLCBGQUxTRSkgQVMgbnVsbHNfZmlyc3QsXG4gICAgICAgICAgQ0FTRSBcbiAgICAgICAgICAgICAgV0hFTiAodS5vcHQgJiAxKSA9IDEgVEhFTiAnREVTQydcbiAgICAgICAgICAgICAgRUxTRSAnQVNDJ1xuICAgICAgICAgIEVORCBBUyBzb3J0X29yZGVyLFxuICAgICAgICAgIGl4LmluZG51bGxzbm90ZGlzdGluY3QgQVMgbnVsbHNfbm90X2Rpc3RpbmN0LFxuICAgICAgICAgIHUub3JkIEFTIGNvbHVtbl9vcmRlcixcbiAgICAgICAgICBwZ19nZXRfaW5kZXhkZWYoaXguaW5kZXhyZWxpZCkgQVMgaW5kZXhfZGVmaW5pdGlvblxuICAgICAgRlJPTSBwZ19jbGFzcyB0XG4gICAgICBKT0lOIHBnX2luZGV4IGl4IE9OIHQub2lkID0gaXguaW5kcmVsaWRcbiAgICAgIEpPSU4gcGdfY2xhc3MgaSBPTiBpLm9pZCA9IGl4LmluZGV4cmVsaWRcbiAgICAgIEpPSU4gcGdfYW0gYW0gT04gaS5yZWxhbSA9IGFtLm9pZFxuICAgICAgSk9JTiBMQVRFUkFMIHVubmVzdChpeC5pbmRrZXksIGl4LmluZG9wdGlvbilcbiAgICAgICAgICBXSVRIIE9SRElOQUxJVFkgQVMgdShhdHRudW0sIG9wdCwgb3JkKSBPTiB0cnVlXG4gICAgICBMRUZUIEpPSU4gcGdfYXR0cmlidXRlIGEgT04gYS5hdHRyZWxpZCA9IHQub2lkIFxuICAgICAgICAgIEFORCBhLmF0dG51bSA9IHUuYXR0bnVtIFxuICAgICAgICAgIEFORCB1LmF0dG51bSA+IDBcbiAgICAgIExFRlQgSk9JTiBMQVRFUkFMIChcbiAgICAgICAgICBTRUxFQ1QgXG4gICAgICAgICAgICAgIHVubmVzdChcbiAgICAgICAgICAgICAgICAgIENBU0UgXG4gICAgICAgICAgICAgICAgICAgICAgV0hFTiBwZ19nZXRfZXhwcihpeC5pbmRleHBycywgaXguaW5kcmVsaWQpIH4gJ15BUlJBWVxcXFxbJyBUSEVOXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ190b19hcnJheShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2V4cF9yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBnX2dldF9leHByKGl4LmluZGV4cHJzLCBpeC5pbmRyZWxpZCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ15BUlJBWVxcXFxbKC4qKVxcXFxdJCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1xcXFwxJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsICdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgIEVMU0VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgQVJSQVlbcGdfZ2V0X2V4cHIoaXguaW5kZXhwcnMsIGl4LmluZHJlbGlkKV1cbiAgICAgICAgICAgICAgICAgIEVORFxuICAgICAgICAgICAgICApIGFzIGNvbHVtbl9leHByXG4gICAgICApIHBncm9vbmdhX2NvbCBPTiBhbS5hbW5hbWUgPSAncGdyb29uZ2EnIEFORCB1LmF0dG51bSA9IDBcbiAgICAgIFdIRVJFIHQucmVsbmFtZSA9ID9cbiAgICAgICAgICBBTkQgKHUuYXR0bnVtID4gMCBPUiAoYW0uYW1uYW1lID0gJ3Bncm9vbmdhJyBBTkQgdS5hdHRudW0gPSAwKSlcbiAgICAgIE9SREVSIEJZIGkucmVsbmFtZSwgdS5vcmQ7XG5gO1xuICAgIGNvbnN0IGluZGV4ZXMgPSAoYXdhaXQgY29tcGFyZURCLnJhdyhpbmRleGVzUXVlcnksIFt0YWJsZU5hbWVdKSkucm93cztcblxuICAgIC8vIEZvcmVpZ24gS2V5cyDsobDtmoxcbiAgICBjb25zdCBmb3JlaWduc1F1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgIHRjLmNvbnN0cmFpbnRfbmFtZSxcbiAgICAgICAga2N1LmNvbHVtbl9uYW1lLFxuICAgICAgICBjY3UudGFibGVfbmFtZSBBUyBmb3JlaWduX3RhYmxlX25hbWUsXG4gICAgICAgIGNjdS5jb2x1bW5fbmFtZSBBUyBmb3JlaWduX2NvbHVtbl9uYW1lLFxuICAgICAgICByYy51cGRhdGVfcnVsZSxcbiAgICAgICAgcmMuZGVsZXRlX3J1bGVcbiAgICAgIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlX2NvbnN0cmFpbnRzIEFTIHRjXG4gICAgICBKT0lOIGluZm9ybWF0aW9uX3NjaGVtYS5rZXlfY29sdW1uX3VzYWdlIEFTIGtjdVxuICAgICAgICBPTiB0Yy5jb25zdHJhaW50X25hbWUgPSBrY3UuY29uc3RyYWludF9uYW1lXG4gICAgICAgIEFORCB0Yy50YWJsZV9zY2hlbWEgPSBrY3UudGFibGVfc2NoZW1hXG4gICAgICBKT0lOIGluZm9ybWF0aW9uX3NjaGVtYS5jb25zdHJhaW50X2NvbHVtbl91c2FnZSBBUyBjY3VcbiAgICAgICAgT04gY2N1LmNvbnN0cmFpbnRfbmFtZSA9IHRjLmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgY2N1LnRhYmxlX3NjaGVtYSA9IHRjLnRhYmxlX3NjaGVtYVxuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEucmVmZXJlbnRpYWxfY29uc3RyYWludHMgQVMgcmNcbiAgICAgICAgT04gcmMuY29uc3RyYWludF9uYW1lID0gdGMuY29uc3RyYWludF9uYW1lXG4gICAgICAgIEFORCByYy5jb25zdHJhaW50X3NjaGVtYSA9IHRjLnRhYmxlX3NjaGVtYVxuICAgICAgV0hFUkUgdGMuY29uc3RyYWludF90eXBlID0gJ0ZPUkVJR04gS0VZJ1xuICAgICAgICBBTkQgdGMudGFibGVfbmFtZSA9ID9cbiAgICBgO1xuICAgIGNvbnN0IGZvcmVpZ25zID0gKGF3YWl0IGNvbXBhcmVEQi5yYXcoZm9yZWlnbnNRdWVyeSwgW3RhYmxlTmFtZV0pKS5yb3dzO1xuXG4gICAgcmV0dXJuIFtjb2x1bW5zLCBpbmRleGVzLCBmb3JlaWduc107XG4gIH1cblxuICBwcml2YXRlIHJlc3RvcmVNaWdyYXRpb25JbmRleFR5cGUoXG4gICAgaW5kZXg6IFBpY2s8UGdJbmRleCwgXCJpc191bmlxdWVcIiB8IFwiaW5kZXhfdHlwZVwiPixcbiAgICBhY2Nlc3NNZXRob2Q/OiBzdHJpbmcsXG4gICk6IE1pZ3JhdGlvbkluZGV4W1widHlwZVwiXSB7XG4gICAgY29uc3QgcmVzb2x2ZWRBY2Nlc3NNZXRob2QgPSAoYWNjZXNzTWV0aG9kID8/IGluZGV4LmluZGV4X3R5cGUpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAocmVzb2x2ZWRBY2Nlc3NNZXRob2QgPT09IFwiaG5zd1wiIHx8IHJlc29sdmVkQWNjZXNzTWV0aG9kID09PSBcIml2ZmZsYXRcIikge1xuICAgICAgcmV0dXJuIHJlc29sdmVkQWNjZXNzTWV0aG9kO1xuICAgIH1cblxuICAgIHJldHVybiBpbmRleC5pc191bmlxdWUgPyBcInVuaXF1ZVwiIDogXCJpbmRleFwiO1xuICB9XG5cbiAgcHJpdmF0ZSByZXN0b3JlR2VuZXJpY1VzaW5nKFxuICAgIGFjY2Vzc01ldGhvZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICApOiBNaWdyYXRpb25JbmRleFtcInVzaW5nXCJdIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWFjY2Vzc01ldGhvZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBub3JtYWxpemVkID0gYWNjZXNzTWV0aG9kLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKCF0aGlzLmdlbmVyaWNJbmRleFR5cGVzLmhhcyhub3JtYWxpemVkKSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gbm9ybWFsaXplZCBhcyBNaWdyYXRpb25JbmRleFtcInVzaW5nXCJdO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVZlY3RvckluZGV4T3B0aW9ucyhcbiAgICB0eXBlOiBNaWdyYXRpb25JbmRleFtcInR5cGVcIl0sXG4gICAgd2l0aE9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICk6IFBpY2s8TWlncmF0aW9uSW5kZXgsIFwibVwiIHwgXCJlZkNvbnN0cnVjdGlvblwiIHwgXCJsaXN0c1wiPiB7XG4gICAgaWYgKHR5cGUgPT09IFwiaG5zd1wiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi4odGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMubSkgIT09IHVuZGVmaW5lZFxuICAgICAgICAgID8geyBtOiB0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5tKSB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICAgIC4uLih0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5lZl9jb25zdHJ1Y3Rpb24pICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgZWZDb25zdHJ1Y3Rpb246IHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLmVmX2NvbnN0cnVjdGlvbikgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gXCJpdmZmbGF0XCIpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5saXN0cykgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IHsgbGlzdHM6IHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLmxpc3RzKSB9XG4gICAgICAgIDoge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUludGVnZXJPcHRpb24odmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZWQgPSBOdW1iZXIucGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICByZXR1cm4gTnVtYmVyLmlzTmFOKHBhcnNlZCkgPyB1bmRlZmluZWQgOiBwYXJzZWQ7XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RJbmRleENvbHVtbk9wY2xhc3MoY29sdW1uRGVmaW5pdGlvbjogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWNvbHVtbkRlZmluaXRpb24pIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgdHJpbW1lZCA9IGNvbHVtbkRlZmluaXRpb25cbiAgICAgIC5yZXBsYWNlKC9cXHMrTlVMTFNcXHMrKEZJUlNUfExBU1QpXFxzKiQvaSwgXCJcIilcbiAgICAgIC5yZXBsYWNlKC9cXHMrKEFTQ3xERVNDKVxccyokL2ksIFwiXCIpXG4gICAgICAudHJpbSgpO1xuICAgIGNvbnN0IHRva2VucyA9IHRoaXMudG9rZW5pemVUb3BMZXZlbCh0cmltbWVkKTtcblxuICAgIGlmICh0b2tlbnMubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAodG9rZW5zW3Rva2Vucy5sZW5ndGggLSAyXT8udG9VcHBlckNhc2UoKSA9PT0gXCJDT0xMQVRFXCIpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRva2Vucy5hdCgtMSk7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlSW5kZXhEZWZpbml0aW9uKGluZGV4RGVmaW5pdGlvbjogc3RyaW5nKToge1xuICAgIGFjY2Vzc01ldGhvZD86IHN0cmluZztcbiAgICBjb2x1bW5EZWZpbml0aW9uczogc3RyaW5nW107XG4gICAgd2l0aE9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIH0ge1xuICAgIGNvbnN0IGFjY2Vzc01ldGhvZCA9IGluZGV4RGVmaW5pdGlvbi5tYXRjaCgvXFxiVVNJTkdcXHMrKFthLXpfXVtcXHddKikvaSk/LlsxXT8udG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCB1c2luZ01hdGNoSW5kZXggPSBpbmRleERlZmluaXRpb24uc2VhcmNoKC9cXGJVU0lOR1xcYi9pKTtcbiAgICBjb25zdCBjb2x1bW5zU3RhcnQgPSB1c2luZ01hdGNoSW5kZXggPj0gMCA/IGluZGV4RGVmaW5pdGlvbi5pbmRleE9mKFwiKFwiLCB1c2luZ01hdGNoSW5kZXgpIDogLTE7XG4gICAgY29uc3QgY29sdW1uc0VuZCA9XG4gICAgICBjb2x1bW5zU3RhcnQgPj0gMCA/IHRoaXMuZmluZE1hdGNoaW5nUGFyZW50aGVzaXMoaW5kZXhEZWZpbml0aW9uLCBjb2x1bW5zU3RhcnQpIDogLTE7XG4gICAgY29uc3QgY29sdW1uRGVmaW5pdGlvbnMgPVxuICAgICAgY29sdW1uc1N0YXJ0ID49IDAgJiYgY29sdW1uc0VuZCA+IGNvbHVtbnNTdGFydFxuICAgICAgICA/IHRoaXMuc3BsaXRUb3BMZXZlbChpbmRleERlZmluaXRpb24uc2xpY2UoY29sdW1uc1N0YXJ0ICsgMSwgY29sdW1uc0VuZCksIFwiLFwiKVxuICAgICAgICA6IFtdO1xuXG4gICAgY29uc3Qgd2l0aE1hdGNoID0gL1xcYldJVEhcXHMqXFwoL2kuZXhlYyhpbmRleERlZmluaXRpb24pO1xuICAgIGNvbnN0IHdpdGhTdGFydCA9IHdpdGhNYXRjaCA/IGluZGV4RGVmaW5pdGlvbi5pbmRleE9mKFwiKFwiLCB3aXRoTWF0Y2guaW5kZXgpIDogLTE7XG4gICAgY29uc3Qgd2l0aEVuZCA9IHdpdGhTdGFydCA+PSAwID8gdGhpcy5maW5kTWF0Y2hpbmdQYXJlbnRoZXNpcyhpbmRleERlZmluaXRpb24sIHdpdGhTdGFydCkgOiAtMTtcbiAgICBjb25zdCB3aXRoT3B0aW9ucyA9XG4gICAgICB3aXRoU3RhcnQgPj0gMCAmJiB3aXRoRW5kID4gd2l0aFN0YXJ0XG4gICAgICAgID8gdGhpcy5wYXJzZUluZGV4T3B0aW9uRW50cmllcyhpbmRleERlZmluaXRpb24uc2xpY2Uod2l0aFN0YXJ0ICsgMSwgd2l0aEVuZCkpXG4gICAgICAgIDoge307XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWNjZXNzTWV0aG9kLFxuICAgICAgY29sdW1uRGVmaW5pdGlvbnMsXG4gICAgICB3aXRoT3B0aW9ucyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUluZGV4T3B0aW9uRW50cmllcyhvcHRpb25Tb3VyY2U6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnNwbGl0VG9wTGV2ZWwob3B0aW9uU291cmNlLCBcIixcIikucmVkdWNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+KChyZXN1bHQsIGVudHJ5KSA9PiB7XG4gICAgICBjb25zdCBtYXRjaGVkID0gZW50cnkudHJpbSgpLm1hdGNoKC9eKFthLXpfXVtcXHddKilcXHMqPVxccyooLispJC9pKTtcbiAgICAgIGlmICghbWF0Y2hlZCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBbLCBrZXksIHJhd1ZhbHVlXSA9IG1hdGNoZWQ7XG4gICAgICByZXN1bHRba2V5LnRvTG93ZXJDYXNlKCldID0gcmF3VmFsdWUudHJpbSgpLnJlcGxhY2UoL15bJ1wiXXxbJ1wiXSQvZywgXCJcIik7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIHt9KTtcbiAgfVxuXG4gIHByaXZhdGUgc3BsaXRUb3BMZXZlbChzb3VyY2U6IHN0cmluZywgZGVsaW1pdGVyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgaXRlbXM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHN0YXJ0ID0gMDtcbiAgICBsZXQgcGFyZW5EZXB0aCA9IDA7XG4gICAgbGV0IGJyYWNrZXREZXB0aCA9IDA7XG4gICAgbGV0IGluU2luZ2xlUXVvdGUgPSBmYWxzZTtcbiAgICBsZXQgaW5Eb3VibGVRdW90ZSA9IGZhbHNlO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgY29uc3QgbmV4dENoYXIgPSBzb3VyY2VbaW5kZXggKyAxXTtcblxuICAgICAgaWYgKGNoYXIgPT09IFwiJ1wiICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChpblNpbmdsZVF1b3RlICYmIG5leHRDaGFyID09PSBcIidcIikge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5TaW5nbGVRdW90ZSA9ICFpblNpbmdsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09ICdcIicgJiYgIWluU2luZ2xlUXVvdGUpIHtcbiAgICAgICAgaWYgKGluRG91YmxlUXVvdGUgJiYgbmV4dENoYXIgPT09ICdcIicpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluRG91YmxlUXVvdGUgPSAhaW5Eb3VibGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpblNpbmdsZVF1b3RlIHx8IGluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSBcIihcIikge1xuICAgICAgICBwYXJlbkRlcHRoICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09IFwiKVwiKSB7XG4gICAgICAgIHBhcmVuRGVwdGggLT0gMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoY2hhciA9PT0gXCJbXCIpIHtcbiAgICAgICAgYnJhY2tldERlcHRoICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09IFwiXVwiKSB7XG4gICAgICAgIGJyYWNrZXREZXB0aCAtPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09IGRlbGltaXRlciAmJiBwYXJlbkRlcHRoID09PSAwICYmIGJyYWNrZXREZXB0aCA9PT0gMCkge1xuICAgICAgICBpdGVtcy5wdXNoKHNvdXJjZS5zbGljZShzdGFydCwgaW5kZXgpLnRyaW0oKSk7XG4gICAgICAgIHN0YXJ0ID0gaW5kZXggKyAxO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRhaWwgPSBzb3VyY2Uuc2xpY2Uoc3RhcnQpLnRyaW0oKTtcbiAgICBpZiAodGFpbC5sZW5ndGggPiAwKSB7XG4gICAgICBpdGVtcy5wdXNoKHRhaWwpO1xuICAgIH1cblxuICAgIHJldHVybiBpdGVtcztcbiAgfVxuXG4gIHByaXZhdGUgdG9rZW5pemVUb3BMZXZlbChzb3VyY2U6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB0b2tlbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHN0YXJ0ID0gLTE7XG4gICAgbGV0IHBhcmVuRGVwdGggPSAwO1xuICAgIGxldCBicmFja2V0RGVwdGggPSAwO1xuICAgIGxldCBpblNpbmdsZVF1b3RlID0gZmFsc2U7XG4gICAgbGV0IGluRG91YmxlUXVvdGUgPSBmYWxzZTtcblxuICAgIGNvbnN0IHB1c2hUb2tlbiA9IChlbmRJbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdG9rZW4gPSBzb3VyY2Uuc2xpY2Uoc3RhcnQsIGVuZEluZGV4KS50cmltKCk7XG4gICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICB0b2tlbnMucHVzaCh0b2tlbik7XG4gICAgICB9XG4gICAgICBzdGFydCA9IC0xO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgc291cmNlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgY2hhciA9IHNvdXJjZVtpbmRleF07XG4gICAgICBjb25zdCBuZXh0Q2hhciA9IHNvdXJjZVtpbmRleCArIDFdO1xuXG4gICAgICBpZiAoY2hhciA9PT0gXCInXCIgJiYgIWluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluU2luZ2xlUXVvdGUgJiYgbmV4dENoYXIgPT09IFwiJ1wiKSB7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpblNpbmdsZVF1b3RlID0gIWluU2luZ2xlUXVvdGU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gJ1wiJyAmJiAhaW5TaW5nbGVRdW90ZSkge1xuICAgICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgICAgc3RhcnQgPSBpbmRleDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5Eb3VibGVRdW90ZSAmJiBuZXh0Q2hhciA9PT0gJ1wiJykge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5Eb3VibGVRdW90ZSA9ICFpbkRvdWJsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpblNpbmdsZVF1b3RlICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChjaGFyID09PSBcIihcIikge1xuICAgICAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBhcmVuRGVwdGggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhciA9PT0gXCIpXCIpIHtcbiAgICAgICAgICBwYXJlbkRlcHRoIC09IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09IFwiW1wiKSB7XG4gICAgICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICAgICAgc3RhcnQgPSBpbmRleDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJhY2tldERlcHRoICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09IFwiXVwiKSB7XG4gICAgICAgICAgYnJhY2tldERlcHRoIC09IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoL1xccy8udGVzdChjaGFyKSAmJiBwYXJlbkRlcHRoID09PSAwICYmIGJyYWNrZXREZXB0aCA9PT0gMCkge1xuICAgICAgICAgIHB1c2hUb2tlbihpbmRleCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IGluZGV4O1xuICAgICAgfVxuICAgIH1cblxuICAgIHB1c2hUb2tlbihzb3VyY2UubGVuZ3RoKTtcbiAgICByZXR1cm4gdG9rZW5zO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kTWF0Y2hpbmdQYXJlbnRoZXNpcyhzb3VyY2U6IHN0cmluZywgb3BlbkluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBkZXB0aCA9IDA7XG4gICAgbGV0IGluU2luZ2xlUXVvdGUgPSBmYWxzZTtcbiAgICBsZXQgaW5Eb3VibGVRdW90ZSA9IGZhbHNlO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSBvcGVuSW5kZXg7IGluZGV4IDwgc291cmNlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgY2hhciA9IHNvdXJjZVtpbmRleF07XG4gICAgICBjb25zdCBuZXh0Q2hhciA9IHNvdXJjZVtpbmRleCArIDFdO1xuXG4gICAgICBpZiAoY2hhciA9PT0gXCInXCIgJiYgIWluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgaWYgKGluU2luZ2xlUXVvdGUgJiYgbmV4dENoYXIgPT09IFwiJ1wiKSB7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpblNpbmdsZVF1b3RlID0gIWluU2luZ2xlUXVvdGU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gJ1wiJyAmJiAhaW5TaW5nbGVRdW90ZSkge1xuICAgICAgICBpZiAoaW5Eb3VibGVRdW90ZSAmJiBuZXh0Q2hhciA9PT0gJ1wiJykge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5Eb3VibGVRdW90ZSA9ICFpbkRvdWJsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGluU2luZ2xlUXVvdGUgfHwgaW5Eb3VibGVRdW90ZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09IFwiKFwiKSB7XG4gICAgICAgIGRlcHRoICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gXCIpXCIpIHtcbiAgICAgICAgZGVwdGggLT0gMTtcbiAgICAgICAgaWYgKGRlcHRoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIO2KueyglSDthYzsnbTruJTsnZggUEvrpbwg7LC47KGw7ZWY64qUIOuLpOuluCDthYzsnbTruJTsnZggRksg66qp66Gd7J2EIOyhsO2ajO2VqeuLiOuLpC5cbiAgICogUEsg7YOA7J6FIOuzgOqyvSDsi5wg6rSA66CoIEZLIOygnOyVveyhsOqxtOydhCDsgq3soJwv67O16rWs7ZWY6riwIOychO2VtCDsgqzsmqnrkKnri4jri6QuXG4gICAqL1xuICBhc3luYyBnZXRSZWZlcmVuY2luZ0ZvcmVpZ25LZXlzKGRiOiBLbmV4LCB0YWJsZU5hbWU6IHN0cmluZyk6IFByb21pc2U8UmVmZXJlbmNpbmdGb3JlaWduS2V5W10+IHtcbiAgICBjb25zdCBxdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICB0Yy50YWJsZV9uYW1lLFxuICAgICAgICB0Yy5jb25zdHJhaW50X25hbWUsXG4gICAgICAgIGtjdS5jb2x1bW5fbmFtZSxcbiAgICAgICAgY2N1LnRhYmxlX25hbWUgQVMgcmVmZXJlbmNlZF90YWJsZV9uYW1lLFxuICAgICAgICBjY3UuY29sdW1uX25hbWUgQVMgcmVmZXJlbmNlZF9jb2x1bW5fbmFtZSxcbiAgICAgICAgcmMudXBkYXRlX3J1bGUsXG4gICAgICAgIHJjLmRlbGV0ZV9ydWxlXG4gICAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZV9jb25zdHJhaW50cyBBUyB0Y1xuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEua2V5X2NvbHVtbl91c2FnZSBBUyBrY3VcbiAgICAgICAgT04gdGMuY29uc3RyYWludF9uYW1lID0ga2N1LmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgdGMudGFibGVfc2NoZW1hID0ga2N1LnRhYmxlX3NjaGVtYVxuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEuY29uc3RyYWludF9jb2x1bW5fdXNhZ2UgQVMgY2N1XG4gICAgICAgIE9OIGNjdS5jb25zdHJhaW50X25hbWUgPSB0Yy5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIGNjdS50YWJsZV9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLnJlZmVyZW50aWFsX2NvbnN0cmFpbnRzIEFTIHJjXG4gICAgICAgIE9OIHJjLmNvbnN0cmFpbnRfbmFtZSA9IHRjLmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgcmMuY29uc3RyYWludF9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIFdIRVJFIHRjLmNvbnN0cmFpbnRfdHlwZSA9ICdGT1JFSUdOIEtFWSdcbiAgICAgICAgQU5EIGNjdS50YWJsZV9uYW1lID0gP1xuICAgICAgICBBTkQgdGMudGFibGVfc2NoZW1hID0gJ3B1YmxpYydcbiAgICBgO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGIucmF3KHF1ZXJ5LCBbdGFibGVOYW1lXSk7XG4gICAgcmV0dXJuIHJlc3VsdC5yb3dzLm1hcChcbiAgICAgIChyb3c6IHtcbiAgICAgICAgdGFibGVfbmFtZTogc3RyaW5nO1xuICAgICAgICBjb25zdHJhaW50X25hbWU6IHN0cmluZztcbiAgICAgICAgY29sdW1uX25hbWU6IHN0cmluZztcbiAgICAgICAgcmVmZXJlbmNlZF90YWJsZV9uYW1lOiBzdHJpbmc7XG4gICAgICAgIHJlZmVyZW5jZWRfY29sdW1uX25hbWU6IHN0cmluZztcbiAgICAgICAgdXBkYXRlX3J1bGU6IHN0cmluZztcbiAgICAgICAgZGVsZXRlX3J1bGU6IHN0cmluZztcbiAgICAgIH0pID0+ICh7XG4gICAgICAgIHRhYmxlTmFtZTogcm93LnRhYmxlX25hbWUsXG4gICAgICAgIGNvbnN0cmFpbnROYW1lOiByb3cuY29uc3RyYWludF9uYW1lLFxuICAgICAgICBjb2x1bW5OYW1lOiByb3cuY29sdW1uX25hbWUsXG4gICAgICAgIHJlZmVyZW5jZWRUYWJsZU5hbWU6IHJvdy5yZWZlcmVuY2VkX3RhYmxlX25hbWUsXG4gICAgICAgIHJlZmVyZW5jZWRDb2x1bW5OYW1lOiByb3cucmVmZXJlbmNlZF9jb2x1bW5fbmFtZSxcbiAgICAgICAgb25VcGRhdGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihyb3cudXBkYXRlX3J1bGUpLFxuICAgICAgICBvbkRlbGV0ZTogdGhpcy5tYXBDb25zdHJhaW50QWN0aW9uKHJvdy5kZWxldGVfcnVsZSksXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIHZlY3RvciDsu6zrn7zsnZggZGltZW5zaW9uc+ulvCDsobDtmoztlanri4jri6QuXG4gICAqIHBnX2F0dHJpYnV0ZeydmCBhdHR0eXBtb2Tsl5DshJwg7LCo7JuQIOyImOulvCDstpTstpztlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFZlY3RvckRpbWVuc2lvbnMoXG4gICAgY29tcGFyZURCOiBSYXdDYXBhYmxlS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+PiB7XG4gICAgY29uc3QgcXVlcnkgPSBgXG4gICAgICBTRUxFQ1RcbiAgICAgICAgYS5hdHRuYW1lIGFzIGNvbHVtbl9uYW1lLFxuICAgICAgICBhLmF0dHR5cG1vZCBhcyBkaW1lbnNpb25zXG4gICAgICBGUk9NIHBnX2F0dHJpYnV0ZSBhXG4gICAgICBKT0lOIHBnX2NsYXNzIGMgT04gYS5hdHRyZWxpZCA9IGMub2lkXG4gICAgICBKT0lOIHBnX3R5cGUgdCBPTiBhLmF0dHR5cGlkID0gdC5vaWRcbiAgICAgIFdIRVJFIGMucmVsbmFtZSA9ID9cbiAgICAgICAgQU5EIHQudHlwbmFtZSA9ICd2ZWN0b3InXG4gICAgICAgIEFORCBhLmF0dG51bSA+IDBcbiAgICBgO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbXBhcmVEQi5yYXcocXVlcnksIFt0YWJsZU5hbWVdKTtcbiAgICBjb25zdCBkaW1lbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG4gICAgZm9yIChjb25zdCByb3cgb2YgcmVzdWx0LnJvd3MpIHtcbiAgICAgIC8vIGF0dHR5cG1vZOyXkOyEnCDsi6TsoJwgZGltZW5zaW9ucyDqsJIg7LaU7LacXG4gICAgICBkaW1lbnNpb25zW3Jvdy5jb2x1bW5fbmFtZV0gPSByb3cuZGltZW5zaW9ucyA+IDAgPyByb3cuZGltZW5zaW9ucyA6IDA7XG4gICAgfVxuICAgIHJldHVybiBkaW1lbnNpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvc3RncmVTUUwg7Lus65+8IO2DgOyeheydhCDrtoTshJ3tlZjsl6wgTWlncmF0aW9uQ29sdW1uIOqwneyytOuhnCDrs4DtmZjtlanri4jri6QuXG4gICAqL1xuICByZXNvbHZlREJDb2xUeXBlKFxuICAgIGRiQ29sdW1uOiBQZ0NvbHVtbixcbiAgKTogUGljazxcbiAgICBNaWdyYXRpb25Db2x1bW4sXG4gICAgXCJ0eXBlXCIgfCBcImxlbmd0aFwiIHwgXCJwcmVjaXNpb25cIiB8IFwic2NhbGVcIiB8IFwibnVtYmVyVHlwZVwiIHwgXCJkaW1lbnNpb25zXCJcbiAgPiB7XG4gICAgY29uc3QgeyB1ZHRfbmFtZTogX3VkdF9uYW1lLCBjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGgsIHByZWNpc2lvbiwgbnVtZXJpY19zY2FsZSB9ID0gZGJDb2x1bW47XG5cbiAgICBjb25zdCB7IHVkdF9uYW1lLCBzaW5nbGVPckFycmF5IH0gPSAoKCkgPT4ge1xuICAgICAgaWYgKF91ZHRfbmFtZS5zdGFydHNXaXRoKFwiX1wiKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHVkdF9uYW1lOiBfdWR0X25hbWUuc3Vic3RyaW5nKDEpLFxuICAgICAgICAgIHNpbmdsZU9yQXJyYXk6IFwiW11cIiBhcyBjb25zdCxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHVkdF9uYW1lOiBfdWR0X25hbWUsXG4gICAgICAgIHNpbmdsZU9yQXJyYXk6IFwiXCIgYXMgY29uc3QsXG4gICAgICB9O1xuICAgIH0pKCk7XG5cbiAgICAvLyBVVUlEXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInV1aWRcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYHV1aWQke3NpbmdsZU9yQXJyYXl9YCB9O1xuICAgIH1cblxuICAgIC8vIEludGVnZXIgdHlwZXNcbiAgICBpZiAodWR0X25hbWUgPT09IFwiaW50NFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgaW50ZWdlciR7c2luZ2xlT3JBcnJheX1gIH07XG4gICAgfVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJpbnQ4XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBiaWdJbnRlZ2VyJHtzaW5nbGVPckFycmF5fWAgfTtcbiAgICB9XG5cbiAgICAvLyBTdHJpbmcgdHlwZXNcbiAgICBpZiAodWR0X25hbWUgPT09IFwidmFyY2hhclwiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBgc3RyaW5nJHtzaW5nbGVPckFycmF5fWAsXG4gICAgICAgIC4uLihjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGggJiYge1xuICAgICAgICAgIGxlbmd0aDogY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoLFxuICAgICAgICB9KSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ0ZXh0XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBzdHJpbmcke3NpbmdsZU9yQXJyYXl9YCB9OyAvLyBTdHJpbmdQcm9wIHdpdGhvdXQgbGVuZ3RoXG4gICAgfVxuXG4gICAgLy8gTnVtYmVyT3JOdW1lcmljIHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcIm51bWVyaWNcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogYG51bWJlck9yTnVtZXJpYyR7c2luZ2xlT3JBcnJheX1gLFxuICAgICAgICBudW1iZXJUeXBlOiBcIm51bWVyaWNcIixcbiAgICAgICAgLi4uKHByZWNpc2lvbiAhPT0gbnVsbCAmJlxuICAgICAgICAgIG51bWVyaWNfc2NhbGUgIT09IG51bGwgJiYge1xuICAgICAgICAgICAgcHJlY2lzaW9uOiBwcmVjaXNpb24sXG4gICAgICAgICAgICBzY2FsZTogbnVtZXJpY19zY2FsZSxcbiAgICAgICAgICB9KSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJmbG9hdDRcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYG51bWJlck9yTnVtZXJpYyR7c2luZ2xlT3JBcnJheX1gLCBudW1iZXJUeXBlOiBcInJlYWxcIiB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwiZmxvYXQ4XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBudW1iZXJPck51bWVyaWMke3NpbmdsZU9yQXJyYXl9YCwgbnVtYmVyVHlwZTogXCJkb3VibGUgcHJlY2lzaW9uXCIgfTtcbiAgICB9XG5cbiAgICAvLyBCb29sZWFuXG4gICAgaWYgKHVkdF9uYW1lID09PSBcImJvb2xcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYGJvb2xlYW4ke3NpbmdsZU9yQXJyYXl9YCB9O1xuICAgIH1cblxuICAgIC8vIFRpbWVzdGFtcHogdHlwZXNcbiAgICBpZiAodWR0X25hbWUgPT09IFwidGltZXN0YW1wdHpcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogYGRhdGUke3NpbmdsZU9yQXJyYXl9YCxcbiAgICAgICAgLi4uKHByZWNpc2lvbiAhPT0gbnVsbCAmJiB7XG4gICAgICAgICAgcHJlY2lzaW9uOiBwcmVjaXNpb24sXG4gICAgICAgIH0pLFxuICAgICAgfTsgLy8gRGF0ZVByb3Ag4oaSIHRpbWVzdGFtcHR6XG4gICAgfVxuXG4gICAgLy8gSlNPTlxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJqc29uXCIgfHwgdWR0X25hbWUgPT09IFwianNvbmJcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogXCJqc29uXCIgfTtcbiAgICB9XG5cbiAgICAvLyBWZWN0b3IgKHBndmVjdG9yKVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ2ZWN0b3JcIikge1xuICAgICAgLy8gdmVjdG9yIO2DgOyeheydmCDssKjsm5Ag7IiY64qUIGNvbHVtbl9kZWZhdWx064KYIOuzhOuPhCDsv7zrpqzroZwg7ZmV7J247ZW07JW8IO2VqFxuICAgICAgLy8g7ZiE7J6s64qUIOq4sOuzuOqwkiAw7Jy866GcIOyEpOyglSAo7Iuk7KCcIGRpbWVuc2lvbnPripQgZ2V0TWlncmF0aW9uU2V0RnJvbURC7JeQ7IScIOuzhOuPhCDsv7zrpqzroZwg7ZmV7J24KVxuICAgICAgcmV0dXJuIHsgdHlwZTogYHZlY3RvciR7c2luZ2xlT3JBcnJheX1gLCBkaW1lbnNpb25zOiAwIH07XG4gICAgfVxuXG4gICAgLy8gdHN2ZWN0b3IgKFBvc3RncmVTUUwg7KCE66y4IOqygOyDieyaqSDtg4DsnoUpXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInRzdmVjdG9yXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwidHN2ZWN0b3JcIiB9O1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgcmVzb2x2ZSDrtojqsIDriqXtlZwgUG9zdGdyZVNRTCDsu6zrn7wg7YOA7J6FOiAke3VkdF9uYW1lfWApO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyID0gbmV3IFBvc3RncmVTUUxTY2hlbWFSZWFkZXJDbGFzcygpO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0NBdUVN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