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,427 +1,426 @@
1
- import { spawn } from "child_process";
2
- import fs from "fs";
3
- import os from "os";
1
+ import { __esmMin } from "../_virtual/rolldown_runtime.js";
2
+ import { Sonamu, init_sonamu } from "../api/sonamu.js";
4
3
  import path from "path";
5
- import { Sonamu } from "../api/sonamu.js";
6
- /** contract/ 디렉터리 절대 경로 반환 (apiRootPath 기준) */ function getContractDir() {
7
- return path.join(Sonamu.apiRootPath, "..", "..", "contract");
4
+ import os from "os";
5
+ import fs from "fs";
6
+ import { spawn } from "child_process";
7
+
8
+ //#region src/ui/cdd-service.ts
9
+ /** contract/ 디렉터리 절대 경로 반환 (apiRootPath 기준) */
10
+ function getContractDir() {
11
+ return path.join(Sonamu.apiRootPath, "..", "..", "contract");
8
12
  }
9
- /** 프로젝트 루트 경로 반환 */ function getProjectRoot() {
10
- return path.join(Sonamu.apiRootPath, "..", "..");
13
+ /** 프로젝트 루트 경로 반환 */
14
+ function getProjectRoot() {
15
+ return path.join(Sonamu.apiRootPath, "..", "..");
11
16
  }
12
- /** 경로가 contract/ 디렉터리 내부인지 검증 */ function assertInsideContractDir(filePath) {
13
- const contractDir = getContractDir();
14
- const resolved = path.resolve(contractDir, filePath);
15
- if (!resolved.startsWith(contractDir + path.sep) && resolved !== contractDir) {
16
- throw new Error(`경로가 contract/ 디렉터리 밖을 참조합니다: ${filePath}`);
17
- }
17
+ /** 경로가 contract/ 디렉터리 내부인지 검증 */
18
+ function assertInsideContractDir(filePath) {
19
+ const contractDir = getContractDir();
20
+ const resolved = path.resolve(contractDir, filePath);
21
+ if (!resolved.startsWith(contractDir + path.sep) && resolved !== contractDir) {
22
+ throw new Error(`경로가 contract/ 디렉터리 밖을 참조합니다: ${filePath}`);
23
+ }
18
24
  }
19
- /** 파일명에서 CddFileType 판별 */ function detectFileType(fileName) {
20
- if (fileName.endsWith(".contract.md")) return "contract";
21
- if (fileName.endsWith(".rules.json")) return "rules";
22
- return undefined;
25
+ /** 파일명에서 CddFileType 판별 */
26
+ function detectFileType(fileName) {
27
+ if (fileName.endsWith(".contract.md")) return "contract";
28
+ if (fileName.endsWith(".rules.json")) return "rules";
29
+ return undefined;
23
30
  }
24
- /** 디렉터리를 재귀 탐색하여 CddTreeNode 트리를 생성 */ function scanDirectory(dirPath, relativeTo) {
25
- const entries = fs.readdirSync(dirPath, {
26
- withFileTypes: true
27
- });
28
- const nodes = [];
29
- for (const entry of entries){
30
- const fullPath = path.join(dirPath, entry.name);
31
- const relPath = path.relative(relativeTo, fullPath);
32
- if (entry.isDirectory()) {
33
- if (entry.name === "rules") continue;
34
- const children = scanDirectory(fullPath, relativeTo);
35
- if (children.length > 0) {
36
- nodes.push({
37
- name: entry.name,
38
- path: relPath,
39
- type: "directory",
40
- children
41
- });
42
- }
43
- } else if (entry.isFile()) {
44
- const fileType = detectFileType(entry.name);
45
- if (fileType && fileType !== "rules") {
46
- nodes.push({
47
- name: entry.name,
48
- path: relPath,
49
- type: "file",
50
- fileType
51
- });
52
- }
53
- }
54
- }
55
- return nodes;
31
+ /** 디렉터리를 재귀 탐색하여 CddTreeNode 트리를 생성 */
32
+ function scanDirectory(dirPath, relativeTo) {
33
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
34
+ const nodes = [];
35
+ for (const entry of entries) {
36
+ const fullPath = path.join(dirPath, entry.name);
37
+ const relPath = path.relative(relativeTo, fullPath);
38
+ if (entry.isDirectory()) {
39
+ if (entry.name === "rules") continue;
40
+ const children = scanDirectory(fullPath, relativeTo);
41
+ if (children.length > 0) {
42
+ nodes.push({
43
+ name: entry.name,
44
+ path: relPath,
45
+ type: "directory",
46
+ children
47
+ });
48
+ }
49
+ } else if (entry.isFile()) {
50
+ const fileType = detectFileType(entry.name);
51
+ if (fileType && fileType !== "rules") {
52
+ nodes.push({
53
+ name: entry.name,
54
+ path: relPath,
55
+ type: "file",
56
+ fileType
57
+ });
58
+ }
59
+ }
60
+ }
61
+ return nodes;
56
62
  }
57
- /** contract/ 디렉터리의 트리 구조를 반환 */ export function getCddTree() {
58
- const contractDir = getContractDir();
59
- if (!fs.existsSync(contractDir)) {
60
- return {
61
- exists: false,
62
- tree: []
63
- };
64
- }
65
- const tree = scanDirectory(contractDir, contractDir);
66
- return {
67
- exists: true,
68
- tree
69
- };
63
+ /** contract/ 디렉터리의 트리 구조를 반환 */
64
+ function getCddTree() {
65
+ const contractDir = getContractDir();
66
+ if (!fs.existsSync(contractDir)) {
67
+ return {
68
+ exists: false,
69
+ tree: []
70
+ };
71
+ }
72
+ const tree = scanDirectory(contractDir, contractDir);
73
+ return {
74
+ exists: true,
75
+ tree
76
+ };
70
77
  }
71
- /** 파일 내용을 읽어 반환 (contract.md → markdown 원문, rules.json → JSON 문자열) */ export function readContent(filePath) {
72
- assertInsideContractDir(filePath);
73
- const contractDir = getContractDir();
74
- const absPath = path.resolve(contractDir, filePath);
75
- if (!fs.existsSync(absPath)) {
76
- throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
77
- }
78
- const content = fs.readFileSync(absPath, "utf-8");
79
- const fileType = detectFileType(path.basename(filePath));
80
- return {
81
- content,
82
- fileType: fileType ?? "contract"
83
- };
78
+ /** 파일 내용을 읽어 반환 (contract.md → markdown 원문, rules.json → JSON 문자열) */
79
+ function readContent(filePath) {
80
+ assertInsideContractDir(filePath);
81
+ const contractDir = getContractDir();
82
+ const absPath = path.resolve(contractDir, filePath);
83
+ if (!fs.existsSync(absPath)) {
84
+ throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
85
+ }
86
+ const content = fs.readFileSync(absPath, "utf-8");
87
+ const fileType = detectFileType(path.basename(filePath));
88
+ return {
89
+ content,
90
+ fileType: fileType ?? "contract"
91
+ };
84
92
  }
85
- /** 파일을 외부 에디터로 직접 편집 */ export async function editContent(filePath) {
86
- assertInsideContractDir(filePath);
87
- const contractDir = getContractDir();
88
- const absPath = path.resolve(contractDir, filePath);
89
- if (!fs.existsSync(absPath)) {
90
- throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
91
- }
92
- const editor = resolveEditorCli();
93
- await runEditor(editor, absPath);
94
- return {
95
- success: true,
96
- filePath
97
- };
93
+ /** 파일을 외부 에디터로 직접 편집 */
94
+ async function editContent(filePath) {
95
+ assertInsideContractDir(filePath);
96
+ const contractDir = getContractDir();
97
+ const absPath = path.resolve(contractDir, filePath);
98
+ if (!fs.existsSync(absPath)) {
99
+ throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
100
+ }
101
+ const editor = resolveEditorCli();
102
+ await runEditor(editor, absPath);
103
+ return {
104
+ success: true,
105
+ filePath
106
+ };
98
107
  }
99
- /** 에디터별 앱 번들 CLI 경로 + --wait 플래그 매핑 */ const EDITOR_CLI_MAP = {
100
- "Visual Studio Code": {
101
- cli: "Contents/Resources/app/bin/code",
102
- waitFlag: "--wait"
103
- },
104
- Zed: {
105
- cli: "Contents/MacOS/cli",
106
- waitFlag: "--wait"
107
- },
108
- Cursor: {
109
- cli: "Contents/Resources/app/bin/cursor",
110
- waitFlag: "--wait"
111
- }
112
- };
113
- /** 앱 번들 CLI 경로를 resolve. wait=false이면 --wait 플래그를 생략 */ function resolveEditorCli(options) {
114
- const wait = options?.wait ?? true;
115
- const appName = Sonamu.config.externalEditor ?? "Visual Studio Code";
116
- const mapping = EDITOR_CLI_MAP[appName];
117
- if (!mapping) {
118
- throw new Error(`지원되지 않는 에디터입니다: ${appName} (지원: ${Object.keys(EDITOR_CLI_MAP).join(", ")})`);
119
- }
120
- const searchPaths = [
121
- `/Applications/${appName}.app`,
122
- `${os.homedir()}/Applications/${appName}.app`
123
- ];
124
- const bundlePath = searchPaths.find((p)=>fs.existsSync(p));
125
- if (!bundlePath) {
126
- throw new Error(`앱 번들을 찾을 수 없습니다: ${appName} (/Applications 확인)`);
127
- }
128
- const cliBin = path.join(bundlePath, mapping.cli);
129
- if (!fs.existsSync(cliBin)) {
130
- throw new Error(`에디터 CLI를 찾을 수 없습니다: ${cliBin}`);
131
- }
132
- return {
133
- bin: cliBin,
134
- args: wait ? [
135
- mapping.waitFlag
136
- ] : []
137
- };
108
+ /** 앱 번들 CLI 경로를 resolve. wait=false이면 --wait 플래그를 생략 */
109
+ function resolveEditorCli(options) {
110
+ const wait = options?.wait ?? true;
111
+ const appName = Sonamu.config.externalEditor ?? "Visual Studio Code";
112
+ const mapping = EDITOR_CLI_MAP[appName];
113
+ if (!mapping) {
114
+ throw new Error(`지원되지 않는 에디터입니다: ${appName} (지원: ${Object.keys(EDITOR_CLI_MAP).join(", ")})`);
115
+ }
116
+ const searchPaths = [`/Applications/${appName}.app`, `${os.homedir()}/Applications/${appName}.app`];
117
+ const bundlePath = searchPaths.find((p) => fs.existsSync(p));
118
+ if (!bundlePath) {
119
+ throw new Error(`앱 번들을 찾을 수 없습니다: ${appName} (/Applications 확인)`);
120
+ }
121
+ const cliBin = path.join(bundlePath, mapping.cli);
122
+ if (!fs.existsSync(cliBin)) {
123
+ throw new Error(`에디터 CLI를 찾을 수 없습니다: ${cliBin}`);
124
+ }
125
+ return {
126
+ bin: cliBin,
127
+ args: wait ? [mapping.waitFlag] : []
128
+ };
138
129
  }
139
- /** 에디터 CLI를 실행하고 탭이 닫힐 때까지 대기 */ function runEditor(editor, filePath) {
140
- return new Promise((resolve, reject)=>{
141
- const child = spawn(editor.bin, [
142
- ...editor.args,
143
- filePath
144
- ], {
145
- stdio: "inherit"
146
- });
147
- child.on("error", (err)=>{
148
- reject(new Error(`에디터 실행 실패 (${editor.bin}): ${err.message}`));
149
- });
150
- child.on("close", (code)=>{
151
- if (code === 0) {
152
- resolve();
153
- } else {
154
- reject(new Error(`에디터가 비정상 종료되었습니다 (exit code: ${code})`));
155
- }
156
- });
157
- });
130
+ /** 에디터 CLI를 실행하고 탭이 닫힐 때까지 대기 */
131
+ function runEditor(editor, filePath) {
132
+ return new Promise((resolve, reject) => {
133
+ const child = spawn(editor.bin, [...editor.args, filePath], { stdio: "inherit" });
134
+ child.on("error", (err) => {
135
+ reject(new Error(`에디터 실행 실패 (${editor.bin}): ${err.message}`));
136
+ });
137
+ child.on("close", (code) => {
138
+ if (code === 0) {
139
+ resolve();
140
+ } else {
141
+ reject(new Error(`에디터가 비정상 종료되었습니다 (exit code: ${code})`));
142
+ }
143
+ });
144
+ });
158
145
  }
159
- /** 소스 파일을 외부 에디터로 열기 (대기하지 않음) */ export function openSourceFile(filePath) {
160
- const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(Sonamu.apiRootPath, filePath);
161
- if (!fs.existsSync(absPath)) {
162
- throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
163
- }
164
- const editor = resolveEditorCli({
165
- wait: false
166
- });
167
- const child = spawn(editor.bin, [
168
- ...editor.args,
169
- absPath
170
- ], {
171
- stdio: "ignore",
172
- detached: true
173
- });
174
- child.unref();
146
+ /** 소스 파일을 외부 에디터로 열기 (대기하지 않음) */
147
+ function openSourceFile(filePath) {
148
+ const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(Sonamu.apiRootPath, filePath);
149
+ if (!fs.existsSync(absPath)) {
150
+ throw new Error(`파일을 찾을 수 없습니다: ${filePath}`);
151
+ }
152
+ const editor = resolveEditorCli({ wait: false });
153
+ const child = spawn(editor.bin, [...editor.args, absPath], {
154
+ stdio: "ignore",
155
+ detached: true
156
+ });
157
+ child.unref();
175
158
  }
176
- /* ========================================================================
177
- * Rules API
178
- * ======================================================================== */ /** contract/rules/ 디렉터리 내 .rules.json 파일 목록 반환 */ export function listRules() {
179
- const contractDir = getContractDir();
180
- const rulesDir = path.join(contractDir, "rules");
181
- if (!fs.existsSync(rulesDir)) return {
182
- rules: []
183
- };
184
- const entries = fs.readdirSync(rulesDir, {
185
- withFileTypes: true
186
- });
187
- const rules = [];
188
- for (const entry of entries){
189
- if (!entry.isFile() || !entry.name.endsWith(".rules.json")) continue;
190
- const key = entry.name.replace(/\.rules\.json$/, "");
191
- const relPath = `rules/${entry.name}`;
192
- const absPath = path.join(rulesDir, entry.name);
193
- try {
194
- const raw = fs.readFileSync(absPath, "utf-8");
195
- const doc = JSON.parse(raw);
196
- rules.push({
197
- key,
198
- path: relPath,
199
- description: typeof doc.description === "string" ? doc.description : "",
200
- ruleCount: Array.isArray(doc.rules) ? doc.rules.length : 0
201
- });
202
- } catch (err) {
203
- rules.push({
204
- key,
205
- path: relPath,
206
- description: "",
207
- ruleCount: 0,
208
- parseError: err instanceof Error ? err.message : String(err)
209
- });
210
- }
211
- }
212
- return {
213
- rules
214
- };
159
+ /** contract/rules/ 디렉터리 내 .rules.json 파일 목록 반환 */
160
+ function listRules() {
161
+ const contractDir = getContractDir();
162
+ const rulesDir = path.join(contractDir, "rules");
163
+ if (!fs.existsSync(rulesDir)) return { rules: [] };
164
+ const entries = fs.readdirSync(rulesDir, { withFileTypes: true });
165
+ const rules = [];
166
+ for (const entry of entries) {
167
+ if (!entry.isFile() || !entry.name.endsWith(".rules.json")) continue;
168
+ const key = entry.name.replace(/\.rules\.json$/, "");
169
+ const relPath = `rules/${entry.name}`;
170
+ const absPath = path.join(rulesDir, entry.name);
171
+ try {
172
+ const raw = fs.readFileSync(absPath, "utf-8");
173
+ const doc = JSON.parse(raw);
174
+ rules.push({
175
+ key,
176
+ path: relPath,
177
+ description: typeof doc.description === "string" ? doc.description : "",
178
+ ruleCount: Array.isArray(doc.rules) ? doc.rules.length : 0
179
+ });
180
+ } catch (err) {
181
+ rules.push({
182
+ key,
183
+ path: relPath,
184
+ description: "",
185
+ ruleCount: 0,
186
+ parseError: err instanceof Error ? err.message : String(err)
187
+ });
188
+ }
189
+ }
190
+ return { rules };
215
191
  }
216
- /** rules 파일 상세 반환 */ export function readRule(ruleKey) {
217
- const contractDir = getContractDir();
218
- const absPath = path.join(contractDir, "rules", `${ruleKey}.rules.json`);
219
- if (!fs.existsSync(absPath)) {
220
- throw new Error(`Rules 파일을 찾을 수 없습니다: ${ruleKey}`);
221
- }
222
- const raw = fs.readFileSync(absPath, "utf-8");
223
- const doc = JSON.parse(raw);
224
- return {
225
- key: ruleKey,
226
- path: `rules/${ruleKey}.rules.json`,
227
- description: typeof doc.description === "string" ? doc.description : "",
228
- rules: Array.isArray(doc.rules) ? doc.rules : []
229
- };
192
+ /** rules 파일 상세 반환 */
193
+ function readRule(ruleKey) {
194
+ const contractDir = getContractDir();
195
+ const absPath = path.join(contractDir, "rules", `${ruleKey}.rules.json`);
196
+ if (!fs.existsSync(absPath)) {
197
+ throw new Error(`Rules 파일을 찾을 수 없습니다: ${ruleKey}`);
198
+ }
199
+ const raw = fs.readFileSync(absPath, "utf-8");
200
+ const doc = JSON.parse(raw);
201
+ return {
202
+ key: ruleKey,
203
+ path: `rules/${ruleKey}.rules.json`,
204
+ description: typeof doc.description === "string" ? doc.description : "",
205
+ rules: Array.isArray(doc.rules) ? doc.rules : []
206
+ };
230
207
  }
231
- /** rules 파일에 규칙 추가 */ export function addRule(req) {
232
- const contractDir = getContractDir();
233
- const rulesDir = path.join(contractDir, "rules");
234
- const absPath = path.join(rulesDir, `${req.ruleKey}.rules.json`);
235
- if (!fs.existsSync(absPath)) {
236
- throw new Error(`Rules 파일을 찾을 수 없습니다: ${req.ruleKey}`);
237
- }
238
- const raw = fs.readFileSync(absPath, "utf-8");
239
- const doc = JSON.parse(raw);
240
- const rules = Array.isArray(doc.rules) ? doc.rules : [];
241
- const nextId = generateNextRuleId(rules);
242
- const newEntry = {
243
- id: nextId,
244
- when: req.when,
245
- instruction: req.instruction
246
- };
247
- if (req.examples && req.examples.length > 0) {
248
- newEntry.examples = req.examples;
249
- }
250
- rules.push(newEntry);
251
- doc.rules = rules;
252
- fs.writeFileSync(absPath, `${JSON.stringify(doc, null, 2)}\n`, "utf-8");
253
- return {
254
- key: req.ruleKey,
255
- path: `rules/${req.ruleKey}.rules.json`,
256
- description: typeof doc.description === "string" ? doc.description : "",
257
- rules
258
- };
208
+ /** rules 파일에 규칙 추가 */
209
+ function addRule(req) {
210
+ const contractDir = getContractDir();
211
+ const rulesDir = path.join(contractDir, "rules");
212
+ const absPath = path.join(rulesDir, `${req.ruleKey}.rules.json`);
213
+ if (!fs.existsSync(absPath)) {
214
+ throw new Error(`Rules 파일을 찾을 수 없습니다: ${req.ruleKey}`);
215
+ }
216
+ const raw = fs.readFileSync(absPath, "utf-8");
217
+ const doc = JSON.parse(raw);
218
+ const rules = Array.isArray(doc.rules) ? doc.rules : [];
219
+ const nextId = generateNextRuleId(rules);
220
+ const newEntry = {
221
+ id: nextId,
222
+ when: req.when,
223
+ instruction: req.instruction
224
+ };
225
+ if (req.examples && req.examples.length > 0) {
226
+ newEntry.examples = req.examples;
227
+ }
228
+ rules.push(newEntry);
229
+ doc.rules = rules;
230
+ fs.writeFileSync(absPath, `${JSON.stringify(doc, null, 2)}\n`, "utf-8");
231
+ return {
232
+ key: req.ruleKey,
233
+ path: `rules/${req.ruleKey}.rules.json`,
234
+ description: typeof doc.description === "string" ? doc.description : "",
235
+ rules
236
+ };
259
237
  }
260
- /** 기존 id 패턴을 분석하여 다음 순번 id 생성 */ function generateNextRuleId(rules) {
261
- if (rules.length === 0) return "R-001";
262
- const numericPattern = /^(.+?)(\d+)$/;
263
- let bestPrefix = "R-";
264
- let maxNum = 0;
265
- for (const rule of rules){
266
- const match = numericPattern.exec(rule.id);
267
- if (match) {
268
- const prefix = match[1];
269
- const num = Number.parseInt(match[2], 10);
270
- if (num > maxNum) {
271
- bestPrefix = prefix;
272
- maxNum = num;
273
- }
274
- }
275
- }
276
- const nextNum = maxNum + 1;
277
- const padLen = Math.max(3, String(maxNum).length);
278
- return `${bestPrefix}${String(nextNum).padStart(padLen, "0")}`;
238
+ /** 기존 id 패턴을 분석하여 다음 순번 id 생성 */
239
+ function generateNextRuleId(rules) {
240
+ if (rules.length === 0) return "R-001";
241
+ const numericPattern = /^(.+?)(\d+)$/;
242
+ let bestPrefix = "R-";
243
+ let maxNum = 0;
244
+ for (const rule of rules) {
245
+ const match = numericPattern.exec(rule.id);
246
+ if (match) {
247
+ const prefix = match[1];
248
+ const num = Number.parseInt(match[2], 10);
249
+ if (num > maxNum) {
250
+ bestPrefix = prefix;
251
+ maxNum = num;
252
+ }
253
+ }
254
+ }
255
+ const nextNum = maxNum + 1;
256
+ const padLen = Math.max(3, String(maxNum).length);
257
+ return `${bestPrefix}${String(nextNum).padStart(padLen, "0")}`;
279
258
  }
280
- /* ========================================================================
281
- * AC API (modules/cdd ac-list 파싱 로직 복사)
282
- * ======================================================================== */ /** describe/test 패턴 파싱 */ function parseAcEntries(content) {
283
- const entries = [];
284
- const lines = content.split("\n");
285
- let currentDescribe = null;
286
- let describeDepth = 0;
287
- let braceDepth = 0;
288
- let pendingTestAs = false;
289
- let testAsBraceDepth = 0;
290
- let testAsNeedName = false;
291
- for (const line of lines){
292
- const trimmed = line.trim();
293
- const describeMatch = trimmed.match(/^describe\(["'`](.+?)["'`]/);
294
- if (describeMatch) {
295
- currentDescribe = describeMatch[1];
296
- describeDepth = braceDepth;
297
- }
298
- const testMatch = trimmed.match(/^(?:test|it)\(["'`](.+?)["'`]/);
299
- if (testMatch) {
300
- entries.push({
301
- describe: currentDescribe,
302
- test: testMatch[1]
303
- });
304
- }
305
- if (!pendingTestAs && trimmed.match(/^testAs\s*\(/)) {
306
- const inlineMatch = trimmed.match(/^testAs\s*\(\s*\{[^}]*\}\s*,\s*["'`](.+?)["'`]/);
307
- if (inlineMatch) {
308
- entries.push({
309
- describe: currentDescribe,
310
- test: inlineMatch[1]
311
- });
312
- } else {
313
- pendingTestAs = true;
314
- testAsBraceDepth = 0;
315
- testAsNeedName = false;
316
- for (const ch of trimmed){
317
- if (ch === "{") testAsBraceDepth++;
318
- if (ch === "}") testAsBraceDepth--;
319
- }
320
- if (testAsBraceDepth <= 0) {
321
- testAsNeedName = true;
322
- const nameMatch = trimmed.match(/}\s*,\s*["'`](.+?)["'`]/);
323
- if (nameMatch) {
324
- entries.push({
325
- describe: currentDescribe,
326
- test: nameMatch[1]
327
- });
328
- pendingTestAs = false;
329
- testAsNeedName = false;
330
- }
331
- }
332
- }
333
- } else if (pendingTestAs) {
334
- if (!testAsNeedName) {
335
- for (const ch of trimmed){
336
- if (ch === "{") testAsBraceDepth++;
337
- if (ch === "}") testAsBraceDepth--;
338
- }
339
- if (testAsBraceDepth <= 0) {
340
- testAsNeedName = true;
341
- const nameMatch = trimmed.match(/}\s*,\s*["'`](.+?)["'`]/);
342
- if (nameMatch) {
343
- entries.push({
344
- describe: currentDescribe,
345
- test: nameMatch[1]
346
- });
347
- pendingTestAs = false;
348
- testAsNeedName = false;
349
- }
350
- }
351
- } else {
352
- const nameMatch = trimmed.match(/^["'`](.+?)["'`]/);
353
- if (nameMatch) {
354
- entries.push({
355
- describe: currentDescribe,
356
- test: nameMatch[1]
357
- });
358
- pendingTestAs = false;
359
- testAsNeedName = false;
360
- }
361
- }
362
- }
363
- for (const ch of trimmed){
364
- if (ch === "{") braceDepth++;
365
- if (ch === "}") {
366
- braceDepth--;
367
- if (currentDescribe && braceDepth <= describeDepth) {
368
- currentDescribe = null;
369
- }
370
- }
371
- }
372
- }
373
- return entries;
259
+ /** describe/test 패턴 파싱 */
260
+ function parseAcEntries(content) {
261
+ const entries = [];
262
+ const lines = content.split("\n");
263
+ let currentDescribe = null;
264
+ let describeDepth = 0;
265
+ let braceDepth = 0;
266
+ let pendingTestAs = false;
267
+ let testAsBraceDepth = 0;
268
+ let testAsNeedName = false;
269
+ for (const line of lines) {
270
+ const trimmed = line.trim();
271
+ const describeMatch = trimmed.match(/^describe\(["'`](.+?)["'`]/);
272
+ if (describeMatch) {
273
+ currentDescribe = describeMatch[1];
274
+ describeDepth = braceDepth;
275
+ }
276
+ const testMatch = trimmed.match(/^(?:test|it)\(["'`](.+?)["'`]/);
277
+ if (testMatch) {
278
+ entries.push({
279
+ describe: currentDescribe,
280
+ test: testMatch[1]
281
+ });
282
+ }
283
+ if (!pendingTestAs && trimmed.match(/^testAs\s*\(/)) {
284
+ const inlineMatch = trimmed.match(/^testAs\s*\(\s*\{[^}]*\}\s*,\s*["'`](.+?)["'`]/);
285
+ if (inlineMatch) {
286
+ entries.push({
287
+ describe: currentDescribe,
288
+ test: inlineMatch[1]
289
+ });
290
+ } else {
291
+ pendingTestAs = true;
292
+ testAsBraceDepth = 0;
293
+ testAsNeedName = false;
294
+ for (const ch of trimmed) {
295
+ if (ch === "{") testAsBraceDepth++;
296
+ if (ch === "}") testAsBraceDepth--;
297
+ }
298
+ if (testAsBraceDepth <= 0) {
299
+ testAsNeedName = true;
300
+ const nameMatch = trimmed.match(/}\s*,\s*["'`](.+?)["'`]/);
301
+ if (nameMatch) {
302
+ entries.push({
303
+ describe: currentDescribe,
304
+ test: nameMatch[1]
305
+ });
306
+ pendingTestAs = false;
307
+ testAsNeedName = false;
308
+ }
309
+ }
310
+ }
311
+ } else if (pendingTestAs) {
312
+ if (!testAsNeedName) {
313
+ for (const ch of trimmed) {
314
+ if (ch === "{") testAsBraceDepth++;
315
+ if (ch === "}") testAsBraceDepth--;
316
+ }
317
+ if (testAsBraceDepth <= 0) {
318
+ testAsNeedName = true;
319
+ const nameMatch = trimmed.match(/}\s*,\s*["'`](.+?)["'`]/);
320
+ if (nameMatch) {
321
+ entries.push({
322
+ describe: currentDescribe,
323
+ test: nameMatch[1]
324
+ });
325
+ pendingTestAs = false;
326
+ testAsNeedName = false;
327
+ }
328
+ }
329
+ } else {
330
+ const nameMatch = trimmed.match(/^["'`](.+?)["'`]/);
331
+ if (nameMatch) {
332
+ entries.push({
333
+ describe: currentDescribe,
334
+ test: nameMatch[1]
335
+ });
336
+ pendingTestAs = false;
337
+ testAsNeedName = false;
338
+ }
339
+ }
340
+ }
341
+ for (const ch of trimmed) {
342
+ if (ch === "{") braceDepth++;
343
+ if (ch === "}") {
344
+ braceDepth--;
345
+ if (currentDescribe && braceDepth <= describeDepth) {
346
+ currentDescribe = null;
347
+ }
348
+ }
349
+ }
350
+ }
351
+ return entries;
374
352
  }
375
- /** 프로젝트 내 *.test.ts 파일을 스캔하여 AC 목록 반환 */ export function getAcList() {
376
- const projectRoot = getProjectRoot();
377
- const files = findTestFiles(projectRoot);
378
- const acFiles = [];
379
- for (const absPath of files){
380
- const content = fs.readFileSync(absPath, "utf-8");
381
- const entries = parseAcEntries(content);
382
- if (entries.length > 0) {
383
- acFiles.push({
384
- path: path.relative(projectRoot, absPath),
385
- entries
386
- });
387
- }
388
- }
389
- const total = acFiles.reduce((sum, f)=>sum + f.entries.length, 0);
390
- return {
391
- files: acFiles,
392
- total
393
- };
353
+ /** 프로젝트 내 *.test.ts 파일을 스캔하여 AC 목록 반환 */
354
+ function getAcList() {
355
+ const projectRoot = getProjectRoot();
356
+ const files = findTestFiles(projectRoot);
357
+ const acFiles = [];
358
+ for (const absPath of files) {
359
+ const content = fs.readFileSync(absPath, "utf-8");
360
+ const entries = parseAcEntries(content);
361
+ if (entries.length > 0) {
362
+ acFiles.push({
363
+ path: path.relative(projectRoot, absPath),
364
+ entries
365
+ });
366
+ }
367
+ }
368
+ const total = acFiles.reduce((sum, f) => sum + f.entries.length, 0);
369
+ return {
370
+ files: acFiles,
371
+ total
372
+ };
394
373
  }
395
- /** *.test.ts 파일을 재귀 탐색 (node_modules, dist 제외) */ function findTestFiles(dir) {
396
- const results = [];
397
- const IGNORE = new Set([
398
- "node_modules",
399
- "dist",
400
- ".git",
401
- "contract"
402
- ]);
403
- function walk(currentDir) {
404
- let entries;
405
- try {
406
- entries = fs.readdirSync(currentDir, {
407
- withFileTypes: true
408
- });
409
- } catch {
410
- return;
411
- }
412
- for (const entry of entries){
413
- if (IGNORE.has(entry.name)) continue;
414
- const fullPath = path.join(currentDir, entry.name);
415
- if (entry.isDirectory()) {
416
- walk(fullPath);
417
- } else if (entry.isFile() && entry.name.endsWith(".test.ts")) {
418
- results.push(fullPath);
419
- }
420
- }
421
- }
422
- walk(dir);
423
- results.sort();
424
- return results;
374
+ /** *.test.ts 파일을 재귀 탐색 (node_modules, dist 제외) */
375
+ function findTestFiles(dir) {
376
+ const results = [];
377
+ const IGNORE = new Set([
378
+ "node_modules",
379
+ "dist",
380
+ ".git",
381
+ "contract"
382
+ ]);
383
+ function walk(currentDir) {
384
+ let entries;
385
+ try {
386
+ entries = fs.readdirSync(currentDir, { withFileTypes: true });
387
+ } catch {
388
+ return;
389
+ }
390
+ for (const entry of entries) {
391
+ if (IGNORE.has(entry.name)) continue;
392
+ const fullPath = path.join(currentDir, entry.name);
393
+ if (entry.isDirectory()) {
394
+ walk(fullPath);
395
+ } else if (entry.isFile() && entry.name.endsWith(".test.ts")) {
396
+ results.push(fullPath);
397
+ }
398
+ }
399
+ }
400
+ walk(dir);
401
+ results.sort();
402
+ return results;
425
403
  }
404
+ var EDITOR_CLI_MAP;
405
+ var init_cdd_service = __esmMin((() => {
406
+ init_sonamu();
407
+ EDITOR_CLI_MAP = {
408
+ "Visual Studio Code": {
409
+ cli: "Contents/Resources/app/bin/code",
410
+ waitFlag: "--wait"
411
+ },
412
+ Zed: {
413
+ cli: "Contents/MacOS/cli",
414
+ waitFlag: "--wait"
415
+ },
416
+ Cursor: {
417
+ cli: "Contents/Resources/app/bin/cursor",
418
+ waitFlag: "--wait"
419
+ }
420
+ };
421
+ }));
426
422
 
427
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91aS9jZGQtc2VydmljZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3biB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ2RkQWNFbnRyeSxcbiAgQ2RkQWNGaWxlLFxuICBDZGRBY0xpc3RSZXN1bHQsXG4gIENkZEFkZFJ1bGVSZXF1ZXN0LFxuICBDZGRDb250ZW50UmVzdWx0LFxuICBDZGRGaWxlVHlwZSxcbiAgQ2RkUnVsZURldGFpbCxcbiAgQ2RkUnVsZUVudHJ5LFxuICBDZGRSdWxlU3VtbWFyeSxcbiAgQ2RkVHJlZU5vZGUsXG59IGZyb20gXCIuL2NkZC10eXBlc1wiO1xuXG5leHBvcnQgdHlwZSB7XG4gIENkZEFjRW50cnksXG4gIENkZEFjRmlsZSxcbiAgQ2RkQWNMaXN0UmVzdWx0LFxuICBDZGRBZGRSdWxlUmVxdWVzdCxcbiAgQ2RkQ29udGVudFJlc3VsdCxcbiAgQ2RkRmlsZVR5cGUsXG4gIENkZFJ1bGVEZXRhaWwsXG4gIENkZFJ1bGVFbnRyeSxcbiAgQ2RkUnVsZVN1bW1hcnksXG4gIENkZFRyZWVOb2RlLFxufSBmcm9tIFwiLi9jZGQtdHlwZXNcIjtcblxuLyoqIGNvbnRyYWN0LyDrlJTroInthLDrpqwg7KCI64yAIOqyveuhnCDrsJjtmZggKGFwaVJvb3RQYXRoIOq4sOykgCkgKi9cbmZ1bmN0aW9uIGdldENvbnRyYWN0RGlyKCk6IHN0cmluZyB7XG4gIHJldHVybiBwYXRoLmpvaW4oU29uYW11LmFwaVJvb3RQYXRoLCBcIi4uXCIsIFwiLi5cIiwgXCJjb250cmFjdFwiKTtcbn1cblxuLyoqIO2UhOuhnOygne2KuCDro6jtirgg6rK966GcIOuwmO2ZmCAqL1xuZnVuY3Rpb24gZ2V0UHJvamVjdFJvb3QoKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGguam9pbihTb25hbXUuYXBpUm9vdFBhdGgsIFwiLi5cIiwgXCIuLlwiKTtcbn1cblxuLyoqIOqyveuhnOqwgCBjb250cmFjdC8g65SU66CJ7YSw66asIOuCtOu2gOyduOyngCDqsoDspp0gKi9cbmZ1bmN0aW9uIGFzc2VydEluc2lkZUNvbnRyYWN0RGlyKGZpbGVQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgY29udHJhY3REaXIgPSBnZXRDb250cmFjdERpcigpO1xuICBjb25zdCByZXNvbHZlZCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuICBpZiAoIXJlc29sdmVkLnN0YXJ0c1dpdGgoY29udHJhY3REaXIgKyBwYXRoLnNlcCkgJiYgcmVzb2x2ZWQgIT09IGNvbnRyYWN0RGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDqsr3roZzqsIAgY29udHJhY3QvIOuUlOugie2EsOumrCDrsJbsnYQg7LC47KGw7ZWp64uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG59XG5cbi8qKiDtjIzsnbzrqoXsl5DshJwgQ2RkRmlsZVR5cGUg7YyQ67OEICovXG5mdW5jdGlvbiBkZXRlY3RGaWxlVHlwZShmaWxlTmFtZTogc3RyaW5nKTogQ2RkRmlsZVR5cGUgfCB1bmRlZmluZWQge1xuICBpZiAoZmlsZU5hbWUuZW5kc1dpdGgoXCIuY29udHJhY3QubWRcIikpIHJldHVybiBcImNvbnRyYWN0XCI7XG4gIGlmIChmaWxlTmFtZS5lbmRzV2l0aChcIi5ydWxlcy5qc29uXCIpKSByZXR1cm4gXCJydWxlc1wiO1xuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKiog65SU66CJ7YSw66as66W8IOyerOq3gCDtg5Dsg4ntlZjsl6wgQ2RkVHJlZU5vZGUg7Yq466as66W8IOyDneyEsSAqL1xuZnVuY3Rpb24gc2NhbkRpcmVjdG9yeShkaXJQYXRoOiBzdHJpbmcsIHJlbGF0aXZlVG86IHN0cmluZyk6IENkZFRyZWVOb2RlW10ge1xuICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoZGlyUGF0aCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICBjb25zdCBub2RlczogQ2RkVHJlZU5vZGVbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKGRpclBhdGgsIGVudHJ5Lm5hbWUpO1xuICAgIGNvbnN0IHJlbFBhdGggPSBwYXRoLnJlbGF0aXZlKHJlbGF0aXZlVG8sIGZ1bGxQYXRoKTtcblxuICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBpZiAoZW50cnkubmFtZSA9PT0gXCJydWxlc1wiKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IGNoaWxkcmVuID0gc2NhbkRpcmVjdG9yeShmdWxsUGF0aCwgcmVsYXRpdmVUbyk7XG4gICAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgICBuYW1lOiBlbnRyeS5uYW1lLFxuICAgICAgICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgICAgICAgdHlwZTogXCJkaXJlY3RvcnlcIixcbiAgICAgICAgICBjaGlsZHJlbixcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChlbnRyeS5pc0ZpbGUoKSkge1xuICAgICAgY29uc3QgZmlsZVR5cGUgPSBkZXRlY3RGaWxlVHlwZShlbnRyeS5uYW1lKTtcbiAgICAgIGlmIChmaWxlVHlwZSAmJiBmaWxlVHlwZSAhPT0gXCJydWxlc1wiKSB7XG4gICAgICAgIG5vZGVzLnB1c2goe1xuICAgICAgICAgIG5hbWU6IGVudHJ5Lm5hbWUsXG4gICAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgICB0eXBlOiBcImZpbGVcIixcbiAgICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5vZGVzO1xufVxuXG4vKiogY29udHJhY3QvIOuUlOugie2EsOumrOydmCDtirjrpqwg6rWs7KGw66W8IOuwmO2ZmCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENkZFRyZWUoKTogeyBleGlzdHM6IGJvb2xlYW47IHRyZWU6IENkZFRyZWVOb2RlW10gfSB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNvbnRyYWN0RGlyKSkge1xuICAgIHJldHVybiB7IGV4aXN0czogZmFsc2UsIHRyZWU6IFtdIH07XG4gIH1cbiAgY29uc3QgdHJlZSA9IHNjYW5EaXJlY3RvcnkoY29udHJhY3REaXIsIGNvbnRyYWN0RGlyKTtcbiAgcmV0dXJuIHsgZXhpc3RzOiB0cnVlLCB0cmVlIH07XG59XG5cbi8qKiDtjIzsnbwg64K07Jqp7J2EIOydveyWtCDrsJjtmZggKGNvbnRyYWN0Lm1kIOKGkiBtYXJrZG93biDsm5DrrLgsIHJ1bGVzLmpzb24g4oaSIEpTT04g66y47J6Q7Je0KSAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRDb250ZW50KGZpbGVQYXRoOiBzdHJpbmcpOiBDZGRDb250ZW50UmVzdWx0IHtcbiAgYXNzZXJ0SW5zaWRlQ29udHJhY3REaXIoZmlsZVBhdGgpO1xuXG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICBjb25zdCBmaWxlVHlwZSA9IGRldGVjdEZpbGVUeXBlKHBhdGguYmFzZW5hbWUoZmlsZVBhdGgpKTtcblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQsXG4gICAgZmlsZVR5cGU6IGZpbGVUeXBlID8/IFwiY29udHJhY3RcIixcbiAgfTtcbn1cblxuLyoqIO2MjOydvOydhCDsmbjrtoAg7JeQ65SU7YSw66GcIOyngeygkSDtjrjsp5EgKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlZGl0Q29udGVudChcbiAgZmlsZVBhdGg6IHN0cmluZyxcbik6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyBmaWxlUGF0aDogc3RyaW5nIH0+IHtcbiAgYXNzZXJ0SW5zaWRlQ29udHJhY3REaXIoZmlsZVBhdGgpO1xuXG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGgucmVzb2x2ZShjb250cmFjdERpciwgZmlsZVBhdGgpO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgY29uc3QgZWRpdG9yID0gcmVzb2x2ZUVkaXRvckNsaSgpO1xuICBhd2FpdCBydW5FZGl0b3IoZWRpdG9yLCBhYnNQYXRoKTtcblxuICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBmaWxlUGF0aCB9O1xufVxuXG4vKiog7JeQ65SU7YSw67OEIOyVsSDrsojrk6Qg64K0IENMSSDqsr3roZwgKyAtLXdhaXQg7ZSM656Y6re4IOunpO2VkSAqL1xuY29uc3QgRURJVE9SX0NMSV9NQVA6IFJlY29yZDxzdHJpbmcsIHsgY2xpOiBzdHJpbmc7IHdhaXRGbGFnOiBzdHJpbmcgfT4gPSB7XG4gIFwiVmlzdWFsIFN0dWRpbyBDb2RlXCI6IHsgY2xpOiBcIkNvbnRlbnRzL1Jlc291cmNlcy9hcHAvYmluL2NvZGVcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbiAgWmVkOiB7IGNsaTogXCJDb250ZW50cy9NYWNPUy9jbGlcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbiAgQ3Vyc29yOiB7IGNsaTogXCJDb250ZW50cy9SZXNvdXJjZXMvYXBwL2Jpbi9jdXJzb3JcIiwgd2FpdEZsYWc6IFwiLS13YWl0XCIgfSxcbn07XG5cbi8qKiDslbEg67KI65OkIENMSSDqsr3roZzrpbwgcmVzb2x2ZS4gd2FpdD1mYWxzZeydtOuptCAtLXdhaXQg7ZSM656Y6re466W8IOyDneuetSAqL1xuZnVuY3Rpb24gcmVzb2x2ZUVkaXRvckNsaShvcHRpb25zPzogeyB3YWl0PzogYm9vbGVhbiB9KTogeyBiaW46IHN0cmluZzsgYXJnczogc3RyaW5nW10gfSB7XG4gIGNvbnN0IHdhaXQgPSBvcHRpb25zPy53YWl0ID8/IHRydWU7XG4gIGNvbnN0IGFwcE5hbWUgPSBTb25hbXUuY29uZmlnLmV4dGVybmFsRWRpdG9yID8/IFwiVmlzdWFsIFN0dWRpbyBDb2RlXCI7XG4gIGNvbnN0IG1hcHBpbmcgPSBFRElUT1JfQ0xJX01BUFthcHBOYW1lXTtcbiAgaWYgKCFtYXBwaW5nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYOyngOybkOuQmOyngCDslYrripQg7JeQ65SU7YSw7J6F64uI64ukOiAke2FwcE5hbWV9ICjsp4Dsm5A6ICR7T2JqZWN0LmtleXMoRURJVE9SX0NMSV9NQVApLmpvaW4oXCIsIFwiKX0pYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3Qgc2VhcmNoUGF0aHMgPSBbXG4gICAgYC9BcHBsaWNhdGlvbnMvJHthcHBOYW1lfS5hcHBgLFxuICAgIGAke29zLmhvbWVkaXIoKX0vQXBwbGljYXRpb25zLyR7YXBwTmFtZX0uYXBwYCxcbiAgXTtcbiAgY29uc3QgYnVuZGxlUGF0aCA9IHNlYXJjaFBhdGhzLmZpbmQoKHApID0+IGZzLmV4aXN0c1N5bmMocCkpO1xuICBpZiAoIWJ1bmRsZVBhdGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOyVsSDrsojrk6TsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7YXBwTmFtZX0gKC9BcHBsaWNhdGlvbnMg7ZmV7J24KWApO1xuICB9XG5cbiAgY29uc3QgY2xpQmluID0gcGF0aC5qb2luKGJ1bmRsZVBhdGgsIG1hcHBpbmcuY2xpKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNsaUJpbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYOyXkOuUlO2EsCBDTEnrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7Y2xpQmlufWApO1xuICB9XG5cbiAgcmV0dXJuIHsgYmluOiBjbGlCaW4sIGFyZ3M6IHdhaXQgPyBbbWFwcGluZy53YWl0RmxhZ10gOiBbXSB9O1xufVxuXG4vKiog7JeQ65SU7YSwIENMSeulvCDsi6TtlontlZjqs6Ag7YOt7J20IOuLq+2ekCDrlYzquYzsp4Ag64yA6riwICovXG5mdW5jdGlvbiBydW5FZGl0b3IoZWRpdG9yOiB7IGJpbjogc3RyaW5nOyBhcmdzOiBzdHJpbmdbXSB9LCBmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bihlZGl0b3IuYmluLCBbLi4uZWRpdG9yLmFyZ3MsIGZpbGVQYXRoXSwge1xuICAgICAgc3RkaW86IFwiaW5oZXJpdFwiLFxuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICByZWplY3QobmV3IEVycm9yKGDsl5DrlJTthLAg7Iuk7ZaJIOyLpO2MqCAoJHtlZGl0b3IuYmlufSk6ICR7ZXJyLm1lc3NhZ2V9YCkpO1xuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJjbG9zZVwiLCAoY29kZSkgPT4ge1xuICAgICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihg7JeQ65SU7YSw6rCAIOu5hOygleyDgSDsooXro4zrkJjsl4jsirXri4jri6QgKGV4aXQgY29kZTogJHtjb2RlfSlgKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKiog7IaM7IqkIO2MjOydvOydhCDsmbjrtoAg7JeQ65SU7YSw66GcIOyXtOq4sCAo64yA6riw7ZWY7KeAIOyViuydjCkgKi9cbmV4cG9ydCBmdW5jdGlvbiBvcGVuU291cmNlRmlsZShmaWxlUGF0aDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLmlzQWJzb2x1dGUoZmlsZVBhdGgpID8gZmlsZVBhdGggOiBwYXRoLnJlc29sdmUoU29uYW11LmFwaVJvb3RQYXRoLCBmaWxlUGF0aCk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGFic1BhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDtjIzsnbzsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7ZmlsZVBhdGh9YCk7XG4gIH1cblxuICBjb25zdCBlZGl0b3IgPSByZXNvbHZlRWRpdG9yQ2xpKHsgd2FpdDogZmFsc2UgfSk7XG4gIGNvbnN0IGNoaWxkID0gc3Bhd24oZWRpdG9yLmJpbiwgWy4uLmVkaXRvci5hcmdzLCBhYnNQYXRoXSwge1xuICAgIHN0ZGlvOiBcImlnbm9yZVwiLFxuICAgIGRldGFjaGVkOiB0cnVlLFxuICB9KTtcbiAgY2hpbGQudW5yZWYoKTtcbn1cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBSdWxlcyBBUElcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4vKiogY29udHJhY3QvcnVsZXMvIOuUlOugie2EsOumrCDrgrQgLnJ1bGVzLmpzb24g7YyM7J28IOuqqeuhnSDrsJjtmZggKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0UnVsZXMoKTogeyBydWxlczogQ2RkUnVsZVN1bW1hcnlbXSB9IHtcbiAgY29uc3QgY29udHJhY3REaXIgPSBnZXRDb250cmFjdERpcigpO1xuICBjb25zdCBydWxlc0RpciA9IHBhdGguam9pbihjb250cmFjdERpciwgXCJydWxlc1wiKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKHJ1bGVzRGlyKSkgcmV0dXJuIHsgcnVsZXM6IFtdIH07XG5cbiAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKHJ1bGVzRGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gIGNvbnN0IHJ1bGVzOiBDZGRSdWxlU3VtbWFyeVtdID0gW107XG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgaWYgKCFlbnRyeS5pc0ZpbGUoKSB8fCAhZW50cnkubmFtZS5lbmRzV2l0aChcIi5ydWxlcy5qc29uXCIpKSBjb250aW51ZTtcblxuICAgIGNvbnN0IGtleSA9IGVudHJ5Lm5hbWUucmVwbGFjZSgvXFwucnVsZXNcXC5qc29uJC8sIFwiXCIpO1xuICAgIGNvbnN0IHJlbFBhdGggPSBgcnVsZXMvJHtlbnRyeS5uYW1lfWA7XG4gICAgY29uc3QgYWJzUGF0aCA9IHBhdGguam9pbihydWxlc0RpciwgZW50cnkubmFtZSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmF3ID0gZnMucmVhZEZpbGVTeW5jKGFic1BhdGgsIFwidXRmLThcIik7XG4gICAgICBjb25zdCBkb2MgPSBKU09OLnBhcnNlKHJhdykgYXMgeyBkZXNjcmlwdGlvbj86IHN0cmluZzsgcnVsZXM/OiB1bmtub3duW10gfTtcbiAgICAgIHJ1bGVzLnB1c2goe1xuICAgICAgICBrZXksXG4gICAgICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0eXBlb2YgZG9jLmRlc2NyaXB0aW9uID09PSBcInN0cmluZ1wiID8gZG9jLmRlc2NyaXB0aW9uIDogXCJcIixcbiAgICAgICAgcnVsZUNvdW50OiBBcnJheS5pc0FycmF5KGRvYy5ydWxlcykgPyBkb2MucnVsZXMubGVuZ3RoIDogMCxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcnVsZXMucHVzaCh7XG4gICAgICAgIGtleSxcbiAgICAgICAgcGF0aDogcmVsUGF0aCxcbiAgICAgICAgZGVzY3JpcHRpb246IFwiXCIsXG4gICAgICAgIHJ1bGVDb3VudDogMCxcbiAgICAgICAgcGFyc2VFcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgcnVsZXMgfTtcbn1cblxuLyoqIHJ1bGVzIO2MjOydvCDsg4HshLgg67CY7ZmYICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZFJ1bGUocnVsZUtleTogc3RyaW5nKTogQ2RkUnVsZURldGFpbCB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGguam9pbihjb250cmFjdERpciwgXCJydWxlc1wiLCBgJHtydWxlS2V5fS5ydWxlcy5qc29uYCk7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGFic1BhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBSdWxlcyDtjIzsnbzsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6Q6ICR7cnVsZUtleX1gKTtcbiAgfVxuXG4gIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICBjb25zdCBkb2MgPSBKU09OLnBhcnNlKHJhdykgYXMgeyBkZXNjcmlwdGlvbj86IHN0cmluZzsgcnVsZXM/OiBDZGRSdWxlRW50cnlbXSB9O1xuXG4gIHJldHVybiB7XG4gICAga2V5OiBydWxlS2V5LFxuICAgIHBhdGg6IGBydWxlcy8ke3J1bGVLZXl9LnJ1bGVzLmpzb25gLFxuICAgIGRlc2NyaXB0aW9uOiB0eXBlb2YgZG9jLmRlc2NyaXB0aW9uID09PSBcInN0cmluZ1wiID8gZG9jLmRlc2NyaXB0aW9uIDogXCJcIixcbiAgICBydWxlczogQXJyYXkuaXNBcnJheShkb2MucnVsZXMpID8gZG9jLnJ1bGVzIDogW10sXG4gIH07XG59XG5cbi8qKiBydWxlcyDtjIzsnbzsl5Ag6rec7LmZIOy2lOqwgCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZFJ1bGUocmVxOiBDZGRBZGRSdWxlUmVxdWVzdCk6IENkZFJ1bGVEZXRhaWwge1xuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IHJ1bGVzRGlyID0gcGF0aC5qb2luKGNvbnRyYWN0RGlyLCBcInJ1bGVzXCIpO1xuICBjb25zdCBhYnNQYXRoID0gcGF0aC5qb2luKHJ1bGVzRGlyLCBgJHtyZXEucnVsZUtleX0ucnVsZXMuanNvbmApO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUnVsZXMg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke3JlcS5ydWxlS2V5fWApO1xuICB9XG5cbiAgY29uc3QgcmF3ID0gZnMucmVhZEZpbGVTeW5jKGFic1BhdGgsIFwidXRmLThcIik7XG4gIGNvbnN0IGRvYyA9IEpTT04ucGFyc2UocmF3KSBhcyB7IGRlc2NyaXB0aW9uPzogc3RyaW5nOyBydWxlcz86IENkZFJ1bGVFbnRyeVtdIH07XG4gIGNvbnN0IHJ1bGVzOiBDZGRSdWxlRW50cnlbXSA9IEFycmF5LmlzQXJyYXkoZG9jLnJ1bGVzKSA/IGRvYy5ydWxlcyA6IFtdO1xuXG4gIGNvbnN0IG5leHRJZCA9IGdlbmVyYXRlTmV4dFJ1bGVJZChydWxlcyk7XG4gIGNvbnN0IG5ld0VudHJ5OiBDZGRSdWxlRW50cnkgPSB7XG4gICAgaWQ6IG5leHRJZCxcbiAgICB3aGVuOiByZXEud2hlbixcbiAgICBpbnN0cnVjdGlvbjogcmVxLmluc3RydWN0aW9uLFxuICB9O1xuICBpZiAocmVxLmV4YW1wbGVzICYmIHJlcS5leGFtcGxlcy5sZW5ndGggPiAwKSB7XG4gICAgbmV3RW50cnkuZXhhbXBsZXMgPSByZXEuZXhhbXBsZXM7XG4gIH1cblxuICBydWxlcy5wdXNoKG5ld0VudHJ5KTtcbiAgZG9jLnJ1bGVzID0gcnVsZXM7XG5cbiAgZnMud3JpdGVGaWxlU3luYyhhYnNQYXRoLCBgJHtKU09OLnN0cmluZ2lmeShkb2MsIG51bGwsIDIpfVxcbmAsIFwidXRmLThcIik7XG5cbiAgcmV0dXJuIHtcbiAgICBrZXk6IHJlcS5ydWxlS2V5LFxuICAgIHBhdGg6IGBydWxlcy8ke3JlcS5ydWxlS2V5fS5ydWxlcy5qc29uYCxcbiAgICBkZXNjcmlwdGlvbjogdHlwZW9mIGRvYy5kZXNjcmlwdGlvbiA9PT0gXCJzdHJpbmdcIiA/IGRvYy5kZXNjcmlwdGlvbiA6IFwiXCIsXG4gICAgcnVsZXMsXG4gIH07XG59XG5cbi8qKiDquLDsobQgaWQg7Yyo7YS07J2EIOu2hOyEne2VmOyXrCDri6TsnYwg7Iic67KIIGlkIOyDneyEsSAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVOZXh0UnVsZUlkKHJ1bGVzOiBDZGRSdWxlRW50cnlbXSk6IHN0cmluZyB7XG4gIGlmIChydWxlcy5sZW5ndGggPT09IDApIHJldHVybiBcIlItMDAxXCI7XG5cbiAgY29uc3QgbnVtZXJpY1BhdHRlcm4gPSAvXiguKz8pKFxcZCspJC87XG4gIGxldCBiZXN0UHJlZml4ID0gXCJSLVwiO1xuICBsZXQgbWF4TnVtID0gMDtcblxuICBmb3IgKGNvbnN0IHJ1bGUgb2YgcnVsZXMpIHtcbiAgICBjb25zdCBtYXRjaCA9IG51bWVyaWNQYXR0ZXJuLmV4ZWMocnVsZS5pZCk7XG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCBwcmVmaXggPSBtYXRjaFsxXTtcbiAgICAgIGNvbnN0IG51bSA9IE51bWJlci5wYXJzZUludChtYXRjaFsyXSwgMTApO1xuICAgICAgaWYgKG51bSA+IG1heE51bSkge1xuICAgICAgICBiZXN0UHJlZml4ID0gcHJlZml4O1xuICAgICAgICBtYXhOdW0gPSBudW07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgbmV4dE51bSA9IG1heE51bSArIDE7XG4gIGNvbnN0IHBhZExlbiA9IE1hdGgubWF4KDMsIFN0cmluZyhtYXhOdW0pLmxlbmd0aCk7XG4gIHJldHVybiBgJHtiZXN0UHJlZml4fSR7U3RyaW5nKG5leHROdW0pLnBhZFN0YXJ0KHBhZExlbiwgXCIwXCIpfWA7XG59XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQUMgQVBJIChtb2R1bGVzL2NkZCBhYy1saXN0IO2MjOyLsSDroZzsp4Eg67O17IKsKVxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cbi8qKiBkZXNjcmliZS90ZXN0IO2MqO2EtCDtjIzsi7EgKi9cbmZ1bmN0aW9uIHBhcnNlQWNFbnRyaWVzKGNvbnRlbnQ6IHN0cmluZyk6IENkZEFjRW50cnlbXSB7XG4gIGNvbnN0IGVudHJpZXM6IENkZEFjRW50cnlbXSA9IFtdO1xuICBjb25zdCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoXCJcXG5cIik7XG5cbiAgbGV0IGN1cnJlbnREZXNjcmliZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGxldCBkZXNjcmliZURlcHRoID0gMDtcbiAgbGV0IGJyYWNlRGVwdGggPSAwO1xuICBsZXQgcGVuZGluZ1Rlc3RBcyA9IGZhbHNlO1xuICBsZXQgdGVzdEFzQnJhY2VEZXB0aCA9IDA7XG4gIGxldCB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuXG4gIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgIGNvbnN0IHRyaW1tZWQgPSBsaW5lLnRyaW0oKTtcblxuICAgIGNvbnN0IGRlc2NyaWJlTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9eZGVzY3JpYmVcXChbXCInYF0oLis/KVtcIidgXS8pO1xuICAgIGlmIChkZXNjcmliZU1hdGNoKSB7XG4gICAgICBjdXJyZW50RGVzY3JpYmUgPSBkZXNjcmliZU1hdGNoWzFdO1xuICAgICAgZGVzY3JpYmVEZXB0aCA9IGJyYWNlRGVwdGg7XG4gICAgfVxuXG4gICAgY29uc3QgdGVzdE1hdGNoID0gdHJpbW1lZC5tYXRjaCgvXig/OnRlc3R8aXQpXFwoW1wiJ2BdKC4rPylbXCInYF0vKTtcbiAgICBpZiAodGVzdE1hdGNoKSB7XG4gICAgICBlbnRyaWVzLnB1c2goe1xuICAgICAgICBkZXNjcmliZTogY3VycmVudERlc2NyaWJlLFxuICAgICAgICB0ZXN0OiB0ZXN0TWF0Y2hbMV0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoIXBlbmRpbmdUZXN0QXMgJiYgdHJpbW1lZC5tYXRjaCgvXnRlc3RBc1xccypcXCgvKSkge1xuICAgICAgY29uc3QgaW5saW5lTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9edGVzdEFzXFxzKlxcKFxccypcXHtbXn1dKlxcfVxccyosXFxzKltcIidgXSguKz8pW1wiJ2BdLyk7XG4gICAgICBpZiAoaW5saW5lTWF0Y2gpIHtcbiAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogaW5saW5lTWF0Y2hbMV0gfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZW5kaW5nVGVzdEFzID0gdHJ1ZTtcbiAgICAgICAgdGVzdEFzQnJhY2VEZXB0aCA9IDA7XG4gICAgICAgIHRlc3RBc05lZWROYW1lID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3QgY2ggb2YgdHJpbW1lZCkge1xuICAgICAgICAgIGlmIChjaCA9PT0gXCJ7XCIpIHRlc3RBc0JyYWNlRGVwdGgrKztcbiAgICAgICAgICBpZiAoY2ggPT09IFwifVwiKSB0ZXN0QXNCcmFjZURlcHRoLS07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRlc3RBc0JyYWNlRGVwdGggPD0gMCkge1xuICAgICAgICAgIHRlc3RBc05lZWROYW1lID0gdHJ1ZTtcbiAgICAgICAgICBjb25zdCBuYW1lTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC99XFxzKixcXHMqW1wiJ2BdKC4rPylbXCInYF0vKTtcbiAgICAgICAgICBpZiAobmFtZU1hdGNoKSB7XG4gICAgICAgICAgICBlbnRyaWVzLnB1c2goeyBkZXNjcmliZTogY3VycmVudERlc2NyaWJlLCB0ZXN0OiBuYW1lTWF0Y2hbMV0gfSk7XG4gICAgICAgICAgICBwZW5kaW5nVGVzdEFzID0gZmFsc2U7XG4gICAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGVuZGluZ1Rlc3RBcykge1xuICAgICAgaWYgKCF0ZXN0QXNOZWVkTmFtZSkge1xuICAgICAgICBmb3IgKGNvbnN0IGNoIG9mIHRyaW1tZWQpIHtcbiAgICAgICAgICBpZiAoY2ggPT09IFwie1wiKSB0ZXN0QXNCcmFjZURlcHRoKys7XG4gICAgICAgICAgaWYgKGNoID09PSBcIn1cIikgdGVzdEFzQnJhY2VEZXB0aC0tO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0ZXN0QXNCcmFjZURlcHRoIDw9IDApIHtcbiAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IHRydWU7XG4gICAgICAgICAgY29uc3QgbmFtZU1hdGNoID0gdHJpbW1lZC5tYXRjaCgvfVxccyosXFxzKltcIidgXSguKz8pW1wiJ2BdLyk7XG4gICAgICAgICAgaWYgKG5hbWVNYXRjaCkge1xuICAgICAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogbmFtZU1hdGNoWzFdIH0pO1xuICAgICAgICAgICAgcGVuZGluZ1Rlc3RBcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGVzdEFzTmVlZE5hbWUgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG5hbWVNYXRjaCA9IHRyaW1tZWQubWF0Y2goL15bXCInYF0oLis/KVtcIidgXS8pO1xuICAgICAgICBpZiAobmFtZU1hdGNoKSB7XG4gICAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogbmFtZU1hdGNoWzFdIH0pO1xuICAgICAgICAgIHBlbmRpbmdUZXN0QXMgPSBmYWxzZTtcbiAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBjaCBvZiB0cmltbWVkKSB7XG4gICAgICBpZiAoY2ggPT09IFwie1wiKSBicmFjZURlcHRoKys7XG4gICAgICBpZiAoY2ggPT09IFwifVwiKSB7XG4gICAgICAgIGJyYWNlRGVwdGgtLTtcbiAgICAgICAgaWYgKGN1cnJlbnREZXNjcmliZSAmJiBicmFjZURlcHRoIDw9IGRlc2NyaWJlRGVwdGgpIHtcbiAgICAgICAgICBjdXJyZW50RGVzY3JpYmUgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVudHJpZXM7XG59XG5cbi8qKiDtlITroZzsoJ3tirgg64K0ICoudGVzdC50cyDtjIzsnbzsnYQg7Iqk7LqU7ZWY7JesIEFDIOuqqeuhnSDrsJjtmZggKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBY0xpc3QoKTogQ2RkQWNMaXN0UmVzdWx0IHtcbiAgY29uc3QgcHJvamVjdFJvb3QgPSBnZXRQcm9qZWN0Um9vdCgpO1xuICBjb25zdCBmaWxlcyA9IGZpbmRUZXN0RmlsZXMocHJvamVjdFJvb3QpO1xuXG4gIGNvbnN0IGFjRmlsZXM6IENkZEFjRmlsZVtdID0gW107XG4gIGZvciAoY29uc3QgYWJzUGF0aCBvZiBmaWxlcykge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoYWJzUGF0aCwgXCJ1dGYtOFwiKTtcbiAgICBjb25zdCBlbnRyaWVzID0gcGFyc2VBY0VudHJpZXMoY29udGVudCk7XG4gICAgaWYgKGVudHJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgYWNGaWxlcy5wdXNoKHtcbiAgICAgICAgcGF0aDogcGF0aC5yZWxhdGl2ZShwcm9qZWN0Um9vdCwgYWJzUGF0aCksXG4gICAgICAgIGVudHJpZXMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjb25zdCB0b3RhbCA9IGFjRmlsZXMucmVkdWNlKChzdW0sIGYpID0+IHN1bSArIGYuZW50cmllcy5sZW5ndGgsIDApO1xuICByZXR1cm4geyBmaWxlczogYWNGaWxlcywgdG90YWwgfTtcbn1cblxuLyoqICoudGVzdC50cyDtjIzsnbzsnYQg7J6s6reAIO2DkOyDiSAobm9kZV9tb2R1bGVzLCBkaXN0IOygnOyZuCkgKi9cbmZ1bmN0aW9uIGZpbmRUZXN0RmlsZXMoZGlyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHJlc3VsdHM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IElHTk9SRSA9IG5ldyBTZXQoW1wibm9kZV9tb2R1bGVzXCIsIFwiZGlzdFwiLCBcIi5naXRcIiwgXCJjb250cmFjdFwiXSk7XG5cbiAgZnVuY3Rpb24gd2FsayhjdXJyZW50RGlyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBsZXQgZW50cmllczogZnMuRGlyZW50W107XG4gICAgdHJ5IHtcbiAgICAgIGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhjdXJyZW50RGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgaWYgKElHTk9SRS5oYXMoZW50cnkubmFtZSkpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oY3VycmVudERpciwgZW50cnkubmFtZSk7XG4gICAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICB3YWxrKGZ1bGxQYXRoKTtcbiAgICAgIH0gZWxzZSBpZiAoZW50cnkuaXNGaWxlKCkgJiYgZW50cnkubmFtZS5lbmRzV2l0aChcIi50ZXN0LnRzXCIpKSB7XG4gICAgICAgIHJlc3VsdHMucHVzaChmdWxsUGF0aCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgd2FsayhkaXIpO1xuICByZXN1bHRzLnNvcnQoKTtcbiAgcmV0dXJuIHJlc3VsdHM7XG59XG4iXSwibmFtZXMiOlsic3Bhd24iLCJmcyIsIm9zIiwicGF0aCIsIlNvbmFtdSIsImdldENvbnRyYWN0RGlyIiwiam9pbiIsImFwaVJvb3RQYXRoIiwiZ2V0UHJvamVjdFJvb3QiLCJhc3NlcnRJbnNpZGVDb250cmFjdERpciIsImZpbGVQYXRoIiwiY29udHJhY3REaXIiLCJyZXNvbHZlZCIsInJlc29sdmUiLCJzdGFydHNXaXRoIiwic2VwIiwiRXJyb3IiLCJkZXRlY3RGaWxlVHlwZSIsImZpbGVOYW1lIiwiZW5kc1dpdGgiLCJ1bmRlZmluZWQiLCJzY2FuRGlyZWN0b3J5IiwiZGlyUGF0aCIsInJlbGF0aXZlVG8iLCJlbnRyaWVzIiwicmVhZGRpclN5bmMiLCJ3aXRoRmlsZVR5cGVzIiwibm9kZXMiLCJlbnRyeSIsImZ1bGxQYXRoIiwibmFtZSIsInJlbFBhdGgiLCJyZWxhdGl2ZSIsImlzRGlyZWN0b3J5IiwiY2hpbGRyZW4iLCJsZW5ndGgiLCJwdXNoIiwidHlwZSIsImlzRmlsZSIsImZpbGVUeXBlIiwiZ2V0Q2RkVHJlZSIsImV4aXN0c1N5bmMiLCJleGlzdHMiLCJ0cmVlIiwicmVhZENvbnRlbnQiLCJhYnNQYXRoIiwiY29udGVudCIsInJlYWRGaWxlU3luYyIsImJhc2VuYW1lIiwiZWRpdENvbnRlbnQiLCJlZGl0b3IiLCJyZXNvbHZlRWRpdG9yQ2xpIiwicnVuRWRpdG9yIiwic3VjY2VzcyIsIkVESVRPUl9DTElfTUFQIiwiY2xpIiwid2FpdEZsYWciLCJaZWQiLCJDdXJzb3IiLCJvcHRpb25zIiwid2FpdCIsImFwcE5hbWUiLCJjb25maWciLCJleHRlcm5hbEVkaXRvciIsIm1hcHBpbmciLCJPYmplY3QiLCJrZXlzIiwic2VhcmNoUGF0aHMiLCJob21lZGlyIiwiYnVuZGxlUGF0aCIsImZpbmQiLCJwIiwiY2xpQmluIiwiYmluIiwiYXJncyIsIlByb21pc2UiLCJyZWplY3QiLCJjaGlsZCIsInN0ZGlvIiwib24iLCJlcnIiLCJtZXNzYWdlIiwiY29kZSIsIm9wZW5Tb3VyY2VGaWxlIiwiaXNBYnNvbHV0ZSIsImRldGFjaGVkIiwidW5yZWYiLCJsaXN0UnVsZXMiLCJydWxlc0RpciIsInJ1bGVzIiwia2V5IiwicmVwbGFjZSIsInJhdyIsImRvYyIsIkpTT04iLCJwYXJzZSIsImRlc2NyaXB0aW9uIiwicnVsZUNvdW50IiwiQXJyYXkiLCJpc0FycmF5IiwicGFyc2VFcnJvciIsIlN0cmluZyIsInJlYWRSdWxlIiwicnVsZUtleSIsImFkZFJ1bGUiLCJyZXEiLCJuZXh0SWQiLCJnZW5lcmF0ZU5leHRSdWxlSWQiLCJuZXdFbnRyeSIsImlkIiwid2hlbiIsImluc3RydWN0aW9uIiwiZXhhbXBsZXMiLCJ3cml0ZUZpbGVTeW5jIiwic3RyaW5naWZ5IiwibnVtZXJpY1BhdHRlcm4iLCJiZXN0UHJlZml4IiwibWF4TnVtIiwicnVsZSIsIm1hdGNoIiwiZXhlYyIsInByZWZpeCIsIm51bSIsIk51bWJlciIsInBhcnNlSW50IiwibmV4dE51bSIsInBhZExlbiIsIk1hdGgiLCJtYXgiLCJwYWRTdGFydCIsInBhcnNlQWNFbnRyaWVzIiwibGluZXMiLCJzcGxpdCIsImN1cnJlbnREZXNjcmliZSIsImRlc2NyaWJlRGVwdGgiLCJicmFjZURlcHRoIiwicGVuZGluZ1Rlc3RBcyIsInRlc3RBc0JyYWNlRGVwdGgiLCJ0ZXN0QXNOZWVkTmFtZSIsImxpbmUiLCJ0cmltbWVkIiwidHJpbSIsImRlc2NyaWJlTWF0Y2giLCJ0ZXN0TWF0Y2giLCJkZXNjcmliZSIsInRlc3QiLCJpbmxpbmVNYXRjaCIsImNoIiwibmFtZU1hdGNoIiwiZ2V0QWNMaXN0IiwicHJvamVjdFJvb3QiLCJmaWxlcyIsImZpbmRUZXN0RmlsZXMiLCJhY0ZpbGVzIiwidG90YWwiLCJyZWR1Y2UiLCJzdW0iLCJmIiwiZGlyIiwicmVzdWx0cyIsIklHTk9SRSIsIlNldCIsIndhbGsiLCJjdXJyZW50RGlyIiwiaGFzIiwic29ydCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBSyxRQUFRLGdCQUFnQjtBQUN0QyxPQUFPQyxRQUFRLEtBQUs7QUFDcEIsT0FBT0MsUUFBUSxLQUFLO0FBQ3BCLE9BQU9DLFVBQVUsT0FBTztBQUN4QixTQUFTQyxNQUFNLFFBQVEsbUJBQWdCO0FBMkJ2Qyw2Q0FBNkMsR0FDN0MsU0FBU0M7SUFDUCxPQUFPRixLQUFLRyxJQUFJLENBQUNGLE9BQU9HLFdBQVcsRUFBRSxNQUFNLE1BQU07QUFDbkQ7QUFFQSxrQkFBa0IsR0FDbEIsU0FBU0M7SUFDUCxPQUFPTCxLQUFLRyxJQUFJLENBQUNGLE9BQU9HLFdBQVcsRUFBRSxNQUFNO0FBQzdDO0FBRUEsK0JBQStCLEdBQy9CLFNBQVNFLHdCQUF3QkMsUUFBZ0I7SUFDL0MsTUFBTUMsY0FBY047SUFDcEIsTUFBTU8sV0FBV1QsS0FBS1UsT0FBTyxDQUFDRixhQUFhRDtJQUMzQyxJQUFJLENBQUNFLFNBQVNFLFVBQVUsQ0FBQ0gsY0FBY1IsS0FBS1ksR0FBRyxLQUFLSCxhQUFhRCxhQUFhO1FBQzVFLE1BQU0sSUFBSUssTUFBTSxDQUFDLDZCQUE2QixFQUFFTixVQUFVO0lBQzVEO0FBQ0Y7QUFFQSx5QkFBeUIsR0FDekIsU0FBU08sZUFBZUMsUUFBZ0I7SUFDdEMsSUFBSUEsU0FBU0MsUUFBUSxDQUFDLGlCQUFpQixPQUFPO0lBQzlDLElBQUlELFNBQVNDLFFBQVEsQ0FBQyxnQkFBZ0IsT0FBTztJQUM3QyxPQUFPQztBQUNUO0FBRUEscUNBQXFDLEdBQ3JDLFNBQVNDLGNBQWNDLE9BQWUsRUFBRUMsVUFBa0I7SUFDeEQsTUFBTUMsVUFBVXZCLEdBQUd3QixXQUFXLENBQUNILFNBQVM7UUFBRUksZUFBZTtJQUFLO0lBQzlELE1BQU1DLFFBQXVCLEVBQUU7SUFFL0IsS0FBSyxNQUFNQyxTQUFTSixRQUFTO1FBQzNCLE1BQU1LLFdBQVcxQixLQUFLRyxJQUFJLENBQUNnQixTQUFTTSxNQUFNRSxJQUFJO1FBQzlDLE1BQU1DLFVBQVU1QixLQUFLNkIsUUFBUSxDQUFDVCxZQUFZTTtRQUUxQyxJQUFJRCxNQUFNSyxXQUFXLElBQUk7WUFDdkIsSUFBSUwsTUFBTUUsSUFBSSxLQUFLLFNBQVM7WUFDNUIsTUFBTUksV0FBV2IsY0FBY1EsVUFBVU47WUFDekMsSUFBSVcsU0FBU0MsTUFBTSxHQUFHLEdBQUc7Z0JBQ3ZCUixNQUFNUyxJQUFJLENBQUM7b0JBQ1ROLE1BQU1GLE1BQU1FLElBQUk7b0JBQ2hCM0IsTUFBTTRCO29CQUNOTSxNQUFNO29CQUNOSDtnQkFDRjtZQUNGO1FBQ0YsT0FBTyxJQUFJTixNQUFNVSxNQUFNLElBQUk7WUFDekIsTUFBTUMsV0FBV3RCLGVBQWVXLE1BQU1FLElBQUk7WUFDMUMsSUFBSVMsWUFBWUEsYUFBYSxTQUFTO2dCQUNwQ1osTUFBTVMsSUFBSSxDQUFDO29CQUNUTixNQUFNRixNQUFNRSxJQUFJO29CQUNoQjNCLE1BQU00QjtvQkFDTk0sTUFBTTtvQkFDTkU7Z0JBQ0Y7WUFDRjtRQUNGO0lBQ0Y7SUFFQSxPQUFPWjtBQUNUO0FBRUEsOEJBQThCLEdBQzlCLE9BQU8sU0FBU2E7SUFDZCxNQUFNN0IsY0FBY047SUFDcEIsSUFBSSxDQUFDSixHQUFHd0MsVUFBVSxDQUFDOUIsY0FBYztRQUMvQixPQUFPO1lBQUUrQixRQUFRO1lBQU9DLE1BQU0sRUFBRTtRQUFDO0lBQ25DO0lBQ0EsTUFBTUEsT0FBT3RCLGNBQWNWLGFBQWFBO0lBQ3hDLE9BQU87UUFBRStCLFFBQVE7UUFBTUM7SUFBSztBQUM5QjtBQUVBLG9FQUFvRSxHQUNwRSxPQUFPLFNBQVNDLFlBQVlsQyxRQUFnQjtJQUMxQ0Qsd0JBQXdCQztJQUV4QixNQUFNQyxjQUFjTjtJQUNwQixNQUFNd0MsVUFBVTFDLEtBQUtVLE9BQU8sQ0FBQ0YsYUFBYUQ7SUFFMUMsSUFBSSxDQUFDVCxHQUFHd0MsVUFBVSxDQUFDSSxVQUFVO1FBQzNCLE1BQU0sSUFBSTdCLE1BQU0sQ0FBQyxlQUFlLEVBQUVOLFVBQVU7SUFDOUM7SUFFQSxNQUFNb0MsVUFBVTdDLEdBQUc4QyxZQUFZLENBQUNGLFNBQVM7SUFDekMsTUFBTU4sV0FBV3RCLGVBQWVkLEtBQUs2QyxRQUFRLENBQUN0QztJQUU5QyxPQUFPO1FBQ0xvQztRQUNBUCxVQUFVQSxZQUFZO0lBQ3hCO0FBQ0Y7QUFFQSxzQkFBc0IsR0FDdEIsT0FBTyxlQUFlVSxZQUNwQnZDLFFBQWdCO0lBRWhCRCx3QkFBd0JDO0lBRXhCLE1BQU1DLGNBQWNOO0lBQ3BCLE1BQU13QyxVQUFVMUMsS0FBS1UsT0FBTyxDQUFDRixhQUFhRDtJQUUxQyxJQUFJLENBQUNULEdBQUd3QyxVQUFVLENBQUNJLFVBQVU7UUFDM0IsTUFBTSxJQUFJN0IsTUFBTSxDQUFDLGVBQWUsRUFBRU4sVUFBVTtJQUM5QztJQUVBLE1BQU13QyxTQUFTQztJQUNmLE1BQU1DLFVBQVVGLFFBQVFMO0lBRXhCLE9BQU87UUFBRVEsU0FBUztRQUFNM0M7SUFBUztBQUNuQztBQUVBLHVDQUF1QyxHQUN2QyxNQUFNNEMsaUJBQW9FO0lBQ3hFLHNCQUFzQjtRQUFFQyxLQUFLO1FBQW1DQyxVQUFVO0lBQVM7SUFDbkZDLEtBQUs7UUFBRUYsS0FBSztRQUFzQkMsVUFBVTtJQUFTO0lBQ3JERSxRQUFRO1FBQUVILEtBQUs7UUFBcUNDLFVBQVU7SUFBUztBQUN6RTtBQUVBLHNEQUFzRCxHQUN0RCxTQUFTTCxpQkFBaUJRLE9BQTRCO0lBQ3BELE1BQU1DLE9BQU9ELFNBQVNDLFFBQVE7SUFDOUIsTUFBTUMsVUFBVXpELE9BQU8wRCxNQUFNLENBQUNDLGNBQWMsSUFBSTtJQUNoRCxNQUFNQyxVQUFVVixjQUFjLENBQUNPLFFBQVE7SUFDdkMsSUFBSSxDQUFDRyxTQUFTO1FBQ1osTUFBTSxJQUFJaEQsTUFDUixDQUFDLGdCQUFnQixFQUFFNkMsUUFBUSxNQUFNLEVBQUVJLE9BQU9DLElBQUksQ0FBQ1osZ0JBQWdCaEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWhGO0lBRUEsTUFBTTZELGNBQWM7UUFDbEIsQ0FBQyxjQUFjLEVBQUVOLFFBQVEsSUFBSSxDQUFDO1FBQzlCLEdBQUczRCxHQUFHa0UsT0FBTyxHQUFHLGNBQWMsRUFBRVAsUUFBUSxJQUFJLENBQUM7S0FDOUM7SUFDRCxNQUFNUSxhQUFhRixZQUFZRyxJQUFJLENBQUMsQ0FBQ0MsSUFBTXRFLEdBQUd3QyxVQUFVLENBQUM4QjtJQUN6RCxJQUFJLENBQUNGLFlBQVk7UUFDZixNQUFNLElBQUlyRCxNQUFNLENBQUMsaUJBQWlCLEVBQUU2QyxRQUFRLG1CQUFtQixDQUFDO0lBQ2xFO0lBRUEsTUFBTVcsU0FBU3JFLEtBQUtHLElBQUksQ0FBQytELFlBQVlMLFFBQVFULEdBQUc7SUFDaEQsSUFBSSxDQUFDdEQsR0FBR3dDLFVBQVUsQ0FBQytCLFNBQVM7UUFDMUIsTUFBTSxJQUFJeEQsTUFBTSxDQUFDLG9CQUFvQixFQUFFd0QsUUFBUTtJQUNqRDtJQUVBLE9BQU87UUFBRUMsS0FBS0Q7UUFBUUUsTUFBTWQsT0FBTztZQUFDSSxRQUFRUixRQUFRO1NBQUMsR0FBRyxFQUFFO0lBQUM7QUFDN0Q7QUFFQSwrQkFBK0IsR0FDL0IsU0FBU0osVUFBVUYsTUFBdUMsRUFBRXhDLFFBQWdCO0lBQzFFLE9BQU8sSUFBSWlFLFFBQVEsQ0FBQzlELFNBQVMrRDtRQUMzQixNQUFNQyxRQUFRN0UsTUFBTWtELE9BQU91QixHQUFHLEVBQUU7ZUFBSXZCLE9BQU93QixJQUFJO1lBQUVoRTtTQUFTLEVBQUU7WUFDMURvRSxPQUFPO1FBQ1Q7UUFFQUQsTUFBTUUsRUFBRSxDQUFDLFNBQVMsQ0FBQ0M7WUFDakJKLE9BQU8sSUFBSTVELE1BQU0sQ0FBQyxXQUFXLEVBQUVrQyxPQUFPdUIsR0FBRyxDQUFDLEdBQUcsRUFBRU8sSUFBSUMsT0FBTyxFQUFFO1FBQzlEO1FBRUFKLE1BQU1FLEVBQUUsQ0FBQyxTQUFTLENBQUNHO1lBQ2pCLElBQUlBLFNBQVMsR0FBRztnQkFDZHJFO1lBQ0YsT0FBTztnQkFDTCtELE9BQU8sSUFBSTVELE1BQU0sQ0FBQyw2QkFBNkIsRUFBRWtFLEtBQUssQ0FBQyxDQUFDO1lBQzFEO1FBQ0Y7SUFDRjtBQUNGO0FBRUEsZ0NBQWdDLEdBQ2hDLE9BQU8sU0FBU0MsZUFBZXpFLFFBQWdCO0lBQzdDLE1BQU1tQyxVQUFVMUMsS0FBS2lGLFVBQVUsQ0FBQzFFLFlBQVlBLFdBQVdQLEtBQUtVLE9BQU8sQ0FBQ1QsT0FBT0csV0FBVyxFQUFFRztJQUV4RixJQUFJLENBQUNULEdBQUd3QyxVQUFVLENBQUNJLFVBQVU7UUFDM0IsTUFBTSxJQUFJN0IsTUFBTSxDQUFDLGVBQWUsRUFBRU4sVUFBVTtJQUM5QztJQUVBLE1BQU13QyxTQUFTQyxpQkFBaUI7UUFBRVMsTUFBTTtJQUFNO0lBQzlDLE1BQU1pQixRQUFRN0UsTUFBTWtELE9BQU91QixHQUFHLEVBQUU7V0FBSXZCLE9BQU93QixJQUFJO1FBQUU3QjtLQUFRLEVBQUU7UUFDekRpQyxPQUFPO1FBQ1BPLFVBQVU7SUFDWjtJQUNBUixNQUFNUyxLQUFLO0FBQ2I7QUFFQTs7NEVBRTRFLEdBRTVFLGdEQUFnRCxHQUNoRCxPQUFPLFNBQVNDO0lBQ2QsTUFBTTVFLGNBQWNOO0lBQ3BCLE1BQU1tRixXQUFXckYsS0FBS0csSUFBSSxDQUFDSyxhQUFhO0lBQ3hDLElBQUksQ0FBQ1YsR0FBR3dDLFVBQVUsQ0FBQytDLFdBQVcsT0FBTztRQUFFQyxPQUFPLEVBQUU7SUFBQztJQUVqRCxNQUFNakUsVUFBVXZCLEdBQUd3QixXQUFXLENBQUMrRCxVQUFVO1FBQUU5RCxlQUFlO0lBQUs7SUFDL0QsTUFBTStELFFBQTBCLEVBQUU7SUFFbEMsS0FBSyxNQUFNN0QsU0FBU0osUUFBUztRQUMzQixJQUFJLENBQUNJLE1BQU1VLE1BQU0sTUFBTSxDQUFDVixNQUFNRSxJQUFJLENBQUNYLFFBQVEsQ0FBQyxnQkFBZ0I7UUFFNUQsTUFBTXVFLE1BQU05RCxNQUFNRSxJQUFJLENBQUM2RCxPQUFPLENBQUMsa0JBQWtCO1FBQ2pELE1BQU01RCxVQUFVLENBQUMsTUFBTSxFQUFFSCxNQUFNRSxJQUFJLEVBQUU7UUFDckMsTUFBTWUsVUFBVTFDLEtBQUtHLElBQUksQ0FBQ2tGLFVBQVU1RCxNQUFNRSxJQUFJO1FBRTlDLElBQUk7WUFDRixNQUFNOEQsTUFBTTNGLEdBQUc4QyxZQUFZLENBQUNGLFNBQVM7WUFDckMsTUFBTWdELE1BQU1DLEtBQUtDLEtBQUssQ0FBQ0g7WUFDdkJILE1BQU1yRCxJQUFJLENBQUM7Z0JBQ1RzRDtnQkFDQXZGLE1BQU00QjtnQkFDTmlFLGFBQWEsT0FBT0gsSUFBSUcsV0FBVyxLQUFLLFdBQVdILElBQUlHLFdBQVcsR0FBRztnQkFDckVDLFdBQVdDLE1BQU1DLE9BQU8sQ0FBQ04sSUFBSUosS0FBSyxJQUFJSSxJQUFJSixLQUFLLENBQUN0RCxNQUFNLEdBQUc7WUFDM0Q7UUFDRixFQUFFLE9BQU82QyxLQUFLO1lBQ1pTLE1BQU1yRCxJQUFJLENBQUM7Z0JBQ1RzRDtnQkFDQXZGLE1BQU00QjtnQkFDTmlFLGFBQWE7Z0JBQ2JDLFdBQVc7Z0JBQ1hHLFlBQVlwQixlQUFlaEUsUUFBUWdFLElBQUlDLE9BQU8sR0FBR29CLE9BQU9yQjtZQUMxRDtRQUNGO0lBQ0Y7SUFFQSxPQUFPO1FBQUVTO0lBQU07QUFDakI7QUFFQSxtQkFBbUIsR0FDbkIsT0FBTyxTQUFTYSxTQUFTQyxPQUFlO0lBQ3RDLE1BQU01RixjQUFjTjtJQUNwQixNQUFNd0MsVUFBVTFDLEtBQUtHLElBQUksQ0FBQ0ssYUFBYSxTQUFTLEdBQUc0RixRQUFRLFdBQVcsQ0FBQztJQUV2RSxJQUFJLENBQUN0RyxHQUFHd0MsVUFBVSxDQUFDSSxVQUFVO1FBQzNCLE1BQU0sSUFBSTdCLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRXVGLFNBQVM7SUFDbkQ7SUFFQSxNQUFNWCxNQUFNM0YsR0FBRzhDLFlBQVksQ0FBQ0YsU0FBUztJQUNyQyxNQUFNZ0QsTUFBTUMsS0FBS0MsS0FBSyxDQUFDSDtJQUV2QixPQUFPO1FBQ0xGLEtBQUthO1FBQ0xwRyxNQUFNLENBQUMsTUFBTSxFQUFFb0csUUFBUSxXQUFXLENBQUM7UUFDbkNQLGFBQWEsT0FBT0gsSUFBSUcsV0FBVyxLQUFLLFdBQVdILElBQUlHLFdBQVcsR0FBRztRQUNyRVAsT0FBT1MsTUFBTUMsT0FBTyxDQUFDTixJQUFJSixLQUFLLElBQUlJLElBQUlKLEtBQUssR0FBRyxFQUFFO0lBQ2xEO0FBQ0Y7QUFFQSxvQkFBb0IsR0FDcEIsT0FBTyxTQUFTZSxRQUFRQyxHQUFzQjtJQUM1QyxNQUFNOUYsY0FBY047SUFDcEIsTUFBTW1GLFdBQVdyRixLQUFLRyxJQUFJLENBQUNLLGFBQWE7SUFDeEMsTUFBTWtDLFVBQVUxQyxLQUFLRyxJQUFJLENBQUNrRixVQUFVLEdBQUdpQixJQUFJRixPQUFPLENBQUMsV0FBVyxDQUFDO0lBRS9ELElBQUksQ0FBQ3RHLEdBQUd3QyxVQUFVLENBQUNJLFVBQVU7UUFDM0IsTUFBTSxJQUFJN0IsTUFBTSxDQUFDLHFCQUFxQixFQUFFeUYsSUFBSUYsT0FBTyxFQUFFO0lBQ3ZEO0lBRUEsTUFBTVgsTUFBTTNGLEdBQUc4QyxZQUFZLENBQUNGLFNBQVM7SUFDckMsTUFBTWdELE1BQU1DLEtBQUtDLEtBQUssQ0FBQ0g7SUFDdkIsTUFBTUgsUUFBd0JTLE1BQU1DLE9BQU8sQ0FBQ04sSUFBSUosS0FBSyxJQUFJSSxJQUFJSixLQUFLLEdBQUcsRUFBRTtJQUV2RSxNQUFNaUIsU0FBU0MsbUJBQW1CbEI7SUFDbEMsTUFBTW1CLFdBQXlCO1FBQzdCQyxJQUFJSDtRQUNKSSxNQUFNTCxJQUFJSyxJQUFJO1FBQ2RDLGFBQWFOLElBQUlNLFdBQVc7SUFDOUI7SUFDQSxJQUFJTixJQUFJTyxRQUFRLElBQUlQLElBQUlPLFFBQVEsQ0FBQzdFLE1BQU0sR0FBRyxHQUFHO1FBQzNDeUUsU0FBU0ksUUFBUSxHQUFHUCxJQUFJTyxRQUFRO0lBQ2xDO0lBRUF2QixNQUFNckQsSUFBSSxDQUFDd0U7SUFDWGYsSUFBSUosS0FBSyxHQUFHQTtJQUVaeEYsR0FBR2dILGFBQWEsQ0FBQ3BFLFNBQVMsR0FBR2lELEtBQUtvQixTQUFTLENBQUNyQixLQUFLLE1BQU0sR0FBRyxFQUFFLENBQUMsRUFBRTtJQUUvRCxPQUFPO1FBQ0xILEtBQUtlLElBQUlGLE9BQU87UUFDaEJwRyxNQUFNLENBQUMsTUFBTSxFQUFFc0csSUFBSUYsT0FBTyxDQUFDLFdBQVcsQ0FBQztRQUN2Q1AsYUFBYSxPQUFPSCxJQUFJRyxXQUFXLEtBQUssV0FBV0gsSUFBSUcsV0FBVyxHQUFHO1FBQ3JFUDtJQUNGO0FBQ0Y7QUFFQSwrQkFBK0IsR0FDL0IsU0FBU2tCLG1CQUFtQmxCLEtBQXFCO0lBQy9DLElBQUlBLE1BQU10RCxNQUFNLEtBQUssR0FBRyxPQUFPO0lBRS9CLE1BQU1nRixpQkFBaUI7SUFDdkIsSUFBSUMsYUFBYTtJQUNqQixJQUFJQyxTQUFTO0lBRWIsS0FBSyxNQUFNQyxRQUFRN0IsTUFBTztRQUN4QixNQUFNOEIsUUFBUUosZUFBZUssSUFBSSxDQUFDRixLQUFLVCxFQUFFO1FBQ3pDLElBQUlVLE9BQU87WUFDVCxNQUFNRSxTQUFTRixLQUFLLENBQUMsRUFBRTtZQUN2QixNQUFNRyxNQUFNQyxPQUFPQyxRQUFRLENBQUNMLEtBQUssQ0FBQyxFQUFFLEVBQUU7WUFDdEMsSUFBSUcsTUFBTUwsUUFBUTtnQkFDaEJELGFBQWFLO2dCQUNiSixTQUFTSztZQUNYO1FBQ0Y7SUFDRjtJQUVBLE1BQU1HLFVBQVVSLFNBQVM7SUFDekIsTUFBTVMsU0FBU0MsS0FBS0MsR0FBRyxDQUFDLEdBQUczQixPQUFPZ0IsUUFBUWxGLE1BQU07SUFDaEQsT0FBTyxHQUFHaUYsYUFBYWYsT0FBT3dCLFNBQVNJLFFBQVEsQ0FBQ0gsUUFBUSxNQUFNO0FBQ2hFO0FBRUE7OzRFQUU0RSxHQUU1RSx3QkFBd0IsR0FDeEIsU0FBU0ksZUFBZXBGLE9BQWU7SUFDckMsTUFBTXRCLFVBQXdCLEVBQUU7SUFDaEMsTUFBTTJHLFFBQVFyRixRQUFRc0YsS0FBSyxDQUFDO0lBRTVCLElBQUlDLGtCQUFpQztJQUNyQyxJQUFJQyxnQkFBZ0I7SUFDcEIsSUFBSUMsYUFBYTtJQUNqQixJQUFJQyxnQkFBZ0I7SUFDcEIsSUFBSUMsbUJBQW1CO0lBQ3ZCLElBQUlDLGlCQUFpQjtJQUVyQixLQUFLLE1BQU1DLFFBQVFSLE1BQU87UUFDeEIsTUFBTVMsVUFBVUQsS0FBS0UsSUFBSTtRQUV6QixNQUFNQyxnQkFBZ0JGLFFBQVFyQixLQUFLLENBQUM7UUFDcEMsSUFBSXVCLGVBQWU7WUFDakJULGtCQUFrQlMsYUFBYSxDQUFDLEVBQUU7WUFDbENSLGdCQUFnQkM7UUFDbEI7UUFFQSxNQUFNUSxZQUFZSCxRQUFRckIsS0FBSyxDQUFDO1FBQ2hDLElBQUl3QixXQUFXO1lBQ2J2SCxRQUFRWSxJQUFJLENBQUM7Z0JBQ1g0RyxVQUFVWDtnQkFDVlksTUFBTUYsU0FBUyxDQUFDLEVBQUU7WUFDcEI7UUFDRjtRQUVBLElBQUksQ0FBQ1AsaUJBQWlCSSxRQUFRckIsS0FBSyxDQUFDLGlCQUFpQjtZQUNuRCxNQUFNMkIsY0FBY04sUUFBUXJCLEtBQUssQ0FBQztZQUNsQyxJQUFJMkIsYUFBYTtnQkFDZjFILFFBQVFZLElBQUksQ0FBQztvQkFBRTRHLFVBQVVYO29CQUFpQlksTUFBTUMsV0FBVyxDQUFDLEVBQUU7Z0JBQUM7WUFDakUsT0FBTztnQkFDTFYsZ0JBQWdCO2dCQUNoQkMsbUJBQW1CO2dCQUNuQkMsaUJBQWlCO2dCQUNqQixLQUFLLE1BQU1TLE1BQU1QLFFBQVM7b0JBQ3hCLElBQUlPLE9BQU8sS0FBS1Y7b0JBQ2hCLElBQUlVLE9BQU8sS0FBS1Y7Z0JBQ2xCO2dCQUNBLElBQUlBLG9CQUFvQixHQUFHO29CQUN6QkMsaUJBQWlCO29CQUNqQixNQUFNVSxZQUFZUixRQUFRckIsS0FBSyxDQUFDO29CQUNoQyxJQUFJNkIsV0FBVzt3QkFDYjVILFFBQVFZLElBQUksQ0FBQzs0QkFBRTRHLFVBQVVYOzRCQUFpQlksTUFBTUcsU0FBUyxDQUFDLEVBQUU7d0JBQUM7d0JBQzdEWixnQkFBZ0I7d0JBQ2hCRSxpQkFBaUI7b0JBQ25CO2dCQUNGO1lBQ0Y7UUFDRixPQUFPLElBQUlGLGVBQWU7WUFDeEIsSUFBSSxDQUFDRSxnQkFBZ0I7Z0JBQ25CLEtBQUssTUFBTVMsTUFBTVAsUUFBUztvQkFDeEIsSUFBSU8sT0FBTyxLQUFLVjtvQkFDaEIsSUFBSVUsT0FBTyxLQUFLVjtnQkFDbEI7Z0JBQ0EsSUFBSUEsb0JBQW9CLEdBQUc7b0JBQ3pCQyxpQkFBaUI7b0JBQ2pCLE1BQU1VLFlBQVlSLFFBQVFyQixLQUFLLENBQUM7b0JBQ2hDLElBQUk2QixXQUFXO3dCQUNiNUgsUUFBUVksSUFBSSxDQUFDOzRCQUFFNEcsVUFBVVg7NEJBQWlCWSxNQUFNRyxTQUFTLENBQUMsRUFBRTt3QkFBQzt3QkFDN0RaLGdCQUFnQjt3QkFDaEJFLGlCQUFpQjtvQkFDbkI7Z0JBQ0Y7WUFDRixPQUFPO2dCQUNMLE1BQU1VLFlBQVlSLFFBQVFyQixLQUFLLENBQUM7Z0JBQ2hDLElBQUk2QixXQUFXO29CQUNiNUgsUUFBUVksSUFBSSxDQUFDO3dCQUFFNEcsVUFBVVg7d0JBQWlCWSxNQUFNRyxTQUFTLENBQUMsRUFBRTtvQkFBQztvQkFDN0RaLGdCQUFnQjtvQkFDaEJFLGlCQUFpQjtnQkFDbkI7WUFDRjtRQUNGO1FBRUEsS0FBSyxNQUFNUyxNQUFNUCxRQUFTO1lBQ3hCLElBQUlPLE9BQU8sS0FBS1o7WUFDaEIsSUFBSVksT0FBTyxLQUFLO2dCQUNkWjtnQkFDQSxJQUFJRixtQkFBbUJFLGNBQWNELGVBQWU7b0JBQ2xERCxrQkFBa0I7Z0JBQ3BCO1lBQ0Y7UUFDRjtJQUNGO0lBRUEsT0FBTzdHO0FBQ1Q7QUFFQSx1Q0FBdUMsR0FDdkMsT0FBTyxTQUFTNkg7SUFDZCxNQUFNQyxjQUFjOUk7SUFDcEIsTUFBTStJLFFBQVFDLGNBQWNGO0lBRTVCLE1BQU1HLFVBQXVCLEVBQUU7SUFDL0IsS0FBSyxNQUFNNUcsV0FBVzBHLE1BQU87UUFDM0IsTUFBTXpHLFVBQVU3QyxHQUFHOEMsWUFBWSxDQUFDRixTQUFTO1FBQ3pDLE1BQU1yQixVQUFVMEcsZUFBZXBGO1FBQy9CLElBQUl0QixRQUFRVyxNQUFNLEdBQUcsR0FBRztZQUN0QnNILFFBQVFySCxJQUFJLENBQUM7Z0JBQ1hqQyxNQUFNQSxLQUFLNkIsUUFBUSxDQUFDc0gsYUFBYXpHO2dCQUNqQ3JCO1lBQ0Y7UUFDRjtJQUNGO0lBRUEsTUFBTWtJLFFBQVFELFFBQVFFLE1BQU0sQ0FBQyxDQUFDQyxLQUFLQyxJQUFNRCxNQUFNQyxFQUFFckksT0FBTyxDQUFDVyxNQUFNLEVBQUU7SUFDakUsT0FBTztRQUFFb0gsT0FBT0U7UUFBU0M7SUFBTTtBQUNqQztBQUVBLGdEQUFnRCxHQUNoRCxTQUFTRixjQUFjTSxHQUFXO0lBQ2hDLE1BQU1DLFVBQW9CLEVBQUU7SUFDNUIsTUFBTUMsU0FBUyxJQUFJQyxJQUFJO1FBQUM7UUFBZ0I7UUFBUTtRQUFRO0tBQVc7SUFFbkUsU0FBU0MsS0FBS0MsVUFBa0I7UUFDOUIsSUFBSTNJO1FBQ0osSUFBSTtZQUNGQSxVQUFVdkIsR0FBR3dCLFdBQVcsQ0FBQzBJLFlBQVk7Z0JBQUV6SSxlQUFlO1lBQUs7UUFDN0QsRUFBRSxPQUFNO1lBQ047UUFDRjtRQUNBLEtBQUssTUFBTUUsU0FBU0osUUFBUztZQUMzQixJQUFJd0ksT0FBT0ksR0FBRyxDQUFDeEksTUFBTUUsSUFBSSxHQUFHO1lBQzVCLE1BQU1ELFdBQVcxQixLQUFLRyxJQUFJLENBQUM2SixZQUFZdkksTUFBTUUsSUFBSTtZQUNqRCxJQUFJRixNQUFNSyxXQUFXLElBQUk7Z0JBQ3ZCaUksS0FBS3JJO1lBQ1AsT0FBTyxJQUFJRCxNQUFNVSxNQUFNLE1BQU1WLE1BQU1FLElBQUksQ0FBQ1gsUUFBUSxDQUFDLGFBQWE7Z0JBQzVENEksUUFBUTNILElBQUksQ0FBQ1A7WUFDZjtRQUNGO0lBQ0Y7SUFFQXFJLEtBQUtKO0lBQ0xDLFFBQVFNLElBQUk7SUFDWixPQUFPTjtBQUNUIn0=
423
+ //#endregion
424
+ init_cdd_service();
425
+ export { addRule, editContent, getAcList, getCddTree, init_cdd_service, listRules, openSourceFile, readContent, readRule };
426
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RkLXNlcnZpY2UuanMiLCJuYW1lcyI6WyJub2RlczogQ2RkVHJlZU5vZGVbXSIsInJ1bGVzOiBDZGRSdWxlU3VtbWFyeVtdIiwicnVsZXM6IENkZFJ1bGVFbnRyeVtdIiwibmV3RW50cnk6IENkZFJ1bGVFbnRyeSIsImVudHJpZXM6IENkZEFjRW50cnlbXSIsImN1cnJlbnREZXNjcmliZTogc3RyaW5nIHwgbnVsbCIsImFjRmlsZXM6IENkZEFjRmlsZVtdIiwicmVzdWx0czogc3RyaW5nW10iLCJlbnRyaWVzOiBmcy5EaXJlbnRbXSIsIkVESVRPUl9DTElfTUFQOiBSZWNvcmQ8c3RyaW5nLCB7IGNsaTogc3RyaW5nOyB3YWl0RmxhZzogc3RyaW5nIH0+Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3VpL2NkZC1zZXJ2aWNlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5cbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGkvc29uYW11XCI7XG5pbXBvcnQge1xuICB0eXBlIENkZEFjRW50cnksXG4gIHR5cGUgQ2RkQWNGaWxlLFxuICB0eXBlIENkZEFjTGlzdFJlc3VsdCxcbiAgdHlwZSBDZGRBZGRSdWxlUmVxdWVzdCxcbiAgdHlwZSBDZGRDb250ZW50UmVzdWx0LFxuICB0eXBlIENkZEZpbGVUeXBlLFxuICB0eXBlIENkZFJ1bGVEZXRhaWwsXG4gIHR5cGUgQ2RkUnVsZUVudHJ5LFxuICB0eXBlIENkZFJ1bGVTdW1tYXJ5LFxuICB0eXBlIENkZFRyZWVOb2RlLFxufSBmcm9tIFwiLi9jZGQtdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUge1xuICBDZGRBY0VudHJ5LFxuICBDZGRBY0ZpbGUsXG4gIENkZEFjTGlzdFJlc3VsdCxcbiAgQ2RkQWRkUnVsZVJlcXVlc3QsXG4gIENkZENvbnRlbnRSZXN1bHQsXG4gIENkZEZpbGVUeXBlLFxuICBDZGRSdWxlRGV0YWlsLFxuICBDZGRSdWxlRW50cnksXG4gIENkZFJ1bGVTdW1tYXJ5LFxuICBDZGRUcmVlTm9kZSxcbn0gZnJvbSBcIi4vY2RkLXR5cGVzXCI7XG5cbi8qKiBjb250cmFjdC8g65SU66CJ7YSw66asIOygiOuMgCDqsr3roZwg67CY7ZmYIChhcGlSb290UGF0aCDquLDspIApICovXG5mdW5jdGlvbiBnZXRDb250cmFjdERpcigpOiBzdHJpbmcge1xuICByZXR1cm4gcGF0aC5qb2luKFNvbmFtdS5hcGlSb290UGF0aCwgXCIuLlwiLCBcIi4uXCIsIFwiY29udHJhY3RcIik7XG59XG5cbi8qKiDtlITroZzsoJ3tirgg66Oo7Yq4IOqyveuhnCDrsJjtmZggKi9cbmZ1bmN0aW9uIGdldFByb2plY3RSb290KCk6IHN0cmluZyB7XG4gIHJldHVybiBwYXRoLmpvaW4oU29uYW11LmFwaVJvb3RQYXRoLCBcIi4uXCIsIFwiLi5cIik7XG59XG5cbi8qKiDqsr3roZzqsIAgY29udHJhY3QvIOuUlOugie2EsOumrCDrgrTrtoDsnbjsp4Ag6rKA7KadICovXG5mdW5jdGlvbiBhc3NlcnRJbnNpZGVDb250cmFjdERpcihmaWxlUGF0aDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgcmVzb2x2ZWQgPSBwYXRoLnJlc29sdmUoY29udHJhY3REaXIsIGZpbGVQYXRoKTtcbiAgaWYgKCFyZXNvbHZlZC5zdGFydHNXaXRoKGNvbnRyYWN0RGlyICsgcGF0aC5zZXApICYmIHJlc29sdmVkICE9PSBjb250cmFjdERpcikge1xuICAgIHRocm93IG5ldyBFcnJvcihg6rK966Gc6rCAIGNvbnRyYWN0LyDrlJTroInthLDrpqwg67CW7J2EIOywuOyhsO2VqeuLiOuLpDogJHtmaWxlUGF0aH1gKTtcbiAgfVxufVxuXG4vKiog7YyM7J2866qF7JeQ7IScIENkZEZpbGVUeXBlIO2MkOuzhCAqL1xuZnVuY3Rpb24gZGV0ZWN0RmlsZVR5cGUoZmlsZU5hbWU6IHN0cmluZyk6IENkZEZpbGVUeXBlIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGZpbGVOYW1lLmVuZHNXaXRoKFwiLmNvbnRyYWN0Lm1kXCIpKSByZXR1cm4gXCJjb250cmFjdFwiO1xuICBpZiAoZmlsZU5hbWUuZW5kc1dpdGgoXCIucnVsZXMuanNvblwiKSkgcmV0dXJuIFwicnVsZXNcIjtcbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqIOuUlOugie2EsOumrOulvCDsnqzqt4Ag7YOQ7IOJ7ZWY7JesIENkZFRyZWVOb2RlIO2KuOumrOulvCDsg53shLEgKi9cbmZ1bmN0aW9uIHNjYW5EaXJlY3RvcnkoZGlyUGF0aDogc3RyaW5nLCByZWxhdGl2ZVRvOiBzdHJpbmcpOiBDZGRUcmVlTm9kZVtdIHtcbiAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKGRpclBhdGgsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgY29uc3Qgbm9kZXM6IENkZFRyZWVOb2RlW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXJQYXRoLCBlbnRyeS5uYW1lKTtcbiAgICBjb25zdCByZWxQYXRoID0gcGF0aC5yZWxhdGl2ZShyZWxhdGl2ZVRvLCBmdWxsUGF0aCk7XG5cbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgaWYgKGVudHJ5Lm5hbWUgPT09IFwicnVsZXNcIikgY29udGludWU7XG4gICAgICBjb25zdCBjaGlsZHJlbiA9IHNjYW5EaXJlY3RvcnkoZnVsbFBhdGgsIHJlbGF0aXZlVG8pO1xuICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbm9kZXMucHVzaCh7XG4gICAgICAgICAgbmFtZTogZW50cnkubmFtZSxcbiAgICAgICAgICBwYXRoOiByZWxQYXRoLFxuICAgICAgICAgIHR5cGU6IFwiZGlyZWN0b3J5XCIsXG4gICAgICAgICAgY2hpbGRyZW4sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW50cnkuaXNGaWxlKCkpIHtcbiAgICAgIGNvbnN0IGZpbGVUeXBlID0gZGV0ZWN0RmlsZVR5cGUoZW50cnkubmFtZSk7XG4gICAgICBpZiAoZmlsZVR5cGUgJiYgZmlsZVR5cGUgIT09IFwicnVsZXNcIikge1xuICAgICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgICBuYW1lOiBlbnRyeS5uYW1lLFxuICAgICAgICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgICAgICAgdHlwZTogXCJmaWxlXCIsXG4gICAgICAgICAgZmlsZVR5cGUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBub2Rlcztcbn1cblxuLyoqIGNvbnRyYWN0LyDrlJTroInthLDrpqzsnZgg7Yq466asIOq1rOyhsOulvCDrsJjtmZggKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDZGRUcmVlKCk6IHsgZXhpc3RzOiBib29sZWFuOyB0cmVlOiBDZGRUcmVlTm9kZVtdIH0ge1xuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhjb250cmFjdERpcikpIHtcbiAgICByZXR1cm4geyBleGlzdHM6IGZhbHNlLCB0cmVlOiBbXSB9O1xuICB9XG4gIGNvbnN0IHRyZWUgPSBzY2FuRGlyZWN0b3J5KGNvbnRyYWN0RGlyLCBjb250cmFjdERpcik7XG4gIHJldHVybiB7IGV4aXN0czogdHJ1ZSwgdHJlZSB9O1xufVxuXG4vKiog7YyM7J28IOuCtOyaqeydhCDsnb3slrQg67CY7ZmYIChjb250cmFjdC5tZCDihpIgbWFya2Rvd24g7JuQ66y4LCBydWxlcy5qc29uIOKGkiBKU09OIOusuOyekOyXtCkgKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkQ29udGVudChmaWxlUGF0aDogc3RyaW5nKTogQ2RkQ29udGVudFJlc3VsdCB7XG4gIGFzc2VydEluc2lkZUNvbnRyYWN0RGlyKGZpbGVQYXRoKTtcblxuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLnJlc29sdmUoY29udHJhY3REaXIsIGZpbGVQYXRoKTtcblxuICBpZiAoIWZzLmV4aXN0c1N5bmMoYWJzUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYO2MjOydvOydhCDssL7snYQg7IiYIOyXhuyKteuLiOuLpDogJHtmaWxlUGF0aH1gKTtcbiAgfVxuXG4gIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoYWJzUGF0aCwgXCJ1dGYtOFwiKTtcbiAgY29uc3QgZmlsZVR5cGUgPSBkZXRlY3RGaWxlVHlwZShwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKSk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb250ZW50LFxuICAgIGZpbGVUeXBlOiBmaWxlVHlwZSA/PyBcImNvbnRyYWN0XCIsXG4gIH07XG59XG5cbi8qKiDtjIzsnbzsnYQg7Jm467aAIOyXkOuUlO2EsOuhnCDsp4HsoJEg7Y647KeRICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZWRpdENvbnRlbnQoXG4gIGZpbGVQYXRoOiBzdHJpbmcsXG4pOiBQcm9taXNlPHsgc3VjY2VzczogYm9vbGVhbjsgZmlsZVBhdGg6IHN0cmluZyB9PiB7XG4gIGFzc2VydEluc2lkZUNvbnRyYWN0RGlyKGZpbGVQYXRoKTtcblxuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLnJlc29sdmUoY29udHJhY3REaXIsIGZpbGVQYXRoKTtcblxuICBpZiAoIWZzLmV4aXN0c1N5bmMoYWJzUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYO2MjOydvOydhCDssL7snYQg7IiYIOyXhuyKteuLiOuLpDogJHtmaWxlUGF0aH1gKTtcbiAgfVxuXG4gIGNvbnN0IGVkaXRvciA9IHJlc29sdmVFZGl0b3JDbGkoKTtcbiAgYXdhaXQgcnVuRWRpdG9yKGVkaXRvciwgYWJzUGF0aCk7XG5cbiAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSwgZmlsZVBhdGggfTtcbn1cblxuLyoqIOyXkOuUlO2EsOuzhCDslbEg67KI65OkIOuCtCBDTEkg6rK966GcICsgLS13YWl0IO2UjOuemOq3uCDrp6TtlZEgKi9cbmNvbnN0IEVESVRPUl9DTElfTUFQOiBSZWNvcmQ8c3RyaW5nLCB7IGNsaTogc3RyaW5nOyB3YWl0RmxhZzogc3RyaW5nIH0+ID0ge1xuICBcIlZpc3VhbCBTdHVkaW8gQ29kZVwiOiB7IGNsaTogXCJDb250ZW50cy9SZXNvdXJjZXMvYXBwL2Jpbi9jb2RlXCIsIHdhaXRGbGFnOiBcIi0td2FpdFwiIH0sXG4gIFplZDogeyBjbGk6IFwiQ29udGVudHMvTWFjT1MvY2xpXCIsIHdhaXRGbGFnOiBcIi0td2FpdFwiIH0sXG4gIEN1cnNvcjogeyBjbGk6IFwiQ29udGVudHMvUmVzb3VyY2VzL2FwcC9iaW4vY3Vyc29yXCIsIHdhaXRGbGFnOiBcIi0td2FpdFwiIH0sXG59O1xuXG4vKiog7JWxIOuyiOuTpCBDTEkg6rK966Gc66W8IHJlc29sdmUuIHdhaXQ9ZmFsc2XsnbTrqbQgLS13YWl0IO2UjOuemOq3uOulvCDsg53rnrUgKi9cbmZ1bmN0aW9uIHJlc29sdmVFZGl0b3JDbGkob3B0aW9ucz86IHsgd2FpdD86IGJvb2xlYW4gfSk6IHsgYmluOiBzdHJpbmc7IGFyZ3M6IHN0cmluZ1tdIH0ge1xuICBjb25zdCB3YWl0ID0gb3B0aW9ucz8ud2FpdCA/PyB0cnVlO1xuICBjb25zdCBhcHBOYW1lID0gU29uYW11LmNvbmZpZy5leHRlcm5hbEVkaXRvciA/PyBcIlZpc3VhbCBTdHVkaW8gQ29kZVwiO1xuICBjb25zdCBtYXBwaW5nID0gRURJVE9SX0NMSV9NQVBbYXBwTmFtZV07XG4gIGlmICghbWFwcGluZykge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGDsp4Dsm5DrkJjsp4Ag7JWK64qUIOyXkOuUlO2EsOyeheuLiOuLpDogJHthcHBOYW1lfSAo7KeA7JuQOiAke09iamVjdC5rZXlzKEVESVRPUl9DTElfTUFQKS5qb2luKFwiLCBcIil9KWAsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHNlYXJjaFBhdGhzID0gW1xuICAgIGAvQXBwbGljYXRpb25zLyR7YXBwTmFtZX0uYXBwYCxcbiAgICBgJHtvcy5ob21lZGlyKCl9L0FwcGxpY2F0aW9ucy8ke2FwcE5hbWV9LmFwcGAsXG4gIF07XG4gIGNvbnN0IGJ1bmRsZVBhdGggPSBzZWFyY2hQYXRocy5maW5kKChwKSA9PiBmcy5leGlzdHNTeW5jKHApKTtcbiAgaWYgKCFidW5kbGVQYXRoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDslbEg67KI65Ok7J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2FwcE5hbWV9ICgvQXBwbGljYXRpb25zIO2ZleyduClgKTtcbiAgfVxuXG4gIGNvbnN0IGNsaUJpbiA9IHBhdGguam9pbihidW5kbGVQYXRoLCBtYXBwaW5nLmNsaSk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhjbGlCaW4pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGDsl5DrlJTthLAgQ0xJ66W8IOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2NsaUJpbn1gKTtcbiAgfVxuXG4gIHJldHVybiB7IGJpbjogY2xpQmluLCBhcmdzOiB3YWl0ID8gW21hcHBpbmcud2FpdEZsYWddIDogW10gfTtcbn1cblxuLyoqIOyXkOuUlO2EsCBDTEnrpbwg7Iuk7ZaJ7ZWY6rOgIO2DreydtCDri6vtnpAg65WM6rmM7KeAIOuMgOq4sCAqL1xuZnVuY3Rpb24gcnVuRWRpdG9yKGVkaXRvcjogeyBiaW46IHN0cmluZzsgYXJnczogc3RyaW5nW10gfSwgZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24oZWRpdG9yLmJpbiwgWy4uLmVkaXRvci5hcmdzLCBmaWxlUGF0aF0sIHtcbiAgICAgIHN0ZGlvOiBcImluaGVyaXRcIixcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgcmVqZWN0KG5ldyBFcnJvcihg7JeQ65SU7YSwIOyLpO2WiSDsi6TtjKggKCR7ZWRpdG9yLmJpbn0pOiAke2Vyci5tZXNzYWdlfWApKTtcbiAgICB9KTtcblxuICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGUpID0+IHtcbiAgICAgIGlmIChjb2RlID09PSAwKSB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoYOyXkOuUlO2EsOqwgCDruYTsoJXsg4Eg7KKF66OM65CY7JeI7Iq164uI64ukIChleGl0IGNvZGU6ICR7Y29kZX0pYCkpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqIOyGjOyKpCDtjIzsnbzsnYQg7Jm467aAIOyXkOuUlO2EsOuhnCDsl7TquLAgKOuMgOq4sO2VmOyngCDslYrsnYwpICovXG5leHBvcnQgZnVuY3Rpb24gb3BlblNvdXJjZUZpbGUoZmlsZVBhdGg6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBhYnNQYXRoID0gcGF0aC5pc0Fic29sdXRlKGZpbGVQYXRoKSA/IGZpbGVQYXRoIDogcGF0aC5yZXNvbHZlKFNvbmFtdS5hcGlSb290UGF0aCwgZmlsZVBhdGgpO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgY29uc3QgZWRpdG9yID0gcmVzb2x2ZUVkaXRvckNsaSh7IHdhaXQ6IGZhbHNlIH0pO1xuICBjb25zdCBjaGlsZCA9IHNwYXduKGVkaXRvci5iaW4sIFsuLi5lZGl0b3IuYXJncywgYWJzUGF0aF0sIHtcbiAgICBzdGRpbzogXCJpZ25vcmVcIixcbiAgICBkZXRhY2hlZDogdHJ1ZSxcbiAgfSk7XG4gIGNoaWxkLnVucmVmKCk7XG59XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogUnVsZXMgQVBJXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi9cblxuLyoqIGNvbnRyYWN0L3J1bGVzLyDrlJTroInthLDrpqwg64K0IC5ydWxlcy5qc29uIO2MjOydvCDrqqnroZ0g67CY7ZmYICovXG5leHBvcnQgZnVuY3Rpb24gbGlzdFJ1bGVzKCk6IHsgcnVsZXM6IENkZFJ1bGVTdW1tYXJ5W10gfSB7XG4gIGNvbnN0IGNvbnRyYWN0RGlyID0gZ2V0Q29udHJhY3REaXIoKTtcbiAgY29uc3QgcnVsZXNEaXIgPSBwYXRoLmpvaW4oY29udHJhY3REaXIsIFwicnVsZXNcIik7XG4gIGlmICghZnMuZXhpc3RzU3luYyhydWxlc0RpcikpIHJldHVybiB7IHJ1bGVzOiBbXSB9O1xuXG4gIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhydWxlc0RpciwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICBjb25zdCBydWxlczogQ2RkUnVsZVN1bW1hcnlbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGlmICghZW50cnkuaXNGaWxlKCkgfHwgIWVudHJ5Lm5hbWUuZW5kc1dpdGgoXCIucnVsZXMuanNvblwiKSkgY29udGludWU7XG5cbiAgICBjb25zdCBrZXkgPSBlbnRyeS5uYW1lLnJlcGxhY2UoL1xcLnJ1bGVzXFwuanNvbiQvLCBcIlwiKTtcbiAgICBjb25zdCByZWxQYXRoID0gYHJ1bGVzLyR7ZW50cnkubmFtZX1gO1xuICAgIGNvbnN0IGFic1BhdGggPSBwYXRoLmpvaW4ocnVsZXNEaXIsIGVudHJ5Lm5hbWUpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICAgICAgY29uc3QgZG9jID0gSlNPTi5wYXJzZShyYXcpIGFzIHsgZGVzY3JpcHRpb24/OiBzdHJpbmc7IHJ1bGVzPzogdW5rbm93bltdIH07XG4gICAgICBydWxlcy5wdXNoKHtcbiAgICAgICAga2V5LFxuICAgICAgICBwYXRoOiByZWxQYXRoLFxuICAgICAgICBkZXNjcmlwdGlvbjogdHlwZW9mIGRvYy5kZXNjcmlwdGlvbiA9PT0gXCJzdHJpbmdcIiA/IGRvYy5kZXNjcmlwdGlvbiA6IFwiXCIsXG4gICAgICAgIHJ1bGVDb3VudDogQXJyYXkuaXNBcnJheShkb2MucnVsZXMpID8gZG9jLnJ1bGVzLmxlbmd0aCA6IDAsXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJ1bGVzLnB1c2goe1xuICAgICAgICBrZXksXG4gICAgICAgIHBhdGg6IHJlbFBhdGgsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBcIlwiLFxuICAgICAgICBydWxlQ291bnQ6IDAsXG4gICAgICAgIHBhcnNlRXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IHJ1bGVzIH07XG59XG5cbi8qKiBydWxlcyDtjIzsnbwg7IOB7IS4IOuwmO2ZmCAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRSdWxlKHJ1bGVLZXk6IHN0cmluZyk6IENkZFJ1bGVEZXRhaWwge1xuICBjb25zdCBjb250cmFjdERpciA9IGdldENvbnRyYWN0RGlyKCk7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLmpvaW4oY29udHJhY3REaXIsIFwicnVsZXNcIiwgYCR7cnVsZUtleX0ucnVsZXMuanNvbmApO1xuXG4gIGlmICghZnMuZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUnVsZXMg7YyM7J287J2EIOywvuydhCDsiJgg7JeG7Iq164uI64ukOiAke3J1bGVLZXl9YCk7XG4gIH1cblxuICBjb25zdCByYXcgPSBmcy5yZWFkRmlsZVN5bmMoYWJzUGF0aCwgXCJ1dGYtOFwiKTtcbiAgY29uc3QgZG9jID0gSlNPTi5wYXJzZShyYXcpIGFzIHsgZGVzY3JpcHRpb24/OiBzdHJpbmc7IHJ1bGVzPzogQ2RkUnVsZUVudHJ5W10gfTtcblxuICByZXR1cm4ge1xuICAgIGtleTogcnVsZUtleSxcbiAgICBwYXRoOiBgcnVsZXMvJHtydWxlS2V5fS5ydWxlcy5qc29uYCxcbiAgICBkZXNjcmlwdGlvbjogdHlwZW9mIGRvYy5kZXNjcmlwdGlvbiA9PT0gXCJzdHJpbmdcIiA/IGRvYy5kZXNjcmlwdGlvbiA6IFwiXCIsXG4gICAgcnVsZXM6IEFycmF5LmlzQXJyYXkoZG9jLnJ1bGVzKSA/IGRvYy5ydWxlcyA6IFtdLFxuICB9O1xufVxuXG4vKiogcnVsZXMg7YyM7J287JeQIOq3nOy5mSDstpTqsIAgKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRSdWxlKHJlcTogQ2RkQWRkUnVsZVJlcXVlc3QpOiBDZGRSdWxlRGV0YWlsIHtcbiAgY29uc3QgY29udHJhY3REaXIgPSBnZXRDb250cmFjdERpcigpO1xuICBjb25zdCBydWxlc0RpciA9IHBhdGguam9pbihjb250cmFjdERpciwgXCJydWxlc1wiKTtcbiAgY29uc3QgYWJzUGF0aCA9IHBhdGguam9pbihydWxlc0RpciwgYCR7cmVxLnJ1bGVLZXl9LnJ1bGVzLmpzb25gKTtcblxuICBpZiAoIWZzLmV4aXN0c1N5bmMoYWJzUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFJ1bGVzIO2MjOydvOydhCDssL7snYQg7IiYIOyXhuyKteuLiOuLpDogJHtyZXEucnVsZUtleX1gKTtcbiAgfVxuXG4gIGNvbnN0IHJhdyA9IGZzLnJlYWRGaWxlU3luYyhhYnNQYXRoLCBcInV0Zi04XCIpO1xuICBjb25zdCBkb2MgPSBKU09OLnBhcnNlKHJhdykgYXMgeyBkZXNjcmlwdGlvbj86IHN0cmluZzsgcnVsZXM/OiBDZGRSdWxlRW50cnlbXSB9O1xuICBjb25zdCBydWxlczogQ2RkUnVsZUVudHJ5W10gPSBBcnJheS5pc0FycmF5KGRvYy5ydWxlcykgPyBkb2MucnVsZXMgOiBbXTtcblxuICBjb25zdCBuZXh0SWQgPSBnZW5lcmF0ZU5leHRSdWxlSWQocnVsZXMpO1xuICBjb25zdCBuZXdFbnRyeTogQ2RkUnVsZUVudHJ5ID0ge1xuICAgIGlkOiBuZXh0SWQsXG4gICAgd2hlbjogcmVxLndoZW4sXG4gICAgaW5zdHJ1Y3Rpb246IHJlcS5pbnN0cnVjdGlvbixcbiAgfTtcbiAgaWYgKHJlcS5leGFtcGxlcyAmJiByZXEuZXhhbXBsZXMubGVuZ3RoID4gMCkge1xuICAgIG5ld0VudHJ5LmV4YW1wbGVzID0gcmVxLmV4YW1wbGVzO1xuICB9XG5cbiAgcnVsZXMucHVzaChuZXdFbnRyeSk7XG4gIGRvYy5ydWxlcyA9IHJ1bGVzO1xuXG4gIGZzLndyaXRlRmlsZVN5bmMoYWJzUGF0aCwgYCR7SlNPTi5zdHJpbmdpZnkoZG9jLCBudWxsLCAyKX1cXG5gLCBcInV0Zi04XCIpO1xuXG4gIHJldHVybiB7XG4gICAga2V5OiByZXEucnVsZUtleSxcbiAgICBwYXRoOiBgcnVsZXMvJHtyZXEucnVsZUtleX0ucnVsZXMuanNvbmAsXG4gICAgZGVzY3JpcHRpb246IHR5cGVvZiBkb2MuZGVzY3JpcHRpb24gPT09IFwic3RyaW5nXCIgPyBkb2MuZGVzY3JpcHRpb24gOiBcIlwiLFxuICAgIHJ1bGVzLFxuICB9O1xufVxuXG4vKiog6riw7KG0IGlkIO2MqO2EtOydhCDrtoTshJ3tlZjsl6wg64uk7J2MIOyInOuyiCBpZCDsg53shLEgKi9cbmZ1bmN0aW9uIGdlbmVyYXRlTmV4dFJ1bGVJZChydWxlczogQ2RkUnVsZUVudHJ5W10pOiBzdHJpbmcge1xuICBpZiAocnVsZXMubGVuZ3RoID09PSAwKSByZXR1cm4gXCJSLTAwMVwiO1xuXG4gIGNvbnN0IG51bWVyaWNQYXR0ZXJuID0gL14oLis/KShcXGQrKSQvO1xuICBsZXQgYmVzdFByZWZpeCA9IFwiUi1cIjtcbiAgbGV0IG1heE51bSA9IDA7XG5cbiAgZm9yIChjb25zdCBydWxlIG9mIHJ1bGVzKSB7XG4gICAgY29uc3QgbWF0Y2ggPSBudW1lcmljUGF0dGVybi5leGVjKHJ1bGUuaWQpO1xuICAgIGlmIChtYXRjaCkge1xuICAgICAgY29uc3QgcHJlZml4ID0gbWF0Y2hbMV07XG4gICAgICBjb25zdCBudW0gPSBOdW1iZXIucGFyc2VJbnQobWF0Y2hbMl0sIDEwKTtcbiAgICAgIGlmIChudW0gPiBtYXhOdW0pIHtcbiAgICAgICAgYmVzdFByZWZpeCA9IHByZWZpeDtcbiAgICAgICAgbWF4TnVtID0gbnVtO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG5leHROdW0gPSBtYXhOdW0gKyAxO1xuICBjb25zdCBwYWRMZW4gPSBNYXRoLm1heCgzLCBTdHJpbmcobWF4TnVtKS5sZW5ndGgpO1xuICByZXR1cm4gYCR7YmVzdFByZWZpeH0ke1N0cmluZyhuZXh0TnVtKS5wYWRTdGFydChwYWRMZW4sIFwiMFwiKX1gO1xufVxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEFDIEFQSSAobW9kdWxlcy9jZGQgYWMtbGlzdCDtjIzsi7Eg66Gc7KeBIOuzteyCrClcbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuXG4vKiogZGVzY3JpYmUvdGVzdCDtjKjthLQg7YyM7IuxICovXG5mdW5jdGlvbiBwYXJzZUFjRW50cmllcyhjb250ZW50OiBzdHJpbmcpOiBDZGRBY0VudHJ5W10ge1xuICBjb25zdCBlbnRyaWVzOiBDZGRBY0VudHJ5W10gPSBbXTtcbiAgY29uc3QgbGluZXMgPSBjb250ZW50LnNwbGl0KFwiXFxuXCIpO1xuXG4gIGxldCBjdXJyZW50RGVzY3JpYmU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBsZXQgZGVzY3JpYmVEZXB0aCA9IDA7XG4gIGxldCBicmFjZURlcHRoID0gMDtcbiAgbGV0IHBlbmRpbmdUZXN0QXMgPSBmYWxzZTtcbiAgbGV0IHRlc3RBc0JyYWNlRGVwdGggPSAwO1xuICBsZXQgdGVzdEFzTmVlZE5hbWUgPSBmYWxzZTtcblxuICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICBjb25zdCB0cmltbWVkID0gbGluZS50cmltKCk7XG5cbiAgICBjb25zdCBkZXNjcmliZU1hdGNoID0gdHJpbW1lZC5tYXRjaCgvXmRlc2NyaWJlXFwoW1wiJ2BdKC4rPylbXCInYF0vKTtcbiAgICBpZiAoZGVzY3JpYmVNYXRjaCkge1xuICAgICAgY3VycmVudERlc2NyaWJlID0gZGVzY3JpYmVNYXRjaFsxXTtcbiAgICAgIGRlc2NyaWJlRGVwdGggPSBicmFjZURlcHRoO1xuICAgIH1cblxuICAgIGNvbnN0IHRlc3RNYXRjaCA9IHRyaW1tZWQubWF0Y2goL14oPzp0ZXN0fGl0KVxcKFtcIidgXSguKz8pW1wiJ2BdLyk7XG4gICAgaWYgKHRlc3RNYXRjaCkge1xuICAgICAgZW50cmllcy5wdXNoKHtcbiAgICAgICAgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSxcbiAgICAgICAgdGVzdDogdGVzdE1hdGNoWzFdLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKCFwZW5kaW5nVGVzdEFzICYmIHRyaW1tZWQubWF0Y2goL150ZXN0QXNcXHMqXFwoLykpIHtcbiAgICAgIGNvbnN0IGlubGluZU1hdGNoID0gdHJpbW1lZC5tYXRjaCgvXnRlc3RBc1xccypcXChcXHMqXFx7W159XSpcXH1cXHMqLFxccypbXCInYF0oLis/KVtcIidgXS8pO1xuICAgICAgaWYgKGlubGluZU1hdGNoKSB7XG4gICAgICAgIGVudHJpZXMucHVzaCh7IGRlc2NyaWJlOiBjdXJyZW50RGVzY3JpYmUsIHRlc3Q6IGlubGluZU1hdGNoWzFdIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVuZGluZ1Rlc3RBcyA9IHRydWU7XG4gICAgICAgIHRlc3RBc0JyYWNlRGVwdGggPSAwO1xuICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IGZhbHNlO1xuICAgICAgICBmb3IgKGNvbnN0IGNoIG9mIHRyaW1tZWQpIHtcbiAgICAgICAgICBpZiAoY2ggPT09IFwie1wiKSB0ZXN0QXNCcmFjZURlcHRoKys7XG4gICAgICAgICAgaWYgKGNoID09PSBcIn1cIikgdGVzdEFzQnJhY2VEZXB0aC0tO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0ZXN0QXNCcmFjZURlcHRoIDw9IDApIHtcbiAgICAgICAgICB0ZXN0QXNOZWVkTmFtZSA9IHRydWU7XG4gICAgICAgICAgY29uc3QgbmFtZU1hdGNoID0gdHJpbW1lZC5tYXRjaCgvfVxccyosXFxzKltcIidgXSguKz8pW1wiJ2BdLyk7XG4gICAgICAgICAgaWYgKG5hbWVNYXRjaCkge1xuICAgICAgICAgICAgZW50cmllcy5wdXNoKHsgZGVzY3JpYmU6IGN1cnJlbnREZXNjcmliZSwgdGVzdDogbmFtZU1hdGNoWzFdIH0pO1xuICAgICAgICAgICAgcGVuZGluZ1Rlc3RBcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGVzdEFzTmVlZE5hbWUgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHBlbmRpbmdUZXN0QXMpIHtcbiAgICAgIGlmICghdGVzdEFzTmVlZE5hbWUpIHtcbiAgICAgICAgZm9yIChjb25zdCBjaCBvZiB0cmltbWVkKSB7XG4gICAgICAgICAgaWYgKGNoID09PSBcIntcIikgdGVzdEFzQnJhY2VEZXB0aCsrO1xuICAgICAgICAgIGlmIChjaCA9PT0gXCJ9XCIpIHRlc3RBc0JyYWNlRGVwdGgtLTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGVzdEFzQnJhY2VEZXB0aCA8PSAwKSB7XG4gICAgICAgICAgdGVzdEFzTmVlZE5hbWUgPSB0cnVlO1xuICAgICAgICAgIGNvbnN0IG5hbWVNYXRjaCA9IHRyaW1tZWQubWF0Y2goL31cXHMqLFxccypbXCInYF0oLis/KVtcIidgXS8pO1xuICAgICAgICAgIGlmIChuYW1lTWF0Y2gpIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaCh7IGRlc2NyaWJlOiBjdXJyZW50RGVzY3JpYmUsIHRlc3Q6IG5hbWVNYXRjaFsxXSB9KTtcbiAgICAgICAgICAgIHBlbmRpbmdUZXN0QXMgPSBmYWxzZTtcbiAgICAgICAgICAgIHRlc3RBc05lZWROYW1lID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBuYW1lTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9eW1wiJ2BdKC4rPylbXCInYF0vKTtcbiAgICAgICAgaWYgKG5hbWVNYXRjaCkge1xuICAgICAgICAgIGVudHJpZXMucHVzaCh7IGRlc2NyaWJlOiBjdXJyZW50RGVzY3JpYmUsIHRlc3Q6IG5hbWVNYXRjaFsxXSB9KTtcbiAgICAgICAgICBwZW5kaW5nVGVzdEFzID0gZmFsc2U7XG4gICAgICAgICAgdGVzdEFzTmVlZE5hbWUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgY2ggb2YgdHJpbW1lZCkge1xuICAgICAgaWYgKGNoID09PSBcIntcIikgYnJhY2VEZXB0aCsrO1xuICAgICAgaWYgKGNoID09PSBcIn1cIikge1xuICAgICAgICBicmFjZURlcHRoLS07XG4gICAgICAgIGlmIChjdXJyZW50RGVzY3JpYmUgJiYgYnJhY2VEZXB0aCA8PSBkZXNjcmliZURlcHRoKSB7XG4gICAgICAgICAgY3VycmVudERlc2NyaWJlID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBlbnRyaWVzO1xufVxuXG4vKiog7ZSE66Gc7KCd7Yq4IOuCtCAqLnRlc3QudHMg7YyM7J287J2EIOyKpOy6lO2VmOyXrCBBQyDrqqnroZ0g67CY7ZmYICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWNMaXN0KCk6IENkZEFjTGlzdFJlc3VsdCB7XG4gIGNvbnN0IHByb2plY3RSb290ID0gZ2V0UHJvamVjdFJvb3QoKTtcbiAgY29uc3QgZmlsZXMgPSBmaW5kVGVzdEZpbGVzKHByb2plY3RSb290KTtcblxuICBjb25zdCBhY0ZpbGVzOiBDZGRBY0ZpbGVbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGFic1BhdGggb2YgZmlsZXMpIHtcbiAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKGFic1BhdGgsIFwidXRmLThcIik7XG4gICAgY29uc3QgZW50cmllcyA9IHBhcnNlQWNFbnRyaWVzKGNvbnRlbnQpO1xuICAgIGlmIChlbnRyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGFjRmlsZXMucHVzaCh7XG4gICAgICAgIHBhdGg6IHBhdGgucmVsYXRpdmUocHJvamVjdFJvb3QsIGFic1BhdGgpLFxuICAgICAgICBlbnRyaWVzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgdG90YWwgPSBhY0ZpbGVzLnJlZHVjZSgoc3VtLCBmKSA9PiBzdW0gKyBmLmVudHJpZXMubGVuZ3RoLCAwKTtcbiAgcmV0dXJuIHsgZmlsZXM6IGFjRmlsZXMsIHRvdGFsIH07XG59XG5cbi8qKiAqLnRlc3QudHMg7YyM7J287J2EIOyerOq3gCDtg5Dsg4kgKG5vZGVfbW9kdWxlcywgZGlzdCDsoJzsmbgpICovXG5mdW5jdGlvbiBmaW5kVGVzdEZpbGVzKGRpcjogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCByZXN1bHRzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBJR05PUkUgPSBuZXcgU2V0KFtcIm5vZGVfbW9kdWxlc1wiLCBcImRpc3RcIiwgXCIuZ2l0XCIsIFwiY29udHJhY3RcIl0pO1xuXG4gIGZ1bmN0aW9uIHdhbGsoY3VycmVudERpcjogc3RyaW5nKTogdm9pZCB7XG4gICAgbGV0IGVudHJpZXM6IGZzLkRpcmVudFtdO1xuICAgIHRyeSB7XG4gICAgICBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoY3VycmVudERpciwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgIGlmIChJR05PUkUuaGFzKGVudHJ5Lm5hbWUpKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKGN1cnJlbnREaXIsIGVudHJ5Lm5hbWUpO1xuICAgICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgd2FsayhmdWxsUGF0aCk7XG4gICAgICB9IGVsc2UgaWYgKGVudHJ5LmlzRmlsZSgpICYmIGVudHJ5Lm5hbWUuZW5kc1dpdGgoXCIudGVzdC50c1wiKSkge1xuICAgICAgICByZXN1bHRzLnB1c2goZnVsbFBhdGgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHdhbGsoZGlyKTtcbiAgcmVzdWx0cy5zb3J0KCk7XG4gIHJldHVybiByZXN1bHRzO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFpQ0EsU0FBUyxpQkFBeUI7QUFDaEMsUUFBTyxLQUFLLEtBQUssT0FBTyxhQUFhLE1BQU0sTUFBTSxXQUFXOzs7QUFJOUQsU0FBUyxpQkFBeUI7QUFDaEMsUUFBTyxLQUFLLEtBQUssT0FBTyxhQUFhLE1BQU0sS0FBSzs7O0FBSWxELFNBQVMsd0JBQXdCLFVBQXdCO0NBQ3ZELE1BQU0sY0FBYyxnQkFBZ0I7Q0FDcEMsTUFBTSxXQUFXLEtBQUssUUFBUSxhQUFhLFNBQVM7QUFDcEQsS0FBSSxDQUFDLFNBQVMsV0FBVyxjQUFjLEtBQUssSUFBSSxJQUFJLGFBQWEsYUFBYTtBQUM1RSxRQUFNLElBQUksTUFBTSxnQ0FBZ0MsV0FBVzs7OztBQUsvRCxTQUFTLGVBQWUsVUFBMkM7QUFDakUsS0FBSSxTQUFTLFNBQVMsZUFBZSxDQUFFLFFBQU87QUFD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