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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-presence-index.d.ts","sourceRoot":"","sources":["../../src/stream/ws-presence-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,KAAK,sBAAsB,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACpG,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAC;AAM7B;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAElE,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9B;IAED,QAAQ,CAAC,KAAK,EAAE,6BAA6B,GAAG,IAAI,CAYnD;IAED,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAKhC;IAED,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAclE;IAED,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAK7B;IAED,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAW1D;IAED,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQnC;IAED,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAQrD;IAED,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAQtD;IAED,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAGrE;IAED,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ7C;IAED,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,wBAAwB,EAAE,CAEtF;IAED,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;IAED,QAAQ,IAAI,sBAAsB,CAkBjC;IAED;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAavF;IAED,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,gBAAgB;CA0BzB"}
@@ -0,0 +1,176 @@
1
+ import { __esmMin } from "../_virtual/_rolldown/runtime.js";
2
+ // src/stream/ws-presence-index.ts
3
+ function matchesNamespace(record, namespace) {
4
+ return namespace === void 0 || namespace === "" || record.namespace === namespace;
5
+ }
6
+ function copyPresence(record) {
7
+ const copy = {
8
+ sessionId: record.sessionId,
9
+ nodeId: record.nodeId,
10
+ namespace: record.namespace,
11
+ active: record.active,
12
+ rooms: new Set(record.rooms),
13
+ connectedAt: new Date(record.connectedAt.getTime()),
14
+ lastSeenAt: new Date(record.lastSeenAt.getTime())
15
+ };
16
+ if (record.userId !== void 0) copy.userId = record.userId;
17
+ return copy;
18
+ }
19
+ function addBinding(index, namespace, id, sessionId) {
20
+ const bindings = index.get(namespace) ?? /* @__PURE__ */ new Map();
21
+ const members = bindings.get(id) ?? /* @__PURE__ */ new Set();
22
+ members.add(sessionId);
23
+ bindings.set(id, members);
24
+ index.set(namespace, bindings);
25
+ }
26
+ function removeBinding(index, namespace, id, sessionId) {
27
+ const bindings = index.get(namespace);
28
+ const members = bindings?.get(id);
29
+ if (!bindings || !members) return;
30
+ members.delete(sessionId);
31
+ if (members.size === 0) bindings.delete(id);
32
+ if (bindings.size === 0) index.delete(namespace);
33
+ }
34
+ var WebSocketPresenceIndex;
35
+ var init_ws_presence_index = __esmMin((() => {
36
+ WebSocketPresenceIndex = class {
37
+ sessions = /* @__PURE__ */ new Map();
38
+ rooms = /* @__PURE__ */ new Map();
39
+ users = /* @__PURE__ */ new Map();
40
+ has(sessionId) {
41
+ return this.sessions.has(sessionId);
42
+ }
43
+ register(input) {
44
+ this.unregister(input.sessionId);
45
+ this.sessions.set(input.sessionId, {
46
+ sessionId: input.sessionId,
47
+ nodeId: input.nodeId,
48
+ namespace: input.namespace,
49
+ active: input.active,
50
+ rooms: /* @__PURE__ */ new Set(),
51
+ connectedAt: new Date(input.connectedAt.getTime()),
52
+ lastSeenAt: new Date(input.connectedAt.getTime())
53
+ });
54
+ }
55
+ activate(sessionId) {
56
+ const record = this.sessions.get(sessionId);
57
+ if (record) record.active = true;
58
+ }
59
+ unregister(sessionId) {
60
+ const record = this.sessions.get(sessionId);
61
+ if (!record) return;
62
+ if (record.userId !== void 0) removeBinding(this.users, record.namespace, record.userId, sessionId);
63
+ for (const roomId of record.rooms) removeBinding(this.rooms, record.namespace, roomId, sessionId);
64
+ this.sessions.delete(sessionId);
65
+ return copyPresence(record);
66
+ }
67
+ touch(sessionId) {
68
+ const record = this.sessions.get(sessionId);
69
+ if (record) record.lastSeenAt = /* @__PURE__ */ new Date();
70
+ }
71
+ setUserId(sessionId, userId) {
72
+ const record = this.sessions.get(sessionId);
73
+ if (!record) return;
74
+ if (record.userId !== void 0) removeBinding(this.users, record.namespace, record.userId, sessionId);
75
+ record.userId = userId;
76
+ addBinding(this.users, record.namespace, userId, sessionId);
77
+ }
78
+ clearUserId(sessionId) {
79
+ const record = this.sessions.get(sessionId);
80
+ if (!record || record.userId === void 0) return;
81
+ removeBinding(this.users, record.namespace, record.userId, sessionId);
82
+ delete record.userId;
83
+ }
84
+ join(sessionId, roomId) {
85
+ const record = this.sessions.get(sessionId);
86
+ if (!record) return;
87
+ record.rooms.add(roomId);
88
+ addBinding(this.rooms, record.namespace, roomId, sessionId);
89
+ }
90
+ leave(sessionId, roomId) {
91
+ const record = this.sessions.get(sessionId);
92
+ if (!record) return;
93
+ record.rooms.delete(roomId);
94
+ removeBinding(this.rooms, record.namespace, roomId, sessionId);
95
+ }
96
+ getConnection(sessionId) {
97
+ const record = this.sessions.get(sessionId);
98
+ return record ? copyPresence(record) : void 0;
99
+ }
100
+ getConnectionCount(namespace) {
101
+ let count = 0;
102
+ for (const record of this.sessions.values()) if (record.active && matchesNamespace(record, namespace)) count += 1;
103
+ return count;
104
+ }
105
+ getRoomMembers(roomId, namespace) {
106
+ return this.getBoundSessions(this.rooms, roomId, namespace).map(copyPresence);
107
+ }
108
+ getRoomMemberCount(roomId, namespace) {
109
+ return this.getBoundSessions(this.rooms, roomId, namespace).length;
110
+ }
111
+ getStats() {
112
+ const byNamespace = {};
113
+ let totalConnections = 0;
114
+ for (const record of this.sessions.values()) {
115
+ if (!record.active) continue;
116
+ byNamespace[record.namespace] = (byNamespace[record.namespace] ?? 0) + 1;
117
+ totalConnections += 1;
118
+ }
119
+ let totalRooms = 0;
120
+ for (const bindings of this.rooms.values()) totalRooms += bindings.size;
121
+ return {
122
+ totalConnections,
123
+ totalRooms,
124
+ byNamespace
125
+ };
126
+ }
127
+ /**
128
+ * audience에 해당하는 활성 세션을 중복 없이 반환한다. 반환값은 내부 상태를 노출하지 않도록 ID와 노드 ID만 담는다.
129
+ */
130
+ queryAudience(audience) {
131
+ const seen = /* @__PURE__ */ new Set();
132
+ const results = [];
133
+ for (const record of this.collectAudience(audience)) {
134
+ if (seen.has(record.sessionId)) continue;
135
+ seen.add(record.sessionId);
136
+ results.push({
137
+ sessionId: record.sessionId,
138
+ nodeId: record.nodeId
139
+ });
140
+ }
141
+ return results;
142
+ }
143
+ collectAudience(audience) {
144
+ switch (audience.type) {
145
+ case "all": return [...this.sessions.values()].filter((record) => record.active && matchesNamespace(record, audience.namespace));
146
+ case "room": return this.getBoundSessions(this.rooms, audience.roomId, audience.namespace);
147
+ case "user": return this.getBoundSessions(this.users, audience.userId, audience.namespace);
148
+ case "connections": {
149
+ const records = [];
150
+ for (const sessionId of audience.connectionIds) {
151
+ const record = this.sessions.get(sessionId);
152
+ if (record?.active && matchesNamespace(record, audience.namespace)) records.push(record);
153
+ }
154
+ return records;
155
+ }
156
+ case "union": return audience.audiences.flatMap((item) => this.collectAudience(item));
157
+ }
158
+ }
159
+ getBoundSessions(index, id, namespace) {
160
+ const namespaces = namespace ? [index.get(namespace)] : [...index.values()];
161
+ const seen = /* @__PURE__ */ new Set();
162
+ const records = [];
163
+ for (const bindings of namespaces) for (const sessionId of bindings?.get(id) ?? []) {
164
+ if (seen.has(sessionId)) continue;
165
+ seen.add(sessionId);
166
+ const record = this.sessions.get(sessionId);
167
+ if (record?.active) records.push(record);
168
+ }
169
+ return records;
170
+ }
171
+ };
172
+ }));
173
+ init_ws_presence_index();
174
+ export { WebSocketPresenceIndex, init_ws_presence_index };
175
+
176
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtcHJlc2VuY2UtaW5kZXguanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmVhbS93cy1wcmVzZW5jZS1pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIFdlYlNvY2tldEF1ZGllbmNlIH0gZnJvbSBcIi4vd3MtYXVkaWVuY2VcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0UmVnaXN0cnlTdGF0cywgdHlwZSBXZWJTb2NrZXRSb29tSWQsIHR5cGUgV2ViU29ja2V0VXNlcklkIH0gZnJvbSBcIi4vd3MtY29yZVwiO1xuaW1wb3J0IHtcbiAgdHlwZSBXZWJTb2NrZXRQcmVzZW5jZVJlZ2lzdHJhdGlvbixcbiAgdHlwZSBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UsXG59IGZyb20gXCIuL3dzLXByZXNlbmNlLXN0b3JlXCI7XG5cbnR5cGUgUHJlc2VuY2VSZWNvcmQgPSBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2U7XG4vLyBuYW1lc3BhY2Ug4oaSIOuwlOyduOuUqSBpZCDihpIg7IS47IWYIElEIOynke2VqS4gdXNlcklk64qUIE1hcCDtgqTroZwg6re464yA66GcIOyNqOyEnCAx6rO8IFwiMVwi7J2EIOq1rOu2hO2VnOuLpFxudHlwZSBCaW5kaW5nSW5kZXg8SWQ+ID0gTWFwPHN0cmluZywgTWFwPElkLCBTZXQ8c3RyaW5nPj4+O1xuXG4vKipcbiAqIOuPmeq4sCBwcmVzZW5jZSDsnbjrjbHsiqQuIHJlZ2lzdHJ57J2YIOuFuOuTnCDroZzsu6wg66mU66qo66as7JmAIGluLW1lbW9yeSBzdG9yZeqwgCDtlajqu5gg7JO064ukLlxuICog7Jm467aA66GcIOuCtOuztOuCtOuKlCBwcmVzZW5jZeuKlCDtla3sg4Eg67O17IKs67O47J2064ukLlxuICovXG5leHBvcnQgY2xhc3MgV2ViU29ja2V0UHJlc2VuY2VJbmRleCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2Vzc2lvbnMgPSBuZXcgTWFwPHN0cmluZywgUHJlc2VuY2VSZWNvcmQ+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcm9vbXM6IEJpbmRpbmdJbmRleDxXZWJTb2NrZXRSb29tSWQ+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IHVzZXJzOiBCaW5kaW5nSW5kZXg8V2ViU29ja2V0VXNlcklkPiA9IG5ldyBNYXAoKTtcblxuICBoYXMoc2Vzc2lvbklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9ucy5oYXMoc2Vzc2lvbklkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKGlucHV0OiBXZWJTb2NrZXRQcmVzZW5jZVJlZ2lzdHJhdGlvbik6IHZvaWQge1xuICAgIC8vIOqwmeydgCDshLjshZjsnYQg64uk7IucIOuTseuhne2VmOuptCDsnbTsoIQg67CU7J2465Sp7J2EIOuovOyggCDsoJXrpqztlbQg6rOg7JWEIOuwlOyduOuUqeydtCDrgqjsp4Ag7JWK6rKMIO2VnOuLpFxuICAgIHRoaXMudW5yZWdpc3RlcihpbnB1dC5zZXNzaW9uSWQpO1xuICAgIHRoaXMuc2Vzc2lvbnMuc2V0KGlucHV0LnNlc3Npb25JZCwge1xuICAgICAgc2Vzc2lvbklkOiBpbnB1dC5zZXNzaW9uSWQsXG4gICAgICBub2RlSWQ6IGlucHV0Lm5vZGVJZCxcbiAgICAgIG5hbWVzcGFjZTogaW5wdXQubmFtZXNwYWNlLFxuICAgICAgYWN0aXZlOiBpbnB1dC5hY3RpdmUsXG4gICAgICByb29tczogbmV3IFNldCgpLFxuICAgICAgY29ubmVjdGVkQXQ6IG5ldyBEYXRlKGlucHV0LmNvbm5lY3RlZEF0LmdldFRpbWUoKSksXG4gICAgICBsYXN0U2VlbkF0OiBuZXcgRGF0ZShpbnB1dC5jb25uZWN0ZWRBdC5nZXRUaW1lKCkpLFxuICAgIH0pO1xuICB9XG5cbiAgYWN0aXZhdGUoc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCByZWNvcmQgPSB0aGlzLnNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICAgIGlmIChyZWNvcmQpIHtcbiAgICAgIHJlY29yZC5hY3RpdmUgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHVucmVnaXN0ZXIoc2Vzc2lvbklkOiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuc2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFyZWNvcmQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKHJlY29yZC51c2VySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmVtb3ZlQmluZGluZyh0aGlzLnVzZXJzLCByZWNvcmQubmFtZXNwYWNlLCByZWNvcmQudXNlcklkLCBzZXNzaW9uSWQpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IHJvb21JZCBvZiByZWNvcmQucm9vbXMpIHtcbiAgICAgIHJlbW92ZUJpbmRpbmcodGhpcy5yb29tcywgcmVjb3JkLm5hbWVzcGFjZSwgcm9vbUlkLCBzZXNzaW9uSWQpO1xuICAgIH1cbiAgICB0aGlzLnNlc3Npb25zLmRlbGV0ZShzZXNzaW9uSWQpO1xuICAgIHJldHVybiBjb3B5UHJlc2VuY2UocmVjb3JkKTtcbiAgfVxuXG4gIHRvdWNoKHNlc3Npb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgcmVjb3JkID0gdGhpcy5zZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAocmVjb3JkKSB7XG4gICAgICByZWNvcmQubGFzdFNlZW5BdCA9IG5ldyBEYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgc2V0VXNlcklkKHNlc3Npb25JZDogc3RyaW5nLCB1c2VySWQ6IFdlYlNvY2tldFVzZXJJZCk6IHZvaWQge1xuICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuc2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFyZWNvcmQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocmVjb3JkLnVzZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZW1vdmVCaW5kaW5nKHRoaXMudXNlcnMsIHJlY29yZC5uYW1lc3BhY2UsIHJlY29yZC51c2VySWQsIHNlc3Npb25JZCk7XG4gICAgfVxuICAgIHJlY29yZC51c2VySWQgPSB1c2VySWQ7XG4gICAgYWRkQmluZGluZyh0aGlzLnVzZXJzLCByZWNvcmQubmFtZXNwYWNlLCB1c2VySWQsIHNlc3Npb25JZCk7XG4gIH1cblxuICBjbGVhclVzZXJJZChzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuc2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFyZWNvcmQgfHwgcmVjb3JkLnVzZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmVtb3ZlQmluZGluZyh0aGlzLnVzZXJzLCByZWNvcmQubmFtZXNwYWNlLCByZWNvcmQudXNlcklkLCBzZXNzaW9uSWQpO1xuICAgIGRlbGV0ZSByZWNvcmQudXNlcklkO1xuICB9XG5cbiAgam9pbihzZXNzaW9uSWQ6IHN0cmluZywgcm9vbUlkOiBXZWJTb2NrZXRSb29tSWQpOiB2b2lkIHtcbiAgICBjb25zdCByZWNvcmQgPSB0aGlzLnNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghcmVjb3JkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmVjb3JkLnJvb21zLmFkZChyb29tSWQpO1xuICAgIGFkZEJpbmRpbmcodGhpcy5yb29tcywgcmVjb3JkLm5hbWVzcGFjZSwgcm9vbUlkLCBzZXNzaW9uSWQpO1xuICB9XG5cbiAgbGVhdmUoc2Vzc2lvbklkOiBzdHJpbmcsIHJvb21JZDogV2ViU29ja2V0Um9vbUlkKTogdm9pZCB7XG4gICAgY29uc3QgcmVjb3JkID0gdGhpcy5zZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIXJlY29yZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHJlY29yZC5yb29tcy5kZWxldGUocm9vbUlkKTtcbiAgICByZW1vdmVCaW5kaW5nKHRoaXMucm9vbXMsIHJlY29yZC5uYW1lc3BhY2UsIHJvb21JZCwgc2Vzc2lvbklkKTtcbiAgfVxuXG4gIGdldENvbm5lY3Rpb24oc2Vzc2lvbklkOiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuc2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgcmV0dXJuIHJlY29yZCA/IGNvcHlQcmVzZW5jZShyZWNvcmQpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgZ2V0Q29ubmVjdGlvbkNvdW50KG5hbWVzcGFjZT86IHN0cmluZyk6IG51bWJlciB7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBmb3IgKGNvbnN0IHJlY29yZCBvZiB0aGlzLnNlc3Npb25zLnZhbHVlcygpKSB7XG4gICAgICBpZiAocmVjb3JkLmFjdGl2ZSAmJiBtYXRjaGVzTmFtZXNwYWNlKHJlY29yZCwgbmFtZXNwYWNlKSkge1xuICAgICAgICBjb3VudCArPSAxO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY291bnQ7XG4gIH1cblxuICBnZXRSb29tTWVtYmVycyhyb29tSWQ6IFdlYlNvY2tldFJvb21JZCwgbmFtZXNwYWNlPzogc3RyaW5nKTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlW10ge1xuICAgIHJldHVybiB0aGlzLmdldEJvdW5kU2Vzc2lvbnModGhpcy5yb29tcywgcm9vbUlkLCBuYW1lc3BhY2UpLm1hcChjb3B5UHJlc2VuY2UpO1xuICB9XG5cbiAgZ2V0Um9vbU1lbWJlckNvdW50KHJvb21JZDogV2ViU29ja2V0Um9vbUlkLCBuYW1lc3BhY2U/OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmdldEJvdW5kU2Vzc2lvbnModGhpcy5yb29tcywgcm9vbUlkLCBuYW1lc3BhY2UpLmxlbmd0aDtcbiAgfVxuXG4gIGdldFN0YXRzKCk6IFdlYlNvY2tldFJlZ2lzdHJ5U3RhdHMge1xuICAgIGNvbnN0IGJ5TmFtZXNwYWNlOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG4gICAgbGV0IHRvdGFsQ29ubmVjdGlvbnMgPSAwO1xuXG4gICAgZm9yIChjb25zdCByZWNvcmQgb2YgdGhpcy5zZXNzaW9ucy52YWx1ZXMoKSkge1xuICAgICAgaWYgKCFyZWNvcmQuYWN0aXZlKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgYnlOYW1lc3BhY2VbcmVjb3JkLm5hbWVzcGFjZV0gPSAoYnlOYW1lc3BhY2VbcmVjb3JkLm5hbWVzcGFjZV0gPz8gMCkgKyAxO1xuICAgICAgdG90YWxDb25uZWN0aW9ucyArPSAxO1xuICAgIH1cblxuICAgIGxldCB0b3RhbFJvb21zID0gMDtcbiAgICBmb3IgKGNvbnN0IGJpbmRpbmdzIG9mIHRoaXMucm9vbXMudmFsdWVzKCkpIHtcbiAgICAgIHRvdGFsUm9vbXMgKz0gYmluZGluZ3Muc2l6ZTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB0b3RhbENvbm5lY3Rpb25zLCB0b3RhbFJvb21zLCBieU5hbWVzcGFjZSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIGF1ZGllbmNl7JeQIO2VtOuLue2VmOuKlCDtmZzshLEg7IS47IWY7J2EIOykkeuztSDsl4bsnbQg67CY7ZmY7ZWc64ukLiDrsJjtmZjqsJLsnYAg64K067aAIOyDge2DnOulvCDrhbjstpztlZjsp4Ag7JWK64+E66GdIElE7JmAIOuFuOuTnCBJROunjCDri7TripTri6QuXG4gICAqL1xuICBxdWVyeUF1ZGllbmNlKGF1ZGllbmNlOiBXZWJTb2NrZXRBdWRpZW5jZSk6IEFycmF5PHsgc2Vzc2lvbklkOiBzdHJpbmc7IG5vZGVJZDogc3RyaW5nIH0+IHtcbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgcmVzdWx0czogQXJyYXk8eyBzZXNzaW9uSWQ6IHN0cmluZzsgbm9kZUlkOiBzdHJpbmcgfT4gPSBbXTtcblxuICAgIGZvciAoY29uc3QgcmVjb3JkIG9mIHRoaXMuY29sbGVjdEF1ZGllbmNlKGF1ZGllbmNlKSkge1xuICAgICAgaWYgKHNlZW4uaGFzKHJlY29yZC5zZXNzaW9uSWQpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgc2Vlbi5hZGQocmVjb3JkLnNlc3Npb25JZCk7XG4gICAgICByZXN1bHRzLnB1c2goeyBzZXNzaW9uSWQ6IHJlY29yZC5zZXNzaW9uSWQsIG5vZGVJZDogcmVjb3JkLm5vZGVJZCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIHByaXZhdGUgY29sbGVjdEF1ZGllbmNlKGF1ZGllbmNlOiBXZWJTb2NrZXRBdWRpZW5jZSk6IFByZXNlbmNlUmVjb3JkW10ge1xuICAgIHN3aXRjaCAoYXVkaWVuY2UudHlwZSkge1xuICAgICAgY2FzZSBcImFsbFwiOlxuICAgICAgICByZXR1cm4gWy4uLnRoaXMuc2Vzc2lvbnMudmFsdWVzKCldLmZpbHRlcihcbiAgICAgICAgICAocmVjb3JkKSA9PiByZWNvcmQuYWN0aXZlICYmIG1hdGNoZXNOYW1lc3BhY2UocmVjb3JkLCBhdWRpZW5jZS5uYW1lc3BhY2UpLFxuICAgICAgICApO1xuICAgICAgY2FzZSBcInJvb21cIjpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Qm91bmRTZXNzaW9ucyh0aGlzLnJvb21zLCBhdWRpZW5jZS5yb29tSWQsIGF1ZGllbmNlLm5hbWVzcGFjZSk7XG4gICAgICBjYXNlIFwidXNlclwiOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRCb3VuZFNlc3Npb25zKHRoaXMudXNlcnMsIGF1ZGllbmNlLnVzZXJJZCwgYXVkaWVuY2UubmFtZXNwYWNlKTtcbiAgICAgIGNhc2UgXCJjb25uZWN0aW9uc1wiOiB7XG4gICAgICAgIGNvbnN0IHJlY29yZHM6IFByZXNlbmNlUmVjb3JkW10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBzZXNzaW9uSWQgb2YgYXVkaWVuY2UuY29ubmVjdGlvbklkcykge1xuICAgICAgICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuc2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgICAgICAgaWYgKHJlY29yZD8uYWN0aXZlICYmIG1hdGNoZXNOYW1lc3BhY2UocmVjb3JkLCBhdWRpZW5jZS5uYW1lc3BhY2UpKSB7XG4gICAgICAgICAgICByZWNvcmRzLnB1c2gocmVjb3JkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlY29yZHM7XG4gICAgICB9XG4gICAgICBjYXNlIFwidW5pb25cIjpcbiAgICAgICAgcmV0dXJuIGF1ZGllbmNlLmF1ZGllbmNlcy5mbGF0TWFwKChpdGVtKSA9PiB0aGlzLmNvbGxlY3RBdWRpZW5jZShpdGVtKSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRCb3VuZFNlc3Npb25zPElkPihcbiAgICBpbmRleDogQmluZGluZ0luZGV4PElkPixcbiAgICBpZDogSWQsXG4gICAgbmFtZXNwYWNlPzogc3RyaW5nLFxuICApOiBQcmVzZW5jZVJlY29yZFtdIHtcbiAgICAvLyBuYW1lc3BhY2XqsIAg7JeG7Jy866m0KOu5iCDrrLjsnpDsl7Qg7Y+s7ZWoKSDrqqjrk6AgbmFtZXNwYWNl7J2YIOuwlOyduOuUqeydhCDrs7jri6RcbiAgICBjb25zdCBuYW1lc3BhY2VzID0gbmFtZXNwYWNlID8gW2luZGV4LmdldChuYW1lc3BhY2UpXSA6IFsuLi5pbmRleC52YWx1ZXMoKV07XG4gICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IHJlY29yZHM6IFByZXNlbmNlUmVjb3JkW10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgYmluZGluZ3Mgb2YgbmFtZXNwYWNlcykge1xuICAgICAgZm9yIChjb25zdCBzZXNzaW9uSWQgb2YgYmluZGluZ3M/LmdldChpZCkgPz8gW10pIHtcbiAgICAgICAgaWYgKHNlZW4uaGFzKHNlc3Npb25JZCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBzZWVuLmFkZChzZXNzaW9uSWQpO1xuXG4gICAgICAgIGNvbnN0IHJlY29yZCA9IHRoaXMuc2Vzc2lvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgICAgIGlmIChyZWNvcmQ/LmFjdGl2ZSkge1xuICAgICAgICAgIHJlY29yZHMucHVzaChyZWNvcmQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlY29yZHM7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hlc05hbWVzcGFjZShyZWNvcmQ6IFByZXNlbmNlUmVjb3JkLCBuYW1lc3BhY2U6IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICByZXR1cm4gbmFtZXNwYWNlID09PSB1bmRlZmluZWQgfHwgbmFtZXNwYWNlID09PSBcIlwiIHx8IHJlY29yZC5uYW1lc3BhY2UgPT09IG5hbWVzcGFjZTtcbn1cblxuZnVuY3Rpb24gY29weVByZXNlbmNlKHJlY29yZDogUHJlc2VuY2VSZWNvcmQpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2Uge1xuICBjb25zdCBjb3B5OiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgPSB7XG4gICAgc2Vzc2lvbklkOiByZWNvcmQuc2Vzc2lvbklkLFxuICAgIG5vZGVJZDogcmVjb3JkLm5vZGVJZCxcbiAgICBuYW1lc3BhY2U6IHJlY29yZC5uYW1lc3BhY2UsXG4gICAgYWN0aXZlOiByZWNvcmQuYWN0aXZlLFxuICAgIHJvb21zOiBuZXcgU2V0KHJlY29yZC5yb29tcyksXG4gICAgY29ubmVjdGVkQXQ6IG5ldyBEYXRlKHJlY29yZC5jb25uZWN0ZWRBdC5nZXRUaW1lKCkpLFxuICAgIGxhc3RTZWVuQXQ6IG5ldyBEYXRlKHJlY29yZC5sYXN0U2VlbkF0LmdldFRpbWUoKSksXG4gIH07XG4gIGlmIChyZWNvcmQudXNlcklkICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb3B5LnVzZXJJZCA9IHJlY29yZC51c2VySWQ7XG4gIH1cbiAgcmV0dXJuIGNvcHk7XG59XG5cbmZ1bmN0aW9uIGFkZEJpbmRpbmc8SWQ+KGluZGV4OiBCaW5kaW5nSW5kZXg8SWQ+LCBuYW1lc3BhY2U6IHN0cmluZywgaWQ6IElkLCBzZXNzaW9uSWQ6IHN0cmluZykge1xuICBjb25zdCBiaW5kaW5ncyA9IGluZGV4LmdldChuYW1lc3BhY2UpID8/IG5ldyBNYXA8SWQsIFNldDxzdHJpbmc+PigpO1xuICBjb25zdCBtZW1iZXJzID0gYmluZGluZ3MuZ2V0KGlkKSA/PyBuZXcgU2V0PHN0cmluZz4oKTtcbiAgbWVtYmVycy5hZGQoc2Vzc2lvbklkKTtcbiAgYmluZGluZ3Muc2V0KGlkLCBtZW1iZXJzKTtcbiAgaW5kZXguc2V0KG5hbWVzcGFjZSwgYmluZGluZ3MpO1xufVxuXG5mdW5jdGlvbiByZW1vdmVCaW5kaW5nPElkPihcbiAgaW5kZXg6IEJpbmRpbmdJbmRleDxJZD4sXG4gIG5hbWVzcGFjZTogc3RyaW5nLFxuICBpZDogSWQsXG4gIHNlc3Npb25JZDogc3RyaW5nLFxuKTogdm9pZCB7XG4gIGNvbnN0IGJpbmRpbmdzID0gaW5kZXguZ2V0KG5hbWVzcGFjZSk7XG4gIGNvbnN0IG1lbWJlcnMgPSBiaW5kaW5ncz8uZ2V0KGlkKTtcbiAgaWYgKCFiaW5kaW5ncyB8fCAhbWVtYmVycykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIG1lbWJlcnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gIGlmIChtZW1iZXJzLnNpemUgPT09IDApIHtcbiAgICBiaW5kaW5ncy5kZWxldGUoaWQpO1xuICB9XG4gIGlmIChiaW5kaW5ncy5zaXplID09PSAwKSB7XG4gICAgaW5kZXguZGVsZXRlKG5hbWVzcGFjZSk7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7QUFpT0EsU0FBUyxpQkFBaUIsUUFBd0IsV0FBd0M7Q0FDeEYsT0FBTyxjQUFjLFVBQWEsY0FBYyxNQUFNLE9BQU8sY0FBYztBQUM3RTtBQUVBLFNBQVMsYUFBYSxRQUFrRDtDQUN0RSxNQUFNLE9BQWlDO0VBQ3JDLFdBQVcsT0FBTztFQUNsQixRQUFRLE9BQU87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
@@ -1,5 +1,8 @@
1
1
  import { type WebSocketAudience } from "./ws-audience";
2
- import { type WebSocketRegistryStats, type WebSocketRoomId, type WebSocketUserId } from "./ws-core";
2
+ import { type MaybePromise, type WebSocketRoomId, type WebSocketUserId } from "./ws-core";
3
+ /**
4
+ * 세션 presence snapshot. live 객체가 아니므로 값을 바꿔도 registry나 store 상태에 영향을 주지 않는다.
5
+ */
3
6
  export type WebSocketSessionPresence = {
4
7
  sessionId: string;
5
8
  nodeId: string;
@@ -10,52 +13,49 @@ export type WebSocketSessionPresence = {
10
13
  lastSeenAt: Date;
11
14
  userId?: WebSocketUserId;
12
15
  };
16
+ export type WebSocketPresenceRegistration = {
17
+ sessionId: string;
18
+ nodeId: string;
19
+ namespace: string;
20
+ active: boolean;
21
+ connectedAt: Date;
22
+ };
23
+ export type WebSocketRoutingPlan = {
24
+ localSessionIds: string[];
25
+ remoteNodeIds: string[];
26
+ };
27
+ /**
28
+ * 클러스터 presence replica 계약. 각 노드의 registry가 자기 세션의 mutation을 세션별 호출 순서대로 전달한다.
29
+ * 모든 메서드는 값이나 promise를 반환할 수 있고, registry는 동기 throw도 rejection으로 바꿔 처리한다.
30
+ * userId는 타입까지 일치해야 매칭된다(1과 "1"은 다르다).
31
+ */
13
32
  export interface WebSocketPresenceStore {
14
- register(input: {
15
- sessionId: string;
16
- nodeId: string;
17
- namespace: string;
18
- active?: boolean;
19
- }): WebSocketSessionPresence;
20
- activate(sessionId: string): void;
21
- unregister(sessionId: string): WebSocketSessionPresence | undefined;
22
- touch(sessionId: string): void;
23
- setUserId(sessionId: string, userId: WebSocketUserId): void;
24
- clearUserId(sessionId: string): void;
25
- join(sessionId: string, roomId: WebSocketRoomId): void;
26
- leave(sessionId: string, roomId: WebSocketRoomId): void;
27
- getConnection(sessionId: string): WebSocketSessionPresence | undefined;
28
- getConnectionCount(namespace?: string): number;
29
- getRoomMembers(roomId: WebSocketRoomId, namespace?: string): WebSocketSessionPresence[];
30
- getStats(): WebSocketRegistryStats;
31
- queryAudience(audience: WebSocketAudience): WebSocketSessionPresence[];
33
+ readonly nodeId?: string;
34
+ register(input: WebSocketPresenceRegistration): MaybePromise<void>;
35
+ activate(sessionId: string): MaybePromise<void>;
36
+ unregister(sessionId: string): MaybePromise<void>;
37
+ setUserId(sessionId: string, userId: WebSocketUserId): MaybePromise<void>;
38
+ clearUserId(sessionId: string): MaybePromise<void>;
39
+ join(sessionId: string, roomId: WebSocketRoomId): MaybePromise<void>;
40
+ leave(sessionId: string, roomId: WebSocketRoomId): MaybePromise<void>;
41
+ resolveRoute(audience: WebSocketAudience, nodeId: string): MaybePromise<WebSocketRoutingPlan>;
42
+ getRoomMemberCount(roomId: WebSocketRoomId, namespace?: string): MaybePromise<number>;
43
+ shutdown?(): MaybePromise<void>;
32
44
  }
45
+ /**
46
+ * 프로세스 메모리에 presence를 두는 store. 단일 노드의 기본값이며, 같은 프로세스의 여러 runtime이 공유하면 클러스터 replica로도 동작한다.
47
+ */
33
48
  export declare class InMemoryWebSocketPresenceStore implements WebSocketPresenceStore {
34
- private readonly connections;
35
- private readonly rooms;
36
- private readonly users;
37
- register(input: {
38
- sessionId: string;
39
- nodeId: string;
40
- namespace: string;
41
- active?: boolean;
42
- }): WebSocketSessionPresence;
49
+ private readonly index;
50
+ register(input: WebSocketPresenceRegistration): void;
43
51
  activate(sessionId: string): void;
44
- unregister(sessionId: string): WebSocketSessionPresence | undefined;
45
- touch(sessionId: string): void;
52
+ unregister(sessionId: string): void;
46
53
  setUserId(sessionId: string, userId: WebSocketUserId): void;
47
54
  clearUserId(sessionId: string): void;
48
55
  join(sessionId: string, roomId: WebSocketRoomId): void;
49
56
  leave(sessionId: string, roomId: WebSocketRoomId): void;
57
+ resolveRoute(audience: WebSocketAudience, nodeId: string): WebSocketRoutingPlan;
58
+ getRoomMemberCount(roomId: WebSocketRoomId, namespace?: string): number;
50
59
  getConnection(sessionId: string): WebSocketSessionPresence | undefined;
51
- getConnectionCount(namespace?: string): number;
52
- getRoomMembers(roomId: WebSocketRoomId, namespace?: string): WebSocketSessionPresence[];
53
- getStats(): WebSocketRegistryStats;
54
- queryAudience(audience: WebSocketAudience): WebSocketSessionPresence[];
55
- private getActiveConnections;
56
- private getBoundConnections;
57
- private getScopedBindings;
58
- private removeRoomBinding;
59
- private removeUserBinding;
60
60
  }
61
61
  //# sourceMappingURL=ws-presence-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ws-presence-store.d.ts","sourceRoot":"","sources":["../../src/stream/ws-presence-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ws-presence-store.d.ts","sourceRoot":"","sources":["../../src/stream/ws-presence-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAG1F;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;IAC5B,WAAW,EAAE,IAAI,CAAC;IAClB,UAAU,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IAErC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,6BAA6B,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClD,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC1E,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEtE,YAAY,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,oBAAoB,CAAC,CAAC;IAE9F,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACtF,QAAQ,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,qBAAa,8BAA+B,YAAW,sBAAsB;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IAEtD,QAAQ,CAAC,KAAK,EAAE,6BAA6B,GAAG,IAAI,CAEnD;IAED,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEhC;IAED,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAElC;IAED,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAE1D;IAED,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEnC;IAED,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAErD;IAED,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAEtD;IAED,YAAY,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,GAAG,oBAAoB,CAa9E;IAED,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;IAGD,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAErE;CACF"}
@@ -1,182 +1,51 @@
1
1
  import { __esmMin } from "../_virtual/_rolldown/runtime.js";
2
- //#region src/stream/ws-presence-store.ts
3
- function getBindingKey(namespace, id) {
4
- return `${namespace}::${id}`;
5
- }
6
- function parseBindingKey(key) {
7
- const [namespace, ...rest] = key.split("::");
8
- return {
9
- namespace,
10
- id: rest.join("::")
11
- };
12
- }
2
+ import { WebSocketPresenceIndex, init_ws_presence_index } from "./ws-presence-index.js";
3
+ // src/stream/ws-presence-store.ts
13
4
  var InMemoryWebSocketPresenceStore;
14
5
  var init_ws_presence_store = __esmMin((() => {
6
+ init_ws_presence_index();
15
7
  InMemoryWebSocketPresenceStore = class {
16
- connections = /* @__PURE__ */ new Map();
17
- rooms = /* @__PURE__ */ new Map();
18
- users = /* @__PURE__ */ new Map();
8
+ index = new WebSocketPresenceIndex();
19
9
  register(input) {
20
- const meta = {
21
- sessionId: input.sessionId,
22
- nodeId: input.nodeId,
23
- namespace: input.namespace,
24
- active: input.active ?? true,
25
- rooms: /* @__PURE__ */ new Set(),
26
- connectedAt: /* @__PURE__ */ new Date(),
27
- lastSeenAt: /* @__PURE__ */ new Date()
28
- };
29
- this.connections.set(input.sessionId, meta);
30
- return meta;
10
+ this.index.register(input);
31
11
  }
32
12
  activate(sessionId) {
33
- const meta = this.connections.get(sessionId);
34
- if (!meta) return;
35
- meta.active = true;
13
+ this.index.activate(sessionId);
36
14
  }
37
15
  unregister(sessionId) {
38
- const meta = this.connections.get(sessionId);
39
- if (!meta) return;
40
- if (meta.userId !== void 0) this.removeUserBinding(meta.namespace, meta.userId, sessionId);
41
- for (const roomId of meta.rooms) this.removeRoomBinding(meta.namespace, roomId, sessionId);
42
- this.connections.delete(sessionId);
43
- return meta;
44
- }
45
- touch(sessionId) {
46
- const meta = this.connections.get(sessionId);
47
- if (!meta) return;
48
- meta.lastSeenAt = /* @__PURE__ */ new Date();
16
+ this.index.unregister(sessionId);
49
17
  }
50
18
  setUserId(sessionId, userId) {
51
- const meta = this.connections.get(sessionId);
52
- if (!meta) return;
53
- if (meta.userId !== void 0) this.removeUserBinding(meta.namespace, meta.userId, sessionId);
54
- meta.userId = userId;
55
- const key = getBindingKey(meta.namespace, String(userId));
56
- const bound = this.users.get(key) ?? /* @__PURE__ */ new Set();
57
- bound.add(sessionId);
58
- this.users.set(key, bound);
19
+ this.index.setUserId(sessionId, userId);
59
20
  }
60
21
  clearUserId(sessionId) {
61
- const meta = this.connections.get(sessionId);
62
- if (!meta || meta.userId === void 0) return;
63
- this.removeUserBinding(meta.namespace, meta.userId, sessionId);
64
- delete meta.userId;
22
+ this.index.clearUserId(sessionId);
65
23
  }
66
24
  join(sessionId, roomId) {
67
- const meta = this.connections.get(sessionId);
68
- if (!meta) return;
69
- meta.rooms.add(roomId);
70
- const key = getBindingKey(meta.namespace, roomId);
71
- const members = this.rooms.get(key) ?? /* @__PURE__ */ new Set();
72
- members.add(sessionId);
73
- this.rooms.set(key, members);
25
+ this.index.join(sessionId, roomId);
74
26
  }
75
27
  leave(sessionId, roomId) {
76
- const meta = this.connections.get(sessionId);
77
- if (!meta) return;
78
- meta.rooms.delete(roomId);
79
- this.removeRoomBinding(meta.namespace, roomId, sessionId);
80
- }
81
- getConnection(sessionId) {
82
- return this.connections.get(sessionId);
83
- }
84
- getConnectionCount(namespace) {
85
- let count = 0;
86
- for (const meta of this.connections.values()) {
87
- if (!meta.active || namespace && meta.namespace !== namespace) continue;
88
- count += 1;
89
- }
90
- return count;
28
+ this.index.leave(sessionId, roomId);
91
29
  }
92
- getRoomMembers(roomId, namespace) {
93
- return this.getBoundConnections(this.rooms, roomId, namespace);
94
- }
95
- getStats() {
96
- const byNamespace = {};
97
- for (const meta of this.connections.values()) {
98
- if (!meta.active) continue;
99
- byNamespace[meta.namespace] = (byNamespace[meta.namespace] ?? 0) + 1;
100
- }
30
+ resolveRoute(audience, nodeId) {
31
+ const localSessionIds = [];
32
+ const remoteNodeIds = /* @__PURE__ */ new Set();
33
+ for (const session of this.index.queryAudience(audience)) if (session.nodeId === nodeId) localSessionIds.push(session.sessionId);
34
+ else remoteNodeIds.add(session.nodeId);
101
35
  return {
102
- totalConnections: Object.values(byNamespace).reduce((sum, count) => sum + count, 0),
103
- totalRooms: this.rooms.size,
104
- byNamespace
36
+ localSessionIds,
37
+ remoteNodeIds: [...remoteNodeIds]
105
38
  };
106
39
  }
107
- queryAudience(audience) {
108
- switch (audience.type) {
109
- case "all": return this.getActiveConnections(audience.namespace);
110
- case "room": return this.getBoundConnections(this.rooms, audience.roomId, audience.namespace);
111
- case "user": return this.getBoundConnections(this.users, String(audience.userId), audience.namespace);
112
- case "connections": {
113
- const metas = [];
114
- for (const connectionId of audience.connectionIds) {
115
- const meta = this.connections.get(connectionId);
116
- if (!meta?.active) continue;
117
- if (audience.namespace && meta.namespace !== audience.namespace) continue;
118
- metas.push(meta);
119
- }
120
- return metas;
121
- }
122
- case "union": {
123
- const seen = /* @__PURE__ */ new Set();
124
- const metas = [];
125
- for (const item of audience.audiences) for (const meta of this.queryAudience(item)) {
126
- if (seen.has(meta.sessionId)) continue;
127
- seen.add(meta.sessionId);
128
- metas.push(meta);
129
- }
130
- return metas;
131
- }
132
- }
133
- }
134
- getActiveConnections(namespace) {
135
- const metas = [];
136
- for (const meta of this.connections.values()) {
137
- if (!meta.active || namespace && meta.namespace !== namespace) continue;
138
- metas.push(meta);
139
- }
140
- return metas;
141
- }
142
- getBoundConnections(bindings, id, namespace) {
143
- const metas = [];
144
- const seen = /* @__PURE__ */ new Set();
145
- for (const members of this.getScopedBindings(bindings, id, namespace)) for (const connectionId of members) {
146
- if (seen.has(connectionId)) continue;
147
- seen.add(connectionId);
148
- const meta = this.connections.get(connectionId);
149
- if (meta?.active) metas.push(meta);
150
- }
151
- return metas;
40
+ getRoomMemberCount(roomId, namespace) {
41
+ return this.index.getRoomMemberCount(roomId, namespace);
152
42
  }
153
- getScopedBindings(bindings, id, namespace) {
154
- if (namespace) {
155
- const exact = bindings.get(getBindingKey(namespace, id));
156
- return exact ? [exact] : [];
157
- }
158
- const matches = [];
159
- for (const [key, members] of bindings) if (parseBindingKey(key).id === id) matches.push(members);
160
- return matches;
161
- }
162
- removeRoomBinding(namespace, roomId, sessionId) {
163
- const key = getBindingKey(namespace, roomId);
164
- const members = this.rooms.get(key);
165
- if (!members) return;
166
- members.delete(sessionId);
167
- if (members.size === 0) this.rooms.delete(key);
168
- }
169
- removeUserBinding(namespace, userId, sessionId) {
170
- const key = getBindingKey(namespace, String(userId));
171
- const members = this.users.get(key);
172
- if (!members) return;
173
- members.delete(sessionId);
174
- if (members.size === 0) this.users.delete(key);
43
+ getConnection(sessionId) {
44
+ return this.index.getConnection(sessionId);
175
45
  }
176
46
  };
177
47
  }));
178
- //#endregion
179
48
  init_ws_presence_store();
180
49
  export { InMemoryWebSocketPresenceStore, init_ws_presence_store };
181
50
 
182
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtcHJlc2VuY2Utc3RvcmUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmVhbS93cy1wcmVzZW5jZS1zdG9yZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIFdlYlNvY2tldEF1ZGllbmNlIH0gZnJvbSBcIi4vd3MtYXVkaWVuY2VcIjtcbmltcG9ydCB7IHR5cGUgV2ViU29ja2V0UmVnaXN0cnlTdGF0cywgdHlwZSBXZWJTb2NrZXRSb29tSWQsIHR5cGUgV2ViU29ja2V0VXNlcklkIH0gZnJvbSBcIi4vd3MtY29yZVwiO1xuXG5leHBvcnQgdHlwZSBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgPSB7XG4gIHNlc3Npb25JZDogc3RyaW5nO1xuICBub2RlSWQ6IHN0cmluZztcbiAgbmFtZXNwYWNlOiBzdHJpbmc7XG4gIGFjdGl2ZTogYm9vbGVhbjtcbiAgcm9vbXM6IFNldDxXZWJTb2NrZXRSb29tSWQ+O1xuICBjb25uZWN0ZWRBdDogRGF0ZTtcbiAgbGFzdFNlZW5BdDogRGF0ZTtcbiAgdXNlcklkPzogV2ViU29ja2V0VXNlcklkO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBXZWJTb2NrZXRQcmVzZW5jZVN0b3JlIHtcbiAgcmVnaXN0ZXIoaW5wdXQ6IHtcbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgICBub2RlSWQ6IHN0cmluZztcbiAgICBuYW1lc3BhY2U6IHN0cmluZztcbiAgICBhY3RpdmU/OiBib29sZWFuO1xuICB9KTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlO1xuICBhY3RpdmF0ZShzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQ7XG4gIHVucmVnaXN0ZXIoc2Vzc2lvbklkOiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgfCB1bmRlZmluZWQ7XG4gIHRvdWNoKHNlc3Npb25JZDogc3RyaW5nKTogdm9pZDtcbiAgc2V0VXNlcklkKHNlc3Npb25JZDogc3RyaW5nLCB1c2VySWQ6IFdlYlNvY2tldFVzZXJJZCk6IHZvaWQ7XG4gIGNsZWFyVXNlcklkKHNlc3Npb25JZDogc3RyaW5nKTogdm9pZDtcbiAgam9pbihzZXNzaW9uSWQ6IHN0cmluZywgcm9vbUlkOiBXZWJTb2NrZXRSb29tSWQpOiB2b2lkO1xuICBsZWF2ZShzZXNzaW9uSWQ6IHN0cmluZywgcm9vbUlkOiBXZWJTb2NrZXRSb29tSWQpOiB2b2lkO1xuICBnZXRDb25uZWN0aW9uKHNlc3Npb25JZDogc3RyaW5nKTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlIHwgdW5kZWZpbmVkO1xuICBnZXRDb25uZWN0aW9uQ291bnQobmFtZXNwYWNlPzogc3RyaW5nKTogbnVtYmVyO1xuICBnZXRSb29tTWVtYmVycyhyb29tSWQ6IFdlYlNvY2tldFJvb21JZCwgbmFtZXNwYWNlPzogc3RyaW5nKTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlW107XG4gIGdldFN0YXRzKCk6IFdlYlNvY2tldFJlZ2lzdHJ5U3RhdHM7XG4gIHF1ZXJ5QXVkaWVuY2UoYXVkaWVuY2U6IFdlYlNvY2tldEF1ZGllbmNlKTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlW107XG59XG5cbmV4cG9ydCBjbGFzcyBJbk1lbW9yeVdlYlNvY2tldFByZXNlbmNlU3RvcmUgaW1wbGVtZW50cyBXZWJTb2NrZXRQcmVzZW5jZVN0b3JlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb25uZWN0aW9ucyA9IG5ldyBNYXA8c3RyaW5nLCBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2U+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcm9vbXMgPSBuZXcgTWFwPHN0cmluZywgU2V0PHN0cmluZz4+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdXNlcnMgPSBuZXcgTWFwPHN0cmluZywgU2V0PHN0cmluZz4+KCk7XG5cbiAgcmVnaXN0ZXIoaW5wdXQ6IHtcbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgICBub2RlSWQ6IHN0cmluZztcbiAgICBuYW1lc3BhY2U6IHN0cmluZztcbiAgICBhY3RpdmU/OiBib29sZWFuO1xuICB9KTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlIHtcbiAgICBjb25zdCBtZXRhOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgPSB7XG4gICAgICBzZXNzaW9uSWQ6IGlucHV0LnNlc3Npb25JZCxcbiAgICAgIG5vZGVJZDogaW5wdXQubm9kZUlkLFxuICAgICAgbmFtZXNwYWNlOiBpbnB1dC5uYW1lc3BhY2UsXG4gICAgICBhY3RpdmU6IGlucHV0LmFjdGl2ZSA/PyB0cnVlLFxuICAgICAgcm9vbXM6IG5ldyBTZXQoKSxcbiAgICAgIGNvbm5lY3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgbGFzdFNlZW5BdDogbmV3IERhdGUoKSxcbiAgICB9O1xuICAgIHRoaXMuY29ubmVjdGlvbnMuc2V0KGlucHV0LnNlc3Npb25JZCwgbWV0YSk7XG4gICAgcmV0dXJuIG1ldGE7XG4gIH1cblxuICBhY3RpdmF0ZShzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmNvbm5lY3Rpb25zLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghbWV0YSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIG1ldGEuYWN0aXZlID0gdHJ1ZTtcbiAgfVxuXG4gIHVucmVnaXN0ZXIoc2Vzc2lvbklkOiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmNvbm5lY3Rpb25zLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghbWV0YSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAobWV0YS51c2VySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5yZW1vdmVVc2VyQmluZGluZyhtZXRhLm5hbWVzcGFjZSwgbWV0YS51c2VySWQsIHNlc3Npb25JZCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByb29tSWQgb2YgbWV0YS5yb29tcykge1xuICAgICAgdGhpcy5yZW1vdmVSb29tQmluZGluZyhtZXRhLm5hbWVzcGFjZSwgcm9vbUlkLCBzZXNzaW9uSWQpO1xuICAgIH1cblxuICAgIHRoaXMuY29ubmVjdGlvbnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgcmV0dXJuIG1ldGE7XG4gIH1cblxuICB0b3VjaChzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmNvbm5lY3Rpb25zLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghbWV0YSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIG1ldGEubGFzdFNlZW5BdCA9IG5ldyBEYXRlKCk7XG4gIH1cblxuICBzZXRVc2VySWQoc2Vzc2lvbklkOiBzdHJpbmcsIHVzZXJJZDogV2ViU29ja2V0VXNlcklkKTogdm9pZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuY29ubmVjdGlvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFtZXRhKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG1ldGEudXNlcklkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMucmVtb3ZlVXNlckJpbmRpbmcobWV0YS5uYW1lc3BhY2UsIG1ldGEudXNlcklkLCBzZXNzaW9uSWQpO1xuICAgIH1cblxuICAgIG1ldGEudXNlcklkID0gdXNlcklkO1xuICAgIGNvbnN0IGtleSA9IGdldEJpbmRpbmdLZXkobWV0YS5uYW1lc3BhY2UsIFN0cmluZyh1c2VySWQpKTtcbiAgICBjb25zdCBib3VuZCA9IHRoaXMudXNlcnMuZ2V0KGtleSkgPz8gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgYm91bmQuYWRkKHNlc3Npb25JZCk7XG4gICAgdGhpcy51c2Vycy5zZXQoa2V5LCBib3VuZCk7XG4gIH1cblxuICBjbGVhclVzZXJJZChzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmNvbm5lY3Rpb25zLmdldChzZXNzaW9uSWQpO1xuICAgIGlmICghbWV0YSB8fCBtZXRhLnVzZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmVVc2VyQmluZGluZyhtZXRhLm5hbWVzcGFjZSwgbWV0YS51c2VySWQsIHNlc3Npb25JZCk7XG4gICAgZGVsZXRlIG1ldGEudXNlcklkO1xuICB9XG5cbiAgam9pbihzZXNzaW9uSWQ6IHN0cmluZywgcm9vbUlkOiBXZWJTb2NrZXRSb29tSWQpOiB2b2lkIHtcbiAgICBjb25zdCBtZXRhID0gdGhpcy5jb25uZWN0aW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIW1ldGEpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBtZXRhLnJvb21zLmFkZChyb29tSWQpO1xuICAgIGNvbnN0IGtleSA9IGdldEJpbmRpbmdLZXkobWV0YS5uYW1lc3BhY2UsIHJvb21JZCk7XG4gICAgY29uc3QgbWVtYmVycyA9IHRoaXMucm9vbXMuZ2V0KGtleSkgPz8gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgbWVtYmVycy5hZGQoc2Vzc2lvbklkKTtcbiAgICB0aGlzLnJvb21zLnNldChrZXksIG1lbWJlcnMpO1xuICB9XG5cbiAgbGVhdmUoc2Vzc2lvbklkOiBzdHJpbmcsIHJvb21JZDogV2ViU29ja2V0Um9vbUlkKTogdm9pZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuY29ubmVjdGlvbnMuZ2V0KHNlc3Npb25JZCk7XG4gICAgaWYgKCFtZXRhKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbWV0YS5yb29tcy5kZWxldGUocm9vbUlkKTtcbiAgICB0aGlzLnJlbW92ZVJvb21CaW5kaW5nKG1ldGEubmFtZXNwYWNlLCByb29tSWQsIHNlc3Npb25JZCk7XG4gIH1cblxuICBnZXRDb25uZWN0aW9uKHNlc3Npb25JZDogc3RyaW5nKTogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgfVxuXG4gIGdldENvbm5lY3Rpb25Db3VudChuYW1lc3BhY2U/OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IG1ldGEgb2YgdGhpcy5jb25uZWN0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgaWYgKCFtZXRhLmFjdGl2ZSB8fCAobmFtZXNwYWNlICYmIG1ldGEubmFtZXNwYWNlICE9PSBuYW1lc3BhY2UpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb3VudCArPSAxO1xuICAgIH1cblxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIGdldFJvb21NZW1iZXJzKHJvb21JZDogV2ViU29ja2V0Um9vbUlkLCBuYW1lc3BhY2U/OiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Qm91bmRDb25uZWN0aW9ucyh0aGlzLnJvb21zLCByb29tSWQsIG5hbWVzcGFjZSk7XG4gIH1cblxuICBnZXRTdGF0cygpOiBXZWJTb2NrZXRSZWdpc3RyeVN0YXRzIHtcbiAgICBjb25zdCBieU5hbWVzcGFjZTogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBtZXRhIG9mIHRoaXMuY29ubmVjdGlvbnMudmFsdWVzKCkpIHtcbiAgICAgIGlmICghbWV0YS5hY3RpdmUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBieU5hbWVzcGFjZVttZXRhLm5hbWVzcGFjZV0gPSAoYnlOYW1lc3BhY2VbbWV0YS5uYW1lc3BhY2VdID8/IDApICsgMTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG90YWxDb25uZWN0aW9uczogT2JqZWN0LnZhbHVlcyhieU5hbWVzcGFjZSkucmVkdWNlKChzdW0sIGNvdW50KSA9PiBzdW0gKyBjb3VudCwgMCksXG4gICAgICB0b3RhbFJvb21zOiB0aGlzLnJvb21zLnNpemUsXG4gICAgICBieU5hbWVzcGFjZSxcbiAgICB9O1xuICB9XG5cbiAgcXVlcnlBdWRpZW5jZShhdWRpZW5jZTogV2ViU29ja2V0QXVkaWVuY2UpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2VbXSB7XG4gICAgc3dpdGNoIChhdWRpZW5jZS50eXBlKSB7XG4gICAgICBjYXNlIFwiYWxsXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmdldEFjdGl2ZUNvbm5lY3Rpb25zKGF1ZGllbmNlLm5hbWVzcGFjZSk7XG4gICAgICBjYXNlIFwicm9vbVwiOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRCb3VuZENvbm5lY3Rpb25zKHRoaXMucm9vbXMsIGF1ZGllbmNlLnJvb21JZCwgYXVkaWVuY2UubmFtZXNwYWNlKTtcbiAgICAgIGNhc2UgXCJ1c2VyXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmdldEJvdW5kQ29ubmVjdGlvbnModGhpcy51c2VycywgU3RyaW5nKGF1ZGllbmNlLnVzZXJJZCksIGF1ZGllbmNlLm5hbWVzcGFjZSk7XG4gICAgICBjYXNlIFwiY29ubmVjdGlvbnNcIjoge1xuICAgICAgICBjb25zdCBtZXRhczogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlW10gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBvZiBhdWRpZW5jZS5jb25uZWN0aW9uSWRzKSB7XG4gICAgICAgICAgY29uc3QgbWV0YSA9IHRoaXMuY29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgaWYgKCFtZXRhPy5hY3RpdmUpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoYXVkaWVuY2UubmFtZXNwYWNlICYmIG1ldGEubmFtZXNwYWNlICE9PSBhdWRpZW5jZS5uYW1lc3BhY2UpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBtZXRhcy5wdXNoKG1ldGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1ldGFzO1xuICAgICAgfVxuICAgICAgY2FzZSBcInVuaW9uXCI6IHtcbiAgICAgICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgICBjb25zdCBtZXRhczogV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlW10gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXVkaWVuY2UuYXVkaWVuY2VzKSB7XG4gICAgICAgICAgZm9yIChjb25zdCBtZXRhIG9mIHRoaXMucXVlcnlBdWRpZW5jZShpdGVtKSkge1xuICAgICAgICAgICAgaWYgKHNlZW4uaGFzKG1ldGEuc2Vzc2lvbklkKSkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2Vlbi5hZGQobWV0YS5zZXNzaW9uSWQpO1xuICAgICAgICAgICAgbWV0YXMucHVzaChtZXRhKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbWV0YXM7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRBY3RpdmVDb25uZWN0aW9ucyhuYW1lc3BhY2U/OiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2VbXSB7XG4gICAgY29uc3QgbWV0YXM6IFdlYlNvY2tldFNlc3Npb25QcmVzZW5jZVtdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IG1ldGEgb2YgdGhpcy5jb25uZWN0aW9ucy52YWx1ZXMoKSkge1xuICAgICAgaWYgKCFtZXRhLmFjdGl2ZSB8fCAobmFtZXNwYWNlICYmIG1ldGEubmFtZXNwYWNlICE9PSBuYW1lc3BhY2UpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBtZXRhcy5wdXNoKG1ldGEpO1xuICAgIH1cblxuICAgIHJldHVybiBtZXRhcztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Qm91bmRDb25uZWN0aW9ucyhcbiAgICBiaW5kaW5nczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgbmFtZXNwYWNlPzogc3RyaW5nLFxuICApOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2VbXSB7XG4gICAgY29uc3QgbWV0YXM6IFdlYlNvY2tldFNlc3Npb25QcmVzZW5jZVtdID0gW107XG4gICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgZm9yIChjb25zdCBtZW1iZXJzIG9mIHRoaXMuZ2V0U2NvcGVkQmluZGluZ3MoYmluZGluZ3MsIGlkLCBuYW1lc3BhY2UpKSB7XG4gICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBvZiBtZW1iZXJzKSB7XG4gICAgICAgIGlmIChzZWVuLmhhcyhjb25uZWN0aW9uSWQpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgc2Vlbi5hZGQoY29ubmVjdGlvbklkKTtcblxuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5jb25uZWN0aW9ucy5nZXQoY29ubmVjdGlvbklkKTtcbiAgICAgICAgaWYgKG1ldGE/LmFjdGl2ZSkge1xuICAgICAgICAgIG1ldGFzLnB1c2gobWV0YSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWV0YXM7XG4gIH1cblxuICBwcml2YXRlIGdldFNjb3BlZEJpbmRpbmdzKFxuICAgIGJpbmRpbmdzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4sXG4gICAgaWQ6IHN0cmluZyxcbiAgICBuYW1lc3BhY2U/OiBzdHJpbmcsXG4gICk6IFNldDxzdHJpbmc+W10ge1xuICAgIGlmIChuYW1lc3BhY2UpIHtcbiAgICAgIGNvbnN0IGV4YWN0ID0gYmluZGluZ3MuZ2V0KGdldEJpbmRpbmdLZXkobmFtZXNwYWNlLCBpZCkpO1xuICAgICAgcmV0dXJuIGV4YWN0ID8gW2V4YWN0XSA6IFtdO1xuICAgIH1cblxuICAgIGNvbnN0IG1hdGNoZXM6IFNldDxzdHJpbmc+W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIG1lbWJlcnNdIG9mIGJpbmRpbmdzKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUJpbmRpbmdLZXkoa2V5KTtcbiAgICAgIGlmIChwYXJzZWQuaWQgPT09IGlkKSB7XG4gICAgICAgIG1hdGNoZXMucHVzaChtZW1iZXJzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWF0Y2hlcztcbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlUm9vbUJpbmRpbmcobmFtZXNwYWNlOiBzdHJpbmcsIHJvb21JZDogV2ViU29ja2V0Um9vbUlkLCBzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGtleSA9IGdldEJpbmRpbmdLZXkobmFtZXNwYWNlLCByb29tSWQpO1xuICAgIGNvbnN0IG1lbWJlcnMgPSB0aGlzLnJvb21zLmdldChrZXkpO1xuICAgIGlmICghbWVtYmVycykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIG1lbWJlcnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgaWYgKG1lbWJlcnMuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy5yb29tcy5kZWxldGUoa2V5KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZVVzZXJCaW5kaW5nKG5hbWVzcGFjZTogc3RyaW5nLCB1c2VySWQ6IFdlYlNvY2tldFVzZXJJZCwgc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBrZXkgPSBnZXRCaW5kaW5nS2V5KG5hbWVzcGFjZSwgU3RyaW5nKHVzZXJJZCkpO1xuICAgIGNvbnN0IG1lbWJlcnMgPSB0aGlzLnVzZXJzLmdldChrZXkpO1xuICAgIGlmICghbWVtYmVycykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIG1lbWJlcnMuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgaWYgKG1lbWJlcnMuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy51c2Vycy5kZWxldGUoa2V5KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0QmluZGluZ0tleShuYW1lc3BhY2U6IHN0cmluZywgaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtuYW1lc3BhY2V9Ojoke2lkfWA7XG59XG5cbmludGVyZmFjZSBQcmVzZW5jZUJpbmRpbmcge1xuICBuYW1lc3BhY2U6IHN0cmluZztcbiAgaWQ6IHN0cmluZztcbn1cblxuZnVuY3Rpb24gcGFyc2VCaW5kaW5nS2V5KGtleTogc3RyaW5nKTogUHJlc2VuY2VCaW5kaW5nIHtcbiAgY29uc3QgW25hbWVzcGFjZSwgLi4ucmVzdF0gPSBrZXkuc3BsaXQoXCI6OlwiKTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lc3BhY2UsXG4gICAgaWQ6IHJlc3Quam9pbihcIjo6XCIpLFxuICB9O1xufVxuIl0sIm1hcHBpbmdzIjoiOztBQTJUQSxTQUFTLGNBQWMsV0FBbUIsSUFBb0I7Q0FDNUQsT0FBTyxHQUFHLFVBQVUsSUFBSTtBQUMxQjtBQU9BLFNBQVMsZ0JBQWdCLEtBQThCO0NBQ3JELE1BQU0sQ0FBQyxXQUFXLEdBQUcsUUFBUSxJQUFJLE1BQU0sSUFBSTtDQUMzQyxPQUFPO0VBQ0w7RUFDQSxJQUFJLEtBQUssS0FBSyxJQUFJO0NBQ3BCO0FBQ0Y7OztDQXZTYSxpQ0FBYixNQUE4RTtFQUM1RSw4QkFBK0IsSUFBSSxJQUFzQztFQUN6RSx3QkFBeUIsSUFBSSxJQUF5QjtFQUN0RCx3QkFBeUIsSUFBSSxJQUF5QjtFQUV0RCxTQUFTLE9BS29CO0dBQzNCLE1BQU0sT0FBaUM7SUFDckMsV0FBVyxNQUFNO0lBQ2pCLFFBQVEsTUFBTTtJQUNkLFdBQVcsTUFBTTtJQUNqQixRQUFRLE1BQU0sVUFBVTtJQUN4Qix1QkFBTyxJQUFJLElBQUk7SUFDZiw2QkFBYSxJQUFJLEtBQUs7SUFDdEIsNEJBQVksSUFBSSxLQUFLO0dBQ3ZCO0dBQ0EsS0FBSyxZQUFZLElBQUksTUFBTSxXQUFXLElBQUk7R0FDMUMsT0FBTztFQUNUO0VBRUEsU0FBUyxXQUF5QjtHQUNoQyxNQUFNLE9BQU8sS0FBSyxZ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
51
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtcHJlc2VuY2Utc3RvcmUuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0cmVhbS93cy1wcmVzZW5jZS1zdG9yZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIFdlYlNvY2tldEF1ZGllbmNlIH0gZnJvbSBcIi4vd3MtYXVkaWVuY2VcIjtcbmltcG9ydCB7IHR5cGUgTWF5YmVQcm9taXNlLCB0eXBlIFdlYlNvY2tldFJvb21JZCwgdHlwZSBXZWJTb2NrZXRVc2VySWQgfSBmcm9tIFwiLi93cy1jb3JlXCI7XG5pbXBvcnQgeyBXZWJTb2NrZXRQcmVzZW5jZUluZGV4IH0gZnJvbSBcIi4vd3MtcHJlc2VuY2UtaW5kZXhcIjtcblxuLyoqXG4gKiDshLjshZggcHJlc2VuY2Ugc25hcHNob3QuIGxpdmUg6rCd7LK06rCAIOyVhOuLiOuvgOuhnCDqsJLsnYQg67CU6r+U64+EIHJlZ2lzdHJ564KYIHN0b3JlIOyDge2DnOyXkCDsmIHtlqXsnYQg7KO87KeAIOyViuuKlOuLpC5cbiAqL1xuZXhwb3J0IHR5cGUgV2ViU29ja2V0U2Vzc2lvblByZXNlbmNlID0ge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgbm9kZUlkOiBzdHJpbmc7XG4gIG5hbWVzcGFjZTogc3RyaW5nO1xuICBhY3RpdmU6IGJvb2xlYW47XG4gIHJvb21zOiBTZXQ8V2ViU29ja2V0Um9vbUlkPjtcbiAgY29ubmVjdGVkQXQ6IERhdGU7XG4gIGxhc3RTZWVuQXQ6IERhdGU7XG4gIHVzZXJJZD86IFdlYlNvY2tldFVzZXJJZDtcbn07XG5cbmV4cG9ydCB0eXBlIFdlYlNvY2tldFByZXNlbmNlUmVnaXN0cmF0aW9uID0ge1xuICBzZXNzaW9uSWQ6IHN0cmluZztcbiAgbm9kZUlkOiBzdHJpbmc7XG4gIG5hbWVzcGFjZTogc3RyaW5nO1xuICBhY3RpdmU6IGJvb2xlYW47XG4gIGNvbm5lY3RlZEF0OiBEYXRlO1xufTtcblxuZXhwb3J0IHR5cGUgV2ViU29ja2V0Um91dGluZ1BsYW4gPSB7XG4gIGxvY2FsU2Vzc2lvbklkczogc3RyaW5nW107XG4gIHJlbW90ZU5vZGVJZHM6IHN0cmluZ1tdO1xufTtcblxuLyoqXG4gKiDtgbTrn6zsiqTthLAgcHJlc2VuY2UgcmVwbGljYSDqs4Tslb0uIOqwgSDrhbjrk5zsnZggcmVnaXN0cnnqsIAg7J6Q6riwIOyEuOyFmOydmCBtdXRhdGlvbuydhCDshLjshZjrs4Qg7Zi47LacIOyInOyEnOuMgOuhnCDsoITri6ztlZzri6QuXG4gKiDrqqjrk6Ag66mU7ISc65Oc64qUIOqwkuydtOuCmCBwcm9taXNl66W8IOuwmO2ZmO2VoCDsiJgg7J6I6rOgLCByZWdpc3RyeeuKlCDrj5nquLAgdGhyb3frj4QgcmVqZWN0aW9u7Jy866GcIOuwlOq/lCDsspjrpqztlZzri6QuXG4gKiB1c2VySWTripQg7YOA7J6F6rmM7KeAIOydvOy5mO2VtOyVvCDrp6Tsua3rkJzri6QoMeqzvCBcIjFcIuydgCDri6TrpbTri6QpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdlYlNvY2tldFByZXNlbmNlU3RvcmUge1xuICAvLyDshKTsoJXtlZjrqbQgcnVudGltZSBub2RlSWTsmYAg6rCZ7JWE7JW8IO2VnOuLpC4g64uk66W066m0IHJ1bnRpbWUg7IOd7ISx7J20IOyLpO2MqO2VnOuLpFxuICByZWFkb25seSBub2RlSWQ/OiBzdHJpbmc7XG4gIHJlZ2lzdGVyKGlucHV0OiBXZWJTb2NrZXRQcmVzZW5jZVJlZ2lzdHJhdGlvbik6IE1heWJlUHJvbWlzZTx2b2lkPjtcbiAgYWN0aXZhdGUoc2Vzc2lvbklkOiBzdHJpbmcpOiBNYXliZVByb21pc2U8dm9pZD47XG4gIHVucmVnaXN0ZXIoc2Vzc2lvbklkOiBzdHJpbmcpOiBNYXliZVByb21pc2U8dm9pZD47XG4gIHNldFVzZXJJZChzZXNzaW9uSWQ6IHN0cmluZywgdXNlcklkOiBXZWJTb2NrZXRVc2VySWQpOiBNYXliZVByb21pc2U8dm9pZD47XG4gIGNsZWFyVXNlcklkKHNlc3Npb25JZDogc3RyaW5nKTogTWF5YmVQcm9taXNlPHZvaWQ+O1xuICBqb2luKHNlc3Npb25JZDogc3RyaW5nLCByb29tSWQ6IFdlYlNvY2tldFJvb21JZCk6IE1heWJlUHJvbWlzZTx2b2lkPjtcbiAgbGVhdmUoc2Vzc2lvbklkOiBzdHJpbmcsIHJvb21JZDogV2ViU29ja2V0Um9vbUlkKTogTWF5YmVQcm9taXNlPHZvaWQ+O1xuICAvLyBub2RlSWQg6rSA7KCQ7JeQ7IScIGF1ZGllbmNl66W8IOuhnOy7rCDshLjshZggSUTsmYAg7KSR67O1IOyXhuuKlCDsm5Dqsqkg64W465OcIElE66GcIOuCmOuIiOuLpC4g67mE7Zmc7ISxIOyEuOyFmOydgCDsoJzsmbjtlZzri6RcbiAgcmVzb2x2ZVJvdXRlKGF1ZGllbmNlOiBXZWJTb2NrZXRBdWRpZW5jZSwgbm9kZUlkOiBzdHJpbmcpOiBNYXliZVByb21pc2U8V2ViU29ja2V0Um91dGluZ1BsYW4+O1xuICAvLyDtgbTrn6zsiqTthLAg7KCE7LK07J2YIO2ZnOyEsSDrsKkg7J247JuQ7IiYXG4gIGdldFJvb21NZW1iZXJDb3VudChyb29tSWQ6IFdlYlNvY2tldFJvb21JZCwgbmFtZXNwYWNlPzogc3RyaW5nKTogTWF5YmVQcm9taXNlPG51bWJlcj47XG4gIHNodXRkb3duPygpOiBNYXliZVByb21pc2U8dm9pZD47XG59XG5cbi8qKlxuICog7ZSE66Gc7IS47IqkIOuplOuqqOumrOyXkCBwcmVzZW5jZeulvCDrkZDripQgc3RvcmUuIOuLqOydvCDrhbjrk5zsnZgg6riw67O46rCS7J2066mwLCDqsJnsnYAg7ZSE66Gc7IS47Iqk7J2YIOyXrOufrCBydW50aW1l7J20IOqzteycoO2VmOuptCDtgbTrn6zsiqTthLAgcmVwbGljYeuhnOuPhCDrj5nsnpHtlZzri6QuXG4gKi9cbmV4cG9ydCBjbGFzcyBJbk1lbW9yeVdlYlNvY2tldFByZXNlbmNlU3RvcmUgaW1wbGVtZW50cyBXZWJTb2NrZXRQcmVzZW5jZVN0b3JlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRleCA9IG5ldyBXZWJTb2NrZXRQcmVzZW5jZUluZGV4KCk7XG5cbiAgcmVnaXN0ZXIoaW5wdXQ6IFdlYlNvY2tldFByZXNlbmNlUmVnaXN0cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5pbmRleC5yZWdpc3RlcihpbnB1dCk7XG4gIH1cblxuICBhY3RpdmF0ZShzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuaW5kZXguYWN0aXZhdGUoc2Vzc2lvbklkKTtcbiAgfVxuXG4gIHVucmVnaXN0ZXIoc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmluZGV4LnVucmVnaXN0ZXIoc2Vzc2lvbklkKTtcbiAgfVxuXG4gIHNldFVzZXJJZChzZXNzaW9uSWQ6IHN0cmluZywgdXNlcklkOiBXZWJTb2NrZXRVc2VySWQpOiB2b2lkIHtcbiAgICB0aGlzLmluZGV4LnNldFVzZXJJZChzZXNzaW9uSWQsIHVzZXJJZCk7XG4gIH1cblxuICBjbGVhclVzZXJJZChzZXNzaW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuaW5kZXguY2xlYXJVc2VySWQoc2Vzc2lvbklkKTtcbiAgfVxuXG4gIGpvaW4oc2Vzc2lvbklkOiBzdHJpbmcsIHJvb21JZDogV2ViU29ja2V0Um9vbUlkKTogdm9pZCB7XG4gICAgdGhpcy5pbmRleC5qb2luKHNlc3Npb25JZCwgcm9vbUlkKTtcbiAgfVxuXG4gIGxlYXZlKHNlc3Npb25JZDogc3RyaW5nLCByb29tSWQ6IFdlYlNvY2tldFJvb21JZCk6IHZvaWQge1xuICAgIHRoaXMuaW5kZXgubGVhdmUoc2Vzc2lvbklkLCByb29tSWQpO1xuICB9XG5cbiAgcmVzb2x2ZVJvdXRlKGF1ZGllbmNlOiBXZWJTb2NrZXRBdWRpZW5jZSwgbm9kZUlkOiBzdHJpbmcpOiBXZWJTb2NrZXRSb3V0aW5nUGxhbiB7XG4gICAgY29uc3QgbG9jYWxTZXNzaW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHJlbW90ZU5vZGVJZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAgIGZvciAoY29uc3Qgc2Vzc2lvbiBvZiB0aGlzLmluZGV4LnF1ZXJ5QXVkaWVuY2UoYXVkaWVuY2UpKSB7XG4gICAgICBpZiAoc2Vzc2lvbi5ub2RlSWQgPT09IG5vZGVJZCkge1xuICAgICAgICBsb2NhbFNlc3Npb25JZHMucHVzaChzZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZW1vdGVOb2RlSWRzLmFkZChzZXNzaW9uLm5vZGVJZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbG9jYWxTZXNzaW9uSWRzLCByZW1vdGVOb2RlSWRzOiBbLi4ucmVtb3RlTm9kZUlkc10gfTtcbiAgfVxuXG4gIGdldFJvb21NZW1iZXJDb3VudChyb29tSWQ6IFdlYlNvY2tldFJvb21JZCwgbmFtZXNwYWNlPzogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5pbmRleC5nZXRSb29tTWVtYmVyQ291bnQocm9vbUlkLCBuYW1lc3BhY2UpO1xuICB9XG5cbiAgLy8g67O17IKs67O47J2EIOuwmO2ZmO2VmOuvgOuhnCDtmLjstpzsnpDqsIAg6rCS7J2EIOuwlOq/lOuPhCBzdG9yZSDsg4Htg5zripQg6re464yA66Gc64ukXG4gIGdldENvbm5lY3Rpb24oc2Vzc2lvbklkOiBzdHJpbmcpOiBXZWJTb2NrZXRTZXNzaW9uUHJlc2VuY2UgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmluZGV4LmdldENvbm5lY3Rpb24oc2Vzc2lvbklkKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7OztDQUU0RCx1QkFBQTtDQXNEL0MsaUNBQWIsTUFBOEU7RUFDNUUsUUFBeUIsSUFBSSx1QkFBdUI7RUFFcEQsU0FBUyxPQUE0QztHQUNuRCxLQUFLLE1BQU0sU0FBUyxLQUFLO0VBQzNCO0VBRUEsU0FBUyxXQUF5QjtHQUNoQyxLQUFLLE1BQU0sU0FBUyxTQUFTO0VBQy9CO0VBRUEsV0FBVyxXQUF5QjtHQUNsQyxLQUFLLE1BQU0sV0FBVyxTQUFTO0VBQ2pDO0VBRUEsVUFBVSxXQUFtQixRQUErQjtHQUMxRCxLQUFLLE1BQU0sVUFBVSxXQUFXLE1BQU07RUFDeEM7RUFFQSxZQUFZLFdBQXlCO0dBQ25DLEtBQUssTUFBTSxZQUFZLFNBQVM7RUFDbEM7RUFFQSxLQUFLLFdBQW1CLFFBQStCO0dBQ3JELEtBQUssTUFBTSxLQUFLLFdBQVcsTUFBTTtFQUNuQztFQUVBLE1BQU0sV0FBbUIsUUFBK0I7R0FDdEQsS0FBSyxNQUFNLE1BQU0sV0FBVyxNQUFNO0VBQ3BDO0VBRUEsYUFBYSxVQUE2QixRQUFzQztHQUM5RSxNQUFNLGtCQUE0QixDQUFDO0dBQ25DLE1BQU0sZ0NBQWdCLElBQUksSUFBWTtHQUV0QyxLQUFLLE1BQU0sV0FBVyxLQUFLLE1BQU0sY0FBYyxRQUFRLEdBQ3JELElBQUksUUFBUSxXQUFXLFFBQ3JCLGdCQUFnQixLQUFLLFFBQVEsU0FBUztRQUV0QyxjQUFjLElBQUksUUFBUSxNQUFNO0dBSXBDLE9BQU87SUFBRTtJQUFpQixlQUFlLENBQUMsR0FBRyxhQUFhO0dBQUU7RUFDOUQ7RUFFQSxtQkFBbUIsUUFBeUIsV0FBNEI7R0FDdEUsT0FBTyxLQUFLLE1BQU0sbUJBQW1CLFFBQVEsU0FBUztFQUN4RDtFQUdBLGNBQWMsV0FBeUQ7R0FDckUsT0FBTyxLQUFLLE1BQU0sY0FBYyxTQUFTO0VBQzNDO0NBQ0YifQ==