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,393 +1,372 @@
1
- /** biome-ignore-all lint/suspicious/noExplicitAny: Puri의 타입은 개별 모델에서 확정되므로 BaseModel에서는 any를 허용함 */ import { getLogger } from "@logtape/logtape";
2
- import { cloneDeep, group, isObject, omit, set } from "radashi";
3
- import { normalizeFilterQuery, validateSonamuFilters } from "../index.js";
4
- import { Sonamu } from "../api/index.js";
5
- import { EntityManager } from "../entity/entity-manager.js";
6
- import { convertDomainToCategory } from "../logger/category.js";
7
- import { getJoinTables, getTableNamesFromWhere } from "../utils/sql-parser.js";
8
- import { chunk } from "../utils/utils.js";
9
- import { DB } from "./db.js";
10
- import { Puri } from "./puri.js";
11
- import { PuriWrapper } from "./puri-wrapper.js";
12
- import { UpsertBuilder } from "./upsert-builder.js";
13
- /**
14
- * 모든 Model 클래스의 기본 클래스
15
- *
16
- * @template TSubsetKey - 서브셋 키 유니온 (예: "A" | "P" | "SS")
17
- * @template TSubsetMapping - 서브셋별 최종 결과 타입 매핑
18
- * @template TSubsetQueries - 서브셋 쿼리 함수 객체
19
- * @template TLoaderQueries - 서브셋별 로더 쿼리 배열 객체
20
- */ export class BaseModelClass {
21
- modelName;
22
- subsetQueries;
23
- loaderQueries;
24
- logger;
25
- constructor(modelName = this.constructor.name, subsetQueries, loaderQueries){
26
- this.modelName = modelName;
27
- this.subsetQueries = subsetQueries;
28
- this.loaderQueries = loaderQueries;
29
- this.logger = getLogger(convertDomainToCategory(this.modelName, "model"));
30
- }
31
- getDB(which) {
32
- return DB.getDB(which);
33
- }
34
- getPuri(which) {
35
- // 트랜잭션 컨텍스트에서 트랜잭션 획득
36
- const trx = DB.getTransactionContext().getTransaction(which);
37
- if (trx) {
38
- return trx;
39
- }
40
- // 트랜잭션이 없으면 새로운 PuriWrapper 반환
41
- const db = this.getDB(which);
42
- return new PuriWrapper(db, new UpsertBuilder());
43
- }
44
- async destroy() {
45
- return DB.destroy();
46
- }
47
- async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
48
- if (!wdb) {
49
- wdb = this.getDB("w");
50
- }
51
- let unqKeys;
52
- let whereInField;
53
- let selectField;
54
- if (unqKeyFields.length > 1) {
55
- whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
56
- selectField = `${whereInField} as tmpUid`;
57
- unqKeys = rows.map((row)=>unqKeyFields.map((field)=>row[field]).join("_"));
58
- } else {
59
- whereInField = unqKeyFields[0];
60
- selectField = unqKeyFields[0];
61
- unqKeys = rows.map((row)=>row[unqKeyFields[0]]);
62
- }
63
- let resultIds = [];
64
- for (const items of chunk(unqKeys, chunkSize)){
65
- const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, items);
66
- resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(String(dbRow.id))));
67
- }
68
- return resultIds;
69
- }
70
- /**
71
- * 특정 서브셋에 대한 쿼리 빌더 획득
72
- *
73
- * @returns qb - 쿼리 빌더 (조건 추가용)
74
- * @returns onSubset - 특정 서브셋 전용 타입이 필요할 때 사용
75
- */ getSubsetQueries(subset) {
76
- if (!this.subsetQueries) {
77
- throw new Error("subsetQueries is not defined");
78
- }
79
- const puriWrapper = new PuriWrapper(this.getDB("r"), new UpsertBuilder());
80
- const qb = this.subsetQueries[subset]?.(puriWrapper);
81
- return {
82
- qb: qb,
83
- onSubset: (_subset)=>qb
84
- };
85
- }
86
- /**
87
- * Enhancer 객체 생성 헬퍼
88
- * 타입 검증 및 추론을 도와줌
89
- */ createEnhancers(enhancers) {
90
- return enhancers;
91
- }
92
- /**
93
- * 서브셋 쿼리 실행
94
- *
95
- * 1. Sonamu 필터 적용 (타입 변환 포함)
96
- * 2. 쿼리 실행 (pagination 적용)
97
- * 3. 로더 실행 (1:N, N:M 관계 데이터 로딩)
98
- * 4. Hydrate (flat → 중첩 객체)
99
- * 5. Enhancer 적용 (virtual 필드 계산)
100
- */ async executeSubsetQuery(params) {
101
- const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
102
- if (!this.loaderQueries) {
103
- throw new Error("loaderQueries is not defined");
104
- }
105
- // Sonamu Filter 적용
106
- if (queryParams.sonamuFilter) {
107
- const normalizedFilter = normalizeFilterQuery(queryParams.sonamuFilter);
108
- this.applySonamuFilters(qb, normalizedFilter);
109
- }
110
- const { num, page } = queryParams;
111
- // COUNT 쿼리 실행 (queryMode: list일 때는 0 리턴)
112
- const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
113
- if (queryParams?.queryMode === "count") {
114
- return {
115
- total
116
- };
117
- }
118
- // LIST 쿼리 실행
119
- const computedRows = await this.executeListQuery(subset, qb, queryParams, num, page, debug);
120
- // Enhancer 적용
121
- const enhancer = params.enhancers?.[subset];
122
- const enhancedRows = await Promise.all(computedRows.map((row)=>enhancer?.(row) ?? row));
123
- // Internal 필드 제거
124
- const entity = EntityManager.get(this.modelName);
125
- const internalFields = entity.subsetsInternal[subset] ?? [];
126
- const rows = internalFields.length > 0 ? enhancedRows.map((row)=>this.omitInternalFields(row, internalFields)) : enhancedRows;
127
- if (queryParams.queryMode === "list") {
128
- // 리스트만 리턴
129
- return {
130
- rows
131
- };
132
- } else {
133
- // 둘다 리턴
134
- return {
135
- rows,
136
- total
137
- };
138
- }
139
- }
140
- /**
141
- * 객체에서 internal 필드 제거
142
- * 중첩 필드(예: "user.email") 및 배열(예: "employees.salary")도 처리
143
- */ omitInternalFields(row, fields) {
144
- const result = cloneDeep(row);
145
- for (const field of fields){
146
- this.deleteField(result, field.split("."));
147
- }
148
- return result;
149
- }
150
- /**
151
- * FilterQuery를 Puri QueryBuilder에 적용
152
- *
153
- * @param qb Puri QueryBuilder 인스턴스
154
- * @param filters FilterQuery 객체
155
- */ applySonamuFilters(qb, filters) {
156
- if (!filters) return;
157
- const entity = EntityManager.get(this.modelName);
158
- // 1. 필터 검증 (Entity 기반)
159
- validateSonamuFilters(filters, entity);
160
- // 2. 검증된 필터 적용
161
- const puri = qb;
162
- for (const [field, condition] of Object.entries(filters)){
163
- if (condition === undefined || condition === null) continue;
164
- // 테이블명.필드명 형식으로 변환
165
- const fullField = entity.getFullFieldName(field);
166
- // 직접 값 (eq와 동일)
167
- if (typeof condition !== "object" || Array.isArray(condition)) {
168
- puri.where(fullField, condition);
169
- continue;
170
- }
171
- // 연산자 객체
172
- for (const [operator, value] of Object.entries(condition)){
173
- this.applyOperator(qb, fullField, operator, value);
174
- }
175
- }
176
- }
177
- /**
178
- * 단일 연산자를 QueryBuilder에 적용
179
- */ applyOperator(qb, field, operator, value) {
180
- const puri = qb;
181
- switch(operator){
182
- case "eq":
183
- puri.where(field, value);
184
- break;
185
- case "ne":
186
- puri.where(field, "!=", value);
187
- break;
188
- case "gt":
189
- puri.where(field, ">", value);
190
- break;
191
- case "gte":
192
- puri.where(field, ">=", value);
193
- break;
194
- case "lt":
195
- puri.where(field, "<", value);
196
- break;
197
- case "lte":
198
- puri.where(field, "<=", value);
199
- break;
200
- case "in":
201
- puri.whereIn(field, value);
202
- break;
203
- case "notIn":
204
- puri.whereNotIn(field, value);
205
- break;
206
- case "contains":
207
- puri.where(field, "like", `%${value}%`);
208
- break;
209
- case "startsWith":
210
- puri.where(field, "like", `${value}%`);
211
- break;
212
- case "endsWith":
213
- puri.where(field, "like", `%${value}`);
214
- break;
215
- case "isNull":
216
- puri.where(field, null);
217
- break;
218
- case "isNotNull":
219
- puri.where(field, "!=", null);
220
- break;
221
- case "before":
222
- puri.where(field, "<", value);
223
- break;
224
- case "after":
225
- puri.where(field, ">", value);
226
- break;
227
- case "between":
228
- {
229
- if (Array.isArray(value) && value.length === 2) {
230
- const [min, max] = value;
231
- puri.where(field, ">=", min).where(field, "<=", max);
232
- }
233
- break;
234
- }
235
- default:
236
- console.warn(`Unsupported operator: ${operator}`);
237
- }
238
- }
239
- /**
240
- * 중첩 필드 삭제 (배열 내 객체도 처리)
241
- */ deleteField(obj, parts) {
242
- if (!obj || typeof obj !== "object") {
243
- return;
244
- }
245
- if (parts.length === 1) {
246
- if (Array.isArray(obj)) {
247
- obj.forEach((item)=>{
248
- if (item && typeof item === "object") {
249
- delete item[parts[0]];
250
- }
251
- });
252
- } else {
253
- delete obj[parts[0]];
254
- }
255
- return;
256
- }
257
- const [first, ...rest] = parts;
258
- const next = obj[first];
259
- if (Array.isArray(next)) {
260
- next.map((item)=>this.deleteField(item, rest));
261
- } else if (next && typeof next === "object") {
262
- this.deleteField(next, rest);
263
- }
264
- }
265
- /**
266
- * COUNT 쿼리 실행 (내부 메서드)
267
- */ async executeCountQuery(qb, params, debug, optimizeCountQuery) {
268
- if (params.queryMode === "list") {
269
- return 0;
270
- }
271
- const countPuri = qb.clone().clear("order").clear("limit").clear("offset");
272
- if (optimizeCountQuery) {
273
- const { default: SqlParser } = await import("node-sql-parser");
274
- const parser = new SqlParser.Parser();
275
- const parsedQuery = parser.astify(countPuri.toQuery(), {
276
- database: Sonamu.config.database.database
277
- });
278
- const leftJoinTables = getJoinTables(parsedQuery, [
279
- "LEFT JOIN"
280
- ]);
281
- const whereTables = getTableNamesFromWhere(parsedQuery);
282
- const tablesToRemove = leftJoinTables.filter((j)=>!whereTables.includes(j));
283
- tablesToRemove.forEach((table)=>{
284
- countPuri.clearJoin(table);
285
- });
286
- }
287
- // COUNT(*)로 전체 레코드 수를 계산
288
- // TODO: qb의 DISTINCT가 있는 경우 처리해야 함
289
- const countResult = await countPuri.clear("select").select({
290
- total: Puri.rawNumber(`COUNT(*)::integer`)
291
- }).first();
292
- if (debug) {
293
- countPuri.debug();
294
- }
295
- return countResult?.total ?? 0;
296
- }
297
- /**
298
- * LIST 쿼리 실행 (내부 메서드)
299
- */ async executeListQuery(subset, qb, params, num, page, debug) {
300
- if (params.queryMode === "count") {
301
- return [];
302
- }
303
- const limitedQb = (()=>{
304
- if (num === 0) {
305
- return qb;
306
- } else {
307
- return qb.limit(num).offset(num * (page - 1));
308
- }
309
- })();
310
- let unloadedRows = await limitedQb;
311
- if (debug) {
312
- qb.debug();
313
- }
314
- // 로더 처리
315
- const loaders = this.loaderQueries[subset];
316
- if (loaders && Array.isArray(loaders)) {
317
- unloadedRows = await this.processLoaders(unloadedRows, loaders, debug);
318
- }
319
- return this.hydrate(unloadedRows);
320
- }
321
- /**
322
- * 재귀적 로더 처리
323
- */ async processLoaders(rows, loaders, debug) {
324
- for (const resolveLoader of loaders){
325
- const { as, refId, qb: resolveLoaderQbFn, loaders: nestedLoaders } = resolveLoader;
326
- const resolveLoaderQb = resolveLoaderQbFn(new PuriWrapper(this.getDB("r"), new UpsertBuilder()), rows.map((row)=>row[refId]));
327
- if (debug) {
328
- resolveLoaderQb.debug();
329
- }
330
- let loadedRows = await resolveLoaderQb;
331
- // 중첩 loaders가 있으면 재귀 처리
332
- if (nestedLoaders && nestedLoaders.length > 0) {
333
- loadedRows = await this.processLoaders(loadedRows, nestedLoaders, debug);
334
- }
335
- const subRowGroups = group(loadedRows, (row)=>row.refId);
336
- rows = rows.map((row)=>{
337
- row[as] = (subRowGroups[row[refId]] ?? []).map((r)=>omit(r, [
338
- "refId"
339
- ]));
340
- return row;
341
- });
342
- }
343
- return rows;
344
- }
345
- /**
346
- * Flat 레코드를 중첩 객체로 변환
347
- *
348
- * - `user__name` → `{ user: { name } }`
349
- * - nullable relation의 경우 id 필드가 null이면 객체 자체를 null로
350
- */ hydrate(rows) {
351
- return rows.map((row)=>{
352
- // nullable relation 처리: 그룹의 id 필드가 null이면 객체 전체를 null로
353
- const nestedKeys = Object.keys(row).filter((key)=>key.includes("__"));
354
- const groups = Object.groupBy(nestedKeys, (key)=>key.split("__")[0]);
355
- // id 필드가 null인 그룹 찾기 (예: parent__id가 null이면 parent 그룹 전체가 null)
356
- const nullKeys = Object.entries(groups).filter(([groupKey, fields])=>{
357
- if (!fields || fields.length === 0) return false;
358
- // 그룹의 id 필드 찾기 (예: "parent__id")
359
- const idField = `${groupKey}__id`;
360
- if (idField in row) {
361
- // id 필드가 null이면 객체 전체가 null
362
- return row[idField] === null;
363
- }
364
- // id 필드가 없으면 기존 로직: 모든 필드가 null인지 확인
365
- return fields.every((field)=>row[field] === null || Array.isArray(row[field]) && row[field].length === 0);
366
- }).map(([key])=>key);
367
- const hydrated = Object.keys(row).reduce((r, field)=>{
368
- if (!field.includes("__")) {
369
- // 일반 필드: 배열 내 객체면 재귀 hydrate
370
- if (Array.isArray(row[field]) && isObject(row[field][0])) {
371
- r[field] = this.hydrate(row[field]);
372
- } else {
373
- r[field] = row[field];
374
- }
375
- return r;
376
- }
377
- // 중첩 필드 처리: user__name → user[name]
378
- const parts = field.split("__");
379
- const objPath = parts[0] + parts.slice(1).map((part)=>`[${part}]`).join("");
380
- r = set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
381
- return r;
382
- }, {});
383
- // null relation 처리
384
- nullKeys.forEach((nullKey)=>{
385
- hydrated[nullKey] = null;
386
- });
387
- return hydrated;
388
- });
389
- }
390
- }
391
- export const BaseModel = new BaseModelClass();
1
+ import { __esmMin } from "../_virtual/rolldown_runtime.js";
2
+ import { convertDomainToCategory, init_category } from "../logger/category.js";
3
+ import { DB, init_db } from "./db.js";
4
+ import { Sonamu, init_sonamu } from "../api/sonamu.js";
5
+ import { EntityManager, init_entity_manager } from "../entity/entity-manager.js";
6
+ import { UpsertBuilder, init_upsert_builder } from "./upsert-builder.js";
7
+ import { init_utils, normalizeFilterQuery, validateSonamuFilters } from "../filter/utils.js";
8
+ import { getJoinTables, getTableNamesFromWhere, init_sql_parser } from "../utils/sql-parser.js";
9
+ import { Puri, init_puri } from "./puri.js";
10
+ import { PuriWrapper, init_puri_wrapper } from "./puri-wrapper.js";
11
+ import { getLogger } from "@logtape/logtape";
12
+ import { cloneDeep, cluster, group, isObject, omit, set } from "radashi";
392
13
 
393
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKiBiaW9tZS1pZ25vcmUtYWxsIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBQdXJp7J2YIO2DgOyeheydgCDqsJzrs4Qg66qo64247JeQ7IScIO2ZleygleuQmOuvgOuhnCBCYXNlTW9kZWzsl5DshJzripQgYW5566W8IO2XiOyaqe2VqCAqL1xuaW1wb3J0IHsgZ2V0TG9nZ2VyLCB0eXBlIExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5pbXBvcnQgdHlwZSB7IEtuZXggfSBmcm9tIFwia25leFwiO1xuaW1wb3J0IHsgY2xvbmVEZWVwLCBncm91cCwgaXNPYmplY3QsIG9taXQsIHNldCB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyB0eXBlIExpc3RSZXN1bHQsIG5vcm1hbGl6ZUZpbHRlclF1ZXJ5LCB2YWxpZGF0ZVNvbmFtdUZpbHRlcnMgfSBmcm9tIFwiLi5cIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgdHlwZSB7IEZpbHRlck9wZXJhdG9yLCBGaWx0ZXJRdWVyeSB9IGZyb20gXCIuLi9maWx0ZXIvdHlwZXNcIjtcbmltcG9ydCB7IGNvbnZlcnREb21haW5Ub0NhdGVnb3J5IH0gZnJvbSBcIi4uL2xvZ2dlci9jYXRlZ29yeVwiO1xuaW1wb3J0IHR5cGUgeyBEYXRhYmFzZVNjaGVtYUV4dGVuZCwgU29uYW11UXVlcnlNb2RlIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBnZXRKb2luVGFibGVzLCBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlIH0gZnJvbSBcIi4uL3V0aWxzL3NxbC1wYXJzZXJcIjtcbmltcG9ydCB7IGNodW5rIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IEVuaGFuY2VyTWFwLCBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uIH0gZnJvbSBcIi4vYmFzZS1tb2RlbC50eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBEQlByZXNldCB9IGZyb20gXCIuL2RiXCI7XG5pbXBvcnQgeyBEQiB9IGZyb20gXCIuL2RiXCI7XG5pbXBvcnQgeyBQdXJpIH0gZnJvbSBcIi4vcHVyaVwiO1xuaW1wb3J0IHR5cGUgeyBVbmlvbkV4dHJhY3RlZFRUYWJsZXMgfSBmcm9tIFwiLi9wdXJpLnR5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IEluZmVyQWxsU3Vic2V0cywgUHVyaUxvYWRlclF1ZXJpZXMsIFB1cmlTdWJzZXRGbiB9IGZyb20gXCIuL3B1cmktc3Vic2V0LnR5cGVzXCI7XG5pbXBvcnQgeyBQdXJpV3JhcHBlciB9IGZyb20gXCIuL3B1cmktd3JhcHBlclwiO1xuaW1wb3J0IHsgVXBzZXJ0QnVpbGRlciB9IGZyb20gXCIuL3Vwc2VydC1idWlsZGVyXCI7XG5cbnR5cGUgVW5rbm93bkRCUmVjb3JkID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbi8qKlxuICog66qo65OgIE1vZGVsIO2BtOuemOyKpOydmCDquLDrs7gg7YG0656Y7IqkXG4gKlxuICogQHRlbXBsYXRlIFRTdWJzZXRLZXkgLSDshJzruIzshYsg7YKkIOycoOuLiOyYqCAo7JiIOiBcIkFcIiB8IFwiUFwiIHwgXCJTU1wiKVxuICogQHRlbXBsYXRlIFRTdWJzZXRNYXBwaW5nIC0g7ISc67iM7IWL67OEIOy1nOyihSDqsrDqs7wg7YOA7J6FIOunpO2VkVxuICogQHRlbXBsYXRlIFRTdWJzZXRRdWVyaWVzIC0g7ISc67iM7IWLIOy/vOumrCDtlajsiJgg6rCd7LK0XG4gKiBAdGVtcGxhdGUgVExvYWRlclF1ZXJpZXMgLSDshJzruIzshYvrs4Qg66Gc642UIOy/vOumrCDrsLDsl7Qg6rCd7LK0XG4gKi9cbmV4cG9ydCBjbGFzcyBCYXNlTW9kZWxDbGFzczxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyA9IG5ldmVyLFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlcixcbiAgVFN1YnNldFF1ZXJpZXMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgUHVyaVN1YnNldEZuPiA9IG5ldmVyLFxuICBUTG9hZGVyUXVlcmllcyBleHRlbmRzIFB1cmlMb2FkZXJRdWVyaWVzPFRTdWJzZXRLZXk+ID0gbmV2ZXIsXG4+IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxvZ2dlcjogTG9nZ2VyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBtb2RlbE5hbWU6IHN0cmluZyA9IHRoaXMuY29uc3RydWN0b3IubmFtZSxcbiAgICBwcm90ZWN0ZWQgc3Vic2V0UXVlcmllcz86IFRTdWJzZXRRdWVyaWVzLFxuICAgIHByb3RlY3RlZCBsb2FkZXJRdWVyaWVzPzogVExvYWRlclF1ZXJpZXMsXG4gICkge1xuICAgIHRoaXMubG9nZ2VyID0gZ2V0TG9nZ2VyKGNvbnZlcnREb21haW5Ub0NhdGVnb3J5KHRoaXMubW9kZWxOYW1lLCBcIm1vZGVsXCIpKTtcbiAgfVxuXG4gIGdldERCKHdoaWNoOiBEQlByZXNldCk6IEtuZXgge1xuICAgIHJldHVybiBEQi5nZXREQih3aGljaCk7XG4gIH1cblxuICBnZXRQdXJpKHdoaWNoOiBEQlByZXNldCk6IFB1cmlXcmFwcGVyIHtcbiAgICAvLyDtirjrnpzsnq3shZgg7Luo7YWN7Iqk7Yq47JeQ7IScIO2KuOuenOyereyFmCDtmo3rk51cbiAgICBjb25zdCB0cnggPSBEQi5nZXRUcmFuc2FjdGlvbkNvbnRleHQoKS5nZXRUcmFuc2FjdGlvbih3aGljaCk7XG4gICAgaWYgKHRyeCkge1xuICAgICAgcmV0dXJuIHRyeDtcbiAgICB9XG5cbiAgICAvLyDtirjrnpzsnq3shZjsnbQg7JeG7Jy866m0IOyDiOuhnOyatCBQdXJpV3JhcHBlciDrsJjtmZhcbiAgICBjb25zdCBkYiA9IHRoaXMuZ2V0REIod2hpY2gpO1xuICAgIHJldHVybiBuZXcgUHVyaVdyYXBwZXIoZGIsIG5ldyBVcHNlcnRCdWlsZGVyKCkpO1xuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpIHtcbiAgICByZXR1cm4gREIuZGVzdHJveSgpO1xuICB9XG5cbiAgYXN5bmMgZ2V0SW5zZXJ0ZWRJZHMoXG4gICAgd2RiOiBLbmV4LFxuICAgIHJvd3M6IFVua25vd25EQlJlY29yZFtdLFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHVucUtleUZpZWxkczogc3RyaW5nW10sXG4gICAgY2h1bmtTaXplOiBudW1iZXIgPSA1MDAsXG4gICkge1xuICAgIGlmICghd2RiKSB7XG4gICAgICB3ZGIgPSB0aGlzLmdldERCKFwid1wiKTtcbiAgICB9XG5cbiAgICBsZXQgdW5xS2V5czogc3RyaW5nW107XG4gICAgbGV0IHdoZXJlSW5GaWVsZDogc3RyaW5nIHwgS25leC5SYXc7XG4gICAgbGV0IHNlbGVjdEZpZWxkOiBzdHJpbmc7XG5cbiAgICBpZiAodW5xS2V5RmllbGRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHdkYi5yYXcoYENPTkNBVF9XUygnXycsICcke3VucUtleUZpZWxkcy5qb2luKFwiLFwiKX0nKWApO1xuICAgICAgc2VsZWN0RmllbGQgPSBgJHt3aGVyZUluRmllbGR9IGFzIHRtcFVpZGA7XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT4gdW5xS2V5RmllbGRzLm1hcCgoZmllbGQpID0+IHJvd1tmaWVsZF0pLmpvaW4oXCJfXCIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hlcmVJbkZpZWxkID0gdW5xS2V5RmllbGRzWzBdO1xuICAgICAgc2VsZWN0RmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT4gcm93W3VucUtleUZpZWxkc1swXV0gYXMgc3RyaW5nKTtcbiAgICB9XG5cbiAgICBsZXQgcmVzdWx0SWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaXRlbXMgb2YgY2h1bmsodW5xS2V5cywgY2h1bmtTaXplKSkge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQgYXMgc3RyaW5nLCBpdGVtcyk7XG4gICAgICByZXN1bHRJZHMgPSByZXN1bHRJZHMuY29uY2F0KFxuICAgICAgICBkYlJvd3MubWFwKChkYlJvdzogVW5rbm93bkRCUmVjb3JkKSA9PiBwYXJzZUludChTdHJpbmcoZGJSb3cuaWQpKSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRJZHM7XG4gIH1cblxuICAvKipcbiAgICog7Yq57KCVIOyEnOu4jOyFi+yXkCDrjIDtlZwg7L+866asIOu5jOuNlCDtmo3rk51cbiAgICpcbiAgICogQHJldHVybnMgcWIgLSDsv7zrpqwg67mM642UICjsobDqsbQg7LaU6rCA7JqpKVxuICAgKiBAcmV0dXJucyBvblN1YnNldCAtIO2KueyglSDshJzruIzshYsg7KCE7JqpIO2DgOyeheydtCDtlYTsmpTtlaAg65WMIOyCrOyaqVxuICAgKi9cbiAgZ2V0U3Vic2V0UXVlcmllczxUIGV4dGVuZHMgVFN1YnNldEtleT4oc3Vic2V0OiBUKSB7XG4gICAgaWYgKCF0aGlzLnN1YnNldFF1ZXJpZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInN1YnNldFF1ZXJpZXMgaXMgbm90IGRlZmluZWRcIik7XG4gICAgfVxuXG4gICAgY29uc3QgcHVyaVdyYXBwZXIgPSBuZXcgUHVyaVdyYXBwZXIodGhpcy5nZXREQihcInJcIiksIG5ldyBVcHNlcnRCdWlsZGVyKCkpO1xuICAgIGNvbnN0IHFiID0gdGhpcy5zdWJzZXRRdWVyaWVzW3N1YnNldF0/LihwdXJpV3JhcHBlcik7XG5cbiAgICAvLyBOb25BbGxvd2VkQXNTaW5nbGVUYWJsZTog64uo7J28IO2FjOydtOu4lCDsu6zrn7wg7KCR6re8IOuwqeyngOyaqSDrp4jsu6RcbiAgICB0eXBlIFFCVGFibGVzID0gVW5pb25FeHRyYWN0ZWRUVGFibGVzPFRTdWJzZXRLZXksIFRTdWJzZXRRdWVyaWVzPiAmIHtcbiAgICAgIE5vbkFsbG93ZWRBc1NpbmdsZVRhYmxlOiB7IF9fZnVsbHRleHRfXzogdHJ1ZSB9O1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgcWI6IHFiIGFzIHVua25vd24gYXMgUHVyaTxEYXRhYmFzZVNjaGVtYUV4dGVuZCwgUUJUYWJsZXMsIHt9PixcbiAgICAgIG9uU3Vic2V0OiAoKF9zdWJzZXQ6IFRTdWJzZXRLZXkgfCByZWFkb25seSBUU3Vic2V0S2V5W10pID0+IHFiKSBhcyB7XG4gICAgICAgIC8vIOuLqOydvCDtgqRcbiAgICAgICAgPFMgZXh0ZW5kcyBUU3Vic2V0S2V5PihzdWJzZXQ6IFMpOiBSZXR1cm5UeXBlPFRTdWJzZXRRdWVyaWVzW1NdPjtcbiAgICAgICAgLy8g7YKkIOuwsOyXtCAtPiDqtZDsp5Htlakg67CY7ZmYXG4gICAgICAgIDxBcnIgZXh0ZW5kcyByZWFkb25seSBUU3Vic2V0S2V5W10+KFxuICAgICAgICAgIHN1YnNldHM6IFsuLi5BcnJdLFxuICAgICAgICApOiBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uPEFyciwgVFN1YnNldFF1ZXJpZXM+O1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVuaGFuY2VyIOqwneyytCDsg53shLEg7Zes7Y28XG4gICAqIO2DgOyehSDqsoDspp0g67CPIOy2lOuhoOydhCDrj4TsmYDspIxcbiAgICovXG4gIGNyZWF0ZUVuaGFuY2VyczxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgZW5oYW5jZXJzOiBFbmhhbmNlck1hcDxcbiAgICAgIFQsXG4gICAgICBJbmZlckFsbFN1YnNldHM8VFN1YnNldFF1ZXJpZXMsIFRMb2FkZXJRdWVyaWVzPixcbiAgICAgIFRTdWJzZXRNYXBwaW5nLFxuICAgICAgVFN1YnNldFF1ZXJpZXNcbiAgICA+LFxuICApIHtcbiAgICByZXR1cm4gZW5oYW5jZXJzO1xuICB9XG5cbiAgLyoqXG4gICAqIOyEnOu4jOyFiyDsv7zrpqwg7Iuk7ZaJXG4gICAqXG4gICAqIDEuIFNvbmFtdSDtlYTthLAg7KCB7JqpICjtg4DsnoUg67OA7ZmYIO2PrO2VqClcbiAgICogMi4g7L+866asIOyLpO2WiSAocGFnaW5hdGlvbiDsoIHsmqkpXG4gICAqIDMuIOuhnOuNlCDsi6TtlokgKDE6TiwgTjpNIOq0gOqzhCDrjbDsnbTthLAg66Gc65SpKVxuICAgKiA0LiBIeWRyYXRlIChmbGF0IOKGkiDspJHssqkg6rCd7LK0KVxuICAgKiA1LiBFbmhhbmNlciDsoIHsmqkgKHZpcnR1YWwg7ZWE65OcIOqzhOyCsClcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGVTdWJzZXRRdWVyeTxcbiAgICBUIGV4dGVuZHMgVFN1YnNldEtleSxcbiAgICBUQ29tcHV0ZWRSZXN1bHRzIGV4dGVuZHMgSW5mZXJBbGxTdWJzZXRzPFRTdWJzZXRRdWVyaWVzLCBUTG9hZGVyUXVlcmllcz4sXG4gICAgTFAgZXh0ZW5kcyB7XG4gICAgICBudW0/OiBudW1iZXI7XG4gICAgICBwYWdlPzogbnVtYmVyO1xuICAgICAgcXVlcnlNb2RlPzogU29uYW11UXVlcnlNb2RlO1xuICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgfSxcbiAgPihcbiAgICBwYXJhbXM6IHtcbiAgICAgIHN1YnNldDogVDtcbiAgICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+O1xuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIG51bTogbnVtYmVyO1xuICAgICAgICBwYWdlOiBudW1iZXI7XG4gICAgICAgIHF1ZXJ5TW9kZT86IFNvbmFtdVF1ZXJ5TW9kZTtcbiAgICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICB9O1xuICAgICAgZGVidWc/OiBib29sZWFuO1xuICAgICAgb3B0aW1pemVDb3VudFF1ZXJ5PzogYm9vbGVhbjtcbiAgICB9ICYgRW5oYW5jZXJQYXJhbTxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZywgVFN1YnNldFF1ZXJpZXM+LFxuICApOiBQcm9taXNlPExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPj4ge1xuICAgIGNvbnN0IHsgc3Vic2V0LCBxYiwgcGFyYW1zOiBxdWVyeVBhcmFtcywgZGVidWcgPSBmYWxzZSwgb3B0aW1pemVDb3VudFF1ZXJ5ID0gZmFsc2UgfSA9IHBhcmFtcztcblxuICAgIGlmICghdGhpcy5sb2FkZXJRdWVyaWVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsb2FkZXJRdWVyaWVzIGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIC8vIFNvbmFtdSBGaWx0ZXIg7KCB7JqpXG4gICAgaWYgKHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcikge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbHRlciA9IG5vcm1hbGl6ZUZpbHRlclF1ZXJ5KHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcik7XG4gICAgICB0aGlzLmFwcGx5U29uYW11RmlsdGVycyhxYiwgbm9ybWFsaXplZEZpbHRlcik7XG4gICAgfVxuXG4gICAgY29uc3QgeyBudW0sIHBhZ2UgfSA9IHF1ZXJ5UGFyYW1zO1xuXG4gICAgLy8gQ09VTlQg7L+866asIOyLpO2WiSAocXVlcnlNb2RlOiBsaXN07J28IOuVjOuKlCAwIOumrO2EtClcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNvdW50UXVlcnkocWIsIHF1ZXJ5UGFyYW1zLCBkZWJ1Zywgb3B0aW1pemVDb3VudFF1ZXJ5KTtcblxuICAgIGlmIChxdWVyeVBhcmFtcz8ucXVlcnlNb2RlID09PSBcImNvdW50XCIpIHtcbiAgICAgIHJldHVybiB7IHRvdGFsIH0gYXMgTGlzdFJlc3VsdDxMUCwgVFN1YnNldE1hcHBpbmdbVF0+O1xuICAgIH1cblxuICAgIC8vIExJU1Qg7L+866asIOyLpO2WiVxuICAgIGNvbnN0IGNvbXB1dGVkUm93cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZUxpc3RRdWVyeShzdWJzZXQsIHFiLCBxdWVyeVBhcmFtcywgbnVtLCBwYWdlLCBkZWJ1Zyk7XG5cbiAgICAvLyBFbmhhbmNlciDsoIHsmqlcbiAgICBjb25zdCBlbmhhbmNlciA9IChwYXJhbXMgYXMgYW55KS5lbmhhbmNlcnM/LltzdWJzZXRdO1xuICAgIGNvbnN0IGVuaGFuY2VkUm93cyA9IChhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGNvbXB1dGVkUm93cy5tYXAoKHJvdykgPT4gZW5oYW5jZXI/Lihyb3cpID8/IHJvdyksXG4gICAgKSkgYXMgVFN1YnNldE1hcHBpbmdbVF1bXTtcblxuICAgIC8vIEludGVybmFsIO2VhOuTnCDsoJzqsbBcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldCh0aGlzLm1vZGVsTmFtZSk7XG4gICAgY29uc3QgaW50ZXJuYWxGaWVsZHMgPSBlbnRpdHkuc3Vic2V0c0ludGVybmFsW3N1YnNldF0gPz8gW107XG4gICAgY29uc3Qgcm93cyA9XG4gICAgICBpbnRlcm5hbEZpZWxkcy5sZW5ndGggPiAwXG4gICAgICAgID8gZW5oYW5jZWRSb3dzLm1hcCgocm93KSA9PiB0aGlzLm9taXRJbnRlcm5hbEZpZWxkcyhyb3csIGludGVybmFsRmllbGRzKSlcbiAgICAgICAgOiBlbmhhbmNlZFJvd3M7XG5cbiAgICBpZiAocXVlcnlQYXJhbXMucXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgLy8g66as7Iqk7Yq466eMIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cyB9IGFzIExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8g65GY64ukIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cywgdG90YWwgfSBhcyBMaXN0UmVzdWx0PExQLCBUU3Vic2V0TWFwcGluZ1tUXT47XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOqwneyytOyXkOyEnCBpbnRlcm5hbCDtlYTrk5wg7KCc6rGwXG4gICAqIOykkeyyqSDtlYTrk5wo7JiIOiBcInVzZXIuZW1haWxcIikg67CPIOuwsOyXtCjsmIg6IFwiZW1wbG95ZWVzLnNhbGFyeVwiKeuPhCDsspjrpqxcbiAgICovXG4gIG9taXRJbnRlcm5hbEZpZWxkczxUIGV4dGVuZHMgb2JqZWN0Pihyb3c6IFQsIGZpZWxkczogc3RyaW5nW10pOiBUIHtcbiAgICBjb25zdCByZXN1bHQgPSBjbG9uZURlZXAocm93KTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykge1xuICAgICAgdGhpcy5kZWxldGVGaWVsZChyZXN1bHQsIGZpZWxkLnNwbGl0KFwiLlwiKSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRmlsdGVyUXVlcnnrpbwgUHVyaSBRdWVyeUJ1aWxkZXLsl5Ag7KCB7JqpXG4gICAqXG4gICAqIEBwYXJhbSBxYiBQdXJpIFF1ZXJ5QnVpbGRlciDsnbjsiqTthLTsiqRcbiAgICogQHBhcmFtIGZpbHRlcnMgRmlsdGVyUXVlcnkg6rCd7LK0XG4gICAqL1xuICBwcm90ZWN0ZWQgYXBwbHlTb25hbXVGaWx0ZXJzPFRFbnRpdHkgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgcWI6IFB1cmk8YW55LCBhbnksIGFueT4sXG4gICAgZmlsdGVycz86IEZpbHRlclF1ZXJ5PFRFbnRpdHk+LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWZpbHRlcnMpIHJldHVybjtcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHRoaXMubW9kZWxOYW1lKTtcblxuICAgIC8vIDEuIO2VhO2EsCDqsoDspp0gKEVudGl0eSDquLDrsJgpXG4gICAgdmFsaWRhdGVTb25hbXVGaWx0ZXJzKGZpbHRlcnMsIGVudGl0eSk7XG5cbiAgICAvLyAyLiDqsoDspp3rkJwg7ZWE7YSwIOyggeyaqVxuICAgIGNvbnN0IHB1cmkgPSBxYiBhcyBhbnk7XG5cbiAgICBmb3IgKGNvbnN0IFtmaWVsZCwgY29uZGl0aW9uXSBvZiBPYmplY3QuZW50cmllcyhmaWx0ZXJzKSkge1xuICAgICAgaWYgKGNvbmRpdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGNvbmRpdGlvbiA9PT0gbnVsbCkgY29udGludWU7XG5cbiAgICAgIC8vIO2FjOydtOu4lOuqhS7tlYTrk5zrqoUg7ZiV7Iud7Jy866GcIOuzgO2ZmFxuICAgICAgY29uc3QgZnVsbEZpZWxkID0gZW50aXR5LmdldEZ1bGxGaWVsZE5hbWUoZmllbGQpO1xuXG4gICAgICAvLyDsp4HsoJEg6rCSIChlceyZgCDrj5nsnbwpXG4gICAgICBpZiAodHlwZW9mIGNvbmRpdGlvbiAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KGNvbmRpdGlvbikpIHtcbiAgICAgICAgcHVyaS53aGVyZShmdWxsRmllbGQsIGNvbmRpdGlvbik7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyDsl7DsgrDsnpAg6rCd7LK0XG4gICAgICBmb3IgKGNvbnN0IFtvcGVyYXRvciwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbikpIHtcbiAgICAgICAgdGhpcy5hcHBseU9wZXJhdG9yKHFiLCBmdWxsRmllbGQsIG9wZXJhdG9yIGFzIEZpbHRlck9wZXJhdG9yLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOuLqOydvCDsl7DsgrDsnpDrpbwgUXVlcnlCdWlsZGVy7JeQIOyggeyaqVxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseU9wZXJhdG9yKFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIGZpZWxkOiBzdHJpbmcsXG4gICAgb3BlcmF0b3I6IEZpbHRlck9wZXJhdG9yLFxuICAgIHZhbHVlOiB1bmtub3duLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBwdXJpID0gcWIgYXMgYW55O1xuXG4gICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgY2FzZSBcImVxXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJuZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIiE9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJndFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj5cIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImd0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJsdFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjxcIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImx0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjw9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpblwiOlxuICAgICAgICBwdXJpLndoZXJlSW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJub3RJblwiOlxuICAgICAgICBwdXJpLndoZXJlTm90SW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJjb250YWluc1wiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcImxpa2VcIiwgYCUke3ZhbHVlfSVgKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJzdGFydHNXaXRoXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwibGlrZVwiLCBgJHt2YWx1ZX0lYCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiZW5kc1dpdGhcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCJsaWtlXCIsIGAlJHt2YWx1ZX1gKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpc051bGxcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiaXNOb3ROdWxsXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiIT1cIiwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYmVmb3JlXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiPFwiLCB2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYWZ0ZXJcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCI+XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJiZXR3ZWVuXCI6IHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgIGNvbnN0IFttaW4sIG1heF0gPSB2YWx1ZTtcbiAgICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIG1pbikud2hlcmUoZmllbGQsIFwiPD1cIiwgbWF4KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS53YXJuKGBVbnN1cHBvcnRlZCBvcGVyYXRvcjogJHtvcGVyYXRvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog7KSR7LKpIO2VhOuTnCDsgq3soJwgKOuwsOyXtCDrgrQg6rCd7LK064+EIOyymOumrClcbiAgICovXG4gIGRlbGV0ZUZpZWxkKG9iajogYW55LCBwYXJ0czogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBpZiAoIW9iaiB8fCB0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICBvYmouZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgIGlmIChpdGVtICYmIHR5cGVvZiBpdGVtID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBkZWxldGUgaXRlbVtwYXJ0c1swXV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBvYmpbcGFydHNbMF1dO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBwYXJ0cztcbiAgICBjb25zdCBuZXh0ID0gb2JqW2ZpcnN0XTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG5leHQpKSB7XG4gICAgICBuZXh0Lm1hcCgoaXRlbSkgPT4gdGhpcy5kZWxldGVGaWVsZChpdGVtLCByZXN0KSk7XG4gICAgfSBlbHNlIGlmIChuZXh0ICYmIHR5cGVvZiBuZXh0ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICB0aGlzLmRlbGV0ZUZpZWxkKG5leHQsIHJlc3QpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDT1VOVCDsv7zrpqwg7Iuk7ZaJICjrgrTrtoAg66mU7ISc65OcKVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlQ291bnRRdWVyeShcbiAgICBxYjogUHVyaTxhbnksIGFueSwgYW55PixcbiAgICBwYXJhbXM6IHsgcXVlcnlNb2RlPzogXCJsaXN0XCIgfCBcImNvdW50XCIgfCBcImJvdGhcIiB9LFxuICAgIGRlYnVnOiBib29sZWFuLFxuICAgIG9wdGltaXplQ291bnRRdWVyeTogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBpZiAocGFyYW1zLnF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGNvbnN0IGNvdW50UHVyaSA9IHFiLmNsb25lKCkuY2xlYXIoXCJvcmRlclwiKS5jbGVhcihcImxpbWl0XCIpLmNsZWFyKFwib2Zmc2V0XCIpO1xuXG4gICAgaWYgKG9wdGltaXplQ291bnRRdWVyeSkge1xuICAgICAgY29uc3QgeyBkZWZhdWx0OiBTcWxQYXJzZXIgfSA9IGF3YWl0IGltcG9ydChcIm5vZGUtc3FsLXBhcnNlclwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG4gICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHBhcnNlci5hc3RpZnkoY291bnRQdXJpLnRvUXVlcnkoKSwge1xuICAgICAgICBkYXRhYmFzZTogU29uYW11LmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBsZWZ0Sm9pblRhYmxlcyA9IGdldEpvaW5UYWJsZXMocGFyc2VkUXVlcnksIFtcIkxFRlQgSk9JTlwiXSk7XG4gICAgICBjb25zdCB3aGVyZVRhYmxlcyA9IGdldFRhYmxlTmFtZXNGcm9tV2hlcmUocGFyc2VkUXVlcnkpO1xuXG4gICAgICBjb25zdCB0YWJsZXNUb1JlbW92ZSA9IGxlZnRKb2luVGFibGVzLmZpbHRlcigoaikgPT4gIXdoZXJlVGFibGVzLmluY2x1ZGVzKGopKTtcbiAgICAgIHRhYmxlc1RvUmVtb3ZlLmZvckVhY2goKHRhYmxlKSA9PiB7XG4gICAgICAgIGNvdW50UHVyaS5jbGVhckpvaW4odGFibGUpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ09VTlQoKinroZwg7KCE7LK0IOugiOy9lOuTnCDsiJjrpbwg6rOE7IKwXG4gICAgLy8gVE9ETzogcWLsnZggRElTVElOQ1TqsIAg7J6I64qUIOqyveyasCDsspjrpqztlbTslbwg7ZWoXG4gICAgY29uc3QgY291bnRSZXN1bHQ6IHsgdG90YWw/OiBudW1iZXIgfSA9IGF3YWl0IGNvdW50UHVyaVxuICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAuc2VsZWN0KHsgdG90YWw6IFB1cmkucmF3TnVtYmVyKGBDT1VOVCgqKTo6aW50ZWdlcmApIH0pXG4gICAgICAuZmlyc3QoKTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY291bnRQdXJpLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvdW50UmVzdWx0Py50b3RhbCA/PyAwO1xuICB9XG5cbiAgLyoqXG4gICAqIExJU1Qg7L+866asIOyLpO2WiSAo64K067aAIOuplOyEnOuTnClcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZXhlY3V0ZUxpc3RRdWVyeTxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIHBhcmFtczogeyBxdWVyeU1vZGU/OiBcImxpc3RcIiB8IFwiY291bnRcIiB8IFwiYm90aFwiIH0sXG4gICAgbnVtOiBudW1iZXIsXG4gICAgcGFnZTogbnVtYmVyLFxuICAgIGRlYnVnOiBib29sZWFuLFxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgaWYgKHBhcmFtcy5xdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGxpbWl0ZWRRYiA9ICgoKSA9PiB7XG4gICAgICBpZiAobnVtID09PSAwKSB7XG4gICAgICAgIHJldHVybiBxYjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBxYi5saW1pdChudW0pLm9mZnNldChudW0gKiAocGFnZSAtIDEpKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuICAgIGxldCB1bmxvYWRlZFJvd3MgPSAoYXdhaXQgbGltaXRlZFFiKSBhcyBhbnlbXTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgcWIuZGVidWcoKTtcbiAgICB9XG5cbiAgICAvLyDroZzrjZQg7LKY66asXG4gICAgY29uc3QgbG9hZGVycyA9ICh0aGlzLmxvYWRlclF1ZXJpZXMgYXMgYW55KVtzdWJzZXRdO1xuICAgIGlmIChsb2FkZXJzICYmIEFycmF5LmlzQXJyYXkobG9hZGVycykpIHtcbiAgICAgIHVubG9hZGVkUm93cyA9IGF3YWl0IHRoaXMucHJvY2Vzc0xvYWRlcnModW5sb2FkZWRSb3dzLCBsb2FkZXJzLCBkZWJ1Zyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuaHlkcmF0ZSh1bmxvYWRlZFJvd3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIOyerOq3gOyggSDroZzrjZQg7LKY66asXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByb2Nlc3NMb2FkZXJzKHJvd3M6IGFueVtdLCBsb2FkZXJzOiBhbnlbXSwgZGVidWc6IGJvb2xlYW4pOiBQcm9taXNlPGFueVtdPiB7XG4gICAgZm9yIChjb25zdCByZXNvbHZlTG9hZGVyIG9mIGxvYWRlcnMpIHtcbiAgICAgIGNvbnN0IHsgYXMsIHJlZklkLCBxYjogcmVzb2x2ZUxvYWRlclFiRm4sIGxvYWRlcnM6IG5lc3RlZExvYWRlcnMgfSA9IHJlc29sdmVMb2FkZXI7XG5cbiAgICAgIGNvbnN0IHJlc29sdmVMb2FkZXJRYiA9IHJlc29sdmVMb2FkZXJRYkZuKFxuICAgICAgICBuZXcgUHVyaVdyYXBwZXIodGhpcy5nZXREQihcInJcIiksIG5ldyBVcHNlcnRCdWlsZGVyKCkpLFxuICAgICAgICByb3dzLm1hcCgocm93KSA9PiByb3dbcmVmSWRdKSxcbiAgICAgICk7XG5cbiAgICAgIGlmIChkZWJ1Zykge1xuICAgICAgICByZXNvbHZlTG9hZGVyUWIuZGVidWcoKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGxvYWRlZFJvd3MgPSAoYXdhaXQgcmVzb2x2ZUxvYWRlclFiKSBhcyBhbnlbXTtcblxuICAgICAgLy8g7KSR7LKpIGxvYWRlcnPqsIAg7J6I7Jy866m0IOyerOq3gCDsspjrpqxcbiAgICAgIGlmIChuZXN0ZWRMb2FkZXJzICYmIG5lc3RlZExvYWRlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICBsb2FkZWRSb3dzID0gYXdhaXQgdGhpcy5wcm9jZXNzTG9hZGVycyhsb2FkZWRSb3dzLCBuZXN0ZWRMb2FkZXJzLCBkZWJ1Zyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1YlJvd0dyb3VwcyA9IGdyb3VwKGxvYWRlZFJvd3MsIChyb3cpID0+IHJvdy5yZWZJZCk7XG5cbiAgICAgIHJvd3MgPSByb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIHJvd1thc10gPSAoc3ViUm93R3JvdXBzW3Jvd1tyZWZJZF1dID8/IFtdKS5tYXAoKHIpID0+IG9taXQociwgW1wicmVmSWRcIl0pKTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiByb3dzO1xuICB9XG5cbiAgLyoqXG4gICAqIEZsYXQg66CI7L2U65Oc66W8IOykkeyyqSDqsJ3ssrTroZwg67OA7ZmYXG4gICAqXG4gICAqIC0gYHVzZXJfX25hbWVgIOKGkiBgeyB1c2VyOiB7IG5hbWUgfSB9YFxuICAgKiAtIG51bGxhYmxlIHJlbGF0aW9u7J2YIOqyveyasCBpZCDtlYTrk5zqsIAgbnVsbOydtOuptCDqsJ3ssrQg7J6Q7LK066W8IG51bGzroZxcbiAgICovXG4gIGh5ZHJhdGU8VCBleHRlbmRzIFVua25vd25EQlJlY29yZD4ocm93czogVFtdKTogVFtdIHtcbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdzogVCkgPT4ge1xuICAgICAgLy8gbnVsbGFibGUgcmVsYXRpb24g7LKY66asOiDqt7jro7nsnZggaWQg7ZWE65Oc6rCAIG51bGzsnbTrqbQg6rCd7LK0IOyghOyytOulvCBudWxs66GcXG4gICAgICBjb25zdCBuZXN0ZWRLZXlzID0gT2JqZWN0LmtleXMocm93KS5maWx0ZXIoKGtleSkgPT4ga2V5LmluY2x1ZGVzKFwiX19cIikpO1xuICAgICAgY29uc3QgZ3JvdXBzID0gT2JqZWN0Lmdyb3VwQnkobmVzdGVkS2V5cywgKGtleSkgPT4ga2V5LnNwbGl0KFwiX19cIilbMF0pO1xuXG4gICAgICAvLyBpZCDtlYTrk5zqsIAgbnVsbOyduCDqt7jro7kg7LC+6riwICjsmIg6IHBhcmVudF9faWTqsIAgbnVsbOydtOuptCBwYXJlbnQg6re466O5IOyghOyytOqwgCBudWxsKVxuICAgICAgY29uc3QgbnVsbEtleXMgPSBPYmplY3QuZW50cmllcyhncm91cHMpXG4gICAgICAgIC5maWx0ZXIoKFtncm91cEtleSwgZmllbGRzXSkgPT4ge1xuICAgICAgICAgIGlmICghZmllbGRzIHx8IGZpZWxkcy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcblxuICAgICAgICAgIC8vIOq3uOujueydmCBpZCDtlYTrk5wg7LC+6riwICjsmIg6IFwicGFyZW50X19pZFwiKVxuICAgICAgICAgIGNvbnN0IGlkRmllbGQgPSBgJHtncm91cEtleX1fX2lkYDtcbiAgICAgICAgICBpZiAoaWRGaWVsZCBpbiByb3cpIHtcbiAgICAgICAgICAgIC8vIGlkIO2VhOuTnOqwgCBudWxs7J2066m0IOqwneyytCDsoITssrTqsIAgbnVsbFxuICAgICAgICAgICAgcmV0dXJuIHJvd1tpZEZpZWxkXSA9PT0gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBpZCDtlYTrk5zqsIAg7JeG7Jy866m0IOq4sOyhtCDroZzsp4E6IOuqqOuToCDtlYTrk5zqsIAgbnVsbOyduOyngCDtmZXsnbhcbiAgICAgICAgICByZXR1cm4gZmllbGRzLmV2ZXJ5KFxuICAgICAgICAgICAgKGZpZWxkKSA9PlxuICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8IChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKSxcbiAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgICAubWFwKChba2V5XSkgPT4ga2V5KTtcblxuICAgICAgY29uc3QgaHlkcmF0ZWQgPSBPYmplY3Qua2V5cyhyb3cpLnJlZHVjZSgociwgZmllbGQpID0+IHtcbiAgICAgICAgaWYgKCFmaWVsZC5pbmNsdWRlcyhcIl9fXCIpKSB7XG4gICAgICAgICAgLy8g7J2867CYIO2VhOuTnDog67Cw7Je0IOuCtCDqsJ3ssrTrqbQg7J6s6reAIGh5ZHJhdGVcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKSkge1xuICAgICAgICAgICAgcltmaWVsZF0gPSB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJbZmllbGRdID0gcm93W2ZpZWxkXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyDspJHssqkg7ZWE65OcIOyymOumrDogdXNlcl9fbmFtZSDihpIgdXNlcltuYW1lXVxuICAgICAgICBjb25zdCBwYXJ0cyA9IGZpZWxkLnNwbGl0KFwiX19cIik7XG4gICAgICAgIGNvbnN0IG9ialBhdGggPVxuICAgICAgICAgIHBhcnRzWzBdICtcbiAgICAgICAgICBwYXJ0c1xuICAgICAgICAgICAgLnNsaWNlKDEpXG4gICAgICAgICAgICAubWFwKChwYXJ0KSA9PiBgWyR7cGFydH1dYClcbiAgICAgICAgICAgIC5qb2luKFwiXCIpO1xuXG4gICAgICAgIHIgPSBzZXQoXG4gICAgICAgICAgcixcbiAgICAgICAgICBvYmpQYXRoLFxuICAgICAgICAgIHJvd1tmaWVsZF0gJiYgQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKVxuICAgICAgICAgICAgPyB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSlcbiAgICAgICAgICAgIDogcm93W2ZpZWxkXSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gcjtcbiAgICAgIH0sIHt9IGFzIFVua25vd25EQlJlY29yZCk7XG5cbiAgICAgIC8vIG51bGwgcmVsYXRpb24g7LKY66asXG4gICAgICBudWxsS2V5cy5mb3JFYWNoKChudWxsS2V5KSA9PiB7XG4gICAgICAgIGh5ZHJhdGVkW251bGxLZXldID0gbnVsbDtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gaHlkcmF0ZWQ7XG4gICAgfSkgYXMgVFtdO1xuICB9XG59XG5cbi8qKlxuICogRW5oYW5jZXIg7YyM652866+47YSwIOyhsOqxtOu2gCDtg4DsnoVcbiAqIFJlcXVpcmVkRW5oYW5jZXJLZXlz6rCAIOyXhuycvOuptCBlbmhhbmNlcnMg7ISg7YOd7KCBLCDsnojsnLzrqbQg7ZWE7IiYXG4gKi9cbnR5cGUgRW5oYW5jZXJQYXJhbTxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyxcbiAgVENvbXB1dGVkUmVzdWx0cyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0UXVlcmllcyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBQdXJpU3Vic2V0Rm4+LFxuPiA9IFtSZXF1aXJlZEVuaGFuY2VyS2V5czxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZz5dIGV4dGVuZHMgW25ldmVyXVxuICA/IHsgZW5oYW5jZXJzPzogRW5oYW5jZXJNYXA8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmcsIFRTdWJzZXRRdWVyaWVzPiB9XG4gIDogeyBlbmhhbmNlcnM6IEVuaGFuY2VyTWFwPFRTdWJzZXRLZXksIFRDb21wdXRlZFJlc3VsdHMsIFRTdWJzZXRNYXBwaW5nLCBUU3Vic2V0UXVlcmllcz4gfTtcblxudHlwZSBSZXF1aXJlZEVuaGFuY2VyS2V5czxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyxcbiAgVENvbXB1dGVkUmVzdWx0cyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuPiA9IHtcbiAgW0sgaW4gVFN1YnNldEtleV06IFRDb21wdXRlZFJlc3VsdHNbS10gZXh0ZW5kcyBUU3Vic2V0TWFwcGluZ1tLXSA/IG5ldmVyIDogSztcbn1bVFN1YnNldEtleV07XG5cbmV4cG9ydCBjb25zdCBCYXNlTW9kZWwgPSBuZXcgQmFzZU1vZGVsQ2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJnZXRMb2dnZXIiLCJjbG9uZURlZXAiLCJncm91cCIsImlzT2JqZWN0Iiwib21pdCIsInNldCIsIm5vcm1hbGl6ZUZpbHRlclF1ZXJ5IiwidmFsaWRhdGVTb25hbXVGaWx0ZXJzIiwiU29uYW11IiwiRW50aXR5TWFuYWdlciIsImNvbnZlcnREb21haW5Ub0NhdGVnb3J5IiwiZ2V0Sm9pblRhYmxlcyIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJjaHVuayIsIkRCIiwiUHVyaSIsIlB1cmlXcmFwcGVyIiwiVXBzZXJ0QnVpbGRlciIsIkJhc2VNb2RlbENsYXNzIiwibG9nZ2VyIiwibW9kZWxOYW1lIiwibmFtZSIsInN1YnNldFF1ZXJpZXMiLCJsb2FkZXJRdWVyaWVzIiwiZ2V0REIiLCJ3aGljaCIsImdldFB1cmkiLCJ0cngiLCJnZXRUcmFuc2FjdGlvbkNvbnRleHQiLCJnZXRUcmFuc2FjdGlvbiIsImRiIiwiZGVzdHJveSIsImdldEluc2VydGVkSWRzIiwid2RiIiwicm93cyIsInRhYmxlTmFtZSIsInVucUtleUZpZWxkcyIsImNodW5rU2l6ZSIsInVucUtleXMiLCJ3aGVyZUluRmllbGQiLCJzZWxlY3RGaWVsZCIsImxlbmd0aCIsInJhdyIsImpvaW4iLCJtYXAiLCJyb3ciLCJmaWVsZCIsInJlc3VsdElkcyIsIml0ZW1zIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJTdHJpbmciLCJpZCIsImdldFN1YnNldFF1ZXJpZXMiLCJzdWJzZXQiLCJFcnJvciIsInB1cmlXcmFwcGVyIiwicWIiLCJvblN1YnNldCIsIl9zdWJzZXQiLCJjcmVhdGVFbmhhbmNlcnMiLCJlbmhhbmNlcnMiLCJleGVjdXRlU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJxdWVyeVBhcmFtcyIsImRlYnVnIiwib3B0aW1pemVDb3VudFF1ZXJ5Iiwic29uYW11RmlsdGVyIiwibm9ybWFsaXplZEZpbHRlciIsImFwcGx5U29uYW11RmlsdGVycyIsIm51bSIsInBhZ2UiLCJ0b3RhbCIsImV4ZWN1dGVDb3VudFF1ZXJ5IiwicXVlcnlNb2RlIiwiY29tcHV0ZWRSb3dzIiwiZXhlY3V0ZUxpc3RRdWVyeSIsImVuaGFuY2VyIiwiZW5oYW5jZWRSb3dzIiwiUHJvbWlzZSIsImFsbCIsImVudGl0eSIsImdldCIsImludGVybmFsRmllbGRzIiwic3Vic2V0c0ludGVybmFsIiwib21pdEludGVybmFsRmllbGRzIiwiZmllbGRzIiwicmVzdWx0IiwiZGVsZXRlRmllbGQiLCJzcGxpdCIsImZpbHRlcnMiLCJwdXJpIiwiY29uZGl0aW9uIiwiT2JqZWN0IiwiZW50cmllcyIsInVuZGVmaW5lZCIsImZ1bGxGaWVsZCIsImdldEZ1bGxGaWVsZE5hbWUiLCJBcnJheSIsImlzQXJyYXkiLCJ3aGVyZSIsIm9wZXJhdG9yIiwidmFsdWUiLCJhcHBseU9wZXJhdG9yIiwid2hlcmVOb3RJbiIsIm1pbiIsIm1heCIsImNvbnNvbGUiLCJ3YXJuIiwib2JqIiwicGFydHMiLCJmb3JFYWNoIiwiaXRlbSIsImZpcnN0IiwicmVzdCIsIm5leHQiLCJjb3VudFB1cmkiLCJjbG9uZSIsImNsZWFyIiwiZGVmYXVsdCIsIlNxbFBhcnNlciIsInBhcnNlciIsIlBhcnNlciIsInBhcnNlZFF1ZXJ5IiwiYXN0aWZ5IiwidG9RdWVyeSIsImRhdGFiYXNlIiwiY29uZmlnIiwibGVmdEpvaW5UYWJsZXMiLCJ3aGVyZVRhYmxlcyIsInRhYmxlc1RvUmVtb3ZlIiwiZmlsdGVyIiwiaiIsImluY2x1ZGVzIiwidGFibGUiLCJjbGVhckpvaW4iLCJjb3VudFJlc3VsdCIsInJhd051bWJlciIsImxpbWl0ZWRRYiIsImxpbWl0Iiwib2Zmc2V0IiwidW5sb2FkZWRSb3dzIiwibG9hZGVycyIsInByb2Nlc3NMb2FkZXJzIiwiaHlkcmF0ZSIsInJlc29sdmVMb2FkZXIiLCJhcyIsInJlZklkIiwicmVzb2x2ZUxvYWRlclFiRm4iLCJuZXN0ZWRMb2FkZXJzIiwicmVzb2x2ZUxvYWRlclFiIiwibG9hZGVkUm93cyIsInN1YlJvd0dyb3VwcyIsInIiLCJuZXN0ZWRLZXlzIiwia2V5cyIsImtleSIsImdyb3VwcyIsImdyb3VwQnkiLCJudWxsS2V5cyIsImdyb3VwS2V5IiwiaWRGaWVsZCIsImV2ZXJ5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJvYmpQYXRoIiwic2xpY2UiLCJwYXJ0IiwibnVsbEtleSIsIkJhc2VNb2RlbCJdLCJtYXBwaW5ncyI6IkFBQUEsa0dBQWtHLEdBQ2xHLFNBQVNBLFNBQVMsUUFBcUIsbUJBQW1CO0FBRTFELFNBQVNDLFNBQVMsRUFBRUMsS0FBSyxFQUFFQyxRQUFRLEVBQUVDLElBQUksRUFBRUMsR0FBRyxRQUFRLFVBQVU7QUFDaEUsU0FBMEJDLG9CQUFvQixFQUFFQyxxQkFBcUIsUUFBUSxjQUFLO0FBQ2xGLFNBQVNDLE1BQU0sUUFBUSxrQkFBUztBQUNoQyxTQUFTQyxhQUFhLFFBQVEsOEJBQTJCO0FBRXpELFNBQVNDLHVCQUF1QixRQUFRLHdCQUFxQjtBQUU3RCxTQUFTQyxhQUFhLEVBQUVDLHNCQUFzQixRQUFRLHlCQUFzQjtBQUM1RSxTQUFTQyxLQUFLLFFBQVEsb0JBQWlCO0FBR3ZDLFNBQVNDLEVBQUUsUUFBUSxVQUFPO0FBQzFCLFNBQVNDLElBQUksUUFBUSxZQUFTO0FBRzlCLFNBQVNDLFdBQVcsUUFBUSxvQkFBaUI7QUFDN0MsU0FBU0MsYUFBYSxRQUFRLHNCQUFtQjtBQUlqRDs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxNQUFNQzs7OztJQU1RQyxPQUFlO0lBRWxDLFlBQ0UsQUFBZ0JDLFlBQW9CLElBQUksQ0FBQyxXQUFXLENBQUNDLElBQUksRUFDekQsQUFBVUMsYUFBOEIsRUFDeEMsQUFBVUMsYUFBOEIsQ0FDeEM7YUFIZ0JILFlBQUFBO2FBQ05FLGdCQUFBQTthQUNBQyxnQkFBQUE7UUFFVixJQUFJLENBQUNK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
14
+ //#region src/database/base-model.ts
15
+ /** biome-ignore-all lint/suspicious/noExplicitAny: Puri의 타입은 개별 모델에서 확정되므로 BaseModel에서는 any를 허용함 */
16
+ var BaseModelClass, BaseModel;
17
+ var init_base_model = __esmMin((() => {
18
+ init_sonamu();
19
+ init_entity_manager();
20
+ init_utils();
21
+ init_category();
22
+ init_sql_parser();
23
+ init_db();
24
+ init_puri();
25
+ init_puri_wrapper();
26
+ init_upsert_builder();
27
+ BaseModelClass = class {
28
+ logger;
29
+ constructor(modelName = this.constructor.name, subsetQueries, loaderQueries) {
30
+ this.modelName = modelName;
31
+ this.subsetQueries = subsetQueries;
32
+ this.loaderQueries = loaderQueries;
33
+ this.logger = getLogger(convertDomainToCategory(this.modelName, "model"));
34
+ }
35
+ getDB(which) {
36
+ return DB.getDB(which);
37
+ }
38
+ getPuri(which) {
39
+ const trx = DB.getTransactionContext().getTransaction(which);
40
+ if (trx) {
41
+ return trx;
42
+ }
43
+ const db = this.getDB(which);
44
+ return new PuriWrapper(db, new UpsertBuilder());
45
+ }
46
+ async destroy() {
47
+ return DB.destroy();
48
+ }
49
+ async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
50
+ if (!wdb) {
51
+ wdb = this.getDB("w");
52
+ }
53
+ let unqKeys;
54
+ let whereInField;
55
+ let selectField;
56
+ if (unqKeyFields.length > 1) {
57
+ whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
58
+ selectField = `${whereInField} as tmpUid`;
59
+ unqKeys = rows.map((row) => unqKeyFields.map((field) => row[field]).join("_"));
60
+ } else {
61
+ whereInField = unqKeyFields[0];
62
+ selectField = unqKeyFields[0];
63
+ unqKeys = rows.map((row) => row[unqKeyFields[0]]);
64
+ }
65
+ let resultIds = [];
66
+ for (const items of cluster(unqKeys, chunkSize)) {
67
+ const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, items);
68
+ resultIds = resultIds.concat(dbRows.map((dbRow) => parseInt(String(dbRow.id))));
69
+ }
70
+ return resultIds;
71
+ }
72
+ /**
73
+ * 특정 서브셋에 대한 쿼리 빌더 획득
74
+ *
75
+ * @returns qb - 쿼리 빌더 (조건 추가용)
76
+ * @returns onSubset - 특정 서브셋 전용 타입이 필요할 때 사용
77
+ */
78
+ getSubsetQueries(subset) {
79
+ if (!this.subsetQueries) {
80
+ throw new Error("subsetQueries is not defined");
81
+ }
82
+ const puriWrapper = new PuriWrapper(this.getDB("r"), new UpsertBuilder());
83
+ const qb = this.subsetQueries[subset]?.(puriWrapper);
84
+ return {
85
+ qb,
86
+ onSubset: ((_subset) => qb)
87
+ };
88
+ }
89
+ /**
90
+ * Enhancer 객체 생성 헬퍼
91
+ * 타입 검증 및 추론을 도와줌
92
+ */
93
+ createEnhancers(enhancers) {
94
+ return enhancers;
95
+ }
96
+ /**
97
+ * 서브셋 쿼리 실행
98
+ *
99
+ * 1. Sonamu 필터 적용 (타입 변환 포함)
100
+ * 2. 쿼리 실행 (pagination 적용)
101
+ * 3. 로더 실행 (1:N, N:M 관계 데이터 로딩)
102
+ * 4. Hydrate (flat → 중첩 객체)
103
+ * 5. Enhancer 적용 (virtual 필드 계산)
104
+ */
105
+ async executeSubsetQuery(params) {
106
+ const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
107
+ if (!this.loaderQueries) {
108
+ throw new Error("loaderQueries is not defined");
109
+ }
110
+ if (queryParams.sonamuFilter) {
111
+ const normalizedFilter = normalizeFilterQuery(queryParams.sonamuFilter);
112
+ this.applySonamuFilters(qb, normalizedFilter);
113
+ }
114
+ const { num, page } = queryParams;
115
+ const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
116
+ if (queryParams?.queryMode === "count") {
117
+ return { total };
118
+ }
119
+ const computedRows = await this.executeListQuery(subset, qb, queryParams, num, page, debug);
120
+ const enhancer = params.enhancers?.[subset];
121
+ const enhancedRows = await Promise.all(computedRows.map((row) => enhancer?.(row) ?? row));
122
+ const entity = EntityManager.get(this.modelName);
123
+ const internalFields = entity.subsetsInternal[subset] ?? [];
124
+ const rows = internalFields.length > 0 ? enhancedRows.map((row) => this.omitInternalFields(row, internalFields)) : enhancedRows;
125
+ if (queryParams.queryMode === "list") {
126
+ return { rows };
127
+ } else {
128
+ return {
129
+ rows,
130
+ total
131
+ };
132
+ }
133
+ }
134
+ /**
135
+ * 객체에서 internal 필드 제거
136
+ * 중첩 필드(예: "user.email") 및 배열(예: "employees.salary")도 처리
137
+ */
138
+ omitInternalFields(row, fields) {
139
+ const result = cloneDeep(row);
140
+ for (const field of fields) {
141
+ this.deleteField(result, field.split("."));
142
+ }
143
+ return result;
144
+ }
145
+ /**
146
+ * FilterQuery를 Puri QueryBuilder에 적용
147
+ *
148
+ * @param qb Puri QueryBuilder 인스턴스
149
+ * @param filters FilterQuery 객체
150
+ */
151
+ applySonamuFilters(qb, filters) {
152
+ if (!filters) return;
153
+ const entity = EntityManager.get(this.modelName);
154
+ validateSonamuFilters(filters, entity);
155
+ const puri = qb;
156
+ for (const [field, condition] of Object.entries(filters)) {
157
+ if (condition === undefined || condition === null) continue;
158
+ const fullField = entity.getFullFieldName(field);
159
+ if (typeof condition !== "object" || Array.isArray(condition)) {
160
+ puri.where(fullField, condition);
161
+ continue;
162
+ }
163
+ for (const [operator, value] of Object.entries(condition)) {
164
+ this.applyOperator(qb, fullField, operator, value);
165
+ }
166
+ }
167
+ }
168
+ /**
169
+ * 단일 연산자를 QueryBuilder에 적용
170
+ */
171
+ applyOperator(qb, field, operator, value) {
172
+ const puri = qb;
173
+ switch (operator) {
174
+ case "eq":
175
+ puri.where(field, value);
176
+ break;
177
+ case "ne":
178
+ puri.where(field, "!=", value);
179
+ break;
180
+ case "gt":
181
+ puri.where(field, ">", value);
182
+ break;
183
+ case "gte":
184
+ puri.where(field, ">=", value);
185
+ break;
186
+ case "lt":
187
+ puri.where(field, "<", value);
188
+ break;
189
+ case "lte":
190
+ puri.where(field, "<=", value);
191
+ break;
192
+ case "in":
193
+ puri.whereIn(field, value);
194
+ break;
195
+ case "notIn":
196
+ puri.whereNotIn(field, value);
197
+ break;
198
+ case "contains":
199
+ puri.where(field, "like", `%${value}%`);
200
+ break;
201
+ case "startsWith":
202
+ puri.where(field, "like", `${value}%`);
203
+ break;
204
+ case "endsWith":
205
+ puri.where(field, "like", `%${value}`);
206
+ break;
207
+ case "isNull":
208
+ puri.where(field, null);
209
+ break;
210
+ case "isNotNull":
211
+ puri.where(field, "!=", null);
212
+ break;
213
+ case "before":
214
+ puri.where(field, "<", value);
215
+ break;
216
+ case "after":
217
+ puri.where(field, ">", value);
218
+ break;
219
+ case "between": {
220
+ if (Array.isArray(value) && value.length === 2) {
221
+ const [min, max] = value;
222
+ puri.where(field, ">=", min).where(field, "<=", max);
223
+ }
224
+ break;
225
+ }
226
+ default: console.warn(`Unsupported operator: ${operator}`);
227
+ }
228
+ }
229
+ /**
230
+ * 중첩 필드 삭제 (배열 내 객체도 처리)
231
+ */
232
+ deleteField(obj, parts) {
233
+ if (!obj || typeof obj !== "object") {
234
+ return;
235
+ }
236
+ if (parts.length === 1) {
237
+ if (Array.isArray(obj)) {
238
+ obj.forEach((item) => {
239
+ if (item && typeof item === "object") {
240
+ delete item[parts[0]];
241
+ }
242
+ });
243
+ } else {
244
+ delete obj[parts[0]];
245
+ }
246
+ return;
247
+ }
248
+ const [first, ...rest] = parts;
249
+ const next = obj[first];
250
+ if (Array.isArray(next)) {
251
+ next.map((item) => this.deleteField(item, rest));
252
+ } else if (next && typeof next === "object") {
253
+ this.deleteField(next, rest);
254
+ }
255
+ }
256
+ /**
257
+ * COUNT 쿼리 실행 (내부 메서드)
258
+ */
259
+ async executeCountQuery(qb, params, debug, optimizeCountQuery) {
260
+ if (params.queryMode === "list") {
261
+ return 0;
262
+ }
263
+ const countPuri = qb.clone().clear("order").clear("limit").clear("offset");
264
+ if (optimizeCountQuery) {
265
+ const { default: SqlParser } = await import("node-sql-parser");
266
+ const parser = new SqlParser.Parser();
267
+ const parsedQuery = parser.astify(countPuri.toQuery(), { database: Sonamu.config.database.database });
268
+ const leftJoinTables = getJoinTables(parsedQuery, ["LEFT JOIN"]);
269
+ const whereTables = getTableNamesFromWhere(parsedQuery);
270
+ const tablesToRemove = leftJoinTables.filter((j) => !whereTables.includes(j));
271
+ tablesToRemove.forEach((table) => {
272
+ countPuri.clearJoin(table);
273
+ });
274
+ }
275
+ const countResult = await countPuri.clear("select").select({ total: Puri.rawNumber(`COUNT(*)::integer`) }).first();
276
+ if (debug) {
277
+ countPuri.debug();
278
+ }
279
+ return countResult?.total ?? 0;
280
+ }
281
+ /**
282
+ * LIST 쿼리 실행 (내부 메서드)
283
+ */
284
+ async executeListQuery(subset, qb, params, num, page, debug) {
285
+ if (params.queryMode === "count") {
286
+ return [];
287
+ }
288
+ const limitedQb = (() => {
289
+ if (num === 0) {
290
+ return qb;
291
+ } else {
292
+ return qb.limit(num).offset(num * (page - 1));
293
+ }
294
+ })();
295
+ let unloadedRows = await limitedQb;
296
+ if (debug) {
297
+ qb.debug();
298
+ }
299
+ const loaders = this.loaderQueries[subset];
300
+ if (loaders && Array.isArray(loaders)) {
301
+ unloadedRows = await this.processLoaders(unloadedRows, loaders, debug);
302
+ }
303
+ return this.hydrate(unloadedRows);
304
+ }
305
+ /**
306
+ * 재귀적 로더 처리
307
+ */
308
+ async processLoaders(rows, loaders, debug) {
309
+ for (const resolveLoader of loaders) {
310
+ const { as, refId, qb: resolveLoaderQbFn, loaders: nestedLoaders } = resolveLoader;
311
+ const resolveLoaderQb = resolveLoaderQbFn(new PuriWrapper(this.getDB("r"), new UpsertBuilder()), rows.map((row) => row[refId]));
312
+ if (debug) {
313
+ resolveLoaderQb.debug();
314
+ }
315
+ let loadedRows = await resolveLoaderQb;
316
+ if (nestedLoaders && nestedLoaders.length > 0) {
317
+ loadedRows = await this.processLoaders(loadedRows, nestedLoaders, debug);
318
+ }
319
+ const subRowGroups = group(loadedRows, (row) => row.refId);
320
+ rows = rows.map((row) => {
321
+ row[as] = (subRowGroups[row[refId]] ?? []).map((r) => omit(r, ["refId"]));
322
+ return row;
323
+ });
324
+ }
325
+ return rows;
326
+ }
327
+ /**
328
+ * Flat 레코드를 중첩 객체로 변환
329
+ *
330
+ * - `user__name` → `{ user: { name } }`
331
+ * - nullable relation의 경우 id 필드가 null이면 객체 자체를 null로
332
+ */
333
+ hydrate(rows) {
334
+ return rows.map((row) => {
335
+ const nestedKeys = Object.keys(row).filter((key) => key.includes("__"));
336
+ const groups = Object.groupBy(nestedKeys, (key) => key.split("__")[0]);
337
+ const nullKeys = Object.entries(groups).filter(([groupKey, fields]) => {
338
+ if (!fields || fields.length === 0) return false;
339
+ const idField = `${groupKey}__id`;
340
+ if (idField in row) {
341
+ return row[idField] === null;
342
+ }
343
+ return fields.every((field) => row[field] === null || Array.isArray(row[field]) && row[field].length === 0);
344
+ }).map(([key]) => key);
345
+ const hydrated = Object.keys(row).reduce((r, field) => {
346
+ if (!field.includes("__")) {
347
+ if (Array.isArray(row[field]) && isObject(row[field][0])) {
348
+ r[field] = this.hydrate(row[field]);
349
+ } else {
350
+ r[field] = row[field];
351
+ }
352
+ return r;
353
+ }
354
+ const parts = field.split("__");
355
+ const objPath = parts[0] + parts.slice(1).map((part) => `[${part}]`).join("");
356
+ r = set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
357
+ return r;
358
+ }, {});
359
+ nullKeys.forEach((nullKey) => {
360
+ hydrated[nullKey] = null;
361
+ });
362
+ return hydrated;
363
+ });
364
+ }
365
+ };
366
+ BaseModel = new BaseModelClass();
367
+ }));
368
+
369
+ //#endregion
370
+ init_base_model();
371
+ export { BaseModel, BaseModelClass, init_base_model };
372
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1tb2RlbC5qcyIsIm5hbWVzIjpbIm1vZGVsTmFtZTogc3RyaW5nIiwic3Vic2V0UXVlcmllcz86IFRTdWJzZXRRdWVyaWVzIiwibG9hZGVyUXVlcmllcz86IFRMb2FkZXJRdWVyaWVzIiwidW5xS2V5czogc3RyaW5nW10iLCJ3aGVyZUluRmllbGQ6IHN0cmluZyB8IEtuZXguUmF3Iiwic2VsZWN0RmllbGQ6IHN0cmluZyIsInJlc3VsdElkczogbnVtYmVyW10iLCJjb3VudFJlc3VsdDogeyB0b3RhbD86IG51bWJlciB9Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RhdGFiYXNlL2Jhc2UtbW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIGJpb21lLWlnbm9yZS1hbGwgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IFB1cmnsnZgg7YOA7J6F7J2AIOqwnOuzhCDrqqjrjbjsl5DshJwg7ZmV7KCV65CY66+A66GcIEJhc2VNb2RlbOyXkOyEnOuKlCBhbnnrpbwg7ZeI7Jqp7ZWoICovXG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHsgdHlwZSBMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHsgdHlwZSBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGNsb25lRGVlcCwgY2x1c3RlciwgZ3JvdXAsIGlzT2JqZWN0LCBvbWl0LCBzZXQgfSBmcm9tIFwicmFkYXNoaVwiO1xuXG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpL3NvbmFtdVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgRmlsdGVyT3BlcmF0b3IsIHR5cGUgRmlsdGVyUXVlcnkgfSBmcm9tIFwiLi4vZmlsdGVyL3R5cGVzXCI7XG5pbXBvcnQgeyBub3JtYWxpemVGaWx0ZXJRdWVyeSwgdmFsaWRhdGVTb25hbXVGaWx0ZXJzIH0gZnJvbSBcIi4uL2ZpbHRlci91dGlsc1wiO1xuaW1wb3J0IHsgY29udmVydERvbWFpblRvQ2F0ZWdvcnkgfSBmcm9tIFwiLi4vbG9nZ2VyL2NhdGVnb3J5XCI7XG5pbXBvcnQgeyB0eXBlIERhdGFiYXNlU2NoZW1hRXh0ZW5kLCB0eXBlIFNvbmFtdVF1ZXJ5TW9kZSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBMaXN0UmVzdWx0IH0gZnJvbSBcIi4uL3V0aWxzL21vZGVsXCI7XG5pbXBvcnQgeyBnZXRKb2luVGFibGVzLCBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlIH0gZnJvbSBcIi4uL3V0aWxzL3NxbC1wYXJzZXJcIjtcbmltcG9ydCB7IHR5cGUgRW5oYW5jZXJNYXAsIHR5cGUgUmVzb2x2ZVN1YnNldEludGVyc2VjdGlvbiB9IGZyb20gXCIuL2Jhc2UtbW9kZWwudHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgREJQcmVzZXQgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgUHVyaSB9IGZyb20gXCIuL3B1cmlcIjtcbmltcG9ydCB7XG4gIHR5cGUgSW5mZXJBbGxTdWJzZXRzLFxuICB0eXBlIFB1cmlMb2FkZXJRdWVyaWVzLFxuICB0eXBlIFB1cmlTdWJzZXRGbixcbn0gZnJvbSBcIi4vcHVyaS1zdWJzZXQudHlwZXNcIjtcbmltcG9ydCB7IFB1cmlXcmFwcGVyIH0gZnJvbSBcIi4vcHVyaS13cmFwcGVyXCI7XG5pbXBvcnQgeyB0eXBlIFVuaW9uRXh0cmFjdGVkVFRhYmxlcyB9IGZyb20gXCIuL3B1cmkudHlwZXNcIjtcbmltcG9ydCB7IFVwc2VydEJ1aWxkZXIgfSBmcm9tIFwiLi91cHNlcnQtYnVpbGRlclwiO1xuXG50eXBlIFVua25vd25EQlJlY29yZCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4vKipcbiAqIOuqqOuToCBNb2RlbCDtgbTrnpjsiqTsnZgg6riw67O4IO2BtOuemOyKpFxuICpcbiAqIEB0ZW1wbGF0ZSBUU3Vic2V0S2V5IC0g7ISc67iM7IWLIO2CpCDsnKDri4jsmKggKOyYiDogXCJBXCIgfCBcIlBcIiB8IFwiU1NcIilcbiAqIEB0ZW1wbGF0ZSBUU3Vic2V0TWFwcGluZyAtIOyEnOu4jOyFi+uzhCDstZzsooUg6rKw6rO8IO2DgOyehSDrp6TtlZFcbiAqIEB0ZW1wbGF0ZSBUU3Vic2V0UXVlcmllcyAtIOyEnOu4jOyFiyDsv7zrpqwg7ZWo7IiYIOqwneyytFxuICogQHRlbXBsYXRlIFRMb2FkZXJRdWVyaWVzIC0g7ISc67iM7IWL67OEIOuhnOuNlCDsv7zrpqwg67Cw7Je0IOqwneyytFxuICovXG5leHBvcnQgY2xhc3MgQmFzZU1vZGVsQ2xhc3M8XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcgPSBuZXZlcixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXIsXG4gIFRTdWJzZXRRdWVyaWVzIGV4dGVuZHMgUmVjb3JkPFRTdWJzZXRLZXksIFB1cmlTdWJzZXRGbj4gPSBuZXZlcixcbiAgVExvYWRlclF1ZXJpZXMgZXh0ZW5kcyBQdXJpTG9hZGVyUXVlcmllczxUU3Vic2V0S2V5PiA9IG5ldmVyLFxuPiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBsb2dnZXI6IExvZ2dlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgbW9kZWxOYW1lOiBzdHJpbmcgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgcHJvdGVjdGVkIHN1YnNldFF1ZXJpZXM/OiBUU3Vic2V0UXVlcmllcyxcbiAgICBwcm90ZWN0ZWQgbG9hZGVyUXVlcmllcz86IFRMb2FkZXJRdWVyaWVzLFxuICApIHtcbiAgICB0aGlzLmxvZ2dlciA9IGdldExvZ2dlcihjb252ZXJ0RG9tYWluVG9DYXRlZ29yeSh0aGlzLm1vZGVsTmFtZSwgXCJtb2RlbFwiKSk7XG4gIH1cblxuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCBuZXcgVXBzZXJ0QnVpbGRlcigpKTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKSB7XG4gICAgcmV0dXJuIERCLmRlc3Ryb3koKTtcbiAgfVxuXG4gIGFzeW5jIGdldEluc2VydGVkSWRzKFxuICAgIHdkYjogS25leCxcbiAgICByb3dzOiBVbmtub3duREJSZWNvcmRbXSxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICB1bnFLZXlGaWVsZHM6IHN0cmluZ1tdLFxuICAgIGNodW5rU2l6ZTogbnVtYmVyID0gNTAwLFxuICApIHtcbiAgICBpZiAoIXdkYikge1xuICAgICAgd2RiID0gdGhpcy5nZXREQihcIndcIik7XG4gICAgfVxuXG4gICAgbGV0IHVucUtleXM6IHN0cmluZ1tdO1xuICAgIGxldCB3aGVyZUluRmllbGQ6IHN0cmluZyB8IEtuZXguUmF3O1xuICAgIGxldCBzZWxlY3RGaWVsZDogc3RyaW5nO1xuXG4gICAgaWYgKHVucUtleUZpZWxkcy5sZW5ndGggPiAxKSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB3ZGIucmF3KGBDT05DQVRfV1MoJ18nLCAnJHt1bnFLZXlGaWVsZHMuam9pbihcIixcIil9JylgKTtcbiAgICAgIHNlbGVjdEZpZWxkID0gYCR7d2hlcmVJbkZpZWxkfSBhcyB0bXBVaWRgO1xuICAgICAgdW5xS2V5cyA9IHJvd3MubWFwKChyb3cpID0+IHVucUtleUZpZWxkcy5tYXAoKGZpZWxkKSA9PiByb3dbZmllbGRdKS5qb2luKFwiX1wiKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHNlbGVjdEZpZWxkID0gdW5xS2V5RmllbGRzWzBdO1xuICAgICAgdW5xS2V5cyA9IHJvd3MubWFwKChyb3cpID0+IHJvd1t1bnFLZXlGaWVsZHNbMF1dIGFzIHN0cmluZyk7XG4gICAgfVxuXG4gICAgbGV0IHJlc3VsdElkczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGl0ZW1zIG9mIGNsdXN0ZXIodW5xS2V5cywgY2h1bmtTaXplKSkge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQgYXMgc3RyaW5nLCBpdGVtcyk7XG4gICAgICByZXN1bHRJZHMgPSByZXN1bHRJZHMuY29uY2F0KFxuICAgICAgICBkYlJvd3MubWFwKChkYlJvdzogVW5rbm93bkRCUmVjb3JkKSA9PiBwYXJzZUludChTdHJpbmcoZGJSb3cuaWQpKSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRJZHM7XG4gIH1cblxuICAvKipcbiAgICog7Yq57KCVIOyEnOu4jOyFi+yXkCDrjIDtlZwg7L+866asIOu5jOuNlCDtmo3rk51cbiAgICpcbiAgICogQHJldHVybnMgcWIgLSDsv7zrpqwg67mM642UICjsobDqsbQg7LaU6rCA7JqpKVxuICAgKiBAcmV0dXJucyBvblN1YnNldCAtIO2KueyglSDshJzruIzshYsg7KCE7JqpIO2DgOyeheydtCDtlYTsmpTtlaAg65WMIOyCrOyaqVxuICAgKi9cbiAgZ2V0U3Vic2V0UXVlcmllczxUIGV4dGVuZHMgVFN1YnNldEtleT4oc3Vic2V0OiBUKSB7XG4gICAgaWYgKCF0aGlzLnN1YnNldFF1ZXJpZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInN1YnNldFF1ZXJpZXMgaXMgbm90IGRlZmluZWRcIik7XG4gICAgfVxuXG4gICAgY29uc3QgcHVyaVdyYXBwZXIgPSBuZXcgUHVyaVdyYXBwZXIodGhpcy5nZXREQihcInJcIiksIG5ldyBVcHNlcnRCdWlsZGVyKCkpO1xuICAgIGNvbnN0IHFiID0gdGhpcy5zdWJzZXRRdWVyaWVzW3N1YnNldF0/LihwdXJpV3JhcHBlcik7XG5cbiAgICAvLyBOb25BbGxvd2VkQXNTaW5nbGVUYWJsZTog64uo7J28IO2FjOydtOu4lCDsu6zrn7wg7KCR6re8IOuwqeyngOyaqSDrp4jsu6RcbiAgICB0eXBlIFFCVGFibGVzID0gVW5pb25FeHRyYWN0ZWRUVGFibGVzPFRTdWJzZXRLZXksIFRTdWJzZXRRdWVyaWVzPiAmIHtcbiAgICAgIE5vbkFsbG93ZWRBc1NpbmdsZVRhYmxlOiB7IF9fZnVsbHRleHRfXzogdHJ1ZSB9O1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgcWI6IHFiIGFzIHVua25vd24gYXMgUHVyaTxEYXRhYmFzZVNjaGVtYUV4dGVuZCwgUUJUYWJsZXMsIHt9PixcbiAgICAgIG9uU3Vic2V0OiAoKF9zdWJzZXQ6IFRTdWJzZXRLZXkgfCByZWFkb25seSBUU3Vic2V0S2V5W10pID0+IHFiKSBhcyB7XG4gICAgICAgIC8vIOuLqOydvCDtgqRcbiAgICAgICAgPFMgZXh0ZW5kcyBUU3Vic2V0S2V5PihzdWJzZXQ6IFMpOiBSZXR1cm5UeXBlPFRTdWJzZXRRdWVyaWVzW1NdPjtcbiAgICAgICAgLy8g7YKkIOuwsOyXtCAtPiDqtZDsp5Htlakg67CY7ZmYXG4gICAgICAgIDxBcnIgZXh0ZW5kcyByZWFkb25seSBUU3Vic2V0S2V5W10+KFxuICAgICAgICAgIHN1YnNldHM6IFsuLi5BcnJdLFxuICAgICAgICApOiBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uPEFyciwgVFN1YnNldFF1ZXJpZXM+O1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVuaGFuY2VyIOqwneyytCDsg53shLEg7Zes7Y28XG4gICAqIO2DgOyehSDqsoDspp0g67CPIOy2lOuhoOydhCDrj4TsmYDspIxcbiAgICovXG4gIGNyZWF0ZUVuaGFuY2VyczxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgZW5oYW5jZXJzOiBFbmhhbmNlck1hcDxcbiAgICAgIFQsXG4gICAgICBJbmZlckFsbFN1YnNldHM8VFN1YnNldFF1ZXJpZXMsIFRMb2FkZXJRdWVyaWVzPixcbiAgICAgIFRTdWJzZXRNYXBwaW5nLFxuICAgICAgVFN1YnNldFF1ZXJpZXNcbiAgICA+LFxuICApIHtcbiAgICByZXR1cm4gZW5oYW5jZXJzO1xuICB9XG5cbiAgLyoqXG4gICAqIOyEnOu4jOyFiyDsv7zrpqwg7Iuk7ZaJXG4gICAqXG4gICAqIDEuIFNvbmFtdSDtlYTthLAg7KCB7JqpICjtg4DsnoUg67OA7ZmYIO2PrO2VqClcbiAgICogMi4g7L+866asIOyLpO2WiSAocGFnaW5hdGlvbiDsoIHsmqkpXG4gICAqIDMuIOuhnOuNlCDsi6TtlokgKDE6TiwgTjpNIOq0gOqzhCDrjbDsnbTthLAg66Gc65SpKVxuICAgKiA0LiBIeWRyYXRlIChmbGF0IOKGkiDspJHssqkg6rCd7LK0KVxuICAgKiA1LiBFbmhhbmNlciDsoIHsmqkgKHZpcnR1YWwg7ZWE65OcIOqzhOyCsClcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGVTdWJzZXRRdWVyeTxcbiAgICBUIGV4dGVuZHMgVFN1YnNldEtleSxcbiAgICBUQ29tcHV0ZWRSZXN1bHRzIGV4dGVuZHMgSW5mZXJBbGxTdWJzZXRzPFRTdWJzZXRRdWVyaWVzLCBUTG9hZGVyUXVlcmllcz4sXG4gICAgTFAgZXh0ZW5kcyB7XG4gICAgICBudW0/OiBudW1iZXI7XG4gICAgICBwYWdlPzogbnVtYmVyO1xuICAgICAgcXVlcnlNb2RlPzogU29uYW11UXVlcnlNb2RlO1xuICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgfSxcbiAgPihcbiAgICBwYXJhbXM6IHtcbiAgICAgIHN1YnNldDogVDtcbiAgICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+O1xuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIG51bTogbnVtYmVyO1xuICAgICAgICBwYWdlOiBudW1iZXI7XG4gICAgICAgIHF1ZXJ5TW9kZT86IFNvbmFtdVF1ZXJ5TW9kZTtcbiAgICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICB9O1xuICAgICAgZGVidWc/OiBib29sZWFuO1xuICAgICAgb3B0aW1pemVDb3VudFF1ZXJ5PzogYm9vbGVhbjtcbiAgICB9ICYgRW5oYW5jZXJQYXJhbTxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZywgVFN1YnNldFF1ZXJpZXM+LFxuICApOiBQcm9taXNlPExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPj4ge1xuICAgIGNvbnN0IHsgc3Vic2V0LCBxYiwgcGFyYW1zOiBxdWVyeVBhcmFtcywgZGVidWcgPSBmYWxzZSwgb3B0aW1pemVDb3VudFF1ZXJ5ID0gZmFsc2UgfSA9IHBhcmFtcztcblxuICAgIGlmICghdGhpcy5sb2FkZXJRdWVyaWVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsb2FkZXJRdWVyaWVzIGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIC8vIFNvbmFtdSBGaWx0ZXIg7KCB7JqpXG4gICAgaWYgKHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcikge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbHRlciA9IG5vcm1hbGl6ZUZpbHRlclF1ZXJ5KHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcik7XG4gICAgICB0aGlzLmFwcGx5U29uYW11RmlsdGVycyhxYiwgbm9ybWFsaXplZEZpbHRlcik7XG4gICAgfVxuXG4gICAgY29uc3QgeyBudW0sIHBhZ2UgfSA9IHF1ZXJ5UGFyYW1zO1xuXG4gICAgLy8gQ09VTlQg7L+866asIOyLpO2WiSAocXVlcnlNb2RlOiBsaXN07J28IOuVjOuKlCAwIOumrO2EtClcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNvdW50UXVlcnkocWIsIHF1ZXJ5UGFyYW1zLCBkZWJ1Zywgb3B0aW1pemVDb3VudFF1ZXJ5KTtcblxuICAgIGlmIChxdWVyeVBhcmFtcz8ucXVlcnlNb2RlID09PSBcImNvdW50XCIpIHtcbiAgICAgIHJldHVybiB7IHRvdGFsIH0gYXMgTGlzdFJlc3VsdDxMUCwgVFN1YnNldE1hcHBpbmdbVF0+O1xuICAgIH1cblxuICAgIC8vIExJU1Qg7L+866asIOyLpO2WiVxuICAgIGNvbnN0IGNvbXB1dGVkUm93cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZUxpc3RRdWVyeShzdWJzZXQsIHFiLCBxdWVyeVBhcmFtcywgbnVtLCBwYWdlLCBkZWJ1Zyk7XG5cbiAgICAvLyBFbmhhbmNlciDsoIHsmqlcbiAgICBjb25zdCBlbmhhbmNlciA9IChwYXJhbXMgYXMgYW55KS5lbmhhbmNlcnM/LltzdWJzZXRdO1xuICAgIGNvbnN0IGVuaGFuY2VkUm93cyA9IChhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGNvbXB1dGVkUm93cy5tYXAoKHJvdykgPT4gZW5oYW5jZXI/Lihyb3cpID8/IHJvdyksXG4gICAgKSkgYXMgVFN1YnNldE1hcHBpbmdbVF1bXTtcblxuICAgIC8vIEludGVybmFsIO2VhOuTnCDsoJzqsbBcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldCh0aGlzLm1vZGVsTmFtZSk7XG4gICAgY29uc3QgaW50ZXJuYWxGaWVsZHMgPSBlbnRpdHkuc3Vic2V0c0ludGVybmFsW3N1YnNldF0gPz8gW107XG4gICAgY29uc3Qgcm93cyA9XG4gICAgICBpbnRlcm5hbEZpZWxkcy5sZW5ndGggPiAwXG4gICAgICAgID8gZW5oYW5jZWRSb3dzLm1hcCgocm93KSA9PiB0aGlzLm9taXRJbnRlcm5hbEZpZWxkcyhyb3csIGludGVybmFsRmllbGRzKSlcbiAgICAgICAgOiBlbmhhbmNlZFJvd3M7XG5cbiAgICBpZiAocXVlcnlQYXJhbXMucXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgLy8g66as7Iqk7Yq466eMIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cyB9IGFzIExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8g65GY64ukIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cywgdG90YWwgfSBhcyBMaXN0UmVzdWx0PExQLCBUU3Vic2V0TWFwcGluZ1tUXT47XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOqwneyytOyXkOyEnCBpbnRlcm5hbCDtlYTrk5wg7KCc6rGwXG4gICAqIOykkeyyqSDtlYTrk5wo7JiIOiBcInVzZXIuZW1haWxcIikg67CPIOuwsOyXtCjsmIg6IFwiZW1wbG95ZWVzLnNhbGFyeVwiKeuPhCDsspjrpqxcbiAgICovXG4gIG9taXRJbnRlcm5hbEZpZWxkczxUIGV4dGVuZHMgb2JqZWN0Pihyb3c6IFQsIGZpZWxkczogc3RyaW5nW10pOiBUIHtcbiAgICBjb25zdCByZXN1bHQgPSBjbG9uZURlZXAocm93KTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykge1xuICAgICAgdGhpcy5kZWxldGVGaWVsZChyZXN1bHQsIGZpZWxkLnNwbGl0KFwiLlwiKSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRmlsdGVyUXVlcnnrpbwgUHVyaSBRdWVyeUJ1aWxkZXLsl5Ag7KCB7JqpXG4gICAqXG4gICAqIEBwYXJhbSBxYiBQdXJpIFF1ZXJ5QnVpbGRlciDsnbjsiqTthLTsiqRcbiAgICogQHBhcmFtIGZpbHRlcnMgRmlsdGVyUXVlcnkg6rCd7LK0XG4gICAqL1xuICBwcm90ZWN0ZWQgYXBwbHlTb25hbXVGaWx0ZXJzPFRFbnRpdHkgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgcWI6IFB1cmk8YW55LCBhbnksIGFueT4sXG4gICAgZmlsdGVycz86IEZpbHRlclF1ZXJ5PFRFbnRpdHk+LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWZpbHRlcnMpIHJldHVybjtcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHRoaXMubW9kZWxOYW1lKTtcblxuICAgIC8vIDEuIO2VhO2EsCDqsoDspp0gKEVudGl0eSDquLDrsJgpXG4gICAgdmFsaWRhdGVTb25hbXVGaWx0ZXJzKGZpbHRlcnMsIGVudGl0eSk7XG5cbiAgICAvLyAyLiDqsoDspp3rkJwg7ZWE7YSwIOyggeyaqVxuICAgIGNvbnN0IHB1cmkgPSBxYiBhcyBhbnk7XG5cbiAgICBmb3IgKGNvbnN0IFtmaWVsZCwgY29uZGl0aW9uXSBvZiBPYmplY3QuZW50cmllcyhmaWx0ZXJzKSkge1xuICAgICAgaWYgKGNvbmRpdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGNvbmRpdGlvbiA9PT0gbnVsbCkgY29udGludWU7XG5cbiAgICAgIC8vIO2FjOydtOu4lOuqhS7tlYTrk5zrqoUg7ZiV7Iud7Jy866GcIOuzgO2ZmFxuICAgICAgY29uc3QgZnVsbEZpZWxkID0gZW50aXR5LmdldEZ1bGxGaWVsZE5hbWUoZmllbGQpO1xuXG4gICAgICAvLyDsp4HsoJEg6rCSIChlceyZgCDrj5nsnbwpXG4gICAgICBpZiAodHlwZW9mIGNvbmRpdGlvbiAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KGNvbmRpdGlvbikpIHtcbiAgICAgICAgcHVyaS53aGVyZShmdWxsRmllbGQsIGNvbmRpdGlvbik7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyDsl7DsgrDsnpAg6rCd7LK0XG4gICAgICBmb3IgKGNvbnN0IFtvcGVyYXRvciwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbikpIHtcbiAgICAgICAgdGhpcy5hcHBseU9wZXJhdG9yKHFiLCBmdWxsRmllbGQsIG9wZXJhdG9yIGFzIEZpbHRlck9wZXJhdG9yLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOuLqOydvCDsl7DsgrDsnpDrpbwgUXVlcnlCdWlsZGVy7JeQIOyggeyaqVxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseU9wZXJhdG9yKFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIGZpZWxkOiBzdHJpbmcsXG4gICAgb3BlcmF0b3I6IEZpbHRlck9wZXJhdG9yLFxuICAgIHZhbHVlOiB1bmtub3duLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBwdXJpID0gcWIgYXMgYW55O1xuXG4gICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgY2FzZSBcImVxXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJuZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIiE9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJndFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj5cIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImd0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJsdFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjxcIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImx0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjw9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpblwiOlxuICAgICAgICBwdXJpLndoZXJlSW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJub3RJblwiOlxuICAgICAgICBwdXJpLndoZXJlTm90SW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJjb250YWluc1wiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcImxpa2VcIiwgYCUke3ZhbHVlfSVgKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJzdGFydHNXaXRoXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwibGlrZVwiLCBgJHt2YWx1ZX0lYCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiZW5kc1dpdGhcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCJsaWtlXCIsIGAlJHt2YWx1ZX1gKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpc051bGxcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiaXNOb3ROdWxsXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiIT1cIiwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYmVmb3JlXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiPFwiLCB2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYWZ0ZXJcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCI+XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJiZXR3ZWVuXCI6IHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgIGNvbnN0IFttaW4sIG1heF0gPSB2YWx1ZTtcbiAgICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIG1pbikud2hlcmUoZmllbGQsIFwiPD1cIiwgbWF4KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS53YXJuKGBVbnN1cHBvcnRlZCBvcGVyYXRvcjogJHtvcGVyYXRvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog7KSR7LKpIO2VhOuTnCDsgq3soJwgKOuwsOyXtCDrgrQg6rCd7LK064+EIOyymOumrClcbiAgICovXG4gIGRlbGV0ZUZpZWxkKG9iajogYW55LCBwYXJ0czogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBpZiAoIW9iaiB8fCB0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICBvYmouZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgIGlmIChpdGVtICYmIHR5cGVvZiBpdGVtID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBkZWxldGUgaXRlbVtwYXJ0c1swXV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBvYmpbcGFydHNbMF1dO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBwYXJ0cztcbiAgICBjb25zdCBuZXh0ID0gb2JqW2ZpcnN0XTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG5leHQpKSB7XG4gICAgICBuZXh0Lm1hcCgoaXRlbSkgPT4gdGhpcy5kZWxldGVGaWVsZChpdGVtLCByZXN0KSk7XG4gICAgfSBlbHNlIGlmIChuZXh0ICYmIHR5cGVvZiBuZXh0ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICB0aGlzLmRlbGV0ZUZpZWxkKG5leHQsIHJlc3QpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDT1VOVCDsv7zrpqwg7Iuk7ZaJICjrgrTrtoAg66mU7ISc65OcKVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlQ291bnRRdWVyeShcbiAgICBxYjogUHVyaTxhbnksIGFueSwgYW55PixcbiAgICBwYXJhbXM6IHsgcXVlcnlNb2RlPzogXCJsaXN0XCIgfCBcImNvdW50XCIgfCBcImJvdGhcIiB9LFxuICAgIGRlYnVnOiBib29sZWFuLFxuICAgIG9wdGltaXplQ291bnRRdWVyeTogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBpZiAocGFyYW1zLnF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGNvbnN0IGNvdW50UHVyaSA9IHFiLmNsb25lKCkuY2xlYXIoXCJvcmRlclwiKS5jbGVhcihcImxpbWl0XCIpLmNsZWFyKFwib2Zmc2V0XCIpO1xuXG4gICAgaWYgKG9wdGltaXplQ291bnRRdWVyeSkge1xuICAgICAgY29uc3QgeyBkZWZhdWx0OiBTcWxQYXJzZXIgfSA9IGF3YWl0IGltcG9ydChcIm5vZGUtc3FsLXBhcnNlclwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG4gICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHBhcnNlci5hc3RpZnkoY291bnRQdXJpLnRvUXVlcnkoKSwge1xuICAgICAgICBkYXRhYmFzZTogU29uYW11LmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBsZWZ0Sm9pblRhYmxlcyA9IGdldEpvaW5UYWJsZXMocGFyc2VkUXVlcnksIFtcIkxFRlQgSk9JTlwiXSk7XG4gICAgICBjb25zdCB3aGVyZVRhYmxlcyA9IGdldFRhYmxlTmFtZXNGcm9tV2hlcmUocGFyc2VkUXVlcnkpO1xuXG4gICAgICBjb25zdCB0YWJsZXNUb1JlbW92ZSA9IGxlZnRKb2luVGFibGVzLmZpbHRlcigoaikgPT4gIXdoZXJlVGFibGVzLmluY2x1ZGVzKGopKTtcbiAgICAgIHRhYmxlc1RvUmVtb3ZlLmZvckVhY2goKHRhYmxlKSA9PiB7XG4gICAgICAgIGNvdW50UHVyaS5jbGVhckpvaW4odGFibGUpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ09VTlQoKinroZwg7KCE7LK0IOugiOy9lOuTnCDsiJjrpbwg6rOE7IKwXG4gICAgLy8gVE9ETzogcWLsnZggRElTVElOQ1TqsIAg7J6I64qUIOqyveyasCDsspjrpqztlbTslbwg7ZWoXG4gICAgY29uc3QgY291bnRSZXN1bHQ6IHsgdG90YWw/OiBudW1iZXIgfSA9IGF3YWl0IGNvdW50UHVyaVxuICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAuc2VsZWN0KHsgdG90YWw6IFB1cmkucmF3TnVtYmVyKGBDT1VOVCgqKTo6aW50ZWdlcmApIH0pXG4gICAgICAuZmlyc3QoKTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY291bnRQdXJpLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvdW50UmVzdWx0Py50b3RhbCA/PyAwO1xuICB9XG5cbiAgLyoqXG4gICAqIExJU1Qg7L+866asIOyLpO2WiSAo64K067aAIOuplOyEnOuTnClcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZXhlY3V0ZUxpc3RRdWVyeTxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIHBhcmFtczogeyBxdWVyeU1vZGU/OiBcImxpc3RcIiB8IFwiY291bnRcIiB8IFwiYm90aFwiIH0sXG4gICAgbnVtOiBudW1iZXIsXG4gICAgcGFnZTogbnVtYmVyLFxuICAgIGRlYnVnOiBib29sZWFuLFxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgaWYgKHBhcmFtcy5xdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGxpbWl0ZWRRYiA9ICgoKSA9PiB7XG4gICAgICBpZiAobnVtID09PSAwKSB7XG4gICAgICAgIHJldHVybiBxYjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBxYi5saW1pdChudW0pLm9mZnNldChudW0gKiAocGFnZSAtIDEpKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuICAgIGxldCB1bmxvYWRlZFJvd3MgPSBhd2FpdCBsaW1pdGVkUWI7XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIHFiLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgLy8g66Gc642UIOyymOumrFxuICAgIGNvbnN0IGxvYWRlcnMgPSAodGhpcy5sb2FkZXJRdWVyaWVzIGFzIGFueSlbc3Vic2V0XTtcbiAgICBpZiAobG9hZGVycyAmJiBBcnJheS5pc0FycmF5KGxvYWRlcnMpKSB7XG4gICAgICB1bmxvYWRlZFJvd3MgPSBhd2FpdCB0aGlzLnByb2Nlc3NMb2FkZXJzKHVubG9hZGVkUm93cywgbG9hZGVycywgZGVidWcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmh5ZHJhdGUodW5sb2FkZWRSb3dzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDsnqzqt4DsoIEg66Gc642UIOyymOumrFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzTG9hZGVycyhyb3dzOiBhbnlbXSwgbG9hZGVyczogYW55W10sIGRlYnVnOiBib29sZWFuKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIGZvciAoY29uc3QgcmVzb2x2ZUxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBjb25zdCB7IGFzLCByZWZJZCwgcWI6IHJlc29sdmVMb2FkZXJRYkZuLCBsb2FkZXJzOiBuZXN0ZWRMb2FkZXJzIH0gPSByZXNvbHZlTG9hZGVyO1xuXG4gICAgICBjb25zdCByZXNvbHZlTG9hZGVyUWIgPSByZXNvbHZlTG9hZGVyUWJGbihcbiAgICAgICAgbmV3IFB1cmlXcmFwcGVyKHRoaXMuZ2V0REIoXCJyXCIpLCBuZXcgVXBzZXJ0QnVpbGRlcigpKSxcbiAgICAgICAgcm93cy5tYXAoKHJvdykgPT4gcm93W3JlZklkXSksXG4gICAgICApO1xuXG4gICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgcmVzb2x2ZUxvYWRlclFiLmRlYnVnKCk7XG4gICAgICB9XG5cbiAgICAgIGxldCBsb2FkZWRSb3dzID0gKGF3YWl0IHJlc29sdmVMb2FkZXJRYikgYXMgYW55W107XG5cbiAgICAgIC8vIOykkeyyqSBsb2FkZXJz6rCAIOyeiOycvOuptCDsnqzqt4Ag7LKY66asXG4gICAgICBpZiAobmVzdGVkTG9hZGVycyAmJiBuZXN0ZWRMb2FkZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbG9hZGVkUm93cyA9IGF3YWl0IHRoaXMucHJvY2Vzc0xvYWRlcnMobG9hZGVkUm93cywgbmVzdGVkTG9hZGVycywgZGVidWcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdWJSb3dHcm91cHMgPSBncm91cChsb2FkZWRSb3dzLCAocm93KSA9PiByb3cucmVmSWQpO1xuXG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbYXNdID0gKHN1YlJvd0dyb3Vwc1tyb3dbcmVmSWRdXSA/PyBbXSkubWFwKChyKSA9PiBvbWl0KHIsIFtcInJlZklkXCJdKSk7XG4gICAgICAgIHJldHVybiByb3c7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGF0IOugiOy9lOuTnOulvCDspJHssqkg6rCd7LK066GcIOuzgO2ZmFxuICAgKlxuICAgKiAtIGB1c2VyX19uYW1lYCDihpIgYHsgdXNlcjogeyBuYW1lIH0gfWBcbiAgICogLSBudWxsYWJsZSByZWxhdGlvbuydmCDqsr3smrAgaWQg7ZWE65Oc6rCAIG51bGzsnbTrqbQg6rCd7LK0IOyekOyytOulvCBudWxs66GcXG4gICAqL1xuICBoeWRyYXRlPFQgZXh0ZW5kcyBVbmtub3duREJSZWNvcmQ+KHJvd3M6IFRbXSk6IFRbXSB7XG4gICAgcmV0dXJuIHJvd3MubWFwKChyb3c6IFQpID0+IHtcbiAgICAgIC8vIG51bGxhYmxlIHJlbGF0aW9uIOyymOumrDog6re466O57J2YIGlkIO2VhOuTnOqwgCBudWxs7J2066m0IOqwneyytCDsoITssrTrpbwgbnVsbOuhnFxuICAgICAgY29uc3QgbmVzdGVkS2V5cyA9IE9iamVjdC5rZXlzKHJvdykuZmlsdGVyKChrZXkpID0+IGtleS5pbmNsdWRlcyhcIl9fXCIpKTtcbiAgICAgIGNvbnN0IGdyb3VwcyA9IE9iamVjdC5ncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcblxuICAgICAgLy8gaWQg7ZWE65Oc6rCAIG51bGzsnbgg6re466O5IOywvuq4sCAo7JiIOiBwYXJlbnRfX2lk6rCAIG51bGzsnbTrqbQgcGFyZW50IOq3uOujuSDsoITssrTqsIAgbnVsbClcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmVudHJpZXMoZ3JvdXBzKVxuICAgICAgICAuZmlsdGVyKChbZ3JvdXBLZXksIGZpZWxkc10pID0+IHtcbiAgICAgICAgICBpZiAoIWZpZWxkcyB8fCBmaWVsZHMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAvLyDqt7jro7nsnZggaWQg7ZWE65OcIOywvuq4sCAo7JiIOiBcInBhcmVudF9faWRcIilcbiAgICAgICAgICBjb25zdCBpZEZpZWxkID0gYCR7Z3JvdXBLZXl9X19pZGA7XG4gICAgICAgICAgaWYgKGlkRmllbGQgaW4gcm93KSB7XG4gICAgICAgICAgICAvLyBpZCDtlYTrk5zqsIAgbnVsbOydtOuptCDqsJ3ssrQg7KCE7LK06rCAIG51bGxcbiAgICAgICAgICAgIHJldHVybiByb3dbaWRGaWVsZF0gPT09IG51bGw7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gaWQg7ZWE65Oc6rCAIOyXhuycvOuptCDquLDsobQg66Gc7KeBOiDrqqjrk6Ag7ZWE65Oc6rCAIG51bGzsnbjsp4Ag7ZmV7J24XG4gICAgICAgICAgcmV0dXJuIGZpZWxkcy5ldmVyeShcbiAgICAgICAgICAgIChmaWVsZCkgPT5cbiAgICAgICAgICAgICAgcm93W2ZpZWxkXSA9PT0gbnVsbCB8fCAoQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiByb3dbZmllbGRdLmxlbmd0aCA9PT0gMCksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm1hcCgoW2tleV0pID0+IGtleSk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIC8vIOydvOuwmCDtlYTrk5w6IOuwsOyXtCDrgrQg6rCd7LK066m0IOyerOq3gCBoeWRyYXRlXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSkpIHtcbiAgICAgICAgICAgIHJbZmllbGRdID0gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7KSR7LKpIO2VhOuTnCDsspjrpqw6IHVzZXJfX25hbWUg4oaSIHVzZXJbbmFtZV1cbiAgICAgICAgY29uc3QgcGFydHMgPSBmaWVsZC5zcGxpdChcIl9fXCIpO1xuICAgICAgICBjb25zdCBvYmpQYXRoID1cbiAgICAgICAgICBwYXJ0c1swXSArXG4gICAgICAgICAgcGFydHNcbiAgICAgICAgICAgIC5zbGljZSgxKVxuICAgICAgICAgICAgLm1hcCgocGFydCkgPT4gYFske3BhcnR9XWApXG4gICAgICAgICAgICAuam9pbihcIlwiKTtcblxuICAgICAgICByID0gc2V0KFxuICAgICAgICAgIHIsXG4gICAgICAgICAgb2JqUGF0aCxcbiAgICAgICAgICByb3dbZmllbGRdICYmIEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSlcbiAgICAgICAgICAgID8gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pXG4gICAgICAgICAgICA6IHJvd1tmaWVsZF0sXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9LCB7fSBhcyBVbmtub3duREJSZWNvcmQpO1xuXG4gICAgICAvLyBudWxsIHJlbGF0aW9uIOyymOumrFxuICAgICAgbnVsbEtleXMuZm9yRWFjaCgobnVsbEtleSkgPT4ge1xuICAgICAgICBoeWRyYXRlZFtudWxsS2V5XSA9IG51bGw7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGh5ZHJhdGVkO1xuICAgIH0pIGFzIFRbXTtcbiAgfVxufVxuXG4vKipcbiAqIEVuaGFuY2VyIO2MjOudvOuvuO2EsCDsobDqsbTrtoAg7YOA7J6FXG4gKiBSZXF1aXJlZEVuaGFuY2VyS2V5c+qwgCDsl4bsnLzrqbQgZW5oYW5jZXJzIOyEoO2DneyggSwg7J6I7Jy866m0IO2VhOyImFxuICovXG50eXBlIEVuaGFuY2VyUGFyYW08XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcsXG4gIFRDb21wdXRlZFJlc3VsdHMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldFF1ZXJpZXMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgUHVyaVN1YnNldEZuPixcbj4gPSBbUmVxdWlyZWRFbmhhbmNlcktleXM8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmc+XSBleHRlbmRzIFtuZXZlcl1cbiAgPyB7IGVuaGFuY2Vycz86IEVuaGFuY2VyTWFwPFRTdWJzZXRLZXksIFRDb21wdXRlZFJlc3VsdHMsIFRTdWJzZXRNYXBwaW5nLCBUU3Vic2V0UXVlcmllcz4gfVxuICA6IHsgZW5oYW5jZXJzOiBFbmhhbmNlck1hcDxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZywgVFN1YnNldFF1ZXJpZXM+IH07XG5cbnR5cGUgUmVxdWlyZWRFbmhhbmNlcktleXM8XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcsXG4gIFRDb21wdXRlZFJlc3VsdHMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55Pixcbj4gPSB7XG4gIFtLIGluIFRTdWJzZXRLZXldOiBUQ29tcHV0ZWRSZXN1bHRzW0tdIGV4dGVuZHMgVFN1YnNldE1hcHBpbmdbS10gPyBuZXZlciA6IEs7XG59W1RTdWJzZXRLZXldO1xuXG5leHBvcnQgY29uc3QgQmFzZU1vZGVsID0gbmV3IEJhc2VNb2RlbENsYXNzKCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBTXVDO3NCQUNrQjthQUVxQjtnQkFDakI7a0JBR2U7VUFHbEQ7WUFDSTtvQkFNZTtzQkFFSTtDQVlwQyxpQkFBYixNQUtFO0VBQ0EsQUFBbUI7RUFFbkIsWUFDRSxBQUFnQkEsWUFBb0IsS0FBSyxZQUFZLE1BQ3JELEFBQVVDLGVBQ1YsQUFBVUMsZUFDVjtHQUhnQjtHQUNOO0dBQ0E7QUFFVixRQUFLLFNBQVMsVUFBVSx3QkFBd0IsS0FBSyxXQUFXLFFBQVEsQ0FBQzs7RUFHM0UsTUFBTSxPQUF1QjtBQUMzQixVQUFPLEdBQUcsTUFBTSxNQUFNOztFQUd4QixRQUFRLE9BQThCO0dBRXBDLE1BQU0sTUFBTSxHQUFHLHVCQUF1QixDQUFDLGVBQWUsTUFBTTtBQUM1RCxPQUFJLEtBQUs7QUFDUCxXQUFPOztHQUlULE1BQU0sS0FBSyxLQUFLLE1BQU0sTUFBTTtBQUM1QixVQUFPLElBQUksWUFBWSxJQUFJLElBQUksZUFBZSxDQUFDOztFQUdqRCxNQUFNLFVBQVU7QUFD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