sonamu 0.11.16 → 0.13.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 (322) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -2
  2. package/dist/ai/agents/agent.js +2 -3
  3. package/dist/ai/agents/index.js +1 -2
  4. package/dist/ai/index.js +1 -2
  5. package/dist/ai/providers/rtzr/api.js +1 -2
  6. package/dist/ai/providers/rtzr/error.js +2 -3
  7. package/dist/ai/providers/rtzr/model.js +1 -2
  8. package/dist/ai/providers/rtzr/options.js +1 -2
  9. package/dist/ai/providers/rtzr/provider.js +1 -2
  10. package/dist/ai/providers/rtzr/utils.js +1 -2
  11. package/dist/api/base-frame.js +4 -4
  12. package/dist/api/caster.d.ts +1 -1
  13. package/dist/api/caster.d.ts.map +1 -1
  14. package/dist/api/caster.js +9 -9
  15. package/dist/api/code-converters.js +6 -5
  16. package/dist/api/config.d.ts +1 -1
  17. package/dist/api/config.d.ts.map +1 -1
  18. package/dist/api/config.js +2 -3
  19. package/dist/api/context.d.ts +2 -3
  20. package/dist/api/context.d.ts.map +1 -1
  21. package/dist/api/context.js +2 -3
  22. package/dist/api/decorators.js +2 -3
  23. package/dist/api/http-validator.js +2 -3
  24. package/dist/api/index.js +8 -3
  25. package/dist/api/secret.js +1 -2
  26. package/dist/api/sonamu.d.ts +3 -5
  27. package/dist/api/sonamu.d.ts.map +1 -1
  28. package/dist/api/sonamu.js +30 -24
  29. package/dist/api/validator.js +1 -2
  30. package/dist/api/websocket-helpers.js +2 -3
  31. package/dist/auth/audit-log/builders.js +1 -2
  32. package/dist/auth/audit-log/client-ip.js +2 -3
  33. package/dist/auth/audit-log/events.js +1 -2
  34. package/dist/auth/audit-log/plugin.d.ts.map +1 -1
  35. package/dist/auth/audit-log/plugin.js +2 -3
  36. package/dist/auth/audit-log-ingestor.js +2 -3
  37. package/dist/auth/auth-generator.js +2 -3
  38. package/dist/auth/better-auth-entities.js +1 -2
  39. package/dist/auth/better-auth-request.js +2 -3
  40. package/dist/auth/index.js +2 -3
  41. package/dist/auth/knex-adapter.js +2 -3
  42. package/dist/auth/plugins/entity-definitions/admin.js +1 -2
  43. package/dist/auth/plugins/entity-definitions/anonymous.js +1 -2
  44. package/dist/auth/plugins/entity-definitions/api-key.js +1 -2
  45. package/dist/auth/plugins/entity-definitions/audit-log.js +1 -2
  46. package/dist/auth/plugins/entity-definitions/index.js +1 -2
  47. package/dist/auth/plugins/entity-definitions/jwt.js +1 -2
  48. package/dist/auth/plugins/entity-definitions/organization.js +1 -2
  49. package/dist/auth/plugins/entity-definitions/passkey.js +1 -2
  50. package/dist/auth/plugins/entity-definitions/phone-number.js +1 -2
  51. package/dist/auth/plugins/entity-definitions/sso.js +1 -2
  52. package/dist/auth/plugins/entity-definitions/two-factor.js +1 -2
  53. package/dist/auth/plugins/entity-definitions/username.js +1 -2
  54. package/dist/auth/plugins/wrappers/admin.d.ts +33 -32
  55. package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
  56. package/dist/auth/plugins/wrappers/admin.js +2 -3
  57. package/dist/auth/plugins/wrappers/anonymous.js +2 -3
  58. package/dist/auth/plugins/wrappers/api-key.js +2 -3
  59. package/dist/auth/plugins/wrappers/jwt.js +2 -3
  60. package/dist/auth/plugins/wrappers/organization.js +2 -3
  61. package/dist/auth/plugins/wrappers/passkey.js +2 -3
  62. package/dist/auth/plugins/wrappers/phone-number.d.ts +43 -1
  63. package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
  64. package/dist/auth/plugins/wrappers/phone-number.js +2 -3
  65. package/dist/auth/plugins/wrappers/sso.d.ts +138 -187
  66. package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -1
  67. package/dist/auth/plugins/wrappers/sso.js +1 -2
  68. package/dist/auth/plugins/wrappers/two-factor.d.ts +51 -10
  69. package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
  70. package/dist/auth/plugins/wrappers/two-factor.js +2 -3
  71. package/dist/auth/plugins/wrappers/username.d.ts +39 -5
  72. package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
  73. package/dist/auth/plugins/wrappers/username.js +2 -3
  74. package/dist/bin/build-config.js +5 -5
  75. package/dist/bin/compiler-policy.js +2 -3
  76. package/dist/bin/fixture.js +7 -5
  77. package/dist/bin/hmr-hook-register.js +1 -2
  78. package/dist/bin/migrate-targets.js +2 -3
  79. package/dist/bin/test-command.js +2 -3
  80. package/dist/bin/ts-loader-register.js +2 -3
  81. package/dist/bin/ts-loader-registration.js +2 -3
  82. package/dist/bin/typecheck-web.js +2 -3
  83. package/dist/cache/cache-manager.js +1 -2
  84. package/dist/cache/decorator.js +2 -3
  85. package/dist/cache/drivers.js +1 -2
  86. package/dist/cache/index.js +2 -3
  87. package/dist/cache-control/cache-control.js +1 -2
  88. package/dist/code-formatting/index.js +2 -3
  89. package/dist/code-formatting/oxfmt.js +2 -3
  90. package/dist/code-formatting/oxlint.js +2 -3
  91. package/dist/compress/compress.js +1 -2
  92. package/dist/compress/index.js +2 -2
  93. package/dist/compress/types.d.ts +1 -1
  94. package/dist/compress/types.d.ts.map +1 -1
  95. package/dist/cone/cone-generator.js +2 -3
  96. package/dist/database/_batch_update.js +1 -2
  97. package/dist/database/base-model.js +4 -4
  98. package/dist/database/db.js +4 -4
  99. package/dist/database/knex.js +2 -3
  100. package/dist/database/puri-wrapper.js +2 -3
  101. package/dist/database/puri.js +23 -22
  102. package/dist/database/puri.types.js +1 -2
  103. package/dist/database/transaction-context.js +1 -2
  104. package/dist/database/upsert-builder.js +2 -3
  105. package/dist/dict/en.js +2 -3
  106. package/dist/dict/index.js +3 -3
  107. package/dist/dict/ko.js +2 -3
  108. package/dist/dict/rc-keys.js +1 -2
  109. package/dist/dict/sd.js +2 -3
  110. package/dist/dict/sonamu-dictionary.js +7 -6
  111. package/dist/dict/utils.js +2 -3
  112. package/dist/entity/entity-manager.d.ts +66 -66
  113. package/dist/entity/entity-manager.js +4 -4
  114. package/dist/entity/entity-template-cone.js +2 -3
  115. package/dist/entity/entity.js +21 -18
  116. package/dist/env.js +1 -2
  117. package/dist/exceptions/error-handler.d.ts.map +1 -1
  118. package/dist/exceptions/error-handler.js +2 -3
  119. package/dist/exceptions/so-exceptions.js +2 -3
  120. package/dist/filter/index.js +3 -2
  121. package/dist/filter/types.js +1 -2
  122. package/dist/filter/utils.js +7 -6
  123. package/dist/index.d.ts +1 -0
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +42 -6
  126. package/dist/logger/category.js +2 -3
  127. package/dist/logger/configure.js +5 -5
  128. package/dist/migration/code-generation.js +23 -16
  129. package/dist/migration/index-where-predicate.js +2 -3
  130. package/dist/migration/migration-set.js +2 -3
  131. package/dist/migration/migrator.js +2 -3
  132. package/dist/migration/postgresql-schema-reader.js +6 -9
  133. package/dist/migration/slack-confirm.js +2 -3
  134. package/dist/naite/naite-reporter.js +2 -3
  135. package/dist/naite/naite.js +10 -8
  136. package/dist/runtime-type.js +2 -3
  137. package/dist/ssr/hmr-opt-out.js +1 -2
  138. package/dist/ssr/index.js +7 -4
  139. package/dist/ssr/registry.js +1 -2
  140. package/dist/ssr/renderer.js +2 -3
  141. package/dist/storage/base-file.js +1 -2
  142. package/dist/storage/buffered-file.js +2 -3
  143. package/dist/storage/drivers.js +1 -2
  144. package/dist/storage/index.js +2 -3
  145. package/dist/storage/s3-driver.js +1 -2
  146. package/dist/storage/storage-manager.js +2 -3
  147. package/dist/storage/uploaded-file.js +2 -3
  148. package/dist/stream/__tests__/ws-test-helpers.d.ts +108 -0
  149. package/dist/stream/__tests__/ws-test-helpers.d.ts.map +1 -0
  150. package/dist/stream/__tests__/ws-test-helpers.js +259 -0
  151. package/dist/stream/index.d.ts +1 -0
  152. package/dist/stream/index.d.ts.map +1 -1
  153. package/dist/stream/index.js +15 -4
  154. package/dist/stream/sse.js +1 -2
  155. package/dist/stream/ws-audience-resolver.d.ts +8 -5
  156. package/dist/stream/ws-audience-resolver.d.ts.map +1 -1
  157. package/dist/stream/ws-audience-resolver.js +17 -15
  158. package/dist/stream/ws-audience.js +1 -2
  159. package/dist/stream/ws-cluster-bus.d.ts +9 -4
  160. package/dist/stream/ws-cluster-bus.d.ts.map +1 -1
  161. package/dist/stream/ws-cluster-bus.js +2 -3
  162. package/dist/stream/ws-core.d.ts +10 -0
  163. package/dist/stream/ws-core.d.ts.map +1 -1
  164. package/dist/stream/ws-delivery.d.ts +30 -4
  165. package/dist/stream/ws-delivery.d.ts.map +1 -1
  166. package/dist/stream/ws-delivery.js +200 -54
  167. package/dist/stream/ws-frame.d.ts +15 -0
  168. package/dist/stream/ws-frame.d.ts.map +1 -0
  169. package/dist/stream/ws-frame.js +28 -0
  170. package/dist/stream/ws-local-connection-store.d.ts +4 -4
  171. package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
  172. package/dist/stream/ws-local-connection-store.js +3 -4
  173. package/dist/stream/ws-presence-index.d.ts +36 -0
  174. package/dist/stream/ws-presence-index.d.ts.map +1 -0
  175. package/dist/stream/ws-presence-index.js +176 -0
  176. package/dist/stream/ws-presence-store.d.ts +39 -39
  177. package/dist/stream/ws-presence-store.d.ts.map +1 -1
  178. package/dist/stream/ws-presence-store.js +23 -154
  179. package/dist/stream/ws-registry.d.ts +45 -17
  180. package/dist/stream/ws-registry.d.ts.map +1 -1
  181. package/dist/stream/ws-registry.js +170 -62
  182. package/dist/stream/ws-session-id.d.ts +14 -0
  183. package/dist/stream/ws-session-id.d.ts.map +1 -0
  184. package/dist/stream/ws-session-id.js +36 -0
  185. package/dist/stream/ws-telemetry-memory.js +3 -4
  186. package/dist/stream/ws-telemetry-trace.js +1 -2
  187. package/dist/stream/ws-telemetry.js +2 -3
  188. package/dist/stream/ws.d.ts +20 -10
  189. package/dist/stream/ws.d.ts.map +1 -1
  190. package/dist/stream/ws.js +60 -38
  191. package/dist/syncer/api-parser.js +2 -3
  192. package/dist/syncer/checksum.js +4 -4
  193. package/dist/syncer/code-generator.js +4 -4
  194. package/dist/syncer/entity-operations.js +2 -3
  195. package/dist/syncer/event-batcher.js +1 -2
  196. package/dist/syncer/file-copy.js +2 -3
  197. package/dist/syncer/file-patterns.js +2 -3
  198. package/dist/syncer/file-tracking.js +2 -3
  199. package/dist/syncer/filesystem-dependencies.js +1 -2
  200. package/dist/syncer/index.js +8 -2
  201. package/dist/syncer/module-loader.js +8 -6
  202. package/dist/syncer/syncer-actions.js +8 -7
  203. package/dist/syncer/syncer.js +13 -8
  204. package/dist/syncer/watcher.js +2 -3
  205. package/dist/tasks/decorator.js +1 -2
  206. package/dist/tasks/step-wrapper.js +2 -3
  207. package/dist/tasks/workflow-manager.js +2 -3
  208. package/dist/template/entity-converter.js +17 -16
  209. package/dist/template/helpers.js +2 -3
  210. package/dist/template/implementations/entity.template.js +2 -3
  211. package/dist/template/implementations/entry-server.template.js +2 -3
  212. package/dist/template/implementations/generated.template.js +2 -3
  213. package/dist/template/implementations/generated_http.template.js +6 -6
  214. package/dist/template/implementations/generated_sso.template.js +2 -3
  215. package/dist/template/implementations/http_validators.template.js +2 -3
  216. package/dist/template/implementations/init_types.template.js +2 -3
  217. package/dist/template/implementations/model.template.js +4 -4
  218. package/dist/template/implementations/model_test.template.js +2 -3
  219. package/dist/template/implementations/queries.template.js +2 -3
  220. package/dist/template/implementations/sd.template.js +2 -3
  221. package/dist/template/implementations/services.template.js +2 -3
  222. package/dist/template/implementations/view_form.template.js +12 -9
  223. package/dist/template/implementations/view_id_all_select.template.js +2 -3
  224. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  225. package/dist/template/implementations/view_list.template.js +19 -17
  226. package/dist/template/implementations/view_search_input.template.js +2 -3
  227. package/dist/template/index.js +9 -3
  228. package/dist/template/template-manager.js +2 -3
  229. package/dist/template/template-types.js +1 -2
  230. package/dist/template/template.js +2 -3
  231. package/dist/template/zod-converter.js +54 -47
  232. package/dist/testing/_relation-graph.js +2 -3
  233. package/dist/testing/bootstrap.js +2 -3
  234. package/dist/testing/data-explorer.js +2 -3
  235. package/dist/testing/dev-test-routes.js +2 -3
  236. package/dist/testing/dev-vitest-manager.js +15 -12
  237. package/dist/testing/faker-mappings.js +1 -2
  238. package/dist/testing/filesystem.js +2 -3
  239. package/dist/testing/fixture-generator.js +2 -3
  240. package/dist/testing/fixture-loader.js +1 -2
  241. package/dist/testing/fixture-manager.js +12 -9
  242. package/dist/testing/global-setup.js +5 -5
  243. package/dist/testing/index.js +6 -3
  244. package/dist/testing/naite-vitest-reporter.js +1 -2
  245. package/dist/testing/parallel-db-manager.js +2 -3
  246. package/dist/testing/vitest-helpers.js +2 -3
  247. package/dist/tooling/__tests__/helpers/sonamu-test-root.js +2 -3
  248. package/dist/tooling/cdd-service.js +1 -2
  249. package/dist/tooling/cli-tooling.js +1 -2
  250. package/dist/tooling/fixture-service.js +1 -2
  251. package/dist/tooling/index.js +1 -2
  252. package/dist/tooling/test-run-client.js +2 -3
  253. package/dist/tsdown.api.config.js +1 -2
  254. package/dist/types/types.js +2 -3
  255. package/dist/ui/ai-api.d.ts.map +1 -1
  256. package/dist/ui/ai-api.js +4 -5
  257. package/dist/ui/ai-client.d.ts +2 -2
  258. package/dist/ui/ai-client.d.ts.map +1 -1
  259. package/dist/ui/ai-client.js +9 -8
  260. package/dist/ui/api.d.ts.map +1 -1
  261. package/dist/ui/api.js +11 -8
  262. package/dist/ui/async-route.js +1 -2
  263. package/dist/ui/cdd-service.js +22 -21
  264. package/dist/ui/migrations-api.js +6 -5
  265. package/dist/ui-web/assets/index-QDMyy31K.js +180 -0
  266. package/dist/ui-web/assets/index-dV7akMFB.css +1 -0
  267. package/dist/ui-web/index.html +2 -2
  268. package/dist/utils/async-utils.js +1 -2
  269. package/dist/utils/class-name.js +1 -2
  270. package/dist/utils/console-util.js +1 -2
  271. package/dist/utils/controller.js +2 -3
  272. package/dist/utils/esm-utils.js +1 -2
  273. package/dist/utils/fs-utils.js +2 -3
  274. package/dist/utils/lodash-able.js +1 -2
  275. package/dist/utils/model.js +1 -2
  276. package/dist/utils/object-utils.js +2 -3
  277. package/dist/utils/path-utils.js +2 -3
  278. package/dist/utils/process-utils.js +2 -3
  279. package/dist/utils/runtime-value.js +1 -2
  280. package/dist/utils/sql-parser.js +2 -3
  281. package/dist/utils/type-utils.js +8 -8
  282. package/dist/utils/utils.js +2 -3
  283. package/dist/utils/zod-error.js +2 -3
  284. package/dist/vector/chunking.js +1 -2
  285. package/dist/vector/config.js +1 -2
  286. package/dist/vector/embedding.js +4 -4
  287. package/package.json +63 -63
  288. package/src/ai/agents/agent.ts +1 -1
  289. package/src/api/__tests__/sonamu.plugins.test.ts +11 -1
  290. package/src/api/__tests__/sonamu.websocket-routes.test.ts +234 -0
  291. package/src/api/__tests__/sonamu.websocket.test.ts +241 -24
  292. package/src/api/config.ts +1 -1
  293. package/src/api/context.ts +2 -8
  294. package/src/api/sonamu.ts +46 -28
  295. package/src/auth/audit-log/plugin.ts +2 -0
  296. package/src/compress/types.ts +1 -1
  297. package/src/exceptions/error-handler.ts +3 -2
  298. package/src/index.ts +1 -0
  299. package/src/stream/__tests__/ws-contracts.test.ts +483 -265
  300. package/src/stream/__tests__/ws-multinode.test.ts +326 -0
  301. package/src/stream/__tests__/ws-registry-async.test.ts +855 -0
  302. package/src/stream/__tests__/ws-test-helpers.ts +360 -0
  303. package/src/stream/__tests__/ws.test.ts +342 -145
  304. package/src/stream/index.ts +1 -0
  305. package/src/stream/ws-audience-resolver.ts +21 -19
  306. package/src/stream/ws-cluster-bus.ts +12 -4
  307. package/src/stream/ws-core.ts +14 -0
  308. package/src/stream/ws-delivery.ts +321 -97
  309. package/src/stream/ws-frame.ts +39 -0
  310. package/src/stream/ws-local-connection-store.ts +10 -9
  311. package/src/stream/ws-presence-index.ts +273 -0
  312. package/src/stream/ws-presence-store.ts +64 -284
  313. package/src/stream/ws-registry.ts +272 -85
  314. package/src/stream/ws-session-id.ts +39 -0
  315. package/src/stream/ws.ts +91 -50
  316. package/src/template/implementations/model.template.ts +3 -3
  317. package/src/template/implementations/view_list.template.ts +12 -13
  318. package/src/ui/ai-api.ts +4 -2
  319. package/src/ui/ai-client.ts +2 -2
  320. package/src/ui/api.ts +58 -62
  321. package/dist/ui-web/assets/index-BMdIyKXS.css +0 -1
  322. package/dist/ui-web/assets/index-LpE8u19O.js +0 -178
@@ -1 +1 @@
1
- {"version":3,"file":"ws-delivery.d.ts","sourceRoot":"","sources":["../../src/stream/ws-delivery.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,KAAK,mBAAmB,EAAiC,MAAM,kBAAkB,CAAC;AAE3F,OAAO,EAAE,KAAK,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,gBAAgB,CAAC;AAKxB,qBAAa,uBAAuB;IAahC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAK1B;IACR,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IAEpD,YACmB,OAAO,EAAE;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,6BAA6B,CAAC;QAChD,gBAAgB,EAAE,yBAAyB,CAAC;QAC5C,UAAU,EAAE,mBAAmB,CAAC;QAChC,mBAAmB,CAAC,EAAE,4BAA4B,CAAC;KACpD,EASF;IAED,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAwEpF;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAI9B;IAED,oBAAoB;;;MAWnB;IAED,OAAO,CAAC,qBAAqB;IA+C7B,OAAO,CAAC,aAAa;IAuBrB,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,eAAe;IA8CvB,OAAO,CAAC,WAAW;CAqBpB"}
1
+ {"version":3,"file":"ws-delivery.d.ts","sourceRoot":"","sources":["../../src/stream/ws-delivery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,KAAK,mBAAmB,EAAiC,MAAM,kBAAkB,CAAC;AAG3F,OAAO,EAAE,KAAK,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,gBAAgB,CAAC;AAKxB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC;CACxB,CAAC;AAeF,qBAAa,uBAAuB;IAahC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,oBAAoB,CAAS;IAErC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IAEzD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmC;IAChE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IAEpD,YACmB,OAAO,EAAE;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,6BAA6B,CAAC;QAEhD,sBAAsB,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,MAAM,EAAE,CAAC;QAClE,gBAAgB,EAAE,yBAAyB,CAAC;QAC5C,UAAU,EAAE,mBAAmB,CAAC;QAChC,mBAAmB,CAAC,EAAE,4BAA4B,CAAC;KACpD,EAOF;IAED,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,IAAI,CAE5D;IAED,aAAa,CAAC,MAAM,EAAE,wBAAwB,EAAE,GAAG,IAAI,CAKtD;IAED;;;OAGG;IACH,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA+E7F;IAGK,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpC;IAED;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrD;IAED,oBAAoB;;;MAWnB;IAGD,OAAO,CAAC,SAAS;IAoBjB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,oBAAoB;YAUd,aAAa;IA8D3B,OAAO,CAAC,qBAAqB;IA4D7B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,eAAe;IA8CvB,OAAO,CAAC,QAAQ;CAkBjB"}
@@ -1,66 +1,181 @@
1
1
  import { __esmMin } from "../_virtual/_rolldown/runtime.js";
2
2
  import { init_runtime_type, runtimeTypeOf } from "../runtime-type.js";
3
+ import { encodeWebSocketFrame, init_ws_frame } from "./ws-frame.js";
3
4
  import { NoopWebSocketTelemetryController, init_ws_telemetry } from "./ws-telemetry.js";
4
5
  import { randomUUID } from "node:crypto";
5
- //#region src/stream/ws-delivery.ts
6
+ // src/stream/ws-delivery.ts
7
+ function getOwnFrame(frames, routeKey) {
8
+ return Object.hasOwn(frames, routeKey) ? frames[routeKey] : void 0;
9
+ }
10
+ function describeError(cause) {
11
+ return cause instanceof Error ? cause.name : runtimeTypeOf(cause);
12
+ }
6
13
  var FAN_OUT_BATCH_SIZE, WebSocketDeliveryEngine;
7
14
  var init_ws_delivery = __esmMin((() => {
8
15
  init_runtime_type();
16
+ init_ws_frame();
9
17
  init_ws_telemetry();
10
18
  FAN_OUT_BATCH_SIZE = 250;
11
19
  WebSocketDeliveryEngine = class {
12
20
  options;
13
21
  pendingFanOutJobs = [];
14
22
  fanOutFlushScheduled = false;
15
- unsubscribe;
23
+ routes = /* @__PURE__ */ new Map();
24
+ publishQueue = Promise.resolve();
25
+ subscription;
26
+ stopped = false;
16
27
  telemetry;
17
28
  unregisterMetricSource;
18
29
  constructor(options) {
19
30
  this.options = options;
20
31
  this.telemetry = this.options.telemetryController ?? new NoopWebSocketTelemetryController();
21
- this.unsubscribe = this.options.clusterBus.subscribe((envelope) => {
22
- this.handleClusterEnvelope(envelope);
23
- });
32
+ this.subscription = this.subscribe();
24
33
  this.unregisterMetricSource = this.telemetry.registerMetricSource({ collect: () => this.getTelemetrySnapshot() });
25
34
  }
35
+ registerRoute(routeKey, outEvents) {
36
+ this.routes.set(routeKey, outEvents);
37
+ }
38
+ replaceRoutes(routes) {
39
+ this.routes.clear();
40
+ for (const route of routes) this.routes.set(route.routeKey, route.outEvents);
41
+ }
42
+ /**
43
+ * 발행 노드에서 route별로 한 번 검증·인코딩하고, 로컬 fan-out은 즉시 큐에 넣는다.
44
+ * 원격 라우팅과 cluster publish는 노드 단위 직렬 큐에서 처리한다. 반환한 promise는 reject하지 않는다.
45
+ */
26
46
  publishToAudience(audience, event, data) {
27
- const routingPlan = this.options.audienceResolver.resolve(audience);
28
- const localTargets = this.options.localConnections.getConnections(routingPlan.localSessionIds);
29
- this.telemetry.emit({
30
- name: "ws.fanout.resolved",
31
- level: "debug",
32
- detail: {
33
- localTargetCount: localTargets.length,
34
- remoteNodeCount: routingPlan.remoteNodeIds.length
47
+ try {
48
+ let declared = false;
49
+ let rejected = false;
50
+ const record = (encoding) => {
51
+ if (encoding.status !== "unknownEvent") declared = true;
52
+ if (encoding.status === "invalidPayload") rejected = true;
53
+ };
54
+ const routeFrames = {};
55
+ for (const [routeKey, outEvents] of this.routes) {
56
+ const encoding = encodeWebSocketFrame(outEvents, event, data);
57
+ record(encoding);
58
+ if (encoding.status === "encoded") routeFrames[routeKey] = encoding.frame;
59
+ }
60
+ const fallbackEncodings = /* @__PURE__ */ new Map();
61
+ const localTargets = [];
62
+ for (const connection of this.options.localConnections.getConnections(this.options.resolveLocalSessionIds(audience))) {
63
+ let frame;
64
+ if (connection.routeKey !== void 0 && this.routes.has(connection.routeKey)) frame = getOwnFrame(routeFrames, connection.routeKey);
65
+ else {
66
+ let encoding = fallbackEncodings.get(connection.outEvents);
67
+ if (!encoding) {
68
+ encoding = encodeWebSocketFrame(connection.outEvents, event, data);
69
+ fallbackEncodings.set(connection.outEvents, encoding);
70
+ record(encoding);
71
+ }
72
+ frame = encoding.status === "encoded" ? encoding.frame : void 0;
73
+ }
74
+ if (frame !== void 0) localTargets.push({
75
+ connection,
76
+ frame
77
+ });
35
78
  }
79
+ if (!declared) this.emitPublishRejected(event, "unknownEvent");
80
+ else if (rejected) this.emitPublishRejected(event, "invalidPayload");
81
+ this.enqueueFanOut(localTargets, event);
82
+ if (Object.keys(routeFrames).length === 0) {
83
+ this.emitFanOutResolved(audience, localTargets.length, 0);
84
+ return Promise.resolve();
85
+ }
86
+ const routing = this.resolveRemoteNodeIds(audience, event);
87
+ const task = this.publishQueue.then(() => routing).then((remoteNodeIds) => this.publishRemote(audience, event, routeFrames, localTargets.length, remoteNodeIds)).catch((cause) => {
88
+ this.emitRouteFailed(event, audience, cause);
89
+ });
90
+ this.publishQueue = task;
91
+ return task;
92
+ } catch (cause) {
93
+ this.emitRouteFailed(event, audience, cause);
94
+ return Promise.resolve();
95
+ }
96
+ }
97
+ async drainPublishes() {
98
+ await Promise.all([this.publishQueue, this.subscription]);
99
+ }
100
+ /**
101
+ * 구독을 해제하고 cluster bus를 종료한다. 구독이 deadline까지 끝나지 않으면 늦게 끝날 때 해제한다.
102
+ */
103
+ async shutdown(deadline) {
104
+ this.stopped = true;
105
+ this.unregisterMetricSource();
106
+ const unsubscribe = await Promise.race([this.subscription, deadline.then(() => null)]);
107
+ if (unsubscribe === null) this.subscription.then((lateUnsubscribe) => {
108
+ this.safeUnsubscribe(lateUnsubscribe);
36
109
  });
37
- this.telemetry.recordMetric({
38
- name: "sonamu.ws.fanout.targets",
39
- kind: "histogram",
40
- value: localTargets.length + routingPlan.remoteNodeIds.length,
41
- unit: "1",
42
- tags: { audience_type: audience.type }
110
+ else this.safeUnsubscribe(unsubscribe);
111
+ try {
112
+ await Promise.resolve().then(() => this.options.clusterBus.shutdown());
113
+ } catch (cause) {
114
+ this.telemetry.emit({
115
+ name: "ws.cluster.shutdown.failed",
116
+ level: "error",
117
+ detail: { errorType: describeError(cause) }
118
+ });
119
+ }
120
+ }
121
+ getTelemetrySnapshot() {
122
+ let pendingFanOutTargets = 0;
123
+ for (const job of this.pendingFanOutJobs) pendingFanOutTargets += Math.max(job.targets.length - job.cursor, 0);
124
+ return {
125
+ pendingFanOutJobs: this.pendingFanOutJobs.length,
126
+ pendingFanOutTargets
127
+ };
128
+ }
129
+ subscribe() {
130
+ return Promise.resolve().then(() => this.options.clusterBus.subscribe((envelope) => {
131
+ this.handleClusterEnvelope(envelope);
132
+ })).then((unsubscribe) => unsubscribe, (cause) => {
133
+ this.telemetry.emit({
134
+ name: "ws.cluster.subscribe.failed",
135
+ level: "error",
136
+ detail: { errorType: describeError(cause) }
137
+ });
43
138
  });
44
- this.enqueueFanOut(localTargets, event, data);
45
- if (routingPlan.remoteNodeIds.length === 0) return;
139
+ }
140
+ safeUnsubscribe(unsubscribe) {
141
+ try {
142
+ unsubscribe?.();
143
+ } catch (cause) {
144
+ this.telemetry.emit({
145
+ name: "ws.cluster.unsubscribe.failed",
146
+ level: "error",
147
+ detail: { errorType: describeError(cause) }
148
+ });
149
+ }
150
+ }
151
+ resolveRemoteNodeIds(audience, event) {
152
+ return this.options.audienceResolver.resolveRemoteNodeIds(audience).catch((cause) => {
153
+ this.emitRouteFailed(event, audience, cause);
154
+ });
155
+ }
156
+ async publishRemote(audience, event, frames, localTargetCount, resolvedNodeIds) {
157
+ const remoteNodeIds = resolvedNodeIds ?? [];
158
+ this.emitFanOutResolved(audience, localTargetCount, remoteNodeIds.length);
159
+ if (remoteNodeIds.length === 0) return;
46
160
  const envelope = {
47
161
  id: randomUUID(),
48
162
  sourceNodeId: this.options.nodeId,
49
- targetNodeIds: routingPlan.remoteNodeIds,
163
+ targetNodeIds: remoteNodeIds,
50
164
  audience,
51
165
  event,
52
- data,
166
+ frames,
53
167
  emittedAt: Date.now()
54
168
  };
55
169
  const publishStartedAt = performance.now();
56
- Promise.resolve(this.options.clusterBus.publish(envelope)).then(() => {
170
+ try {
171
+ await Promise.resolve().then(() => this.options.clusterBus.publish(envelope));
57
172
  const durationMs = performance.now() - publishStartedAt;
58
173
  this.telemetry.emit({
59
174
  name: "ws.cluster.envelope.published",
60
175
  level: "debug",
61
176
  detail: {
62
177
  event,
63
- targetNodeCount: routingPlan.remoteNodeIds.length
178
+ targetNodeCount: remoteNodeIds.length
64
179
  }
65
180
  });
66
181
  this.telemetry.recordSpan({
@@ -70,10 +185,10 @@ var init_ws_delivery = __esmMin((() => {
70
185
  status: "unset",
71
186
  attributes: {
72
187
  event,
73
- targetNodeCount: routingPlan.remoteNodeIds.length
188
+ targetNodeCount: remoteNodeIds.length
74
189
  }
75
190
  });
76
- }).catch((cause) => {
191
+ } catch (cause) {
77
192
  const durationMs = performance.now() - publishStartedAt;
78
193
  this.telemetry.emit({
79
194
  name: "ws.cluster.envelope.failed",
@@ -86,24 +201,12 @@ var init_ws_delivery = __esmMin((() => {
86
201
  durationMs,
87
202
  status: "error",
88
203
  attributes: { event },
89
- errorType: cause instanceof Error ? cause.name : runtimeTypeOf(cause)
204
+ errorType: describeError(cause)
90
205
  });
91
- });
92
- }
93
- async shutdown() {
94
- this.unregisterMetricSource();
95
- this.unsubscribe();
96
- await this.options.clusterBus.shutdown();
97
- }
98
- getTelemetrySnapshot() {
99
- let pendingFanOutTargets = 0;
100
- for (const job of this.pendingFanOutJobs) pendingFanOutTargets += Math.max(job.targets.length - job.cursor, 0);
101
- return {
102
- pendingFanOutJobs: this.pendingFanOutJobs.length,
103
- pendingFanOutTargets
104
- };
206
+ }
105
207
  }
106
208
  handleClusterEnvelope(envelope) {
209
+ if (this.stopped) return;
107
210
  if (envelope.sourceNodeId === this.options.nodeId) {
108
211
  this.telemetry.emit({
109
212
  name: "ws.cluster.envelope.ignored",
@@ -115,7 +218,7 @@ var init_ws_delivery = __esmMin((() => {
115
218
  });
116
219
  return;
117
220
  }
118
- if (envelope.targetNodeIds && envelope.targetNodeIds.length > 0 && !envelope.targetNodeIds.includes(this.options.nodeId)) {
221
+ if (envelope.targetNodeIds.length > 0 && !envelope.targetNodeIds.includes(this.options.nodeId)) {
119
222
  this.telemetry.emit({
120
223
  name: "ws.cluster.envelope.ignored",
121
224
  level: "debug",
@@ -135,9 +238,15 @@ var init_ws_delivery = __esmMin((() => {
135
238
  sourceNodeId: envelope.sourceNodeId
136
239
  }
137
240
  });
138
- const routingPlan = this.options.audienceResolver.resolve(envelope.audience);
139
- const localTargets = this.options.localConnections.getConnections(routingPlan.localSessionIds);
140
- this.enqueueFanOut(localTargets, envelope.event, envelope.data);
241
+ const localTargets = [];
242
+ for (const connection of this.options.localConnections.getConnections(this.options.resolveLocalSessionIds(envelope.audience))) {
243
+ const frame = connection.routeKey === void 0 ? void 0 : getOwnFrame(envelope.frames, connection.routeKey);
244
+ if (frame !== void 0) localTargets.push({
245
+ connection,
246
+ frame
247
+ });
248
+ }
249
+ this.enqueueFanOut(localTargets, envelope.event);
141
250
  this.telemetry.recordSpan({
142
251
  operationName: "ws.cluster.receive",
143
252
  kind: "consumer",
@@ -150,12 +259,49 @@ var init_ws_delivery = __esmMin((() => {
150
259
  }
151
260
  });
152
261
  }
153
- enqueueFanOut(targets, event, data) {
262
+ emitPublishRejected(event, reason) {
263
+ this.telemetry.emit({
264
+ name: "ws.publish.rejected",
265
+ level: "error",
266
+ detail: {
267
+ event,
268
+ reason
269
+ }
270
+ });
271
+ }
272
+ emitRouteFailed(event, audience, cause) {
273
+ this.telemetry.emit({
274
+ name: "ws.fanout.route.failed",
275
+ level: "error",
276
+ detail: {
277
+ event,
278
+ audienceType: audience.type,
279
+ errorType: describeError(cause)
280
+ }
281
+ });
282
+ }
283
+ emitFanOutResolved(audience, localTargetCount, remoteNodeCount) {
284
+ this.telemetry.emit({
285
+ name: "ws.fanout.resolved",
286
+ level: "debug",
287
+ detail: {
288
+ localTargetCount,
289
+ remoteNodeCount
290
+ }
291
+ });
292
+ this.telemetry.recordMetric({
293
+ name: "sonamu.ws.fanout.targets",
294
+ kind: "histogram",
295
+ value: localTargetCount + remoteNodeCount,
296
+ unit: "1",
297
+ tags: { audience_type: audience.type }
298
+ });
299
+ }
300
+ enqueueFanOut(targets, event) {
154
301
  if (targets.length === 0) return;
155
302
  this.pendingFanOutJobs.push({
156
303
  targets,
157
304
  event,
158
- data,
159
305
  cursor: 0
160
306
  });
161
307
  this.telemetry.emit({
@@ -185,7 +331,7 @@ var init_ws_delivery = __esmMin((() => {
185
331
  while (this.pendingFanOutJobs.length > 0 && processed < FAN_OUT_BATCH_SIZE) {
186
332
  const job = this.pendingFanOutJobs[0];
187
333
  while (job.cursor < job.targets.length && processed < FAN_OUT_BATCH_SIZE) {
188
- this.safePublish(job.targets[job.cursor], job.event, job.data);
334
+ this.safeSend(job.targets[job.cursor], job.event);
189
335
  job.cursor += 1;
190
336
  processed += 1;
191
337
  }
@@ -193,7 +339,7 @@ var init_ws_delivery = __esmMin((() => {
193
339
  }
194
340
  } catch (error) {
195
341
  status = "error";
196
- errorType = error instanceof Error ? error.name : runtimeTypeOf(error);
342
+ errorType = describeError(error);
197
343
  throw error;
198
344
  } finally {
199
345
  const durationMs = performance.now() - startedAt;
@@ -213,9 +359,10 @@ var init_ws_delivery = __esmMin((() => {
213
359
  if (this.pendingFanOutJobs.length > 0) this.scheduleFanOutFlush();
214
360
  }
215
361
  }
216
- safePublish(connection, event, data) {
362
+ safeSend(target, event) {
363
+ const { connection, frame } = target;
217
364
  try {
218
- if (!connection.closed) connection.publishUntyped(event, data);
365
+ if (!connection.closed) connection.sendFrame(event, frame);
219
366
  } catch {
220
367
  this.telemetry.emit({
221
368
  name: "ws.fanout.publish.failed",
@@ -230,8 +377,7 @@ var init_ws_delivery = __esmMin((() => {
230
377
  }
231
378
  };
232
379
  }));
233
- //#endregion
234
380
  init_ws_delivery();
235
381
  export { WebSocketDeliveryEngine, init_ws_delivery };
236
382
 
237
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtZGVsaXZlcnkuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmVhbS93cy1kZWxpdmVyeS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5cbmltcG9ydCB7IHJ1bnRpbWVUeXBlT2YgfSBmcm9tIFwiLi4vcnVudGltZS10eXBlXCI7XG5pbXBvcnQgeyB0eXBlIFdlYlNvY2tldEF1ZGllbmNlIH0gZnJvbSBcIi4vd3MtYXVkaWVuY2VcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0QXVkaWVuY2VSZXNvbHZlciB9IGZyb20gXCIuL3dzLWF1ZGllbmNlLXJlc29sdmVyXCI7XG5pbXBvcnQgeyB0eXBlIFdlYlNvY2tldENsdXN0ZXJCdXMsIHR5cGUgV2ViU29ja2V0Q2x1c3RlckVudmVsb3BlIH0gZnJvbSBcIi4vd3MtY2x1c3Rlci1idXNcIjtcbmltcG9ydCB7IHR5cGUgTWFuYWdlZFdlYlNvY2tldENvbm5lY3Rpb24gfSBmcm9tIFwiLi93cy1jb3JlXCI7XG5pbXBvcnQgeyB0eXBlIFdlYlNvY2tldExvY2FsQ29ubmVjdGlvblN0b3JlIH0gZnJvbSBcIi4vd3MtbG9jYWwtY29ubmVjdGlvbi1zdG9yZVwiO1xuaW1wb3J0IHtcbiAgTm9vcFdlYlNvY2tldFRlbGVtZXRyeUNvbnRyb2xsZXIsXG4gIHR5cGUgV2ViU29ja2V0VGVsZW1ldHJ5Q29udHJvbGxlcixcbn0gZnJvbSBcIi4vd3MtdGVsZW1ldHJ5XCI7XG5cbi8vIGZhbi1vdXTsnYQgZXZlbnQgbG9vcCB0aWNrIOuLqOychOuhnCDrgpjriKAg7ZWcIOuyiOyXkCDquLQg64+Z6riwIOujqO2UhOulvCDrp4zrk6Tsp4Ag7JWK6rKMIO2VqFxuY29uc3QgRkFOX09VVF9CQVRDSF9TSVpFID0gMjUwO1xuXG5leHBvcnQgY2xhc3MgV2ViU29ja2V0RGVsaXZlcnlFbmdpbmUge1xuICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdGYW5PdXRKb2JzOiBBcnJheTx7XG4gICAgdGFyZ2V0czogTWFuYWdlZFdlYlNvY2tldENvbm5lY3Rpb25bXTtcbiAgICBldmVudDogc3RyaW5nO1xuICAgIGRhdGE6IHVua25vd247XG4gICAgY3Vyc29yOiBudW1iZXI7XG4gIH0+ID0gW107XG4gIHByaXZhdGUgZmFuT3V0Rmx1c2hTY2hlZHVsZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWFkb25seSB1bnN1YnNjcmliZTogKCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSB0ZWxlbWV0cnk6IFdlYlNvY2tldFRlbGVtZXRyeUNvbnRyb2xsZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgdW5yZWdpc3Rlck1ldHJpY1NvdXJjZTogKCkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IHtcbiAgICAgIG5vZGVJZDogc3RyaW5nO1xuICAgICAgbG9jYWxDb25uZWN0aW9uczogV2ViU29ja2V0TG9jYWxDb25uZWN0aW9uU3RvcmU7XG4gICAgICBhdWRpZW5jZVJlc29sdmVyOiBXZWJTb2NrZXRBdWRpZW5jZVJlc29sdmVyO1xuICAgICAgY2x1c3RlckJ1czogV2ViU29ja2V0Q2x1c3RlckJ1cztcbiAgICAgIHRlbGVtZXRyeUNvbnRyb2xsZXI/OiBXZWJTb2NrZXRUZWxlbWV0cnlDb250cm9sbGVyO1xuICAgIH0sXG4gICkge1xuICAgIHRoaXMudGVsZW1ldHJ5ID0gdGhpcy5vcHRpb25zLnRlbGVtZXRyeUNvbnRyb2xsZXIgPz8gbmV3IE5vb3BXZWJTb2NrZXRUZWxlbWV0cnlDb250cm9sbGVyKCk7XG4gICAgdGhpcy51bnN1YnNjcmliZSA9IHRoaXMub3B0aW9ucy5jbHVzdGVyQnVzLnN1YnNjcmliZSgoZW52ZWxvcGUpID0+IHtcbiAgICAgIHRoaXMuaGFuZGxlQ2x1c3RlckVudmVsb3BlKGVudmVsb3BlKTtcbiAgICB9KTtcbiAgICB0aGlzLnVucmVnaXN0ZXJNZXRyaWNTb3VyY2UgPSB0aGlzLnRlbGVtZXRyeS5yZWdpc3Rlck1ldHJpY1NvdXJjZSh7XG4gICAgICBjb2xsZWN0OiAoKSA9PiB0aGlzLmdldFRlbGVtZXRyeVNuYXBzaG90KCksXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaXNoVG9BdWRpZW5jZTxEYXRhPihhdWRpZW5jZTogV2ViU29ja2V0QXVkaWVuY2UsIGV2ZW50OiBzdHJpbmcsIGRhdGE6IERhdGEpOiB2b2lkIHtcbiAgICBjb25zdCByb3V0aW5nUGxhbiA9IHRoaXMub3B0aW9ucy5hdWRpZW5jZVJlc29sdmVyLnJlc29sdmUoYXVkaWVuY2UpO1xuICAgIGNvbnN0IGxvY2FsVGFyZ2V0cyA9IHRoaXMub3B0aW9ucy5sb2NhbENvbm5lY3Rpb25zLmdldENvbm5lY3Rpb25zKHJvdXRpbmdQbGFuLmxvY2FsU2Vzc2lvbklkcyk7XG5cbiAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgIG5hbWU6IFwid3MuZmFub3V0LnJlc29sdmVkXCIsXG4gICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgZGV0YWlsOiB7XG4gICAgICAgIGxvY2FsVGFyZ2V0Q291bnQ6IGxvY2FsVGFyZ2V0cy5sZW5ndGgsXG4gICAgICAgIHJlbW90ZU5vZGVDb3VudDogcm91dGluZ1BsYW4ucmVtb3RlTm9kZUlkcy5sZW5ndGgsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHRoaXMudGVsZW1ldHJ5LnJlY29yZE1ldHJpYyh7XG4gICAgICBuYW1lOiBcInNvbmFtdS53cy5mYW5vdXQudGFyZ2V0c1wiLFxuICAgICAga2luZDogXCJoaXN0b2dyYW1cIixcbiAgICAgIHZhbHVlOiBsb2NhbFRhcmdldHMubGVuZ3RoICsgcm91dGluZ1BsYW4ucmVtb3RlTm9kZUlkcy5sZW5ndGgsXG4gICAgICB1bml0OiBcIjFcIixcbiAgICAgIHRhZ3M6IHsgYXVkaWVuY2VfdHlwZTogYXVkaWVuY2UudHlwZSB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy5lbnF1ZXVlRmFuT3V0KGxvY2FsVGFyZ2V0cywgZXZlbnQsIGRhdGEpO1xuXG4gICAgaWYgKHJvdXRpbmdQbGFuLnJlbW90ZU5vZGVJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZW52ZWxvcGU6IFdlYlNvY2tldENsdXN0ZXJFbnZlbG9wZSA9IHtcbiAgICAgIGlkOiByYW5kb21VVUlEKCksXG4gICAgICBzb3VyY2VOb2RlSWQ6IHRoaXMub3B0aW9ucy5ub2RlSWQsXG4gICAgICB0YXJnZXROb2RlSWRzOiByb3V0aW5nUGxhbi5yZW1vdGVOb2RlSWRzLFxuICAgICAgYXVkaWVuY2UsXG4gICAgICBldmVudCxcbiAgICAgIGRhdGEsXG4gICAgICBlbWl0dGVkQXQ6IERhdGUubm93KCksXG4gICAgfTtcblxuICAgIGNvbnN0IHB1Ymxpc2hTdGFydGVkQXQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICBQcm9taXNlLnJlc29sdmUodGhpcy5vcHRpb25zLmNsdXN0ZXJCdXMucHVibGlzaChlbnZlbG9wZSkpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHB1Ymxpc2hTdGFydGVkQXQ7XG4gICAgICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgICAgIG5hbWU6IFwid3MuY2x1c3Rlci5lbnZlbG9wZS5wdWJsaXNoZWRcIixcbiAgICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICAgIGRldGFpbDogeyBldmVudCwgdGFyZ2V0Tm9kZUNvdW50OiByb3V0aW5nUGxhbi5yZW1vdGVOb2RlSWRzLmxlbmd0aCB9LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50ZWxlbWV0cnkucmVjb3JkU3Bhbih7XG4gICAgICAgICAgb3BlcmF0aW9uTmFtZTogXCJ3cy5jbHVzdGVyLnB1Ymxpc2hcIixcbiAgICAgICAgICBraW5kOiBcInByb2R1Y2VyXCIsXG4gICAgICAgICAgZHVyYXRpb25NcyxcbiAgICAgICAgICBzdGF0dXM6IFwidW5zZXRcIixcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgIHRhcmdldE5vZGVDb3VudDogcm91dGluZ1BsYW4ucmVtb3RlTm9kZUlkcy5sZW5ndGgsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChjYXVzZTogdW5rbm93bikgPT4ge1xuICAgICAgICBjb25zdCBkdXJhdGlvbk1zID0gcGVyZm9ybWFuY2Uubm93KCkgLSBwdWJsaXNoU3RhcnRlZEF0O1xuICAgICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgICBuYW1lOiBcIndzLmNsdXN0ZXIuZW52ZWxvcGUuZmFpbGVkXCIsXG4gICAgICAgICAgbGV2ZWw6IFwiZXJyb3JcIixcbiAgICAgICAgICBkZXRhaWw6IHsgZXZlbnQgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudGVsZW1ldHJ5LnJlY29yZFNwYW4oe1xuICAgICAgICAgIG9wZXJhdGlvbk5hbWU6IFwid3MuY2x1c3Rlci5wdWJsaXNoXCIsXG4gICAgICAgICAga2luZDogXCJwcm9kdWNlclwiLFxuICAgICAgICAgIGR1cmF0aW9uTXMsXG4gICAgICAgICAgc3RhdHVzOiBcImVycm9yXCIsXG4gICAgICAgICAgYXR0cmlidXRlczogeyBldmVudCB9LFxuICAgICAgICAgIGVycm9yVHlwZTogY2F1c2UgaW5zdGFuY2VvZiBFcnJvciA/IGNhdXNlLm5hbWUgOiBydW50aW1lVHlwZU9mKGNhdXNlKSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHNodXRkb3duKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMudW5yZWdpc3Rlck1ldHJpY1NvdXJjZSgpO1xuICAgIHRoaXMudW5zdWJzY3JpYmUoKTtcbiAgICBhd2FpdCB0aGlzLm9wdGlvbnMuY2x1c3RlckJ1cy5zaHV0ZG93bigpO1xuICB9XG5cbiAgZ2V0VGVsZW1ldHJ5U25hcHNob3QoKSB7XG4gICAgbGV0IHBlbmRpbmdGYW5PdXRUYXJnZXRzID0gMDtcblxuICAgIGZvciAoY29uc3Qgam9iIG9mIHRoaXMucGVuZGluZ0Zhbk91dEpvYnMpIHtcbiAgICAgIHBlbmRpbmdGYW5PdXRUYXJnZXRzICs9IE1hdGgubWF4KGpvYi50YXJnZXRzLmxlbmd0aCAtIGpvYi5jdXJzb3IsIDApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwZW5kaW5nRmFuT3V0Sm9iczogdGhpcy5wZW5kaW5nRmFuT3V0Sm9icy5sZW5ndGgsXG4gICAgICBwZW5kaW5nRmFuT3V0VGFyZ2V0cyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVDbHVzdGVyRW52ZWxvcGUoZW52ZWxvcGU6IFdlYlNvY2tldENsdXN0ZXJFbnZlbG9wZSk6IHZvaWQge1xuICAgIGlmIChlbnZlbG9wZS5zb3VyY2VOb2RlSWQgPT09IHRoaXMub3B0aW9ucy5ub2RlSWQpIHtcbiAgICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgICBuYW1lOiBcIndzLmNsdXN0ZXIuZW52ZWxvcGUuaWdub3JlZFwiLFxuICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICBkZXRhaWw6IHsgcmVhc29uOiBcInNlbGZTb3VyY2VcIiwgZXZlbnQ6IGVudmVsb3BlLmV2ZW50IH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBlbnZlbG9wZS50YXJnZXROb2RlSWRzICYmXG4gICAgICBlbnZlbG9wZS50YXJnZXROb2RlSWRzLmxlbmd0aCA+IDAgJiZcbiAgICAgICFlbnZlbG9wZS50YXJnZXROb2RlSWRzLmluY2x1ZGVzKHRoaXMub3B0aW9ucy5ub2RlSWQpXG4gICAgKSB7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLmVudmVsb3BlLmlnbm9yZWRcIixcbiAgICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgICAgZGV0YWlsOiB7IHJlYXNvbjogXCJ0YXJnZXRNaXNtYXRjaFwiLCBldmVudDogZW52ZWxvcGUuZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YXJ0ZWRBdCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLmVudmVsb3BlLnJlY2VpdmVkXCIsXG4gICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgZGV0YWlsOiB7IGV2ZW50OiBlbnZlbG9wZS5ldmVudCwgc291cmNlTm9kZUlkOiBlbnZlbG9wZS5zb3VyY2VOb2RlSWQgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJvdXRpbmdQbGFuID0gdGhpcy5vcHRpb25zLmF1ZGllbmNlUmVzb2x2ZXIucmVzb2x2ZShlbnZlbG9wZS5hdWRpZW5jZSk7XG4gICAgY29uc3QgbG9jYWxUYXJnZXRzID0gdGhpcy5vcHRpb25zLmxvY2FsQ29ubmVjdGlvbnMuZ2V0Q29ubmVjdGlvbnMocm91dGluZ1BsYW4ubG9jYWxTZXNzaW9uSWRzKTtcbiAgICB0aGlzLmVucXVldWVGYW5PdXQobG9jYWxUYXJnZXRzLCBlbnZlbG9wZS5ldmVudCwgZW52ZWxvcGUuZGF0YSk7XG5cbiAgICB0aGlzLnRlbGVtZXRyeS5yZWNvcmRTcGFuKHtcbiAgICAgIG9wZXJhdGlvbk5hbWU6IFwid3MuY2x1c3Rlci5yZWNlaXZlXCIsXG4gICAgICBraW5kOiBcImNvbnN1bWVyXCIsXG4gICAgICBkdXJhdGlvbk1zOiBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWRBdCxcbiAgICAgIHN0YXR1czogXCJ1bnNldFwiLFxuICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICBldmVudDogZW52ZWxvcGUuZXZlbnQsXG4gICAgICAgIHNvdXJjZU5vZGVJZDogZW52ZWxvcGUuc291cmNlTm9kZUlkLFxuICAgICAgICBsb2NhbFRhcmdldENvdW50OiBsb2NhbFRhcmdldHMubGVuZ3RoLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZW5xdWV1ZUZhbk91dDxEYXRhPihcbiAgICB0YXJnZXRzOiBNYW5hZ2VkV2ViU29ja2V0Q29ubmVjdGlvbltdLFxuICAgIGV2ZW50OiBzdHJpbmcsXG4gICAgZGF0YTogRGF0YSxcbiAgKTogdm9pZCB7XG4gICAgaWYgKHRhcmdldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nRmFuT3V0Sm9icy5wdXNoKHtcbiAgICAgIHRhcmdldHMsXG4gICAgICBldmVudCxcbiAgICAgIGRhdGEsXG4gICAgICBjdXJzb3I6IDAsXG4gICAgfSk7XG4gICAgdGhpcy50ZWxlbWV0cnkuZW1pdCh7XG4gICAgICBuYW1lOiBcIndzLmZhbm91dC5lbnF1ZXVlZFwiLFxuICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgIGRldGFpbDogeyB0YXJnZXRDb3VudDogdGFyZ2V0cy5sZW5ndGgsIGV2ZW50IH0sXG4gICAgfSk7XG4gICAgdGhpcy5zY2hlZHVsZUZhbk91dEZsdXNoKCk7XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlRmFuT3V0Rmx1c2goKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmFuT3V0Rmx1c2hTY2hlZHVsZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmZhbk91dEZsdXNoU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgdGhpcy5mYW5PdXRGbHVzaFNjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5mbHVzaEZhbk91dEpvYnMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZmx1c2hGYW5PdXRKb2JzKCk6IHZvaWQge1xuICAgIGNvbnN0IHN0YXJ0ZWRBdCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIGxldCBwcm9jZXNzZWQgPSAwO1xuICAgIGxldCBzdGF0dXM6IFwidW5zZXRcIiB8IFwiZXJyb3JcIiA9IFwidW5zZXRcIjtcbiAgICBsZXQgZXJyb3JUeXBlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgd2hpbGUgKHRoaXMucGVuZGluZ0Zhbk91dEpvYnMubGVuZ3RoID4gMCAmJiBwcm9jZXNzZWQgPCBGQU5fT1VUX0JBVENIX1NJWkUpIHtcbiAgICAgICAgY29uc3Qgam9iID0gdGhpcy5wZW5kaW5nRmFuT3V0Sm9ic1swXTtcblxuICAgICAgICB3aGlsZSAoam9iLmN1cnNvciA8IGpvYi50YXJnZXRzLmxlbmd0aCAmJiBwcm9jZXNzZWQgPCBGQU5fT1VUX0JBVENIX1NJWkUpIHtcbiAgICAgICAgICB0aGlzLnNhZmVQdWJsaXNoKGpvYi50YXJnZXRzW2pvYi5jdXJzb3JdLCBqb2IuZXZlbnQsIGpvYi5kYXRhKTtcbiAgICAgICAgICBqb2IuY3Vyc29yICs9IDE7XG4gICAgICAgICAgcHJvY2Vzc2VkICs9IDE7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoam9iLmN1cnNvciA+PSBqb2IudGFyZ2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLnBlbmRpbmdGYW5PdXRKb2JzLnNoaWZ0KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgc3RhdHVzID0gXCJlcnJvclwiO1xuICAgICAgZXJyb3JUeXBlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm5hbWUgOiBydW50aW1lVHlwZU9mKGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBjb25zdCBkdXJhdGlvbk1zID0gcGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5mYW5vdXQuZmx1c2hlZFwiLFxuICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICBkZXRhaWw6IHsgcHJvY2Vzc2VkQ291bnQ6IHByb2Nlc3NlZCB9LFxuICAgICAgfSk7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5yZWNvcmRTcGFuKHtcbiAgICAgICAgb3BlcmF0aW9uTmFtZTogXCJ3cy5mYW5vdXQuZGlzcGF0Y2hcIixcbiAgICAgICAga2luZDogXCJpbnRlcm5hbFwiLFxuICAgICAgICBkdXJhdGlvbk1zLFxuICAgICAgICBzdGF0dXMsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHsgcHJvY2Vzc2VkQ291bnQ6IHByb2Nlc3NlZCB9LFxuICAgICAgICBlcnJvclR5cGUsXG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMucGVuZGluZ0Zhbk91dEpvYnMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlRmFuT3V0Rmx1c2goKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNhZmVQdWJsaXNoPERhdGE+KFxuICAgIGNvbm5lY3Rpb246IE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uLFxuICAgIGV2ZW50OiBzdHJpbmcsXG4gICAgZGF0YTogRGF0YSxcbiAgKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghY29ubmVjdGlvbi5jbG9zZWQpIHtcbiAgICAgICAgY29ubmVjdGlvbi5wdWJsaXNoVW50eXBlZChldmVudCwgZGF0YSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5mYW5vdXQucHVibGlzaC5mYWlsZWRcIixcbiAgICAgICAgbGV2ZWw6IFwiZXJyb3JcIixcbiAgICAgICAgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmlkLFxuICAgICAgICBuYW1lc3BhY2U6IGNvbm5lY3Rpb24ubmFtZXNwYWNlLFxuICAgICAgICB1c2VySWQ6IGNvbm5lY3Rpb24udXNlcklkLFxuICAgICAgICBkZXRhaWw6IHsgZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgY29ubmVjdGlvbi5jbG9zZSgxMDExLCBcIldlYlNvY2tldCBwdWJsaXNoIGZhaWxlZFwiKTtcbiAgICB9XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OzttQkFFK0M7bUJBU3hCO0NBR2pCLHFCQUFxQjtDQUVkLDBCQUFiLE1BQXFDO0VBYWhCO0VBWm5CLG9CQUtLLENBQUM7RUFDTix1QkFBK0I7RUFDL0I7RUFDQTtFQUNBO0VBRUEsWUFDRSxTQU9BO0dBUGlCLEtBQUEsVUFBQTtHQVFqQixLQUFLLFlBQVksS0FBSyxRQUFRLHVCQUF1QixJQUFJLGlDQUFpQztHQUMxRixLQUFLLGNBQWMsS0FBSyxRQUFRLFdBQVcsV0FBVyxhQUFhO0lBQ2pFLEtBQUssc0JBQXNCLFFBQVE7R0FDckMsQ0FBQztHQUNELEtBQUsseUJBQXlCLEtBQUssVUFBVSxxQkFBcUIsRUFDaEUsZUFBZSxLQUFLLHFCQUFxQixFQUMzQyxDQUFDO0VBQ0g7RUFFQSxrQkFBd0IsVUFBNkIsT0FBZSxNQUFrQjtHQUNwRixNQUFNLGNBQWMsS0FBSyxRQUFRLGlCQUFpQixRQUFRLFFBQVE7R0FDbEUsTUFBTSxlQUFlLEtBQUssUUFBUSxpQkFBaUIsZUFBZSxZQUFZLGVBQWU7R0FFN0YsS0FBSyxVQUFVLEtBQUs7SUFDbEIsTUFBTTtJQUNOLE9BQU87SUFDUCxRQUFRO0tBQ04sa0JBQWtCLGFBQWE7S0FDL0IsaUJBQWlCLFlBQVksY0FBYztJQUM3QztHQUNGLENBQUM7R0FDRCxLQUFLLFVBQVUsYUFBYTtJQUMxQixNQUFNO0lBQ04sTUFBTTtJQUNOLE9BQU8sYUFBYSxTQUFTLFlBQVksY0FBYztJQUN2RCxNQUFNO0lBQ04sTUFBTSxFQUFFLGVBQWUsU0FBUyxLQUFLO0dBQ3ZDLENBQUM7R0FFRCxLQUFLLGNBQWMsY0FBYyxPQUFPLElBQUk7R0FFNUMsSUFBSSxZQUFZLGNBQWMsV0FBVyxHQUN2QztHQUdGLE1BQU0sV0FBcUM7SUFDekMsSUFBSSxXQUFXO0lBQ2YsY0FBYyxLQUFLLFFBQVE7SUFDM0IsZUFBZSxZQUFZO0lBQzNC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
383
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtZGVsaXZlcnkuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmVhbS93cy1kZWxpdmVyeS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5cbmltcG9ydCB7IHR5cGUgeiB9IGZyb20gXCJ6b2RcIjtcblxuaW1wb3J0IHsgcnVudGltZVR5cGVPZiB9IGZyb20gXCIuLi9ydW50aW1lLXR5cGVcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0QXVkaWVuY2UgfSBmcm9tIFwiLi93cy1hdWRpZW5jZVwiO1xuaW1wb3J0IHsgdHlwZSBXZWJTb2NrZXRBdWRpZW5jZVJlc29sdmVyIH0gZnJvbSBcIi4vd3MtYXVkaWVuY2UtcmVzb2x2ZXJcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0Q2x1c3RlckJ1cywgdHlwZSBXZWJTb2NrZXRDbHVzdGVyRW52ZWxvcGUgfSBmcm9tIFwiLi93cy1jbHVzdGVyLWJ1c1wiO1xuaW1wb3J0IHsgdHlwZSBXZWJTb2NrZXRGcmFtZUNvbm5lY3Rpb24gfSBmcm9tIFwiLi93cy1jb3JlXCI7XG5pbXBvcnQgeyBlbmNvZGVXZWJTb2NrZXRGcmFtZSwgdHlwZSBXZWJTb2NrZXRGcmFtZUVuY29kaW5nIH0gZnJvbSBcIi4vd3MtZnJhbWVcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0TG9jYWxDb25uZWN0aW9uU3RvcmUgfSBmcm9tIFwiLi93cy1sb2NhbC1jb25uZWN0aW9uLXN0b3JlXCI7XG5pbXBvcnQge1xuICBOb29wV2ViU29ja2V0VGVsZW1ldHJ5Q29udHJvbGxlcixcbiAgdHlwZSBXZWJTb2NrZXRUZWxlbWV0cnlDb250cm9sbGVyLFxufSBmcm9tIFwiLi93cy10ZWxlbWV0cnlcIjtcblxuLy8gZmFuLW91dOydhCBldmVudCBsb29wIHRpY2sg64uo7JyE66GcIOuCmOuIoCDtlZwg67KI7JeQIOq4tCDrj5nquLAg66Oo7ZSE66W8IOunjOuTpOyngCDslYrqsowg7ZWoXG5jb25zdCBGQU5fT1VUX0JBVENIX1NJWkUgPSAyNTA7XG5cbmV4cG9ydCB0eXBlIFdlYlNvY2tldFJvdXRlRGVmaW5pdGlvbiA9IHtcbiAgcm91dGVLZXk6IHN0cmluZztcbiAgb3V0RXZlbnRzOiB6LlpvZE9iamVjdDtcbn07XG5cbnR5cGUgRmFuT3V0VGFyZ2V0ID0ge1xuICBjb25uZWN0aW9uOiBXZWJTb2NrZXRGcmFtZUNvbm5lY3Rpb247XG4gIGZyYW1lOiBzdHJpbmc7XG59O1xuXG50eXBlIEZhbk91dEpvYiA9IHtcbiAgdGFyZ2V0czogRmFuT3V0VGFyZ2V0W107XG4gIGV2ZW50OiBzdHJpbmc7XG4gIGN1cnNvcjogbnVtYmVyO1xufTtcblxudHlwZSBVbnN1YnNjcmliZSA9ICgpID0+IHZvaWQ7XG5cbmV4cG9ydCBjbGFzcyBXZWJTb2NrZXREZWxpdmVyeUVuZ2luZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGVuZGluZ0Zhbk91dEpvYnM6IEZhbk91dEpvYltdID0gW107XG4gIHByaXZhdGUgZmFuT3V0Rmx1c2hTY2hlZHVsZWQgPSBmYWxzZTtcbiAgLy8gcm91dGVLZXkg4oaSIG91dEV2ZW50cy4g66qo65OgIOuFuOuTnOqwgCDqsJnsnYAgcm91dGUg7KeR7ZWp7J2EIOuTseuhne2VmOuvgOuhnCByb3V0ZUtleeuKlCDtgbTrn6zsiqTthLAg7KCE7LK07JeQ7IScIOydvOq0gOuQnOuLpFxuICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlcyA9IG5ldyBNYXA8c3RyaW5nLCB6LlpvZE9iamVjdD4oKTtcbiAgLy8g64W465OcIOuLqOychCDsp4HroKwgcHVibGlzaCDtgZAuIOyVnuyEoCBwdWJsaXNo7J2YIOudvOyasO2MheydtCDripDroKTrj4Qg7JuQ6rKpIGVudmVsb3BlIOyInOyEnOqwgCDrkqTrsJTrgIzsp4Ag7JWK64qU64ukXG4gIHByaXZhdGUgcHVibGlzaFF1ZXVlOiBQcm9taXNlPHZvaWQ+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Vic2NyaXB0aW9uOiBQcm9taXNlPFVuc3Vic2NyaWJlIHwgdW5kZWZpbmVkPjtcbiAgcHJpdmF0ZSBzdG9wcGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGVsZW1ldHJ5OiBXZWJTb2NrZXRUZWxlbWV0cnlDb250cm9sbGVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHVucmVnaXN0ZXJNZXRyaWNTb3VyY2U6ICgpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiB7XG4gICAgICBub2RlSWQ6IHN0cmluZztcbiAgICAgIGxvY2FsQ29ubmVjdGlvbnM6IFdlYlNvY2tldExvY2FsQ29ubmVjdGlvblN0b3JlO1xuICAgICAgLy8gcmVnaXN0cnkg66mU66qo66asIOq4sOykgOycvOuhnCBhdWRpZW5jZeyXkCDsho3tlZwg66Gc7LusIO2ZnOyEsSDshLjshZggSUTrpbwg67CY7ZmY7ZWc64ukXG4gICAgICByZXNvbHZlTG9jYWxTZXNzaW9uSWRzOiAoYXVkaWVuY2U6IFdlYlNvY2tldEF1ZGllbmNlKSA9PiBzdHJpbmdbXTtcbiAgICAgIGF1ZGllbmNlUmVzb2x2ZXI6IFdlYlNvY2tldEF1ZGllbmNlUmVzb2x2ZXI7XG4gICAgICBjbHVzdGVyQnVzOiBXZWJTb2NrZXRDbHVzdGVyQnVzO1xuICAgICAgdGVsZW1ldHJ5Q29udHJvbGxlcj86IFdlYlNvY2tldFRlbGVtZXRyeUNvbnRyb2xsZXI7XG4gICAgfSxcbiAgKSB7XG4gICAgdGhpcy50ZWxlbWV0cnkgPSB0aGlzLm9wdGlvbnMudGVsZW1ldHJ5Q29udHJvbGxlciA/PyBuZXcgTm9vcFdlYlNvY2tldFRlbGVtZXRyeUNvbnRyb2xsZXIoKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbiA9IHRoaXMuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyTWV0cmljU291cmNlID0gdGhpcy50ZWxlbWV0cnkucmVnaXN0ZXJNZXRyaWNTb3VyY2Uoe1xuICAgICAgY29sbGVjdDogKCkgPT4gdGhpcy5nZXRUZWxlbWV0cnlTbmFwc2hvdCgpLFxuICAgIH0pO1xuICB9XG5cbiAgcmVnaXN0ZXJSb3V0ZShyb3V0ZUtleTogc3RyaW5nLCBvdXRFdmVudHM6IHouWm9kT2JqZWN0KTogdm9pZCB7XG4gICAgdGhpcy5yb3V0ZXMuc2V0KHJvdXRlS2V5LCBvdXRFdmVudHMpO1xuICB9XG5cbiAgcmVwbGFjZVJvdXRlcyhyb3V0ZXM6IFdlYlNvY2tldFJvdXRlRGVmaW5pdGlvbltdKTogdm9pZCB7XG4gICAgdGhpcy5yb3V0ZXMuY2xlYXIoKTtcbiAgICBmb3IgKGNvbnN0IHJvdXRlIG9mIHJvdXRlcykge1xuICAgICAgdGhpcy5yb3V0ZXMuc2V0KHJvdXRlLnJvdXRlS2V5LCByb3V0ZS5vdXRFdmVudHMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDrsJztlokg64W465Oc7JeQ7IScIHJvdXRl67OE66GcIO2VnCDrsogg6rKA7KadwrfsnbjsvZTrlKntlZjqs6AsIOuhnOy7rCBmYW4tb3V07J2AIOymieyLnCDtgZDsl5Ag64Sj64qU64ukLlxuICAgKiDsm5Dqsqkg65287Jqw7YyF6rO8IGNsdXN0ZXIgcHVibGlzaOuKlCDrhbjrk5wg64uo7JyEIOyngeugrCDtgZDsl5DshJwg7LKY66as7ZWc64ukLiDrsJjtmZjtlZwgcHJvbWlzZeuKlCByZWplY3TtlZjsp4Ag7JWK64qU64ukLlxuICAgKi9cbiAgcHVibGlzaFRvQXVkaWVuY2U8RGF0YT4oYXVkaWVuY2U6IFdlYlNvY2tldEF1ZGllbmNlLCBldmVudDogc3RyaW5nLCBkYXRhOiBEYXRhKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBkZWNsYXJlZCA9IGZhbHNlO1xuICAgICAgbGV0IHJlamVjdGVkID0gZmFsc2U7XG4gICAgICBjb25zdCByZWNvcmQgPSAoZW5jb2Rpbmc6IFdlYlNvY2tldEZyYW1lRW5jb2RpbmcpID0+IHtcbiAgICAgICAgaWYgKGVuY29kaW5nLnN0YXR1cyAhPT0gXCJ1bmtub3duRXZlbnRcIikge1xuICAgICAgICAgIGRlY2xhcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5jb2Rpbmcuc3RhdHVzID09PSBcImludmFsaWRQYXlsb2FkXCIpIHtcbiAgICAgICAgICByZWplY3RlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIOydtOuypO2KuOulvCDshKDslrjtlZwgcm91dGXrp4jri6Qg7ZWcIOuyiOunjCDqsoDspp3Ct+yduOy9lOuUqe2VnOuLpC4g7JuQ6rKpIOyImOyLoOyekOuPhCDsnbQgZnJhbWXsnYQg6re464yA66GcIOuwm+uKlOuLpFxuICAgICAgY29uc3Qgcm91dGVGcmFtZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGZvciAoY29uc3QgW3JvdXRlS2V5LCBvdXRFdmVudHNdIG9mIHRoaXMucm91dGVzKSB7XG4gICAgICAgIGNvbnN0IGVuY29kaW5nID0gZW5jb2RlV2ViU29ja2V0RnJhbWUob3V0RXZlbnRzLCBldmVudCwgZGF0YSk7XG4gICAgICAgIHJlY29yZChlbmNvZGluZyk7XG4gICAgICAgIGlmIChlbmNvZGluZy5zdGF0dXMgPT09IFwiZW5jb2RlZFwiKSB7XG4gICAgICAgICAgcm91dGVGcmFtZXNbcm91dGVLZXldID0gZW5jb2RpbmcuZnJhbWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gcm91dGUgdGFibGXsl5Ag7JeG64qUIOuhnOy7rCDsl7DqsrDsnYAg7J6Q6riwIOyKpO2CpOuniOuhnCDsnbjsvZTrlKntlZzri6Qo7Iqk7YKk66eIIOqwneyytOuLuSDtlZwg67KIKVxuICAgICAgY29uc3QgZmFsbGJhY2tFbmNvZGluZ3MgPSBuZXcgTWFwPHouWm9kT2JqZWN0LCBXZWJTb2NrZXRGcmFtZUVuY29kaW5nPigpO1xuICAgICAgY29uc3QgbG9jYWxUYXJnZXRzOiBGYW5PdXRUYXJnZXRbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uIG9mIHRoaXMub3B0aW9ucy5sb2NhbENvbm5lY3Rpb25zLmdldENvbm5lY3Rpb25zKFxuICAgICAgICB0aGlzLm9wdGlvbnMucmVzb2x2ZUxvY2FsU2Vzc2lvbklkcyhhdWRpZW5jZSksXG4gICAgICApKSB7XG4gICAgICAgIGxldCBmcmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoY29ubmVjdGlvbi5yb3V0ZUtleSAhPT0gdW5kZWZpbmVkICYmIHRoaXMucm91dGVzLmhhcyhjb25uZWN0aW9uLnJvdXRlS2V5KSkge1xuICAgICAgICAgIGZyYW1lID0gZ2V0T3duRnJhbWUocm91dGVGcmFtZXMsIGNvbm5lY3Rpb24ucm91dGVLZXkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxldCBlbmNvZGluZyA9IGZhbGxiYWNrRW5jb2RpbmdzLmdldChjb25uZWN0aW9uLm91dEV2ZW50cyk7XG4gICAgICAgICAgaWYgKCFlbmNvZGluZykge1xuICAgICAgICAgICAgZW5jb2RpbmcgPSBlbmNvZGVXZWJTb2NrZXRGcmFtZShjb25uZWN0aW9uLm91dEV2ZW50cywgZXZlbnQsIGRhdGEpO1xuICAgICAgICAgICAgZmFsbGJhY2tFbmNvZGluZ3Muc2V0KGNvbm5lY3Rpb24ub3V0RXZlbnRzLCBlbmNvZGluZyk7XG4gICAgICAgICAgICByZWNvcmQoZW5jb2RpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmcmFtZSA9IGVuY29kaW5nLnN0YXR1cyA9PT0gXCJlbmNvZGVkXCIgPyBlbmNvZGluZy5mcmFtZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOydtOuypO2KuOulvCDshKDslrjtlZjsp4Ag7JWK7JWY6rGw64KYIOqygOymneyXkCDsi6TtjKjtlZwgcm91dGXsnZgg7Jew6rKw7J2AIOuLq+yngCDslYrqs6Ag6rG064SI65u064ukXG4gICAgICAgIGlmIChmcmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbG9jYWxUYXJnZXRzLnB1c2goeyBjb25uZWN0aW9uLCBmcmFtZSB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWRlY2xhcmVkKSB7XG4gICAgICAgIHRoaXMuZW1pdFB1Ymxpc2hSZWplY3RlZChldmVudCwgXCJ1bmtub3duRXZlbnRcIik7XG4gICAgICB9IGVsc2UgaWYgKHJlamVjdGVkKSB7XG4gICAgICAgIHRoaXMuZW1pdFB1Ymxpc2hSZWplY3RlZChldmVudCwgXCJpbnZhbGlkUGF5bG9hZFwiKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5lbnF1ZXVlRmFuT3V0KGxvY2FsVGFyZ2V0cywgZXZlbnQpO1xuXG4gICAgICBpZiAoT2JqZWN0LmtleXMocm91dGVGcmFtZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aGlzLmVtaXRGYW5PdXRSZXNvbHZlZChhdWRpZW5jZSwgbG9jYWxUYXJnZXRzLmxlbmd0aCwgMCk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgIH1cblxuICAgICAgLy8g7JuQ6rKpIOudvOyasO2MhShzdG9yZSDsobDtmowp7J2AIOyVnuyEoCBwdWJsaXNo66W8IOq4sOuLpOumrOyngCDslYrqs6Ag7KeA6riIIOuwlOuhnCDsi5zsnpHtlZzri6QuIHN0b3Jl6rCAIOupiOy2sOuPhCDrsoTsiqTtirgg67mE7Jqp7J20IE7Dl1TqsIAg7JWE64uMIOyVvSBU64ukLlxuICAgICAgLy8g67CY66m0IGVudmVsb3BlIOuwnO2WieydgCDrhbjrk5wg64uo7JyEIO2BkOyXkCDsnbTslrQg67aZ7JesIHB1Ymxpc2gg7Iic7ISc66W8IOyngO2CqOuLpC4g65KkIHB1Ymxpc2jsnZgg65287Jqw7YyF7J20IOuovOyggCDrgZ3rgpjrj4Qg7JWeIOuwnO2WieydhCDquLDri6TrprDri6RcbiAgICAgIGNvbnN0IHJvdXRpbmcgPSB0aGlzLnJlc29sdmVSZW1vdGVOb2RlSWRzKGF1ZGllbmNlLCBldmVudCk7XG4gICAgICBjb25zdCB0YXNrID0gdGhpcy5wdWJsaXNoUXVldWVcbiAgICAgICAgLnRoZW4oKCkgPT4gcm91dGluZylcbiAgICAgICAgLnRoZW4oKHJlbW90ZU5vZGVJZHMpID0+XG4gICAgICAgICAgdGhpcy5wdWJsaXNoUmVtb3RlKGF1ZGllbmNlLCBldmVudCwgcm91dGVGcmFtZXMsIGxvY2FsVGFyZ2V0cy5sZW5ndGgsIHJlbW90ZU5vZGVJZHMpLFxuICAgICAgICApXG4gICAgICAgIC5jYXRjaCgoY2F1c2U6IHVua25vd24pID0+IHtcbiAgICAgICAgICB0aGlzLmVtaXRSb3V0ZUZhaWxlZChldmVudCwgYXVkaWVuY2UsIGNhdXNlKTtcbiAgICAgICAgfSk7XG4gICAgICB0aGlzLnB1Ymxpc2hRdWV1ZSA9IHRhc2s7XG4gICAgICByZXR1cm4gdGFzaztcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgLy8g7Iqk7YKk66eIIHRyYW5zZm9ybSDsmIjsmbgg65OxIOyYiOyDge2VmOyngCDrqrvtlZwg7Iuk7Yyo64+EIO2YuOy2nOyekOyXkOqyjCByZWplY3TroZwg7IOI7KeAIOyViuqyjCDtlZzri6RcbiAgICAgIHRoaXMuZW1pdFJvdXRlRmFpbGVkKGV2ZW50LCBhdWRpZW5jZSwgY2F1c2UpO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOynhO2WiSDspJHsnbggcHVibGlzaCjsm5Dqsqkg7Y+s7ZWoKeyZgCDqtazrj4Ug7Iuc64+E6rCAIOuqqOuRkCDrgZ3rgpjrqbQgcmVzb2x2Ze2VnOuLpFxuICBhc3luYyBkcmFpblB1Ymxpc2hlcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wdWJsaXNoUXVldWUsIHRoaXMuc3Vic2NyaXB0aW9uXSk7XG4gIH1cblxuICAvKipcbiAgICog6rWs64+F7J2EIO2VtOygnO2VmOqzoCBjbHVzdGVyIGJ1c+ulvCDsooXro4ztlZzri6QuIOq1rOuPheydtCBkZWFkbGluZeq5jOyngCDrgZ3rgpjsp4Ag7JWK7Jy866m0IOuKpuqyjCDrgZ3rgqAg65WMIO2VtOygnO2VnOuLpC5cbiAgICovXG4gIGFzeW5jIHNodXRkb3duKGRlYWRsaW5lOiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zdG9wcGVkID0gdHJ1ZTtcbiAgICB0aGlzLnVucmVnaXN0ZXJNZXRyaWNTb3VyY2UoKTtcblxuICAgIGNvbnN0IHVuc3Vic2NyaWJlID0gYXdhaXQgUHJvbWlzZS5yYWNlKFt0aGlzLnN1YnNjcmlwdGlvbiwgZGVhZGxpbmUudGhlbigoKSA9PiBudWxsKV0pO1xuICAgIGlmICh1bnN1YnNjcmliZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb24udGhlbigobGF0ZVVuc3Vic2NyaWJlKSA9PiB7XG4gICAgICAgIHRoaXMuc2FmZVVuc3Vic2NyaWJlKGxhdGVVbnN1YnNjcmliZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zYWZlVW5zdWJzY3JpYmUodW5zdWJzY3JpYmUpO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHRoaXMub3B0aW9ucy5jbHVzdGVyQnVzLnNodXRkb3duKCkpO1xuICAgIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLnNodXRkb3duLmZhaWxlZFwiLFxuICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICBkZXRhaWw6IHsgZXJyb3JUeXBlOiBkZXNjcmliZUVycm9yKGNhdXNlKSB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0VGVsZW1ldHJ5U25hcHNob3QoKSB7XG4gICAgbGV0IHBlbmRpbmdGYW5PdXRUYXJnZXRzID0gMDtcblxuICAgIGZvciAoY29uc3Qgam9iIG9mIHRoaXMucGVuZGluZ0Zhbk91dEpvYnMpIHtcbiAgICAgIHBlbmRpbmdGYW5PdXRUYXJnZXRzICs9IE1hdGgubWF4KGpvYi50YXJnZXRzLmxlbmd0aCAtIGpvYi5jdXJzb3IsIDApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwZW5kaW5nRmFuT3V0Sm9iczogdGhpcy5wZW5kaW5nRmFuT3V0Sm9icy5sZW5ndGgsXG4gICAgICBwZW5kaW5nRmFuT3V0VGFyZ2V0cyxcbiAgICB9O1xuICB9XG5cbiAgLy8g6rWs64+FIOyLpO2MqOuKlCDroZzsu6wg7KCE7JqpIOuPmeyekeycvOuhnCDsiJjroLTsi5ztgqTqs6AgdGVsZW1ldHJ566eMIOuCqOq4tOuLpFxuICBwcml2YXRlIHN1YnNjcmliZSgpOiBQcm9taXNlPFVuc3Vic2NyaWJlIHwgdW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbigoKSA9PlxuICAgICAgICB0aGlzLm9wdGlvbnMuY2x1c3RlckJ1cy5zdWJzY3JpYmUoKGVudmVsb3BlKSA9PiB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVDbHVzdGVyRW52ZWxvcGUoZW52ZWxvcGUpO1xuICAgICAgICB9KSxcbiAgICAgIClcbiAgICAgIC50aGVuKFxuICAgICAgICAodW5zdWJzY3JpYmUpID0+IHVuc3Vic2NyaWJlLFxuICAgICAgICAoY2F1c2U6IHVua25vd24pID0+IHtcbiAgICAgICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgICAgIG5hbWU6IFwid3MuY2x1c3Rlci5zdWJzY3JpYmUuZmFpbGVkXCIsXG4gICAgICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICAgICAgZGV0YWlsOiB7IGVycm9yVHlwZTogZGVzY3JpYmVFcnJvcihjYXVzZSkgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9LFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2FmZVVuc3Vic2NyaWJlKHVuc3Vic2NyaWJlOiBVbnN1YnNjcmliZSB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB1bnN1YnNjcmliZT8uKCk7XG4gICAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgICBuYW1lOiBcIndzLmNsdXN0ZXIudW5zdWJzY3JpYmUuZmFpbGVkXCIsXG4gICAgICAgIGxldmVsOiBcImVycm9yXCIsXG4gICAgICAgIGRldGFpbDogeyBlcnJvclR5cGU6IGRlc2NyaWJlRXJyb3IoY2F1c2UpIH0sXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvLyDrnbzsmrDtjIUg7Iuk7Yyo64qUIOyXrOq4sOyEnCB0ZWxlbWV0cnnroZwg67CU6r+UIHVuZGVmaW5lZOulvCDrj4zroKTspIDri6QuIOymieyLnCBjYXRjaOulvCDrtpnsnbTrr4DroZwg7YGQIOywqOuhgOulvCDquLDri6TrpqzripQg64+Z7JWI7JeQ64+EIHVuaGFuZGxlZCByZWplY3Rpb27snbQg7IOd6riw7KeAIOyViuuKlOuLpFxuICBwcml2YXRlIHJlc29sdmVSZW1vdGVOb2RlSWRzKFxuICAgIGF1ZGllbmNlOiBXZWJTb2NrZXRBdWRpZW5jZSxcbiAgICBldmVudDogc3RyaW5nLFxuICApOiBQcm9taXNlPHN0cmluZ1tdIHwgdW5kZWZpbmVkPiB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5hdWRpZW5jZVJlc29sdmVyLnJlc29sdmVSZW1vdGVOb2RlSWRzKGF1ZGllbmNlKS5jYXRjaCgoY2F1c2U6IHVua25vd24pID0+IHtcbiAgICAgIHRoaXMuZW1pdFJvdXRlRmFpbGVkKGV2ZW50LCBhdWRpZW5jZSwgY2F1c2UpO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcHVibGlzaFJlbW90ZShcbiAgICBhdWRpZW5jZTogV2ViU29ja2V0QXVkaWVuY2UsXG4gICAgZXZlbnQ6IHN0cmluZyxcbiAgICBmcmFtZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICAgbG9jYWxUYXJnZXRDb3VudDogbnVtYmVyLFxuICAgIHJlc29sdmVkTm9kZUlkczogc3RyaW5nW10gfCB1bmRlZmluZWQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIOudvOyasO2MhSDsi6TtjKgodW5kZWZpbmVkKSDsi5wg66Gc7LusIOyghOuLrOydgCDsnbTrr7gg64Gd64Ks7Jy866+A66GcIOydtCBwdWJsaXNo7J2YIOybkOqyqSBlbnZlbG9wZeunjCDqsbTrhIjrm7Tri6RcbiAgICBjb25zdCByZW1vdGVOb2RlSWRzID0gcmVzb2x2ZWROb2RlSWRzID8/IFtdO1xuICAgIHRoaXMuZW1pdEZhbk91dFJlc29sdmVkKGF1ZGllbmNlLCBsb2NhbFRhcmdldENvdW50LCByZW1vdGVOb2RlSWRzLmxlbmd0aCk7XG4gICAgaWYgKHJlbW90ZU5vZGVJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZW52ZWxvcGU6IFdlYlNvY2tldENsdXN0ZXJFbnZlbG9wZSA9IHtcbiAgICAgIGlkOiByYW5kb21VVUlEKCksXG4gICAgICBzb3VyY2VOb2RlSWQ6IHRoaXMub3B0aW9ucy5ub2RlSWQsXG4gICAgICB0YXJnZXROb2RlSWRzOiByZW1vdGVOb2RlSWRzLFxuICAgICAgYXVkaWVuY2UsXG4gICAgICBldmVudCxcbiAgICAgIGZyYW1lcyxcbiAgICAgIGVtaXR0ZWRBdDogRGF0ZS5ub3coKSxcbiAgICB9O1xuXG4gICAgY29uc3QgcHVibGlzaFN0YXJ0ZWRBdCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHRoaXMub3B0aW9ucy5jbHVzdGVyQnVzLnB1Ymxpc2goZW52ZWxvcGUpKTtcbiAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHB1Ymxpc2hTdGFydGVkQXQ7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLmVudmVsb3BlLnB1Ymxpc2hlZFwiLFxuICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICBkZXRhaWw6IHsgZXZlbnQsIHRhcmdldE5vZGVDb3VudDogcmVtb3RlTm9kZUlkcy5sZW5ndGggfSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy50ZWxlbWV0cnkucmVjb3JkU3Bhbih7XG4gICAgICAgIG9wZXJhdGlvbk5hbWU6IFwid3MuY2x1c3Rlci5wdWJsaXNoXCIsXG4gICAgICAgIGtpbmQ6IFwicHJvZHVjZXJcIixcbiAgICAgICAgZHVyYXRpb25NcyxcbiAgICAgICAgc3RhdHVzOiBcInVuc2V0XCIsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICBldmVudCxcbiAgICAgICAgICB0YXJnZXROb2RlQ291bnQ6IHJlbW90ZU5vZGVJZHMubGVuZ3RoLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHB1Ymxpc2hTdGFydGVkQXQ7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLmVudmVsb3BlLmZhaWxlZFwiLFxuICAgICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgICBkZXRhaWw6IHsgZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy50ZWxlbWV0cnkucmVjb3JkU3Bhbih7XG4gICAgICAgIG9wZXJhdGlvbk5hbWU6IFwid3MuY2x1c3Rlci5wdWJsaXNoXCIsXG4gICAgICAgIGtpbmQ6IFwicHJvZHVjZXJcIixcbiAgICAgICAgZHVyYXRpb25NcyxcbiAgICAgICAgc3RhdHVzOiBcImVycm9yXCIsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHsgZXZlbnQgfSxcbiAgICAgICAgZXJyb3JUeXBlOiBkZXNjcmliZUVycm9yKGNhdXNlKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIOyImOyLoCDrhbjrk5zripQgc3RvcmUg7JeG7J20IOyekOq4sCDrqZTrqqjrpqzroZwgYXVkaWVuY2Xrpbwg7ZW07ISd7ZWY6rOgLCDqsIEg7Jew6rKw7J2YIHJvdXRlIGZyYW1l7J2EIOyerOqygOymnSDsl4bsnbQg6re464yA66GcIOuztOuCuOuLpFxuICBwcml2YXRlIGhhbmRsZUNsdXN0ZXJFbnZlbG9wZShlbnZlbG9wZTogV2ViU29ja2V0Q2x1c3RlckVudmVsb3BlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc3RvcHBlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChlbnZlbG9wZS5zb3VyY2VOb2RlSWQgPT09IHRoaXMub3B0aW9ucy5ub2RlSWQpIHtcbiAgICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgICBuYW1lOiBcIndzLmNsdXN0ZXIuZW52ZWxvcGUuaWdub3JlZFwiLFxuICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICBkZXRhaWw6IHsgcmVhc29uOiBcInNlbGZTb3VyY2VcIiwgZXZlbnQ6IGVudmVsb3BlLmV2ZW50IH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBlbnZlbG9wZS50YXJnZXROb2RlSWRzLmxlbmd0aCA+IDAgJiZcbiAgICAgICFlbnZlbG9wZS50YXJnZXROb2RlSWRzLmluY2x1ZGVzKHRoaXMub3B0aW9ucy5ub2RlSWQpXG4gICAgKSB7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLmVudmVsb3BlLmlnbm9yZWRcIixcbiAgICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgICAgZGV0YWlsOiB7IHJlYXNvbjogXCJ0YXJnZXRNaXNtYXRjaFwiLCBldmVudDogZW52ZWxvcGUuZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YXJ0ZWRBdCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgbmFtZTogXCJ3cy5jbHVzdGVyLmVudmVsb3BlLnJlY2VpdmVkXCIsXG4gICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgZGV0YWlsOiB7IGV2ZW50OiBlbnZlbG9wZS5ldmVudCwgc291cmNlTm9kZUlkOiBlbnZlbG9wZS5zb3VyY2VOb2RlSWQgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGxvY2FsVGFyZ2V0czogRmFuT3V0VGFyZ2V0W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb24gb2YgdGhpcy5vcHRpb25zLmxvY2FsQ29ubmVjdGlvbnMuZ2V0Q29ubmVjdGlvbnMoXG4gICAgICB0aGlzLm9wdGlvbnMucmVzb2x2ZUxvY2FsU2Vzc2lvbklkcyhlbnZlbG9wZS5hdWRpZW5jZSksXG4gICAgKSkge1xuICAgICAgY29uc3QgZnJhbWUgPVxuICAgICAgICBjb25uZWN0aW9uLnJvdXRlS2V5ID09PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgIDogZ2V0T3duRnJhbWUoZW52ZWxvcGUuZnJhbWVzLCBjb25uZWN0aW9uLnJvdXRlS2V5KTtcbiAgICAgIGlmIChmcmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxvY2FsVGFyZ2V0cy5wdXNoKHsgY29ubmVjdGlvbiwgZnJhbWUgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuZW5xdWV1ZUZhbk91dChsb2NhbFRhcmdldHMsIGVudmVsb3BlLmV2ZW50KTtcblxuICAgIHRoaXMudGVsZW1ldHJ5LnJlY29yZFNwYW4oe1xuICAgICAgb3BlcmF0aW9uTmFtZTogXCJ3cy5jbHVzdGVyLnJlY2VpdmVcIixcbiAgICAgIGtpbmQ6IFwiY29uc3VtZXJcIixcbiAgICAgIGR1cmF0aW9uTXM6IHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRlZEF0LFxuICAgICAgc3RhdHVzOiBcInVuc2V0XCIsXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgIGV2ZW50OiBlbnZlbG9wZS5ldmVudCxcbiAgICAgICAgc291cmNlTm9kZUlkOiBlbnZlbG9wZS5zb3VyY2VOb2RlSWQsXG4gICAgICAgIGxvY2FsVGFyZ2V0Q291bnQ6IGxvY2FsVGFyZ2V0cy5sZW5ndGgsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0UHVibGlzaFJlamVjdGVkKGV2ZW50OiBzdHJpbmcsIHJlYXNvbjogXCJ1bmtub3duRXZlbnRcIiB8IFwiaW52YWxpZFBheWxvYWRcIik6IHZvaWQge1xuICAgIHRoaXMudGVsZW1ldHJ5LmVtaXQoe1xuICAgICAgbmFtZTogXCJ3cy5wdWJsaXNoLnJlamVjdGVkXCIsXG4gICAgICBsZXZlbDogXCJlcnJvclwiLFxuICAgICAgZGV0YWlsOiB7IGV2ZW50LCByZWFzb24gfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdFJvdXRlRmFpbGVkKGV2ZW50OiBzdHJpbmcsIGF1ZGllbmNlOiBXZWJTb2NrZXRBdWRpZW5jZSwgY2F1c2U6IHVua25vd24pOiB2b2lkIHtcbiAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgIG5hbWU6IFwid3MuZmFub3V0LnJvdXRlLmZhaWxlZFwiLFxuICAgICAgbGV2ZWw6IFwiZXJyb3JcIixcbiAgICAgIGRldGFpbDogeyBldmVudCwgYXVkaWVuY2VUeXBlOiBhdWRpZW5jZS50eXBlLCBlcnJvclR5cGU6IGRlc2NyaWJlRXJyb3IoY2F1c2UpIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGVtaXRGYW5PdXRSZXNvbHZlZChcbiAgICBhdWRpZW5jZTogV2ViU29ja2V0QXVkaWVuY2UsXG4gICAgbG9jYWxUYXJnZXRDb3VudDogbnVtYmVyLFxuICAgIHJlbW90ZU5vZGVDb3VudDogbnVtYmVyLFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgIG5hbWU6IFwid3MuZmFub3V0LnJlc29sdmVkXCIsXG4gICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgZGV0YWlsOiB7IGxvY2FsVGFyZ2V0Q291bnQsIHJlbW90ZU5vZGVDb3VudCB9LFxuICAgIH0pO1xuICAgIHRoaXMudGVsZW1ldHJ5LnJlY29yZE1ldHJpYyh7XG4gICAgICBuYW1lOiBcInNvbmFtdS53cy5mYW5vdXQudGFyZ2V0c1wiLFxuICAgICAga2luZDogXCJoaXN0b2dyYW1cIixcbiAgICAgIHZhbHVlOiBsb2NhbFRhcmdldENvdW50ICsgcmVtb3RlTm9kZUNvdW50LFxuICAgICAgdW5pdDogXCIxXCIsXG4gICAgICB0YWdzOiB7IGF1ZGllbmNlX3R5cGU6IGF1ZGllbmNlLnR5cGUgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZW5xdWV1ZUZhbk91dCh0YXJnZXRzOiBGYW5PdXRUYXJnZXRbXSwgZXZlbnQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0YXJnZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMucGVuZGluZ0Zhbk91dEpvYnMucHVzaCh7XG4gICAgICB0YXJnZXRzLFxuICAgICAgZXZlbnQsXG4gICAgICBjdXJzb3I6IDAsXG4gICAgfSk7XG4gICAgdGhpcy50ZWxlbWV0cnkuZW1pdCh7XG4gICAgICBuYW1lOiBcIndzLmZhbm91dC5lbnF1ZXVlZFwiLFxuICAgICAgbGV2ZWw6IFwiZGVidWdcIixcbiAgICAgIGRldGFpbDogeyB0YXJnZXRDb3VudDogdGFyZ2V0cy5sZW5ndGgsIGV2ZW50IH0sXG4gICAgfSk7XG4gICAgdGhpcy5zY2hlZHVsZUZhbk91dEZsdXNoKCk7XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlRmFuT3V0Rmx1c2goKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmFuT3V0Rmx1c2hTY2hlZHVsZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmZhbk91dEZsdXNoU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgdGhpcy5mYW5PdXRGbHVzaFNjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5mbHVzaEZhbk91dEpvYnMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZmx1c2hGYW5PdXRKb2JzKCk6IHZvaWQge1xuICAgIGNvbnN0IHN0YXJ0ZWRBdCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIGxldCBwcm9jZXNzZWQgPSAwO1xuICAgIGxldCBzdGF0dXM6IFwidW5zZXRcIiB8IFwiZXJyb3JcIiA9IFwidW5zZXRcIjtcbiAgICBsZXQgZXJyb3JUeXBlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgd2hpbGUgKHRoaXMucGVuZGluZ0Zhbk91dEpvYnMubGVuZ3RoID4gMCAmJiBwcm9jZXNzZWQgPCBGQU5fT1VUX0JBVENIX1NJWkUpIHtcbiAgICAgICAgY29uc3Qgam9iID0gdGhpcy5wZW5kaW5nRmFuT3V0Sm9ic1swXTtcblxuICAgICAgICB3aGlsZSAoam9iLmN1cnNvciA8IGpvYi50YXJnZXRzLmxlbmd0aCAmJiBwcm9jZXNzZWQgPCBGQU5fT1VUX0JBVENIX1NJWkUpIHtcbiAgICAgICAgICB0aGlzLnNhZmVTZW5kKGpvYi50YXJnZXRzW2pvYi5jdXJzb3JdLCBqb2IuZXZlbnQpO1xuICAgICAgICAgIGpvYi5jdXJzb3IgKz0gMTtcbiAgICAgICAgICBwcm9jZXNzZWQgKz0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChqb2IuY3Vyc29yID49IGpvYi50YXJnZXRzLmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMucGVuZGluZ0Zhbk91dEpvYnMuc2hpZnQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBzdGF0dXMgPSBcImVycm9yXCI7XG4gICAgICBlcnJvclR5cGUgPSBkZXNjcmliZUVycm9yKGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBjb25zdCBkdXJhdGlvbk1zID0gcGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydGVkQXQ7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5mYW5vdXQuZmx1c2hlZFwiLFxuICAgICAgICBsZXZlbDogXCJkZWJ1Z1wiLFxuICAgICAgICBkZXRhaWw6IHsgcHJvY2Vzc2VkQ291bnQ6IHByb2Nlc3NlZCB9LFxuICAgICAgfSk7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5yZWNvcmRTcGFuKHtcbiAgICAgICAgb3BlcmF0aW9uTmFtZTogXCJ3cy5mYW5vdXQuZGlzcGF0Y2hcIixcbiAgICAgICAga2luZDogXCJpbnRlcm5hbFwiLFxuICAgICAgICBkdXJhdGlvbk1zLFxuICAgICAgICBzdGF0dXMsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHsgcHJvY2Vzc2VkQ291bnQ6IHByb2Nlc3NlZCB9LFxuICAgICAgICBlcnJvclR5cGUsXG4gICAgICB9KTtcblxuICAgICAgaWYgKHRoaXMucGVuZGluZ0Zhbk91dEpvYnMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlRmFuT3V0Rmx1c2goKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNhZmVTZW5kKHRhcmdldDogRmFuT3V0VGFyZ2V0LCBldmVudDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgeyBjb25uZWN0aW9uLCBmcmFtZSB9ID0gdGFyZ2V0O1xuICAgIHRyeSB7XG4gICAgICBpZiAoIWNvbm5lY3Rpb24uY2xvc2VkKSB7XG4gICAgICAgIGNvbm5lY3Rpb24uc2VuZEZyYW1lKGV2ZW50LCBmcmFtZSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aGlzLnRlbGVtZXRyeS5lbWl0KHtcbiAgICAgICAgbmFtZTogXCJ3cy5mYW5vdXQucHVibGlzaC5mYWlsZWRcIixcbiAgICAgICAgbGV2ZWw6IFwiZXJyb3JcIixcbiAgICAgICAgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmlkLFxuICAgICAgICBuYW1lc3BhY2U6IGNvbm5lY3Rpb24ubmFtZXNwYWNlLFxuICAgICAgICB1c2VySWQ6IGNvbm5lY3Rpb24udXNlcklkLFxuICAgICAgICBkZXRhaWw6IHsgZXZlbnQgfSxcbiAgICAgIH0pO1xuICAgICAgY29ubmVjdGlvbi5jbG9zZSgxMDExLCBcIldlYlNvY2tldCBwdWJsaXNoIGZhaWxlZFwiKTtcbiAgICB9XG4gIH1cbn1cblxuLy8g7JuQ6rKp7JeQ7IScIOyYqCBmcmFtZXPripQgcHJvdG90eXBlIO2CpOulvCDrrLTsi5ztlZjqs6Ag7J6Q6riwIOyGjeyEseunjCDsnb3ripTri6RcbmZ1bmN0aW9uIGdldE93bkZyYW1lKGZyYW1lczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgcm91dGVLZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBPYmplY3QuaGFzT3duKGZyYW1lcywgcm91dGVLZXkpID8gZnJhbWVzW3JvdXRlS2V5XSA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZGVzY3JpYmVFcnJvcihjYXVzZTogdW5rbm93bik6IHN0cmluZyB7XG4gIHJldHVybiBjYXVzZSBpbnN0YW5jZW9mIEVycm9yID8gY2F1c2UubmFtZSA6IHJ1bnRpbWVUeXBlT2YoY2F1c2UpO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUEwZkEsU0FBUyxZQUFZLFFBQWdDLFVBQXNDO0NBQ3pGLE9BQU8sT0FBTyxPQUFPLFFBQVEsUUFBUSxJQUFJLE9BQU8sWUFBWTtBQUM5RDtBQUVBLFNBQVMsY0FBYyxPQUF3QjtDQUM3QyxPQUFPLGlCQUFpQixRQUFRLE1BQU0sT0FBTyxjQUFjLEtBQUs7QUFDbEU7OztDQTVmK0Msa0JBQUE7Q0FLK0IsY0FBQTtDQUt2RCxrQkFBQTtDQUdqQixxQkFBcUI7Q0FvQmQsMEJBQWIsTUFBcUM7RUFhaEI7RUFabkIsb0JBQWtELENBQUM7RUFDbkQsdUJBQStCO0VBRS9CLHlCQUEwQixJQUFJLElBQXlCO0VBRXZELGVBQXNDLFFBQVEs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
@@ -0,0 +1,15 @@
1
+ import { type z } from "zod";
2
+ export type WebSocketFrameEncoding = {
3
+ status: "encoded";
4
+ frame: string;
5
+ } | {
6
+ status: "unknownEvent";
7
+ } | {
8
+ status: "invalidPayload";
9
+ };
10
+ /**
11
+ * outEvents 스키마로 payload를 검증하고 `{event, data}` frame 문자열로 인코딩한다.
12
+ * 같은 스키마로 인코딩한 frame은 로컬·원격 수신자 모두에게 같은 바이트로 전달된다.
13
+ */
14
+ export declare function encodeWebSocketFrame<Data>(outEvents: z.ZodObject, event: string, data: Data): WebSocketFrameEncoding;
15
+ //# sourceMappingURL=ws-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-frame.d.ts","sourceRoot":"","sources":["../../src/stream/ws-frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,cAAc,CAAA;CAAE,GAC1B;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEjC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EACvC,SAAS,EAAE,CAAC,CAAC,SAAS,EACtB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,GACT,sBAAsB,CAkBxB"}
@@ -0,0 +1,28 @@
1
+ import { __esmMin } from "../_virtual/_rolldown/runtime.js";
2
+ // src/stream/ws-frame.ts
3
+ /**
4
+ * outEvents 스키마로 payload를 검증하고 `{event, data}` frame 문자열로 인코딩한다.
5
+ * 같은 스키마로 인코딩한 frame은 로컬·원격 수신자 모두에게 같은 바이트로 전달된다.
6
+ */
7
+ function encodeWebSocketFrame(outEvents, event, data) {
8
+ const schema = getEventSchema(outEvents, event);
9
+ if (!schema) return { status: "unknownEvent" };
10
+ const parsed = schema.safeParse(data);
11
+ if (!parsed.success) return { status: "invalidPayload" };
12
+ return {
13
+ status: "encoded",
14
+ frame: JSON.stringify({
15
+ event,
16
+ data: parsed.data
17
+ })
18
+ };
19
+ }
20
+ function getEventSchema(outEvents, event) {
21
+ const eventSchemas = outEvents["shape"];
22
+ return Object.hasOwn(eventSchemas, event) ? eventSchemas[event] : void 0;
23
+ }
24
+ var init_ws_frame = __esmMin((() => {}));
25
+ init_ws_frame();
26
+ export { encodeWebSocketFrame, init_ws_frame };
27
+
28
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtZnJhbWUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmVhbS93cy1mcmFtZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIHogfSBmcm9tIFwiem9kXCI7XG5cbmV4cG9ydCB0eXBlIFdlYlNvY2tldEZyYW1lRW5jb2RpbmcgPVxuICB8IHsgc3RhdHVzOiBcImVuY29kZWRcIjsgZnJhbWU6IHN0cmluZyB9XG4gIHwgeyBzdGF0dXM6IFwidW5rbm93bkV2ZW50XCIgfVxuICB8IHsgc3RhdHVzOiBcImludmFsaWRQYXlsb2FkXCIgfTtcblxuLyoqXG4gKiBvdXRFdmVudHMg7Iqk7YKk66eI66GcIHBheWxvYWTrpbwg6rKA7Kad7ZWY6rOgIGB7ZXZlbnQsIGRhdGF9YCBmcmFtZSDrrLjsnpDsl7TroZwg7J247L2U65Sp7ZWc64ukLlxuICog6rCZ7J2AIOyKpO2CpOuniOuhnCDsnbjsvZTrlKntlZwgZnJhbWXsnYAg66Gc7Luswrfsm5Dqsqkg7IiY7Iug7J6QIOuqqOuRkOyXkOqyjCDqsJnsnYAg67CU7J207Yq466GcIOyghOuLrOuQnOuLpC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZVdlYlNvY2tldEZyYW1lPERhdGE+KFxuICBvdXRFdmVudHM6IHouWm9kT2JqZWN0LFxuICBldmVudDogc3RyaW5nLFxuICBkYXRhOiBEYXRhLFxuKTogV2ViU29ja2V0RnJhbWVFbmNvZGluZyB7XG4gIGNvbnN0IHNjaGVtYSA9IGdldEV2ZW50U2NoZW1hKG91dEV2ZW50cywgZXZlbnQpO1xuICBpZiAoIXNjaGVtYSkge1xuICAgIHJldHVybiB7IHN0YXR1czogXCJ1bmtub3duRXZlbnRcIiB9O1xuICB9XG5cbiAgY29uc3QgcGFyc2VkID0gc2NoZW1hLnNhZmVQYXJzZShkYXRhKTtcbiAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgIHJldHVybiB7IHN0YXR1czogXCJpbnZhbGlkUGF5bG9hZFwiIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHN0YXR1czogXCJlbmNvZGVkXCIsXG4gICAgZnJhbWU6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIGV2ZW50LFxuICAgICAgZGF0YTogcGFyc2VkLmRhdGEsXG4gICAgfSksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldEV2ZW50U2NoZW1hKG91dEV2ZW50czogei5ab2RPYmplY3QsIGV2ZW50OiBzdHJpbmcpOiB6LlpvZFR5cGUgfCB1bmRlZmluZWQge1xuICBjb25zdCBldmVudFNjaGVtYXM6IFJlY29yZDxzdHJpbmcsIHouWm9kVHlwZT4gPSBvdXRFdmVudHNbXCJzaGFwZVwiXTtcbiAgcmV0dXJuIE9iamVjdC5oYXNPd24oZXZlbnRTY2hlbWFzLCBldmVudCkgPyBldmVudFNjaGVtYXNbZXZlbnRdIDogdW5kZWZpbmVkO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFXQSxTQUFnQixxQkFDZCxXQUNBLE9BQ0EsTUFDd0I7Q0FDeEIsTUFBTSxTQUFTLGVBQWUsV0FBVyxLQUFLO0NBQzlDLElBQUksQ0FBQyxRQUNILE9BQU8sRUFBRSxRQUFRLGVBQWU7Q0FHbEMsTUFBTSxTQUFTLE9BQU8sVUFBVSxJQUFJO0NBQ3BDLElBQUksQ0FBQyxPQUFPLFNBQ1YsT0FBTyxFQUFFLFFBQVEsaUJBQWlCO0NBR3BDLE9BQU87RUFDTCxRQUFRO0VBQ1IsT0FBTyxLQUFLLFVBQVU7R0FDcEI7R0FDQSxNQUFNLE9BQU87RUFDZixDQUFDO0NBQ0g7QUFDRjtBQUVBLFNBQVMsZUFBZSxXQUF3QixPQUFzQztDQUNwRixNQUFNLGVBQTBDLFVBQVU7Q0FDMUQsT0FBTyxPQUFPLE9BQU8sY0FBYyxLQUFLLElBQUksYUFBYSxTQUFTO0FBQ3BFIn0=
@@ -1,11 +1,11 @@
1
- import { type ManagedWebSocketConnection } from "./ws-core";
1
+ import { type WebSocketFrameConnection } from "./ws-core";
2
2
  import { type WebSocketTelemetryConnectionSnapshot } from "./ws-telemetry";
3
3
  export declare class WebSocketLocalConnectionStore {
4
4
  private readonly connections;
5
- register(connection: ManagedWebSocketConnection): void;
5
+ register(connection: WebSocketFrameConnection): void;
6
6
  unregister(connectionId: string): void;
7
- getConnection(connectionId: string): ManagedWebSocketConnection | undefined;
8
- getConnections(connectionIds: string[]): ManagedWebSocketConnection[];
7
+ getConnection(connectionId: string): WebSocketFrameConnection | undefined;
8
+ getConnections(connectionIds: string[]): WebSocketFrameConnection[];
9
9
  getTelemetrySnapshot(): WebSocketTelemetryConnectionSnapshot;
10
10
  closeAll(code?: number, reason?: string): void;
11
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ws-local-connection-store.d.ts","sourceRoot":"","sources":["../../src/stream/ws-local-connection-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EACL,KAAK,oCAAoC,EAE1C,MAAM,gBAAgB,CAAC;AAExB,qBAAa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiD;IAE7E,QAAQ,CAAC,UAAU,EAAE,0BAA0B,GAAG,IAAI,CAErD;IAED,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAErC;IAED,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CAE1E;IAED,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,0BAA0B,EAAE,CAmBpE;IAED,oBAAoB,IAAI,oCAAoC,CAmB3D;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAI7C;CACF"}
1
+ {"version":3,"file":"ws-local-connection-store.d.ts","sourceRoot":"","sources":["../../src/stream/ws-local-connection-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EACL,KAAK,oCAAoC,EAE1C,MAAM,gBAAgB,CAAC;AAExB,qBAAa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+C;IAE3E,QAAQ,CAAC,UAAU,EAAE,wBAAwB,GAAG,IAAI,CAEnD;IAED,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAErC;IAED,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAExE;IAED,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,wBAAwB,EAAE,CAmBlE;IAED,oBAAoB,IAAI,oCAAoC,CAmB3D;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAK7C;CACF"}
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "../_virtual/_rolldown/runtime.js";
2
2
  import { init_runtime_value, isFunctionValue } from "../utils/runtime-value.js";
3
- //#region src/stream/ws-local-connection-store.ts
3
+ // src/stream/ws-local-connection-store.ts
4
4
  function isTelemetryInspectableConnection(connection) {
5
5
  return "getTelemetrySnapshot" in connection && isFunctionValue(connection.getTelemetrySnapshot);
6
6
  }
@@ -46,12 +46,11 @@ var init_ws_local_connection_store = __esmMin((() => {
46
46
  return snapshot;
47
47
  }
48
48
  closeAll(code, reason) {
49
- for (const connection of this.connections.values()) connection.close(code, reason);
49
+ for (const connection of Array.from(this.connections.values())) connection.close(code, reason);
50
50
  }
51
51
  };
52
52
  }));
53
- //#endregion
54
53
  init_ws_local_connection_store();
55
54
  export { WebSocketLocalConnectionStore, init_ws_local_connection_store };
56
55
 
57
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtbG9jYWwtY29ubmVjdGlvbi1zdG9yZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWFtL3dzLWxvY2FsLWNvbm5lY3Rpb24tc3RvcmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNGdW5jdGlvblZhbHVlIH0gZnJvbSBcIi4uL3V0aWxzL3J1bnRpbWUtdmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgTWFuYWdlZFdlYlNvY2tldENvbm5lY3Rpb24gfSBmcm9tIFwiLi93cy1jb3JlXCI7XG5pbXBvcnQge1xuICB0eXBlIFdlYlNvY2tldFRlbGVtZXRyeUNvbm5lY3Rpb25TbmFwc2hvdCxcbiAgdHlwZSBUZWxlbWV0cnlJbnNwZWN0YWJsZUNvbm5lY3Rpb24sXG59IGZyb20gXCIuL3dzLXRlbGVtZXRyeVwiO1xuXG5leHBvcnQgY2xhc3MgV2ViU29ja2V0TG9jYWxDb25uZWN0aW9uU3RvcmUge1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbm5lY3Rpb25zID0gbmV3IE1hcDxzdHJpbmcsIE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uPigpO1xuXG4gIHJlZ2lzdGVyKGNvbm5lY3Rpb246IE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5jb25uZWN0aW9ucy5zZXQoY29ubmVjdGlvbi5pZCwgY29ubmVjdGlvbik7XG4gIH1cblxuICB1bnJlZ2lzdGVyKGNvbm5lY3Rpb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb25uZWN0aW9ucy5kZWxldGUoY29ubmVjdGlvbklkKTtcbiAgfVxuXG4gIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcpOiBNYW5hZ2VkV2ViU29ja2V0Q29ubmVjdGlvbiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk7XG4gIH1cblxuICBnZXRDb25uZWN0aW9ucyhjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSk6IE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uW10ge1xuICAgIGNvbnN0IHRhcmdldHM6IE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uW10gPSBbXTtcbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBvZiBjb25uZWN0aW9uSWRzKSB7XG4gICAgICBpZiAoc2Vlbi5oYXMoY29ubmVjdGlvbklkKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHNlZW4uYWRkKGNvbm5lY3Rpb25JZCk7XG5cbiAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLmNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpO1xuICAgICAgaWYgKCFjb25uZWN0aW9uIHx8IGNvbm5lY3Rpb24uY2xvc2VkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB0YXJnZXRzLnB1c2goY29ubmVjdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhcmdldHM7XG4gIH1cblxuICBnZXRUZWxlbWV0cnlTbmFwc2hvdCgpOiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uU25hcHNob3Qge1xuICAgIGNvbnN0IHNuYXBzaG90OiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uU25hcHNob3QgPSB7XG4gICAgICBwZW5kaW5nSW5ib3VuZE1lc3NhZ2VzOiAwLFxuICAgICAgcGVuZGluZ091dGJvdW5kTWVzc2FnZXM6IDAsXG4gICAgICBzb2NrZXRCdWZmZXJlZEJ5dGVzOiAwLFxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb24gb2YgdGhpcy5jb25uZWN0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgaWYgKCFpc1RlbGVtZXRyeUluc3BlY3RhYmxlQ29ubmVjdGlvbihjb25uZWN0aW9uKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29ubmVjdGlvblNuYXBzaG90ID0gY29ubmVjdGlvbi5nZXRUZWxlbWV0cnlTbmFwc2hvdCgpO1xuICAgICAgc25hcHNob3QucGVuZGluZ0luYm91bmRNZXNzYWdlcyArPSBjb25uZWN0aW9uU25hcHNob3QucGVuZGluZ0luYm91bmRNZXNzYWdlcztcbiAgICAgIHNuYXBzaG90LnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzICs9IGNvbm5lY3Rpb25TbmFwc2hvdC5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcztcbiAgICAgIHNuYXBzaG90LnNvY2tldEJ1ZmZlcmVkQnl0ZXMgKz0gY29ubmVjdGlvblNuYXBzaG90LnNvY2tldEJ1ZmZlcmVkQnl0ZXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNuYXBzaG90O1xuICB9XG5cbiAgY2xvc2VBbGwoY29kZT86IG51bWJlciwgcmVhc29uPzogc3RyaW5nKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBjb25uZWN0aW9uIG9mIHRoaXMuY29ubmVjdGlvbnMudmFsdWVzKCkpIHtcbiAgICAgIGNvbm5lY3Rpb24uY2xvc2UoY29kZSwgcmVhc29uKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNUZWxlbWV0cnlJbnNwZWN0YWJsZUNvbm5lY3Rpb24oXG4gIGNvbm5lY3Rpb246IE1hbmFnZWRXZWJTb2NrZXRDb25uZWN0aW9uLFxuKTogY29ubmVjdGlvbiBpcyBNYW5hZ2VkV2ViU29ja2V0Q29ubmVjdGlvbiAmIFRlbGVtZXRyeUluc3BlY3RhYmxlQ29ubmVjdGlvbiB7XG4gIHJldHVybiBcImdldFRlbGVtZXRyeVNuYXBzaG90XCIgaW4gY29ubmVjdGlvbiAmJiBpc0Z1bmN0aW9uVmFsdWUoY29ubmVjdGlvbi5nZXRUZWxlbWV0cnlTbmFwc2hvdCk7XG59XG4iXSwibWFwcGluZ3MiOiI7OztBQXVFQSxTQUFTLGlDQUNQLFlBQzJFO0NBQzNFLE9BQU8sMEJBQTBCLGNBQWMsZ0JBQWdCLFdBQVcsb0JBQW9CO0FBQ2hHOzs7b0JBM0V3RDtDQU8zQyxnQ0FBYixNQUEyQztFQUN6Qyw4QkFBK0IsSUFBSSxJQUF3QztFQUUzRSxTQUFTLFlBQThDO0dBQ3JELEtBQUssWUFBWSxJQUFJLFdBQVcsSUFBSSxVQUFVO0VBQ2hEO0VBRUEsV0FBVyxjQUE0QjtHQUNyQyxLQUFLLFlBQVksT0FBTyxZQUFZO0VBQ3RDO0VBRUEsY0FBYyxjQUE4RDtHQUMxRSxPQUFPLEtBQUssWUFBWSxJQUFJLFlBQVk7RUFDMUM7RUFFQSxlQUFlLGVBQXVEO0dBQ3BFLE1BQU0sVUFBd0MsQ0FBQztHQUMvQyxNQUFNLHVCQUFPLElBQUksSUFBWTtHQUU3QixLQUFLLE1BQU0sZ0JBQWdCLGVBQWU7SUFDeEMsSUFBSSxLQUFLLElBQUksWUFBWSxHQUN2QjtJQUVGLEtBQUssSUFBSSxZQUFZO0lBRXJCLE1BQU0sYUFBYSxLQUFLLFlBQVksSUFBSSxZQUFZO0lBQ3BELElBQUksQ0FBQyxjQUFjLFdBQVcsUUFDNUI7SUFHRixRQUFRLEtBQUssVUFBVTtHQUN6QjtHQUVBLE9BQU87RUFDVDtFQUVBLHVCQUE2RDtHQUMzRCxNQUFNLFdBQWlEO0lBQ3JELHdCQUF3QjtJQUN4Qix5QkFBeUI7SUFDekIscUJBQXFCO0dBQ3ZCO0dBRUEsS0FBSyxNQUFNLGNBQWMsS0FBSyxZQUFZLE9BQU8sR0FBRztJQUNsRCxJQUFJLENBQUMsaUNBQWlDLFVBQVUsR0FDOUM7SUFHRixNQUFNLHFCQUFxQixXQUFXLHFCQUFxQjtJQUMzRCxTQUFTLDBCQUEwQixtQkFBbUI7SUFDdEQsU0FBUywyQkFBMkIsbUJBQW1CO0lBQ3ZELFNBQVMsdUJBQXVCLG1CQUFtQjtHQUNyRDtHQUVBLE9BQU87RUFDVDtFQUVBLFNBQVMsTUFBZSxRQUF1QjtHQUM3QyxLQUFLLE1BQU0sY0FBYyxLQUFLLFlBQVksT0FBTyxHQUMvQyxXQUFXLE1BQU0sTUFBTSxNQUFNO0VBRWpDO0NBQ0YifQ==
56
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtbG9jYWwtY29ubmVjdGlvbi1zdG9yZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWFtL3dzLWxvY2FsLWNvbm5lY3Rpb24tc3RvcmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNGdW5jdGlvblZhbHVlIH0gZnJvbSBcIi4uL3V0aWxzL3J1bnRpbWUtdmFsdWVcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0RnJhbWVDb25uZWN0aW9uIH0gZnJvbSBcIi4vd3MtY29yZVwiO1xuaW1wb3J0IHtcbiAgdHlwZSBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uU25hcHNob3QsXG4gIHR5cGUgVGVsZW1ldHJ5SW5zcGVjdGFibGVDb25uZWN0aW9uLFxufSBmcm9tIFwiLi93cy10ZWxlbWV0cnlcIjtcblxuZXhwb3J0IGNsYXNzIFdlYlNvY2tldExvY2FsQ29ubmVjdGlvblN0b3JlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb25uZWN0aW9ucyA9IG5ldyBNYXA8c3RyaW5nLCBXZWJTb2NrZXRGcmFtZUNvbm5lY3Rpb24+KCk7XG5cbiAgcmVnaXN0ZXIoY29ubmVjdGlvbjogV2ViU29ja2V0RnJhbWVDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5jb25uZWN0aW9ucy5zZXQoY29ubmVjdGlvbi5pZCwgY29ubmVjdGlvbik7XG4gIH1cblxuICB1bnJlZ2lzdGVyKGNvbm5lY3Rpb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb25uZWN0aW9ucy5kZWxldGUoY29ubmVjdGlvbklkKTtcbiAgfVxuXG4gIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcpOiBXZWJTb2NrZXRGcmFtZUNvbm5lY3Rpb24gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpO1xuICB9XG5cbiAgZ2V0Q29ubmVjdGlvbnMoY29ubmVjdGlvbklkczogc3RyaW5nW10pOiBXZWJTb2NrZXRGcmFtZUNvbm5lY3Rpb25bXSB7XG4gICAgY29uc3QgdGFyZ2V0czogV2ViU29ja2V0RnJhbWVDb25uZWN0aW9uW10gPSBbXTtcbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBvZiBjb25uZWN0aW9uSWRzKSB7XG4gICAgICBpZiAoc2Vlbi5oYXMoY29ubmVjdGlvbklkKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHNlZW4uYWRkKGNvbm5lY3Rpb25JZCk7XG5cbiAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLmNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpO1xuICAgICAgaWYgKCFjb25uZWN0aW9uIHx8IGNvbm5lY3Rpb24uY2xvc2VkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB0YXJnZXRzLnB1c2goY29ubmVjdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhcmdldHM7XG4gIH1cblxuICBnZXRUZWxlbWV0cnlTbmFwc2hvdCgpOiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uU25hcHNob3Qge1xuICAgIGNvbnN0IHNuYXBzaG90OiBXZWJTb2NrZXRUZWxlbWV0cnlDb25uZWN0aW9uU25hcHNob3QgPSB7XG4gICAgICBwZW5kaW5nSW5ib3VuZE1lc3NhZ2VzOiAwLFxuICAgICAgcGVuZGluZ091dGJvdW5kTWVzc2FnZXM6IDAsXG4gICAgICBzb2NrZXRCdWZmZXJlZEJ5dGVzOiAwLFxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb24gb2YgdGhpcy5jb25uZWN0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgaWYgKCFpc1RlbGVtZXRyeUluc3BlY3RhYmxlQ29ubmVjdGlvbihjb25uZWN0aW9uKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29ubmVjdGlvblNuYXBzaG90ID0gY29ubmVjdGlvbi5nZXRUZWxlbWV0cnlTbmFwc2hvdCgpO1xuICAgICAgc25hcHNob3QucGVuZGluZ0luYm91bmRNZXNzYWdlcyArPSBjb25uZWN0aW9uU25hcHNob3QucGVuZGluZ0luYm91bmRNZXNzYWdlcztcbiAgICAgIHNuYXBzaG90LnBlbmRpbmdPdXRib3VuZE1lc3NhZ2VzICs9IGNvbm5lY3Rpb25TbmFwc2hvdC5wZW5kaW5nT3V0Ym91bmRNZXNzYWdlcztcbiAgICAgIHNuYXBzaG90LnNvY2tldEJ1ZmZlcmVkQnl0ZXMgKz0gY29ubmVjdGlvblNuYXBzaG90LnNvY2tldEJ1ZmZlcmVkQnl0ZXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNuYXBzaG90O1xuICB9XG5cbiAgY2xvc2VBbGwoY29kZT86IG51bWJlciwgcmVhc29uPzogc3RyaW5nKTogdm9pZCB7XG4gICAgLy8gY2xvc2Ug64+E7KSRIHVucmVnaXN0ZXLqsIAgTWFw7J2EIOuwlOq+uOuvgOuhnCDrs7Xsgqzrs7jsnYQg7Iic7ZqM7ZWc64ukXG4gICAgZm9yIChjb25zdCBjb25uZWN0aW9uIG9mIEFycmF5LmZyb20odGhpcy5jb25uZWN0aW9ucy52YWx1ZXMoKSkpIHtcbiAgICAgIGNvbm5lY3Rpb24uY2xvc2UoY29kZSwgcmVhc29uKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNUZWxlbWV0cnlJbnNwZWN0YWJsZUNvbm5lY3Rpb24oXG4gIGNvbm5lY3Rpb246IFdlYlNvY2tldEZyYW1lQ29ubmVjdGlvbixcbik6IGNvbm5lY3Rpb24gaXMgV2ViU29ja2V0RnJhbWVDb25uZWN0aW9uICYgVGVsZW1ldHJ5SW5zcGVjdGFibGVDb25uZWN0aW9uIHtcbiAgcmV0dXJuIFwiZ2V0VGVsZW1ldHJ5U25hcHNob3RcIiBpbiBjb25uZWN0aW9uICYmIGlzRnVuY3Rpb25WYWx1ZShjb25uZWN0aW9uLmdldFRlbGVtZXRyeVNuYXBzaG90KTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7O0FBd0VBLFNBQVMsaUNBQ1AsWUFDeUU7Q0FDekUsT0FBTywwQkFBMEIsY0FBYyxnQkFBZ0IsV0FBVyxvQkFBb0I7QUFDaEc7OztDQTVFd0QsbUJBQUE7Q0FPM0MsZ0NBQWIsTUFBMkM7RUFDekMsOEJBQStCLElBQUksSUFBc0M7RUFFekUsU0FBUyxZQUE0QztHQUNuRCxLQUFLLFlBQVksSUFBSSxXQUFXLElBQUksVUFBVTtFQUNoRDtFQUVBLFdBQVcsY0FBNEI7R0FDckMsS0FBSyxZQUFZLE9BQU8sWUFBWTtFQUN0QztFQUVBLGNBQWMsY0FBNEQ7R0FDeEUsT0FBTyxLQUFLLFlBQVksSUFBSSxZQUFZO0VBQzFDO0VBRUEsZUFBZSxlQUFxRDtHQUNsRSxNQUFNLFVBQXNDLENBQUM7R0FDN0MsTUFBTSx1QkFBTyxJQUFJLElBQVk7R0FFN0IsS0FBSyxNQUFNLGdCQUFnQixlQUFlO0lBQ3hDLElBQUksS0FBSyxJQUFJLFlBQVksR0FDdkI7SUFFRixLQUFLLElBQUksWUFBWTtJQUVyQixNQUFNLGFBQWEsS0FBSyxZQUFZLElBQUksWUFBWTtJQUNwRCxJQUFJLENBQUMsY0FBYyxXQUFXLFFBQzVCO0lBR0YsUUFBUSxLQUFLLFVBQVU7R0FDekI7R0FFQSxPQUFPO0VBQ1Q7RUFFQSx1QkFBNkQ7R0FDM0QsTUFBTSxXQUFpRDtJQUNyRCx3QkFBd0I7SUFDeEIseUJBQXlCO0lBQ3pCLHFCQUFxQjtHQUN2QjtHQUVBLEtBQUssTUFBTSxjQUFjLEtBQUssWUFBWSxPQUFPLEdBQUc7SUFDbEQsSUFBSSxDQUFDLGlDQUFpQyxVQUFVLEdBQzlDO0lBR0YsTUFBTSxxQkFBcUIsV0FBVyxxQkFBcUI7SUFDM0QsU0FBUywwQkFBMEIsbUJBQW1CO0lBQ3RELFNBQVMsMkJBQTJCLG1CQUFtQjtJQUN2RCxTQUFTLHVCQUF1QixtQkFBbUI7R0FDckQ7R0FFQSxPQUFPO0VBQ1Q7RUFFQSxTQUFTLE1BQWUsUUFBdUI7R0FFN0MsS0FBSyxNQUFNLGNBQWMsTUFBTSxLQUFLLEtBQUssWUFBWSxPQUFPLENBQUMsR0FDM0QsV0FBVyxNQUFNLE1BQU0sTUFBTTtFQUVqQztDQUNGIn0=
@@ -0,0 +1,36 @@
1
+ import { type WebSocketAudience } from "./ws-audience";
2
+ import { type WebSocketRegistryStats, type WebSocketRoomId, type WebSocketUserId } from "./ws-core";
3
+ import { type WebSocketPresenceRegistration, type WebSocketSessionPresence } from "./ws-presence-store";
4
+ /**
5
+ * 동기 presence 인덱스. registry의 노드 로컬 메모리와 in-memory store가 함께 쓴다.
6
+ * 외부로 내보내는 presence는 항상 복사본이다.
7
+ */
8
+ export declare class WebSocketPresenceIndex {
9
+ private readonly sessions;
10
+ private readonly rooms;
11
+ private readonly users;
12
+ has(sessionId: string): boolean;
13
+ register(input: WebSocketPresenceRegistration): void;
14
+ activate(sessionId: string): void;
15
+ unregister(sessionId: string): WebSocketSessionPresence | undefined;
16
+ touch(sessionId: string): void;
17
+ setUserId(sessionId: string, userId: WebSocketUserId): void;
18
+ clearUserId(sessionId: string): void;
19
+ join(sessionId: string, roomId: WebSocketRoomId): void;
20
+ leave(sessionId: string, roomId: WebSocketRoomId): void;
21
+ getConnection(sessionId: string): WebSocketSessionPresence | undefined;
22
+ getConnectionCount(namespace?: string): number;
23
+ getRoomMembers(roomId: WebSocketRoomId, namespace?: string): WebSocketSessionPresence[];
24
+ getRoomMemberCount(roomId: WebSocketRoomId, namespace?: string): number;
25
+ getStats(): WebSocketRegistryStats;
26
+ /**
27
+ * audience에 해당하는 활성 세션을 중복 없이 반환한다. 반환값은 내부 상태를 노출하지 않도록 ID와 노드 ID만 담는다.
28
+ */
29
+ queryAudience(audience: WebSocketAudience): Array<{
30
+ sessionId: string;
31
+ nodeId: string;
32
+ }>;
33
+ private collectAudience;
34
+ private getBoundSessions;
35
+ }
36
+ //# sourceMappingURL=ws-presence-index.d.ts.map