gemi 0.122.0 → 0.124.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.
- package/dist/ai/index.js +2 -2
- package/dist/ai/index.js.map +1 -1
- package/dist/app/App.d.ts +9 -0
- package/dist/app/App.d.ts.map +1 -1
- package/dist/app/index.js +1 -1
- package/dist/auth/AuthController.d.ts.map +1 -1
- package/dist/bin/gemi.js +4 -1
- package/dist/bin/gemi.js.map +3 -3
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-7ftj43vp.js → chunk-019wz697.js} +2 -2
- package/dist/{chunk-7ftj43vp.js.map → chunk-019wz697.js.map} +1 -1
- package/dist/{chunk-s5k3yq6t.js → chunk-121p4g9j.js} +2 -2
- package/dist/{chunk-s5k3yq6t.js.map → chunk-121p4g9j.js.map} +1 -1
- package/dist/{chunk-tewhms9w.js → chunk-17dndh5z.js} +2 -2
- package/dist/{chunk-3gsv1vv1.js.map → chunk-17dndh5z.js.map} +1 -1
- package/dist/{chunk-r01aqf0q.js → chunk-1qwhty9p.js} +2 -2
- package/dist/{chunk-r01aqf0q.js.map → chunk-1qwhty9p.js.map} +1 -1
- package/dist/{chunk-471htqmz.js → chunk-1rnh9qrp.js} +2 -2
- package/dist/{chunk-471htqmz.js.map → chunk-1rnh9qrp.js.map} +1 -1
- package/dist/{chunk-dedqr5wb.js → chunk-2affxmkn.js} +2 -2
- package/dist/{chunk-dedqr5wb.js.map → chunk-2affxmkn.js.map} +1 -1
- package/dist/{chunk-19dpzp4y.js → chunk-2n4490pk.js} +3 -3
- package/dist/{chunk-19dpzp4y.js.map → chunk-2n4490pk.js.map} +1 -1
- package/dist/{chunk-9xyxbxgk.js → chunk-30xxc6r7.js} +2 -2
- package/dist/{chunk-9xyxbxgk.js.map → chunk-30xxc6r7.js.map} +1 -1
- package/dist/{chunk-vx7hvyvq.js → chunk-34fkx6kb.js} +2 -2
- package/dist/{chunk-vx7hvyvq.js.map → chunk-34fkx6kb.js.map} +1 -1
- package/dist/{chunk-5nj94s66.js → chunk-3hqwz48c.js} +4 -4
- package/dist/{chunk-5nj94s66.js.map → chunk-3hqwz48c.js.map} +1 -1
- package/dist/{chunk-dhbgrv58.js → chunk-3j6s5bmx.js} +1 -1
- package/dist/{chunk-cskqet01.js → chunk-3y294mb8.js} +2 -2
- package/dist/{chunk-cskqet01.js.map → chunk-3y294mb8.js.map} +1 -1
- package/dist/{chunk-qsz9241c.js → chunk-4drnyymm.js} +2 -2
- package/dist/{chunk-qsz9241c.js.map → chunk-4drnyymm.js.map} +1 -1
- package/dist/{chunk-zg6hmc48.js → chunk-5e22tm7m.js} +1 -1
- package/dist/chunk-5j50q4g8.js +57 -0
- package/dist/{chunk-3s21p9n2.js.map → chunk-5j50q4g8.js.map} +19 -9
- package/dist/{chunk-0k02tza1.js → chunk-65s834td.js} +1 -1
- package/dist/{chunk-7mmw0jr2.js → chunk-675kzd7z.js} +2 -2
- package/dist/{chunk-7mmw0jr2.js.map → chunk-675kzd7z.js.map} +1 -1
- package/dist/{chunk-gy81nd9a.js → chunk-6bgb1nhq.js} +2 -2
- package/dist/{chunk-gy81nd9a.js.map → chunk-6bgb1nhq.js.map} +1 -1
- package/dist/chunk-70nnh0y7.js +5 -0
- package/dist/{chunk-htgmy3x7.js.map → chunk-70nnh0y7.js.map} +1 -1
- package/dist/{chunk-er8acmch.js → chunk-75ewjc4a.js} +2 -2
- package/dist/{chunk-er8acmch.js.map → chunk-75ewjc4a.js.map} +1 -1
- package/dist/{chunk-2c0s0561.js → chunk-7gfdts60.js} +2 -2
- package/dist/{chunk-2c0s0561.js.map → chunk-7gfdts60.js.map} +1 -1
- package/dist/{chunk-zefs2b6h.js → chunk-8m2htvjn.js} +2 -2
- package/dist/{chunk-zefs2b6h.js.map → chunk-8m2htvjn.js.map} +1 -1
- package/dist/{chunk-dwedx1jb.js → chunk-92sk56n0.js} +3 -3
- package/dist/{chunk-dwedx1jb.js.map → chunk-92sk56n0.js.map} +1 -1
- package/dist/{chunk-yds7zwc3.js → chunk-96a1459v.js} +2 -2
- package/dist/{chunk-yds7zwc3.js.map → chunk-96a1459v.js.map} +1 -1
- package/dist/{chunk-c7qs1xp3.js → chunk-9tr92nwy.js} +2 -2
- package/dist/{chunk-c7qs1xp3.js.map → chunk-9tr92nwy.js.map} +1 -1
- package/dist/{chunk-1wnnkde0.js → chunk-a3g7y70h.js} +3 -3
- package/dist/{chunk-1wnnkde0.js.map → chunk-a3g7y70h.js.map} +1 -1
- package/dist/{chunk-zrcd9hxr.js → chunk-b5afy6k9.js} +2 -2
- package/dist/{chunk-zrcd9hxr.js.map → chunk-b5afy6k9.js.map} +1 -1
- package/dist/{chunk-c0v61fp5.js → chunk-bnt8kx6x.js} +2 -2
- package/dist/{chunk-c0v61fp5.js.map → chunk-bnt8kx6x.js.map} +1 -1
- package/dist/{chunk-5tdxbwzg.js → chunk-bt9qv2jj.js} +3 -3
- package/dist/{chunk-5tdxbwzg.js.map → chunk-bt9qv2jj.js.map} +1 -1
- package/dist/{chunk-y6wt5b6t.js → chunk-c4jnxmf2.js} +1 -1
- package/dist/{chunk-ep0baa9g.js → chunk-cfdwsvtx.js} +2 -2
- package/dist/{chunk-ep0baa9g.js.map → chunk-cfdwsvtx.js.map} +1 -1
- package/dist/{chunk-51w5ktv2.js → chunk-dxfhhw5h.js} +2 -2
- package/dist/{chunk-51w5ktv2.js.map → chunk-dxfhhw5h.js.map} +1 -1
- package/dist/{chunk-pn2x59ge.js → chunk-f29pktad.js} +3 -3
- package/dist/{chunk-pn2x59ge.js.map → chunk-f29pktad.js.map} +1 -1
- package/dist/chunk-f4cmz31h.js +58 -0
- package/dist/{chunk-3rvn9a76.js.map → chunk-f4cmz31h.js.map} +3 -3
- package/dist/{chunk-0ejjgzwc.js → chunk-fn2qfwgx.js} +2 -2
- package/dist/{chunk-0ejjgzwc.js.map → chunk-fn2qfwgx.js.map} +1 -1
- package/dist/{chunk-pemhmjzp.js → chunk-fvrmptd0.js} +3 -3
- package/dist/{chunk-pemhmjzp.js.map → chunk-fvrmptd0.js.map} +1 -1
- package/dist/{chunk-qy8c0gzr.js → chunk-fw7ds23a.js} +2 -2
- package/dist/{chunk-qy8c0gzr.js.map → chunk-fw7ds23a.js.map} +1 -1
- package/dist/{chunk-fenc5tpv.js → chunk-h3p8qzft.js} +2 -2
- package/dist/{chunk-fenc5tpv.js.map → chunk-h3p8qzft.js.map} +1 -1
- package/dist/{chunk-wjkh2gem.js → chunk-j7v7dft7.js} +1 -1
- package/dist/chunk-jctb7v53.js +4 -0
- package/dist/chunk-jctb7v53.js.map +10 -0
- package/dist/{chunk-wqe47c0j.js → chunk-jys8y39p.js} +2 -2
- package/dist/{chunk-wqe47c0j.js.map → chunk-jys8y39p.js.map} +1 -1
- package/dist/{chunk-m83zm86m.js → chunk-kc924zjz.js} +2 -2
- package/dist/{chunk-m83zm86m.js.map → chunk-kc924zjz.js.map} +1 -1
- package/dist/{chunk-32n8t8x6.js → chunk-kzsjyvvc.js} +2 -2
- package/dist/{chunk-32n8t8x6.js.map → chunk-kzsjyvvc.js.map} +1 -1
- package/dist/{chunk-meg8rtr6.js → chunk-mqtfaqx5.js} +2 -2
- package/dist/{chunk-meg8rtr6.js.map → chunk-mqtfaqx5.js.map} +1 -1
- package/dist/{chunk-7g649j8h.js → chunk-mrswc6qw.js} +2 -2
- package/dist/{chunk-7g649j8h.js.map → chunk-mrswc6qw.js.map} +1 -1
- package/dist/{chunk-gc2dz11k.js → chunk-mvkz22p4.js} +2 -2
- package/dist/{chunk-gc2dz11k.js.map → chunk-mvkz22p4.js.map} +1 -1
- package/dist/{chunk-4acpw92g.js → chunk-n0r5xyk2.js} +3 -3
- package/dist/{chunk-4acpw92g.js.map → chunk-n0r5xyk2.js.map} +1 -1
- package/dist/{chunk-cca0grq3.js → chunk-n1a2zj5z.js} +2 -2
- package/dist/{chunk-cca0grq3.js.map → chunk-n1a2zj5z.js.map} +1 -1
- package/dist/{chunk-d5f1m3d2.js → chunk-nkzmk7v3.js} +2 -2
- package/dist/{chunk-d5f1m3d2.js.map → chunk-nkzmk7v3.js.map} +1 -1
- package/dist/{chunk-3gsv1vv1.js → chunk-nn2jeat2.js} +2 -2
- package/dist/{chunk-tewhms9w.js.map → chunk-nn2jeat2.js.map} +1 -1
- package/dist/chunk-nnarmbjv.js +5 -0
- package/dist/chunk-nnarmbjv.js.map +10 -0
- package/dist/{chunk-h43jp8ws.js → chunk-pe46a5a5.js} +2 -2
- package/dist/{chunk-h43jp8ws.js.map → chunk-pe46a5a5.js.map} +1 -1
- package/dist/{chunk-6yhpprzs.js → chunk-pmyh33v5.js} +2 -2
- package/dist/{chunk-6yhpprzs.js.map → chunk-pmyh33v5.js.map} +1 -1
- package/dist/{chunk-mr94nfp1.js → chunk-pya4rqm2.js} +3 -3
- package/dist/{chunk-mr94nfp1.js.map → chunk-pya4rqm2.js.map} +1 -1
- package/dist/{chunk-jaa6xkeh.js → chunk-qdj8ek8z.js} +2 -2
- package/dist/{chunk-jaa6xkeh.js.map → chunk-qdj8ek8z.js.map} +1 -1
- package/dist/{chunk-0yj0s1pn.js → chunk-qhz0x97z.js} +2 -2
- package/dist/{chunk-0yj0s1pn.js.map → chunk-qhz0x97z.js.map} +1 -1
- package/dist/chunk-qycwjzsv.js +9 -0
- package/dist/chunk-qycwjzsv.js.map +10 -0
- package/dist/{chunk-nz8z8jr1.js → chunk-rpyczdta.js} +3 -3
- package/dist/{chunk-nz8z8jr1.js.map → chunk-rpyczdta.js.map} +1 -1
- package/dist/{chunk-9rr5h818.js → chunk-rtawbqec.js} +3 -3
- package/dist/{chunk-9rr5h818.js.map → chunk-rtawbqec.js.map} +1 -1
- package/dist/{chunk-3wnghdsx.js → chunk-rttrpjqk.js} +2 -2
- package/dist/{chunk-3wnghdsx.js.map → chunk-rttrpjqk.js.map} +1 -1
- package/dist/{chunk-m53fgf20.js → chunk-s5jxc63j.js} +3 -3
- package/dist/{chunk-m53fgf20.js.map → chunk-s5jxc63j.js.map} +1 -1
- package/dist/{chunk-48gmyaxc.js → chunk-sd0c2001.js} +2 -2
- package/dist/{chunk-48gmyaxc.js.map → chunk-sd0c2001.js.map} +1 -1
- package/dist/chunk-skf89vrv.js +5 -0
- package/dist/chunk-skf89vrv.js.map +10 -0
- package/dist/chunk-szn2n976.js +24 -0
- package/dist/{chunk-2yw4yezc.js.map → chunk-szn2n976.js.map} +3 -3
- package/dist/{chunk-gemzbw7f.js → chunk-v2ggafz1.js} +2 -2
- package/dist/{chunk-gemzbw7f.js.map → chunk-v2ggafz1.js.map} +1 -1
- package/dist/{chunk-rhek27sj.js → chunk-v8v5qfnh.js} +3 -3
- package/dist/{chunk-rhek27sj.js.map → chunk-v8v5qfnh.js.map} +1 -1
- package/dist/{chunk-d2c3947c.js → chunk-w3812s34.js} +2 -2
- package/dist/{chunk-d2c3947c.js.map → chunk-w3812s34.js.map} +1 -1
- package/dist/{chunk-tk135gmj.js → chunk-w4z6x54b.js} +3 -3
- package/dist/{chunk-tk135gmj.js.map → chunk-w4z6x54b.js.map} +1 -1
- package/dist/{chunk-65beps2q.js → chunk-w61sphn5.js} +3 -3
- package/dist/{chunk-65beps2q.js.map → chunk-w61sphn5.js.map} +1 -1
- package/dist/{chunk-cvr5624r.js → chunk-wbg2tza5.js} +1 -1
- package/dist/{chunk-9d2d08qm.js → chunk-y434jc1c.js} +2 -2
- package/dist/{chunk-9d2d08qm.js.map → chunk-y434jc1c.js.map} +1 -1
- package/dist/{chunk-shfe0b22.js → chunk-ykz38t0t.js} +2 -2
- package/dist/{chunk-shfe0b22.js.map → chunk-ykz38t0t.js.map} +1 -1
- package/dist/{chunk-krk7mcgm.js → chunk-yzhv93b0.js} +3 -3
- package/dist/{chunk-krk7mcgm.js.map → chunk-yzhv93b0.js.map} +1 -1
- package/dist/{chunk-rhvc1axc.js → chunk-z5jydj5r.js} +2 -2
- package/dist/{chunk-rhvc1axc.js.map → chunk-z5jydj5r.js.map} +1 -1
- package/dist/chunk-zmf3vhex.js +10 -0
- package/dist/{chunk-dyp0wg9e.js.map → chunk-zmf3vhex.js.map} +8 -4
- package/dist/{chunk-sx340k85.js → chunk-zsfwcdqn.js} +2 -2
- package/dist/{chunk-sx340k85.js.map → chunk-zsfwcdqn.js.map} +1 -1
- package/dist/{chunk-4fx8p02c.js → chunk-zsvav1dk.js} +2 -2
- package/dist/{chunk-4fx8p02c.js.map → chunk-zsvav1dk.js.map} +1 -1
- package/dist/chunks/{ThemeProvider-BLI4zpLu.js → ThemeProvider-CbOx8IRl.js} +581 -2
- package/dist/chunks/ThemeProvider-CbOx8IRl.js.map +1 -0
- package/dist/client/auth/useEmailCode.d.ts.map +1 -1
- package/dist/client/auth/useSignIn.d.ts.map +1 -1
- package/dist/client/auth/useSignOut.d.ts.map +1 -1
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +216 -8
- package/dist/client/index.js.map +1 -1
- package/dist/client/init.d.ts +8 -0
- package/dist/client/init.d.ts.map +1 -1
- package/dist/client/realtime/FakeSocket.d.ts +47 -0
- package/dist/client/realtime/FakeSocket.d.ts.map +1 -0
- package/dist/client/realtime/RealtimeClient.d.ts +169 -0
- package/dist/client/realtime/RealtimeClient.d.ts.map +1 -0
- package/dist/client/realtime/RealtimeContext.d.ts +8 -0
- package/dist/client/realtime/RealtimeContext.d.ts.map +1 -0
- package/dist/client/realtime/useChannelSubscription.d.ts +32 -0
- package/dist/client/realtime/useChannelSubscription.d.ts.map +1 -0
- package/dist/client/rpc.d.ts +11 -0
- package/dist/client/rpc.d.ts.map +1 -1
- package/dist/client/useChannel.d.ts +87 -0
- package/dist/client/useChannel.d.ts.map +1 -0
- package/dist/client/useMutation.d.ts.map +1 -1
- package/dist/client/useQuery.d.ts +13 -0
- package/dist/client/useQuery.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/Broadcast.d.ts +68 -0
- package/dist/facades/Broadcast.d.ts.map +1 -0
- package/dist/facades/index.d.ts +1 -0
- package/dist/facades/index.d.ts.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/gemi.d.ts +19 -6
- package/dist/http/ChannelRouter.d.ts +171 -0
- package/dist/http/ChannelRouter.d.ts.map +1 -0
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +2 -2
- package/dist/kernel/Kernel.d.ts +6 -0
- package/dist/kernel/Kernel.d.ts.map +1 -1
- package/dist/kernel/index.js +3 -3
- package/dist/kernel/index.js.map +5 -6
- package/dist/kernel/providers.d.ts +2 -2
- package/dist/kernel/providers.d.ts.map +1 -1
- package/dist/orm/context.d.ts.map +1 -1
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/Server.d.ts.map +1 -1
- package/dist/server/httpDev.d.ts +1 -2
- package/dist/server/httpDev.d.ts.map +1 -1
- package/dist/server/httpProd.d.ts +1 -1
- package/dist/server/httpProd.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +3 -3
- package/dist/server/shutdown.d.ts +9 -0
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/services/broadcast/BroadcastDriver.d.ts +75 -0
- package/dist/services/broadcast/BroadcastDriver.d.ts.map +1 -0
- package/dist/services/broadcast/BroadcastEvent.d.ts +67 -0
- package/dist/services/broadcast/BroadcastEvent.d.ts.map +1 -0
- package/dist/services/broadcast/BroadcastManager.d.ts +148 -0
- package/dist/services/broadcast/BroadcastManager.d.ts.map +1 -0
- package/dist/services/broadcast/BroadcastServiceProvider.d.ts +26 -0
- package/dist/services/broadcast/BroadcastServiceProvider.d.ts.map +1 -0
- package/dist/services/broadcast/FakeBroadcastManager.d.ts +45 -0
- package/dist/services/broadcast/FakeBroadcastManager.d.ts.map +1 -0
- package/dist/services/broadcast/MemoryBroadcastDriver.d.ts +23 -0
- package/dist/services/broadcast/MemoryBroadcastDriver.d.ts.map +1 -0
- package/dist/services/broadcast/RedisBroadcastDriver.d.ts +155 -0
- package/dist/services/broadcast/RedisBroadcastDriver.d.ts.map +1 -0
- package/dist/services/broadcast/SocketHub.d.ts +201 -0
- package/dist/services/broadcast/SocketHub.d.ts.map +1 -0
- package/dist/services/broadcast/brand.d.ts +16 -0
- package/dist/services/broadcast/brand.d.ts.map +1 -0
- package/dist/services/broadcast/channels.d.ts +77 -0
- package/dist/services/broadcast/channels.d.ts.map +1 -0
- package/dist/services/broadcast/config.d.ts +106 -0
- package/dist/services/broadcast/config.d.ts.map +1 -0
- package/dist/services/broadcast/protocol.d.ts +123 -0
- package/dist/services/broadcast/protocol.d.ts.map +1 -0
- package/dist/services/broadcast/socketTag.d.ts +17 -0
- package/dist/services/broadcast/socketTag.d.ts.map +1 -0
- package/dist/services/broadcast/types.d.ts +27 -0
- package/dist/services/broadcast/types.d.ts.map +1 -0
- package/dist/services/broadcast/wire.d.ts +35 -0
- package/dist/services/broadcast/wire.d.ts.map +1 -0
- package/dist/services/broadcast/workerWarning.d.ts +10 -0
- package/dist/services/broadcast/workerWarning.d.ts.map +1 -0
- package/dist/services/events/EventManager.d.ts +6 -0
- package/dist/services/events/EventManager.d.ts.map +1 -1
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +9 -9
- package/dist/services/index.js.map +4 -3
- package/dist/services/queue/WorkerProcess.d.ts.map +1 -1
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +5 -4
- package/dist/services/router/config.d.ts +7 -0
- package/dist/services/router/config.d.ts.map +1 -1
- package/dist/stats/route-table.js +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/testing/Page.d.ts +8 -0
- package/dist/testing/Page.d.ts.map +1 -1
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +174 -8
- package/dist/testing/index.js.map +1 -1
- package/dist/vitest/index.js +1 -1
- package/package.json +1 -1
- package/skills/gemi-react-best-practices/SKILL.md +3 -1
- package/skills/gemi-react-best-practices/rules/query-live-over-polling.md +56 -0
- package/dist/chunk-2n3pgfnb.js +0 -5
- package/dist/chunk-2n3pgfnb.js.map +0 -10
- package/dist/chunk-2yw4yezc.js +0 -24
- package/dist/chunk-3rvn9a76.js +0 -58
- package/dist/chunk-3s21p9n2.js +0 -57
- package/dist/chunk-dyp0wg9e.js +0 -10
- package/dist/chunk-htgmy3x7.js +0 -5
- package/dist/chunk-krtybgz1.js +0 -4
- package/dist/chunk-krtybgz1.js.map +0 -10
- package/dist/chunk-s07v65x6.js +0 -9
- package/dist/chunk-s07v65x6.js.map +0 -10
- package/dist/chunks/ThemeProvider-BLI4zpLu.js.map +0 -1
- /package/dist/{chunk-dhbgrv58.js.map → chunk-3j6s5bmx.js.map} +0 -0
- /package/dist/{chunk-zg6hmc48.js.map → chunk-5e22tm7m.js.map} +0 -0
- /package/dist/{chunk-0k02tza1.js.map → chunk-65s834td.js.map} +0 -0
- /package/dist/{chunk-y6wt5b6t.js.map → chunk-c4jnxmf2.js.map} +0 -0
- /package/dist/{chunk-wjkh2gem.js.map → chunk-j7v7dft7.js.map} +0 -0
- /package/dist/{chunk-cvr5624r.js.map → chunk-wbg2tza5.js.map} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Event } from "../events/Event";
|
|
2
|
+
import { type BroadcastableEvent } from "./brand";
|
|
3
|
+
import { type ChannelParamsArgs, type ChannelTarget } from "./channels";
|
|
4
|
+
export { BROADCAST_EVENT, isBroadcastEvent, type BroadcastableEvent } from "./brand";
|
|
5
|
+
/**
|
|
6
|
+
* An event that is also sent to the sockets on a channel, after its listeners
|
|
7
|
+
* have run.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* export class SiteChanged extends BroadcastEvent<{ pages: string[] }, "changed"> {
|
|
11
|
+
* static name = "SiteChanged";
|
|
12
|
+
* static afterCommit = true;
|
|
13
|
+
* constructor(public site: { publicId: string }, public changes: { pages: string[] }) {
|
|
14
|
+
* super();
|
|
15
|
+
* }
|
|
16
|
+
* broadcastOn() {
|
|
17
|
+
* return this.channel("site.:siteId", { siteId: this.site.publicId });
|
|
18
|
+
* }
|
|
19
|
+
* broadcastAs() {
|
|
20
|
+
* return "changed" as const;
|
|
21
|
+
* }
|
|
22
|
+
* broadcastWith() {
|
|
23
|
+
* return this.changes;
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* SiteChanged.dispatch(site, { pages: ["/about"] });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* It is an `Event`: it needs `static name`, listeners bind to it, `static
|
|
31
|
+
* afterCommit` holds both the listeners and the broadcast until the commit,
|
|
32
|
+
* and under `Event.fake()` it is recorded and **not** broadcast. Without
|
|
33
|
+
* `afterCommit`, a dispatch inside a transaction still runs its listeners at
|
|
34
|
+
* once, and the broadcast itself waits for the commit and is dropped on
|
|
35
|
+
* rollback, as every `Broadcast` emit does.
|
|
36
|
+
*
|
|
37
|
+
* `TPayload` is what `broadcastWith` returns and `TName` what `broadcastAs`
|
|
38
|
+
* returns. List the class on a channel with `.events(SiteChanged)` and the
|
|
39
|
+
* generated `BroadcastRPC` types the client's handler for `changed`.
|
|
40
|
+
*/
|
|
41
|
+
export declare abstract class BroadcastEvent<TPayload = undefined, TName extends string = string> extends Event implements BroadcastableEvent {
|
|
42
|
+
/**
|
|
43
|
+
* Type-only: what `.events(...)` on a channel reads to type `BroadcastRPC`.
|
|
44
|
+
* No field is emitted.
|
|
45
|
+
*/
|
|
46
|
+
readonly __broadcast: {
|
|
47
|
+
name: TName;
|
|
48
|
+
payload: TPayload;
|
|
49
|
+
};
|
|
50
|
+
constructor();
|
|
51
|
+
/**
|
|
52
|
+
* The channel or channels to send this event to: a `this.channel(...)`, a
|
|
53
|
+
* concrete topic such as `` `user.${id}` ``, or an array of them.
|
|
54
|
+
*/
|
|
55
|
+
abstract broadcastOn(): ChannelTarget | string | ReadonlyArray<ChannelTarget | string>;
|
|
56
|
+
/** The event name clients see. Defaults to the class's `static name`. */
|
|
57
|
+
broadcastAs(): TName;
|
|
58
|
+
/**
|
|
59
|
+
* The payload clients receive. Nothing by default: a payload is never
|
|
60
|
+
* derived from the event's fields, so nothing is broadcast by accident.
|
|
61
|
+
* Keep it to ids and a change hint, and never put secrets in it.
|
|
62
|
+
*/
|
|
63
|
+
broadcastWith(): TPayload;
|
|
64
|
+
/** The channel `pattern` names with `params`, for `broadcastOn`. */
|
|
65
|
+
protected channel<P extends string>(pattern: P, ...params: ChannelParamsArgs<P>): ChannelTarget;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=BroadcastEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BroadcastEvent.d.ts","sourceRoot":"","sources":["../../../services/broadcast/BroadcastEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAc,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpF,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAErF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,8BAAsB,cAAc,CAAC,QAAQ,GAAG,SAAS,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM,CACtF,SAAQ,KACR,YAAW,kBAAkB;IAE7B;;;OAGG;IACH,SAAiB,WAAW,EAAE;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC;;IAOjE;;;OAGG;IACH,QAAQ,CAAC,WAAW,IAAI,aAAa,GAAG,MAAM,GAAG,aAAa,CAAC,aAAa,GAAG,MAAM,CAAC;IAEtF,yEAAyE;IACzE,WAAW,IAAI,KAAK;IAIpB;;;;OAIG;IACH,aAAa,IAAI,QAAQ;IAIzB,oEAAoE;IACpE,SAAS,CAAC,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,aAAa;CAGhG"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { Application } from "../../foundation/Application";
|
|
2
|
+
import type { ChannelRouter, ChannelRouterClass } from "../../http/ChannelRouter";
|
|
3
|
+
import type { BroadcastDeliver, BroadcastDriver, BroadcastDriverHooks, BroadcastRevocation } from "./BroadcastDriver";
|
|
4
|
+
import type { BroadcastableEvent } from "./brand";
|
|
5
|
+
import { type ChannelParamsArgs, type ChannelTarget } from "./channels";
|
|
6
|
+
import { type BroadcastConfig } from "./config";
|
|
7
|
+
import type { BroadcastDataArgs, BroadcastEventsFor, SentBroadcast } from "./types";
|
|
8
|
+
/** An emit whose frame is bigger than `maxEventBytes`. Nothing was sent. */
|
|
9
|
+
export declare class BroadcastPayloadTooLargeError extends Error {
|
|
10
|
+
readonly bytes: number;
|
|
11
|
+
readonly limit: number;
|
|
12
|
+
constructor(bytes: number, limit: number, event: string);
|
|
13
|
+
}
|
|
14
|
+
/** Something that carries the sender's socket id: a request, or the id. */
|
|
15
|
+
export type SocketSource = string | null | undefined | Request | {
|
|
16
|
+
rawRequest: Request;
|
|
17
|
+
} | {
|
|
18
|
+
headers: Headers;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Real-time, volatile fan-out to the WebSocket clients subscribed to a
|
|
22
|
+
* channel. Events are hints that something changed, not data: delivery is at
|
|
23
|
+
* most once, nothing is stored or replayed, and a client that may have missed
|
|
24
|
+
* something refetches over HTTP.
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* Broadcast.to("site.:siteId", { siteId: site.publicId }).emit("changed", { pages: ["/about"] });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* The manager builds and checks the frame at the call site, so a bad channel
|
|
31
|
+
* or a payload over the limit throws there, and then hands it to the driver,
|
|
32
|
+
* which decides which processes see it. Inside an ORM transaction the
|
|
33
|
+
* hand-off waits for the commit and is dropped on rollback.
|
|
34
|
+
*
|
|
35
|
+
* Delivery to sockets belongs to the transport, which calls `start` with the
|
|
36
|
+
* function that reaches this process's sockets. Until it does, an emit
|
|
37
|
+
* reaches no socket in this process.
|
|
38
|
+
*/
|
|
39
|
+
export declare class BroadcastManager {
|
|
40
|
+
private readonly options;
|
|
41
|
+
static token: string;
|
|
42
|
+
readonly config: Required<BroadcastConfig>;
|
|
43
|
+
readonly driver: BroadcastDriver;
|
|
44
|
+
private readonly warnedAboutSize;
|
|
45
|
+
private started;
|
|
46
|
+
private hooks;
|
|
47
|
+
private channelRouter;
|
|
48
|
+
constructor(config?: BroadcastConfig, options?: {
|
|
49
|
+
application?: Application;
|
|
50
|
+
/** The app's `ChannelRouter` (`route.channels`). */
|
|
51
|
+
channels?: ChannelRouterClass;
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* The app's `ChannelRouter`, built once, or `null` when `route.channels` is
|
|
55
|
+
* not set (and every subscription is refused). The transport authorizes
|
|
56
|
+
* each `sub` with its `authorize`.
|
|
57
|
+
*/
|
|
58
|
+
get channels(): ChannelRouter | null;
|
|
59
|
+
/**
|
|
60
|
+
* The channel `pattern` names with `params`, or a concrete topic, or a
|
|
61
|
+
* `ChannelTarget` (what `BroadcastEvent.channel()` returns).
|
|
62
|
+
*/
|
|
63
|
+
to<P extends string>(pattern: P | ChannelTarget, ...params: ChannelParamsArgs<P>): PendingBroadcast<BroadcastEventsFor<P>>;
|
|
64
|
+
/** A user's own channel, `user.<id>`: the one the router's `"user"` channel joins. */
|
|
65
|
+
toUser(user: {
|
|
66
|
+
id: unknown;
|
|
67
|
+
} | string | number): PendingBroadcast<BroadcastEventsFor<"user">>;
|
|
68
|
+
/**
|
|
69
|
+
* Skips the socket that made `source`, a request carrying the
|
|
70
|
+
* `X-Gemi-Socket` header (or the id itself), so the client that saved
|
|
71
|
+
* something does not refetch what it already has. Without a valid socket id
|
|
72
|
+
* nobody is skipped.
|
|
73
|
+
*/
|
|
74
|
+
toOthers(source: SocketSource): BroadcastScope;
|
|
75
|
+
/** Sends a `BroadcastEvent` to the channels its `broadcastOn` names. */
|
|
76
|
+
broadcastEvent(event: BroadcastableEvent): void;
|
|
77
|
+
/**
|
|
78
|
+
* Checks and encodes an emit, then hands it to the driver: now, or after
|
|
79
|
+
* the open transaction commits. Throws at the call site for a bad event
|
|
80
|
+
* name, a payload that is not JSON, or one over `maxEventBytes`.
|
|
81
|
+
*/
|
|
82
|
+
send(target: ChannelTarget, event: string, data: unknown, except: string | null): void;
|
|
83
|
+
private prepare;
|
|
84
|
+
private hand;
|
|
85
|
+
/**
|
|
86
|
+
* The hand-off to the driver, after the commit. Never throws: an emit is
|
|
87
|
+
* fire-and-forget, and a driver failure is logged with the topic and event,
|
|
88
|
+
* never the payload.
|
|
89
|
+
*/
|
|
90
|
+
protected publish(sent: SentBroadcast, frame: string): void;
|
|
91
|
+
/** Whether the transport has started delivering to this process's sockets. */
|
|
92
|
+
get isStarted(): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* For the transport: this process starts receiving, and every frame for a
|
|
95
|
+
* topic it has sockets on reaches `deliver` (`server.publish`).
|
|
96
|
+
*/
|
|
97
|
+
start(deliver: BroadcastDeliver, hooks?: BroadcastDriverHooks): Promise<void>;
|
|
98
|
+
/** For the transport: the first local socket joined `topic`. */
|
|
99
|
+
topicAdded(topic: string): void | Promise<void>;
|
|
100
|
+
/** For the transport: the last local socket left `topic`. */
|
|
101
|
+
topicRemoved(topic: string): void | Promise<void>;
|
|
102
|
+
close(): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Closes subscriptions that may no longer be allowed: every socket of a
|
|
105
|
+
* user (`{ user }`: its sockets are closed, and its client reconnects and
|
|
106
|
+
* authorizes every channel again), or every subscription to a channel
|
|
107
|
+
* (`{ channel }`, a pattern with `params` or a topic: each is told
|
|
108
|
+
* `denied` with `revoked`). Sign-out calls it for the user.
|
|
109
|
+
*
|
|
110
|
+
* Inside an ORM transaction it waits for the commit, so the
|
|
111
|
+
* resubscriptions it causes are authorized against the committed state.
|
|
112
|
+
* Never throws for a transport problem; a bad channel throws at the call
|
|
113
|
+
* site.
|
|
114
|
+
*/
|
|
115
|
+
revoke(target: {
|
|
116
|
+
user: {
|
|
117
|
+
id: unknown;
|
|
118
|
+
} | string | number;
|
|
119
|
+
} | {
|
|
120
|
+
channel: string | ChannelTarget;
|
|
121
|
+
params?: Record<string, unknown>;
|
|
122
|
+
}): void;
|
|
123
|
+
protected sendRevocation(revocation: BroadcastRevocation): void;
|
|
124
|
+
private checkSize;
|
|
125
|
+
}
|
|
126
|
+
/** An emit with its channel chosen: `.emit(event, data)` sends it. */
|
|
127
|
+
export declare class PendingBroadcast<Events extends Record<string, unknown> = Record<string, unknown>> {
|
|
128
|
+
private readonly manager;
|
|
129
|
+
readonly target: ChannelTarget;
|
|
130
|
+
private readonly except;
|
|
131
|
+
constructor(manager: BroadcastManager, target: ChannelTarget, except: string | null);
|
|
132
|
+
/**
|
|
133
|
+
* Sends `event` with `data` (JSON) to every socket on the channel. Returns
|
|
134
|
+
* nothing: delivery is at most once and never acknowledged.
|
|
135
|
+
*/
|
|
136
|
+
emit<E extends keyof Events & string>(event: E, ...data: BroadcastDataArgs<Events[E]>): void;
|
|
137
|
+
}
|
|
138
|
+
/** `Broadcast.toOthers(...)`: the same `to`, with the sender's socket skipped. */
|
|
139
|
+
export declare class BroadcastScope {
|
|
140
|
+
private readonly manager;
|
|
141
|
+
readonly except: string | null;
|
|
142
|
+
constructor(manager: BroadcastManager, except: string | null);
|
|
143
|
+
to<P extends string>(pattern: P | ChannelTarget, ...params: ChannelParamsArgs<P>): PendingBroadcast<BroadcastEventsFor<P>>;
|
|
144
|
+
toUser(user: {
|
|
145
|
+
id: unknown;
|
|
146
|
+
} | string | number): PendingBroadcast<BroadcastEventsFor<"user">>;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=BroadcastManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BroadcastManager.d.ts","sourceRoot":"","sources":["../../../services/broadcast/BroadcastManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ServiceProvider } from "../../support/ServiceProvider";
|
|
2
|
+
import type { BroadcastDriver } from "./BroadcastDriver";
|
|
3
|
+
import type { BroadcastConfig } from "./config";
|
|
4
|
+
export declare class BroadcastServiceProvider extends ServiceProvider {
|
|
5
|
+
register(): void;
|
|
6
|
+
/**
|
|
7
|
+
* Fails the boot on a malformed channel pattern, rather than refusing every
|
|
8
|
+
* subscription to it at runtime.
|
|
9
|
+
*/
|
|
10
|
+
boot(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Says `bye` to the sockets (the server's drain did already, in
|
|
13
|
+
* production; a dev reload retiring this application did not), then stops
|
|
14
|
+
* receiving and closes the driver's connections.
|
|
15
|
+
*/
|
|
16
|
+
shutdown(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The redis driver carries one frame to every instance, and a `toOthers`
|
|
20
|
+
* frame names the socket to skip by a tag keyed from `SECRET` (`socketTag`).
|
|
21
|
+
* Without `SECRET` each process keys it at random, so the sender's own socket
|
|
22
|
+
* on another instance would not recognise its tag and would get its own
|
|
23
|
+
* emit back. Fails the boot in production; warns elsewhere.
|
|
24
|
+
*/
|
|
25
|
+
export declare function assertSharedSecret(config: BroadcastConfig, env?: Record<string, string | undefined>, driver?: BroadcastDriver): void;
|
|
26
|
+
//# sourceMappingURL=BroadcastServiceProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BroadcastServiceProvider.d.ts","sourceRoot":"","sources":["../../../services/broadcast/BroadcastServiceProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGhD,qBAAa,wBAAyB,SAAQ,eAAe;IAC3D,QAAQ;IAcR;;;OAGG;IACH,IAAI;IAaJ;;;;OAIG;IACG,QAAQ;CAKf;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,eAAe,EACvB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,MAAM,CAAC,EAAE,eAAe,GACvB,IAAI,CASN"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Application } from "../../foundation/Application";
|
|
2
|
+
import { BroadcastManager } from "./BroadcastManager";
|
|
3
|
+
import type { BroadcastRevocation } from "./BroadcastDriver";
|
|
4
|
+
import type { SentBroadcast } from "./types";
|
|
5
|
+
/**
|
|
6
|
+
* What `Broadcast.fake()` installs: a `BroadcastManager` that records every
|
|
7
|
+
* emit instead of handing it to a driver.
|
|
8
|
+
*
|
|
9
|
+
* Everything before the hand-off is the real manager's: channels and params
|
|
10
|
+
* are checked, payloads encoded and size-checked, and inside an ORM
|
|
11
|
+
* transaction an emit is recorded only once the transaction commits (and
|
|
12
|
+
* never if it rolls back). So a test sees what clients would have been sent.
|
|
13
|
+
*
|
|
14
|
+
* `restore()` is not optional, for the reason it is not on `Event.fake()`.
|
|
15
|
+
*/
|
|
16
|
+
export declare class FakeBroadcastManager extends BroadcastManager {
|
|
17
|
+
private readonly application;
|
|
18
|
+
private readonly previous;
|
|
19
|
+
readonly sent: SentBroadcast[];
|
|
20
|
+
/** Every `Broadcast.revoke`, as it would travel: `{ user }` or `{ topic }`. */
|
|
21
|
+
readonly revoked: BroadcastRevocation[];
|
|
22
|
+
static install(application: Application): FakeBroadcastManager;
|
|
23
|
+
private constructor();
|
|
24
|
+
private readonly channelsFrom;
|
|
25
|
+
get channels(): import("gemi/http").ChannelRouter;
|
|
26
|
+
protected publish(sent: SentBroadcast): void;
|
|
27
|
+
protected sendRevocation(revocation: BroadcastRevocation): void;
|
|
28
|
+
/** Puts the real manager back. */
|
|
29
|
+
restore(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Asserts something was sent to `channel`: a pattern (`"site.:siteId"`,
|
|
32
|
+
* matching every topic it builds), a concrete topic (`"site.abc123"`), or
|
|
33
|
+
* `"user"` (every `user.<id>`). `event` and `predicate` narrow it.
|
|
34
|
+
*/
|
|
35
|
+
assertSent(channel: string, event?: string, predicate?: (data: any, sent: SentBroadcast) => boolean): void;
|
|
36
|
+
/** Asserts nothing matching was sent. Same arguments as `assertSent`. */
|
|
37
|
+
assertNotSent(channel: string, event?: string, predicate?: (data: any, sent: SentBroadcast) => boolean): void;
|
|
38
|
+
/** Asserts exactly `times` matching emits. */
|
|
39
|
+
assertSentTimes(channel: string, times: number, event?: string, predicate?: (data: any, sent: SentBroadcast) => boolean): void;
|
|
40
|
+
/** Asserts nothing at all was broadcast. */
|
|
41
|
+
assertNothingSent(): void;
|
|
42
|
+
private matching;
|
|
43
|
+
private summary;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=FakeBroadcastManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeBroadcastManager.d.ts","sourceRoot":"","sources":["../../../services/broadcast/FakeBroadcastManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,qBAAa,oBAAqB,SAAQ,gBAAgB;IAmBtD,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAnB3B,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,CAAM;IACpC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,mBAAmB,EAAE,CAAM;IAE7C,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,oBAAoB;IAa9D,OAAO;IAiBP,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+B;IAE5D,IAAa,QAAQ,sCAEpB;cAEkB,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;cAIlC,cAAc,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI;IAIxE,kCAAkC;IAClC,OAAO,IAAI,IAAI;IAQf;;;;OAIG;IACH,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,KAAK,OAAO,GACtD,IAAI;IAQP,yEAAyE;IACzE,aAAa,CACX,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,KAAK,OAAO,GACtD,IAAI;IASP,8CAA8C;IAC9C,eAAe,CACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,KAAK,OAAO,GACtD,IAAI;IAUP,4CAA4C;IAC5C,iBAAiB,IAAI,IAAI;IAQzB,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,OAAO;CAIhB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BroadcastDeliver, BroadcastDriver, BroadcastDriverHooks, BroadcastRevocation } from "./BroadcastDriver";
|
|
2
|
+
/**
|
|
3
|
+
* The default driver: an emit reaches the sockets of **this process only**.
|
|
4
|
+
*
|
|
5
|
+
* Right for one instance whose web processes also run the jobs and cron that
|
|
6
|
+
* emit. Wrong as soon as there are two replicas, or a `gemi queue:work`
|
|
7
|
+
* worker that emits: those frames reach nobody, with nothing to say so. Use
|
|
8
|
+
* the Redis driver there.
|
|
9
|
+
*
|
|
10
|
+
* Before the HTTP server starts the transport, there is nobody to deliver to,
|
|
11
|
+
* and `publish` drops the frame.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MemoryBroadcastDriver implements BroadcastDriver {
|
|
14
|
+
private deliver;
|
|
15
|
+
private hooks;
|
|
16
|
+
/** Whether the transport has started this driver. */
|
|
17
|
+
get started(): boolean;
|
|
18
|
+
publish(topic: string, frame: string): void;
|
|
19
|
+
start(deliver: BroadcastDeliver, hooks?: BroadcastDriverHooks): void;
|
|
20
|
+
revoke(revocation: BroadcastRevocation): void;
|
|
21
|
+
close(): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=MemoryBroadcastDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryBroadcastDriver.d.ts","sourceRoot":"","sources":["../../../services/broadcast/MemoryBroadcastDriver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,KAAK,CAAmC;IAEhD,qDAAqD;IACrD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,oBAAoB,GAAG,IAAI;IAKpE,MAAM,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI;IAI7C,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { RedisOptions } from "bun";
|
|
2
|
+
import type { BroadcastDeliver, BroadcastDriver, BroadcastDriverHooks, BroadcastRevocation } from "./BroadcastDriver";
|
|
3
|
+
/**
|
|
4
|
+
* The part of a Redis client the driver uses: Bun's `RedisClient` has it.
|
|
5
|
+
* Described structurally so tests can hand in a fake (`createClient`).
|
|
6
|
+
*/
|
|
7
|
+
export interface RedisPubSubClient {
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
publish(channel: string, message: string): Promise<number>;
|
|
10
|
+
subscribe(channel: string, listener: (message: string, channel: string) => void): Promise<number>;
|
|
11
|
+
/** Without a listener: drops the channel and every listener on it. */
|
|
12
|
+
unsubscribe(channel: string): Promise<void>;
|
|
13
|
+
ping(): Promise<unknown>;
|
|
14
|
+
close(): void;
|
|
15
|
+
onclose: ((error: Error) => void) | null;
|
|
16
|
+
}
|
|
17
|
+
export interface RedisBroadcastDriverOptions {
|
|
18
|
+
/** Defaults to `app/config/redis.ts`'s `url`, then `REDIS_URL`. */
|
|
19
|
+
url?: string;
|
|
20
|
+
/** Bun `RedisClient` options. Defaults to `app/config/redis.ts`'s `options`. */
|
|
21
|
+
options?: RedisOptions;
|
|
22
|
+
/**
|
|
23
|
+
* Prepended to every topic to name its Redis channel. Default:
|
|
24
|
+
* `gemi:bc:<8 hex characters derived from SECRET>:`, so instances of one
|
|
25
|
+
* app share channels and other apps or environments on the same Redis
|
|
26
|
+
* (which have another `SECRET`) do not. `"gemi:bc:"` without `SECRET`.
|
|
27
|
+
*/
|
|
28
|
+
prefix?: string;
|
|
29
|
+
/**
|
|
30
|
+
* How long a first socket's subscription may wait for Redis before it is
|
|
31
|
+
* denied with `error` (the client retries it). Default `5000`.
|
|
32
|
+
*/
|
|
33
|
+
subscribeTimeoutMs?: number;
|
|
34
|
+
/**
|
|
35
|
+
* How often the subscriber connection is pinged, in ms. A ping that fails
|
|
36
|
+
* or goes unanswered for `subscribeTimeoutMs` drops the connection, which
|
|
37
|
+
* is reconnected (and sockets told `gap`): a connection a proxy cut
|
|
38
|
+
* silently would otherwise stay subscribed to nothing. `0` turns it off.
|
|
39
|
+
* Default `30000`.
|
|
40
|
+
*/
|
|
41
|
+
healthCheckMs?: number;
|
|
42
|
+
/** Builds a client. Default: `new Bun.RedisClient(url, options)`. */
|
|
43
|
+
createClient?: (role: "publisher" | "subscriber") => RedisPubSubClient;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The default channel prefix: `gemi:bc:<8 hex>:`, the hex derived from
|
|
47
|
+
* `secret` with HKDF, never the secret itself. `"gemi:bc:"` without one.
|
|
48
|
+
*/
|
|
49
|
+
export declare function defaultBroadcastPrefix(secret?: string | undefined): string;
|
|
50
|
+
/**
|
|
51
|
+
* Broadcast over Redis pub/sub: an emit reaches the sockets of every process
|
|
52
|
+
* of the app, `gemi queue:work` workers' emits included.
|
|
53
|
+
*
|
|
54
|
+
* - **Publishing.** Every emit is `PUBLISH`ed on `<prefix><topic>`, from a
|
|
55
|
+
* publisher connection opened on the first emit. A process without the
|
|
56
|
+
* HTTP server (a worker) only ever has this one.
|
|
57
|
+
* - **Receiving.** A process that serves sockets has one subscriber
|
|
58
|
+
* connection. It `SUBSCRIBE`s to a topic when the first local socket joins
|
|
59
|
+
* it and `UNSUBSCRIBE`s when the last leaves, so a process receives only the
|
|
60
|
+
* topics its sockets are on. It delivers what it receives, its own emits
|
|
61
|
+
* included: one delivery path, nothing delivered twice.
|
|
62
|
+
* - **Revocations** travel on `<prefix>__control`, and every process applies
|
|
63
|
+
* them. The process that revokes applies it at once too, so its own sockets
|
|
64
|
+
* are covered while Redis is unreachable.
|
|
65
|
+
* - **Reconnects.** When the subscriber connection drops, the driver opens a
|
|
66
|
+
* new one with backoff, subscribes every topic again, and then tells the
|
|
67
|
+
* transport (`onGap`), which sends its sockets `{op:"gap"}` so clients
|
|
68
|
+
* refetch what they may have missed.
|
|
69
|
+
*
|
|
70
|
+
* Needs `SECRET`: a `toOthers` frame names the skipped socket by a tag keyed
|
|
71
|
+
* from it, which every process must compute alike.
|
|
72
|
+
*/
|
|
73
|
+
export declare class RedisBroadcastDriver implements BroadcastDriver {
|
|
74
|
+
private readonly config;
|
|
75
|
+
readonly prefix: string;
|
|
76
|
+
private readonly controlChannel;
|
|
77
|
+
private readonly instanceId;
|
|
78
|
+
private readonly subscribeTimeoutMs;
|
|
79
|
+
private readonly healthCheckMs;
|
|
80
|
+
private publisher;
|
|
81
|
+
private subscriber;
|
|
82
|
+
/** Resolves with the subscriber once it is connected and subscribed. */
|
|
83
|
+
private ready;
|
|
84
|
+
private deliver;
|
|
85
|
+
private hooks;
|
|
86
|
+
/** Topics with local sockets: the ones the subscriber should be on. */
|
|
87
|
+
private readonly wanted;
|
|
88
|
+
/** Topics the current subscriber connection is subscribed to. */
|
|
89
|
+
private readonly active;
|
|
90
|
+
/** Per topic, the tail of its SUBSCRIBE/UNSUBSCRIBE chain. */
|
|
91
|
+
private readonly chains;
|
|
92
|
+
private connectedOnce;
|
|
93
|
+
private reconnectAttempt;
|
|
94
|
+
private reconnectTimer;
|
|
95
|
+
private healthTimer;
|
|
96
|
+
private closed;
|
|
97
|
+
constructor(config?: RedisBroadcastDriverOptions);
|
|
98
|
+
/** Whether the subscriber connection is up and subscribed. */
|
|
99
|
+
get connected(): boolean;
|
|
100
|
+
publish(topic: string, frame: string): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Applies the revocation here at once, then sends it to every other
|
|
103
|
+
* process. A process whose subscriber is reconnecting while it is sent
|
|
104
|
+
* misses it, and re-authorizes every subscription after its gap instead
|
|
105
|
+
* (the transport does, on `onGap`).
|
|
106
|
+
*/
|
|
107
|
+
revoke(revocation: BroadcastRevocation): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Opens the subscriber connection. Resolves once it is connected, or at
|
|
110
|
+
* `subscribeTimeoutMs` when Redis is unreachable, in which case it keeps
|
|
111
|
+
* trying in the background: the HTTP server does not wait on Redis to
|
|
112
|
+
* boot.
|
|
113
|
+
*/
|
|
114
|
+
start(deliver: BroadcastDeliver, hooks?: BroadcastDriverHooks): Promise<void>;
|
|
115
|
+
topicAdded(topic: string): Promise<void>;
|
|
116
|
+
topicRemoved(topic: string): Promise<void>;
|
|
117
|
+
close(): Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Publishes, retrying once on a new publisher: Bun's client that gave up
|
|
120
|
+
* (Redis was away for longer than its retries) fails the first command
|
|
121
|
+
* after Redis is back, before its `onclose` lets it be replaced.
|
|
122
|
+
*/
|
|
123
|
+
private send;
|
|
124
|
+
private dropPublisher;
|
|
125
|
+
/**
|
|
126
|
+
* The publisher, built on first use. Bun's client reconnects it on its
|
|
127
|
+
* own; one that has given up (`onclose`) is replaced on the next publish.
|
|
128
|
+
*/
|
|
129
|
+
private publisherClient;
|
|
130
|
+
private createClient;
|
|
131
|
+
/**
|
|
132
|
+
* Opens a subscriber connection and subscribes the control channel and
|
|
133
|
+
* every wanted topic on it. On failure, or when it drops later, the next
|
|
134
|
+
* one is tried with backoff. Every connection after the first reports a
|
|
135
|
+
* gap, once it is subscribed: what was published in between is lost.
|
|
136
|
+
*/
|
|
137
|
+
private connectSubscriber;
|
|
138
|
+
/** The subscriber connection closed under it. */
|
|
139
|
+
private lost;
|
|
140
|
+
private drop;
|
|
141
|
+
private scheduleReconnect;
|
|
142
|
+
private startHealthCheck;
|
|
143
|
+
/** The connected subscriber, waiting up to `subscribeTimeoutMs` for one. */
|
|
144
|
+
private whenReady;
|
|
145
|
+
/**
|
|
146
|
+
* Brings the subscription to `topic` in line with `wanted`, after whatever
|
|
147
|
+
* was already queued for it: a socket leaving and another joining in the
|
|
148
|
+
* next tick become UNSUBSCRIBE then SUBSCRIBE, in that order.
|
|
149
|
+
*/
|
|
150
|
+
private sync;
|
|
151
|
+
private reconcile;
|
|
152
|
+
private readonly onMessage;
|
|
153
|
+
private onControl;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=RedisBroadcastDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RedisBroadcastDriver.d.ts","sourceRoot":"","sources":["../../../services/broadcast/RedisBroadcastDriver.ts"],"names":[],"mappings":"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"}
|