trellis 3.1.35 → 3.2.2
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/CHANGELOG.md +23 -5
- package/README.md +63 -156
- package/bin/trellis.mjs +2 -75
- package/dist/{better-sqlite-backend-ahx5p0br.js → better-sqlite-backend-2P4F6AOJ.js} +91 -29
- package/dist/boot-middleware-MHLHFCUC.js +9 -0
- package/dist/browser/index.d.ts +18 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +95 -0
- package/dist/{index-53f3b8p8.js → chunk-2W3MHTMG.js} +552 -213
- package/dist/chunk-44FFQKQX.js +142 -0
- package/dist/chunk-4HYPLFJD.js +150 -0
- package/dist/chunk-4XIVMVHC.js +361 -0
- package/dist/{index-yp88he8n.js → chunk-6CTA6MCE.js} +88 -64
- package/dist/chunk-6GEZ6DN5.js +394 -0
- package/dist/chunk-7ZFRVCUE.js +211 -0
- package/dist/chunk-CAG4FULI.js +121 -0
- package/dist/chunk-FF36CQHZ.js +61 -0
- package/dist/{index-h32txmxe.js → chunk-FKQO5A3H.js} +6 -13
- package/dist/{index-nq520y6k.js → chunk-FWRS4CSC.js} +46 -32
- package/dist/chunk-GFZCJ4EH.js +108 -0
- package/dist/chunk-GLM4HGN4.js +55 -0
- package/dist/{index-4cdr7x2x.js → chunk-GU374KWZ.js} +182 -111
- package/dist/chunk-H6JB3PZ3.js +45 -0
- package/dist/chunk-IZX2PLIB.js +1240 -0
- package/dist/chunk-J2TXUFCZ.js +289 -0
- package/dist/chunk-J3WYZO3Q.js +211 -0
- package/dist/{index-xzym9w0m.js → chunk-JA7AIHRK.js} +12 -7
- package/dist/chunk-JHHEXEDM.js +162 -0
- package/dist/chunk-JUEMDWLU.js +233 -0
- package/dist/chunk-KFQGP6VL.js +33 -0
- package/dist/chunk-KIJITUZB.js +419 -0
- package/dist/{index-4wxa8xz4.js → chunk-KQ4A2D2P.js} +162 -23
- package/dist/chunk-KSU2GW22.js +958 -0
- package/dist/{index-rv1p47gp.js → chunk-L5N5PR2S.js} +3015 -2480
- package/dist/{index-h9e2efx4.js → chunk-LNUIGRDZ.js} +71 -55
- package/dist/{index-skhn0agf.js → chunk-MLC5BUYO.js} +19 -20
- package/dist/chunk-MPXUVGT3.js +104 -0
- package/dist/chunk-N6MYZT4O.js +68 -0
- package/dist/chunk-O2AV5WMN.js +48 -0
- package/dist/chunk-PZ4XYZ4J.js +143 -0
- package/dist/chunk-QB5ISE47.js +419 -0
- package/dist/chunk-RSWUFTO2.js +857 -0
- package/dist/chunk-S3XLFZ27.js +1095 -0
- package/dist/{index-w5wccer3.js → chunk-S6GBJ2ZB.js} +28 -12
- package/dist/{index-7pjz3tsy.js → chunk-SGMDTWJJ.js} +57 -15
- package/dist/chunk-SPSPV5BC.js +390 -0
- package/dist/chunk-TCKXSOBP.js +123 -0
- package/dist/chunk-UBGUDMUV.js +59 -0
- package/dist/{index-wt8rz4gn.js → chunk-UQISRW6T.js} +97 -26
- package/dist/chunk-USEINYUL.js +12 -0
- package/dist/{index-bmyt7k8n.js → chunk-UZRUP7QW.js} +12 -4
- package/dist/{index-xhcp6xrn.js → chunk-VBYUTRXX.js} +695 -514
- package/dist/{index-vkpkfwhq.js → chunk-VDAKEOML.js} +234 -194
- package/dist/chunk-WXSWA3MV.js +0 -0
- package/dist/{index-n9f2qyh5.js → chunk-X5FLTRUB.js} +55 -33
- package/dist/{index-h7zxhhhh.js → chunk-XMQ7G77X.js} +46 -38
- package/dist/{index-w7ng765c.js → chunk-YCM7ZYEZ.js} +102 -49
- package/dist/cli/deploy-cli.d.ts +18 -0
- package/dist/cli/deploy-cli.d.ts.map +1 -0
- package/dist/cli/errors.d.ts +6 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/examples.d.ts +23 -0
- package/dist/cli/examples.d.ts.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2426 -6225
- package/dist/client/index.browser.d.ts +29 -0
- package/dist/client/index.browser.d.ts.map +1 -0
- package/dist/client/index.browser.js +64 -0
- package/dist/client/index.d.ts +6 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +41 -21
- package/dist/client/live.d.ts +67 -0
- package/dist/client/live.d.ts.map +1 -0
- package/dist/client/reactive.d.ts +31 -0
- package/dist/client/reactive.d.ts.map +1 -0
- package/dist/client/sdk.browser.d.ts +104 -0
- package/dist/client/sdk.browser.d.ts.map +1 -0
- package/dist/client/sdk.browser.js +9 -0
- package/dist/client/sdk.d.ts +26 -2
- package/dist/client/sdk.d.ts.map +1 -1
- package/dist/client/sdk.js +9 -0
- package/dist/client/vcs-client.d.ts +129 -0
- package/dist/client/vcs-client.d.ts.map +1 -0
- package/dist/cms/index.js +171 -163
- package/dist/{config-8hczw0rs.js → config-PFTP67TR.js} +8 -9
- package/dist/core/computation/index.d.ts +5 -0
- package/dist/core/computation/index.d.ts.map +1 -0
- package/dist/core/computation/rollup.d.ts +18 -0
- package/dist/core/computation/rollup.d.ts.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +171 -104
- package/dist/core/kernel/boot-middleware.d.ts +10 -0
- package/dist/core/kernel/boot-middleware.d.ts.map +1 -0
- package/dist/core/kernel/logic-middleware.d.ts +7 -1
- package/dist/core/kernel/logic-middleware.d.ts.map +1 -1
- package/dist/core/kernel/trellis-kernel.d.ts.map +1 -1
- package/dist/core/ontology/types.d.ts +5 -0
- package/dist/core/ontology/types.d.ts.map +1 -1
- package/dist/core/persist/better-sqlite-backend.d.ts +9 -2
- package/dist/core/persist/better-sqlite-backend.d.ts.map +1 -1
- package/dist/core/persist/factory.d.ts +6 -7
- package/dist/core/persist/factory.d.ts.map +1 -1
- package/dist/core/persist/factory.js +2 -3
- package/dist/core/persist/sqljs-backend.js +2 -3
- package/dist/db/index.d.ts +4 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +67 -54
- package/dist/db/inspector.js +11 -19
- package/dist/db/trellis.css +1 -1
- package/dist/decisions/index.js +9 -10
- package/dist/deploy-LQ7GUGJ5.js +9 -0
- package/dist/deploy-YNVG5E4E.js +9 -0
- package/dist/deploy-cli-24BCHAXY.js +67 -0
- package/dist/deploy-cli-C35HTITO.js +67 -0
- package/dist/embeddings/auto-embed.d.ts +2 -2
- package/dist/embeddings/auto-embed.d.ts.map +1 -1
- package/dist/embeddings/index.js +20 -22
- package/dist/embeddings/search.d.ts +2 -1
- package/dist/embeddings/search.d.ts.map +1 -1
- package/dist/embeddings/store.d.ts +25 -4
- package/dist/embeddings/store.d.ts.map +1 -1
- package/dist/engine.d.ts +59 -19
- package/dist/engine.d.ts.map +1 -1
- package/dist/import-UZEKXU3B.js +10 -0
- package/dist/index.js +102 -93
- package/dist/launch-explorer-HZ4ZJA4X.js +95 -0
- package/dist/links/index.js +24 -26
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/plugins/agent-memory/index.js +316 -0
- package/dist/plugins/idea-garden/index.js +165 -0
- package/dist/plugins/plan-approval/index.js +579 -0
- package/dist/plugins/proactive-watcher/index.js +194 -0
- package/dist/{index-2r4jxwnb.js → query-XYLTJYSA.js} +14 -15
- package/dist/react/index.js +39 -70
- package/dist/react/realtime.js +11 -0
- package/dist/react/schema-hooks.js +87 -0
- package/dist/realtime/broadcast-channel-transport.d.ts +43 -0
- package/dist/realtime/broadcast-channel-transport.d.ts.map +1 -0
- package/dist/realtime/durable-object-relay-transport.d.ts +96 -0
- package/dist/realtime/durable-object-relay-transport.d.ts.map +1 -0
- package/dist/realtime/index.d.ts +44 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +40 -0
- package/dist/realtime/memory-hub.d.ts +32 -0
- package/dist/realtime/memory-hub.d.ts.map +1 -0
- package/dist/realtime/persistent-channel.d.ts +105 -0
- package/dist/realtime/persistent-channel.d.ts.map +1 -0
- package/dist/realtime/presence.d.ts +73 -0
- package/dist/realtime/presence.d.ts.map +1 -0
- package/dist/realtime/relay-persistence.d.ts +37 -0
- package/dist/realtime/relay-persistence.d.ts.map +1 -0
- package/dist/realtime/relay-persistence.js +107 -0
- package/dist/realtime/relay-server.d.ts +103 -0
- package/dist/realtime/relay-server.d.ts.map +1 -0
- package/dist/realtime/room.d.ts +98 -0
- package/dist/realtime/room.d.ts.map +1 -0
- package/dist/realtime/text.d.ts +73 -0
- package/dist/realtime/text.d.ts.map +1 -0
- package/dist/realtime/types.d.ts +89 -0
- package/dist/realtime/types.d.ts.map +1 -0
- package/dist/realtime/websocket-relay-transport.d.ts +28 -0
- package/dist/realtime/websocket-relay-transport.d.ts.map +1 -0
- package/dist/realtime.bundle.js +1100 -0
- package/dist/{remote-manager-xvbg4230.js → remote-manager-ODE3T2KR.js} +25 -15
- package/dist/scaffold/seed.d.ts.map +1 -1
- package/dist/scaffold/write.d.ts +1 -1
- package/dist/scaffold/write.d.ts.map +1 -1
- package/dist/schema/define.d.ts +137 -0
- package/dist/schema/define.d.ts.map +1 -0
- package/dist/schema/entity-projection.d.ts +34 -0
- package/dist/schema/entity-projection.d.ts.map +1 -0
- package/dist/schema/eql.d.ts +46 -0
- package/dist/schema/eql.d.ts.map +1 -0
- package/dist/schema/index.d.ts +21 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +46 -0
- package/dist/schema/kernel-resolve.d.ts +21 -0
- package/dist/schema/kernel-resolve.d.ts.map +1 -0
- package/dist/schema/mutations.d.ts +20 -0
- package/dist/schema/mutations.d.ts.map +1 -0
- package/dist/schema/resolve.d.ts +21 -0
- package/dist/schema/resolve.d.ts.map +1 -0
- package/dist/server/deploy-meta.d.ts +25 -0
- package/dist/server/deploy-meta.d.ts.map +1 -0
- package/dist/server/deploy.d.ts +7 -2
- package/dist/server/deploy.d.ts.map +1 -1
- package/dist/server/index.d.ts +7 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +100 -58
- package/dist/server/node-adapter.js +5 -104
- package/dist/server/realtime.d.ts +14 -3
- package/dist/server/realtime.d.ts.map +1 -1
- package/dist/server/server.d.ts +8 -16
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/sprites.d.ts +18 -1
- package/dist/server/sprites.d.ts.map +1 -1
- package/dist/server/tenancy.d.ts +4 -0
- package/dist/server/tenancy.d.ts.map +1 -1
- package/dist/server/usage-meter.d.ts +53 -0
- package/dist/server/usage-meter.d.ts.map +1 -0
- package/dist/server-MB3OPSPI.js +18 -0
- package/dist/server-ZVWGLLRF.js +18 -0
- package/dist/sprites-KQGTGM6W.js +27 -0
- package/dist/{sprites-vc4qbrp1.js → sprites-RU3E4XQN.js} +6 -7
- package/dist/svelte/index.d.ts +17 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +51 -0
- package/dist/svelte/schema-hooks.d.ts +45 -0
- package/dist/svelte/schema-hooks.d.ts.map +1 -0
- package/dist/svelte/schema-hooks.js +71 -0
- package/dist/svelte/stores.d.ts +78 -0
- package/dist/svelte/stores.d.ts.map +1 -0
- package/dist/sync/http-transport.d.ts +3 -3
- package/dist/sync/http-transport.d.ts.map +1 -1
- package/dist/sync/index.d.ts +15 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +617 -0
- package/dist/sync/memory-room.d.ts +37 -0
- package/dist/sync/memory-room.d.ts.map +1 -0
- package/dist/sync/memory-transport.d.ts +3 -3
- package/dist/sync/memory-transport.d.ts.map +1 -1
- package/dist/sync/partykit-room.d.ts +40 -0
- package/dist/sync/partykit-room.d.ts.map +1 -0
- package/dist/sync/partykit-transport.d.ts +84 -0
- package/dist/sync/partykit-transport.d.ts.map +1 -0
- package/dist/sync/room-core.d.ts +53 -0
- package/dist/sync/room-core.d.ts.map +1 -0
- package/dist/sync/sync-engine.d.ts +40 -2
- package/dist/sync/sync-engine.d.ts.map +1 -1
- package/dist/sync/sync-room-server.d.ts +39 -0
- package/dist/sync/sync-room-server.d.ts.map +1 -0
- package/dist/sync/types.d.ts +70 -3
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/sync/vcs-sync-peer.d.ts +63 -0
- package/dist/sync/vcs-sync-peer.d.ts.map +1 -0
- package/dist/sync/ws-transport.d.ts +2 -2
- package/dist/sync/ws-transport.d.ts.map +1 -1
- package/dist/tenancy-NBLLGCNJ.js +14 -0
- package/dist/tenancy-POMWQP6M.js +16 -0
- package/dist/ui/client.html +355 -67
- package/dist/ui/launch-explorer.d.ts +22 -0
- package/dist/ui/launch-explorer.d.ts.map +1 -0
- package/dist/ui/server.d.ts +1 -1
- package/dist/ui/server.d.ts.map +1 -1
- package/dist/vcs/blob-store.d.ts.map +1 -1
- package/dist/vcs/idb-op-log.d.ts +67 -0
- package/dist/vcs/idb-op-log.d.ts.map +1 -0
- package/dist/vcs/index.d.ts +1 -0
- package/dist/vcs/index.d.ts.map +1 -1
- package/dist/vcs/index.js +81 -72
- package/dist/vcs/issue.d.ts +22 -5
- package/dist/vcs/issue.d.ts.map +1 -1
- package/dist/vcs/lane-materialize.d.ts +5 -0
- package/dist/vcs/lane-materialize.d.ts.map +1 -1
- package/dist/vcs/op-log.d.ts +28 -2
- package/dist/vcs/op-log.d.ts.map +1 -1
- package/dist/vcs/ops.d.ts +10 -0
- package/dist/vcs/ops.d.ts.map +1 -1
- package/dist/vcs/types.d.ts +2 -0
- package/dist/vcs/types.d.ts.map +1 -1
- package/dist/{vm-config-6xhsj6b3.js → vm-config-JI4OXKDQ.js} +9 -10
- package/dist/vue/hooks.d.ts +64 -0
- package/dist/vue/hooks.d.ts.map +1 -0
- package/dist/vue/index.d.ts +19 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +59 -0
- package/dist/vue/schema-hooks.d.ts +41 -0
- package/dist/vue/schema-hooks.d.ts.map +1 -0
- package/dist/vue/schema-hooks.js +64 -0
- package/package.json +130 -17
- package/dist/deploy-999q207z.js +0 -10
- package/dist/engine-y0724kjq.js +0 -8
- package/dist/import-s2b8e0ft.js +0 -11
- package/dist/index-a76rekgs.js +0 -67
- package/dist/index-c9h37r6h.js +0 -1
- package/dist/index-hr9qvv77.js +0 -860
- package/dist/index-k5b0xskw.js +0 -1
- package/dist/index-nzb3am4f.js +0 -80
- package/dist/index-wncptktd.js +0 -292
- package/dist/index-y6a4kj0p.js +0 -43
- package/dist/index-yhwjgfvj.js +0 -342
- package/dist/sdk-bepky0xs.js +0 -16
- package/dist/server-szdjx0nt.js +0 -13
- package/dist/sqlite-backend-0vsmc6qj.js +0 -8
- package/dist/tenancy-pjm32b4v.js +0 -14
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/realtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,YAAY,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,YAAY,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAC;AAErF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,YAAY,EACV,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BroadcastChannelTransport,
|
|
3
|
+
DEFAULT_MAX_RECORDS,
|
|
4
|
+
DurableObjectRelayTransport,
|
|
5
|
+
MemoryHub,
|
|
6
|
+
MemoryRealtimeTransport,
|
|
7
|
+
PersistentChannel,
|
|
8
|
+
REALTIME_PROTOCOL,
|
|
9
|
+
RealtimeRoom,
|
|
10
|
+
RealtimeText,
|
|
11
|
+
WebSocketRelayTransport,
|
|
12
|
+
createPresenceTransport,
|
|
13
|
+
joinPresence,
|
|
14
|
+
localStorageChannelStore
|
|
15
|
+
} from "../chunk-KSU2GW22.js";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_MAX_CHAT,
|
|
18
|
+
DEFAULT_MAX_TEXT_OPS,
|
|
19
|
+
RelayPersistence
|
|
20
|
+
} from "../chunk-GFZCJ4EH.js";
|
|
21
|
+
import "../chunk-UBGUDMUV.js";
|
|
22
|
+
import "../chunk-KFQGP6VL.js";
|
|
23
|
+
export {
|
|
24
|
+
BroadcastChannelTransport,
|
|
25
|
+
DEFAULT_MAX_CHAT,
|
|
26
|
+
DEFAULT_MAX_RECORDS,
|
|
27
|
+
DEFAULT_MAX_TEXT_OPS,
|
|
28
|
+
DurableObjectRelayTransport,
|
|
29
|
+
MemoryHub,
|
|
30
|
+
MemoryRealtimeTransport,
|
|
31
|
+
PersistentChannel,
|
|
32
|
+
REALTIME_PROTOCOL,
|
|
33
|
+
RealtimeRoom,
|
|
34
|
+
RealtimeText,
|
|
35
|
+
RelayPersistence,
|
|
36
|
+
WebSocketRelayTransport,
|
|
37
|
+
createPresenceTransport,
|
|
38
|
+
joinPresence,
|
|
39
|
+
localStorageChannelStore
|
|
40
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process broadcast mesh for realtime presence/broadcast.
|
|
3
|
+
*
|
|
4
|
+
* Useful for tests and for "side-by-side" demos where several simulated peers
|
|
5
|
+
* share one page. Each {@link MemoryRealtimeTransport} delivers messages to
|
|
6
|
+
* every other transport on the same hub (never to itself).
|
|
7
|
+
*/
|
|
8
|
+
import type { RealtimeMessage, RealtimeTransport } from './types.js';
|
|
9
|
+
export declare class MemoryHub {
|
|
10
|
+
private transports;
|
|
11
|
+
/** Create a transport bound to this hub for the given peer id. */
|
|
12
|
+
connect(id: string): MemoryRealtimeTransport;
|
|
13
|
+
/** Number of currently connected transports. */
|
|
14
|
+
size(): number;
|
|
15
|
+
/** @internal */
|
|
16
|
+
_broadcast(from: MemoryRealtimeTransport, message: RealtimeMessage): void;
|
|
17
|
+
/** @internal */
|
|
18
|
+
_remove(transport: MemoryRealtimeTransport): void;
|
|
19
|
+
}
|
|
20
|
+
export declare class MemoryRealtimeTransport implements RealtimeTransport {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
private hub;
|
|
23
|
+
private handlers;
|
|
24
|
+
private closed;
|
|
25
|
+
constructor(hub: MemoryHub, id: string);
|
|
26
|
+
send(message: RealtimeMessage): void;
|
|
27
|
+
onMessage(handler: (message: RealtimeMessage) => void): () => void;
|
|
28
|
+
close(): void;
|
|
29
|
+
/** @internal */
|
|
30
|
+
_deliver(message: RealtimeMessage): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=memory-hub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-hub.d.ts","sourceRoot":"","sources":["../../src/realtime/memory-hub.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErE,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAsC;IAExD,kEAAkE;IAClE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB;IAM5C,gDAAgD;IAChD,IAAI,IAAI,MAAM;IAId,gBAAgB;IAChB,UAAU,CAAC,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAOzE,gBAAgB;IAChB,OAAO,CAAC,SAAS,EAAE,uBAAuB,GAAG,IAAI;CAGlD;AAED,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,QAAQ,CAAiD;IACjE,OAAO,CAAC,MAAM,CAAS;gBAEX,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM;IAKtC,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAKpC,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlE,KAAK,IAAI,IAAI;IAOb,gBAAgB;IAChB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;CAUzC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PersistentChannel — a durable, convergent view over one broadcast channel.
|
|
3
|
+
*
|
|
4
|
+
* Wraps a {@link RealtimeRoom} channel as a **grow-only set** keyed by message
|
|
5
|
+
* id: every record is deduplicated by id and ordered by `(ts, id)`, so the same
|
|
6
|
+
* message arriving from any source (optimistic local send, live broadcast, or a
|
|
7
|
+
* relay replay on reconnect) lands exactly once and in a stable order.
|
|
8
|
+
*
|
|
9
|
+
* There is no single source of truth. Each peer holds its own replica (a
|
|
10
|
+
* pluggable {@link ChannelStore} — `localStorage`, IndexedDB, …) and the relay
|
|
11
|
+
* holds another. They converge on reconnect because union + id-dedup is
|
|
12
|
+
* commutative and idempotent. The store is an instant first-paint cache, not an
|
|
13
|
+
* authority: a refresh repaints from it immediately, then merges whatever the
|
|
14
|
+
* relay replays.
|
|
15
|
+
*
|
|
16
|
+
* const chat = PersistentChannel.create(room, 'chat', {
|
|
17
|
+
* store: localStorageChannelStore(`chat:${roomUrl}`),
|
|
18
|
+
* resolveMeta: (e) => presenceById()[e.from], // capture name/color
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* chat.messages.subscribe((msgs) => render(msgs)); // deduped + sorted
|
|
22
|
+
* chat.send({ text }); // optimistic + broadcast + persist
|
|
23
|
+
*
|
|
24
|
+
* Only the channel's "message" event (configurable) is persisted; transient
|
|
25
|
+
* events like typing indicators stay the caller's concern via `room.on`.
|
|
26
|
+
*/
|
|
27
|
+
import { Signal } from '../client/reactive.js';
|
|
28
|
+
import type { RealtimeRoom } from './room.js';
|
|
29
|
+
import type { BroadcastEvent } from './types.js';
|
|
30
|
+
/** A persisted member of the grow-only set. */
|
|
31
|
+
export interface ChannelRecord<T = unknown> {
|
|
32
|
+
/** Stable dedup key (sender-assigned message id). */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Originating peer id. */
|
|
35
|
+
from: string;
|
|
36
|
+
/** Sender clock (epoch ms) — primary sort key. */
|
|
37
|
+
ts: number;
|
|
38
|
+
/** Application payload (e.g. `{ text }`). */
|
|
39
|
+
payload: T;
|
|
40
|
+
/** Optional sender metadata captured at send/receipt (name, color, …). */
|
|
41
|
+
meta?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Durable backing store for a peer's local replica. Implementations may be sync
|
|
45
|
+
* (`localStorage`) or async (IndexedDB/OPFS); `load` may return a promise.
|
|
46
|
+
*/
|
|
47
|
+
export interface ChannelStore<T = unknown> {
|
|
48
|
+
load(): ChannelRecord<T>[] | Promise<ChannelRecord<T>[]>;
|
|
49
|
+
save(records: ChannelRecord<T>[]): void | Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export interface PersistentChannelOptions<T = unknown> {
|
|
52
|
+
/** Broadcast event name treated as a persisted message. Default `'message'`. */
|
|
53
|
+
event?: string;
|
|
54
|
+
/** Durable replica for this peer. Omit for in-memory only. */
|
|
55
|
+
store?: ChannelStore<T>;
|
|
56
|
+
/** Keep at most the N most recent records. Default 200. */
|
|
57
|
+
max?: number;
|
|
58
|
+
/** Capture sender metadata for an inbound message (e.g. from presence). */
|
|
59
|
+
resolveMeta?: (event: BroadcastEvent) => Record<string, unknown> | undefined;
|
|
60
|
+
/** Injectable clock for local sends. Default `Date.now`. */
|
|
61
|
+
now?: () => number;
|
|
62
|
+
}
|
|
63
|
+
export declare const DEFAULT_MAX_RECORDS = 200;
|
|
64
|
+
export declare class PersistentChannel<T = unknown> {
|
|
65
|
+
/** Reactive, deduped, `(ts, id)`-sorted message list. */
|
|
66
|
+
readonly messages: Signal<ChannelRecord<T>[]>;
|
|
67
|
+
private readonly room;
|
|
68
|
+
private readonly channel;
|
|
69
|
+
private readonly event;
|
|
70
|
+
private readonly store?;
|
|
71
|
+
private readonly max;
|
|
72
|
+
private readonly resolveMeta?;
|
|
73
|
+
private readonly now;
|
|
74
|
+
private records;
|
|
75
|
+
private byId;
|
|
76
|
+
private unsubscribe;
|
|
77
|
+
private disposed;
|
|
78
|
+
private constructor();
|
|
79
|
+
/** Create a persistent view over `room`'s `channel`. */
|
|
80
|
+
static create<T = unknown>(room: RealtimeRoom, channel: string, opts?: PersistentChannelOptions<T>): PersistentChannel<T>;
|
|
81
|
+
/**
|
|
82
|
+
* Optimistically record locally, broadcast to peers, and persist. Returns the
|
|
83
|
+
* stable message id. The room dedups its own id, so the broadcast never
|
|
84
|
+
* echoes back into this channel.
|
|
85
|
+
*/
|
|
86
|
+
send(payload: T, meta?: Record<string, unknown>): string;
|
|
87
|
+
/** Current records (deduped + sorted). Read without subscribing. */
|
|
88
|
+
snapshot(): ChannelRecord<T>[];
|
|
89
|
+
/** Stop listening. Does not clear the durable store. */
|
|
90
|
+
dispose(): void;
|
|
91
|
+
private handleEvent;
|
|
92
|
+
private hydrate;
|
|
93
|
+
/** Insert one record and publish if it was new. */
|
|
94
|
+
private commitOne;
|
|
95
|
+
/** Pure insert with dedup + cap. Returns true when a new record was added. */
|
|
96
|
+
private add;
|
|
97
|
+
private commit;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A {@link ChannelStore} backed by Web Storage (`localStorage` by default).
|
|
101
|
+
* Degrades to in-memory if storage is unavailable or over quota — durability is
|
|
102
|
+
* best-effort, since the relay replica remains authoritative for catch-up.
|
|
103
|
+
*/
|
|
104
|
+
export declare function localStorageChannelStore<T = unknown>(key: string, storage?: Storage | undefined): ChannelStore<T>;
|
|
105
|
+
//# sourceMappingURL=persistent-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistent-channel.d.ts","sourceRoot":"","sources":["../../src/realtime/persistent-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport-agnostic presence — the one place the local-first → cloud-optional
|
|
3
|
+
* gradient is encoded.
|
|
4
|
+
*
|
|
5
|
+
* Presence is ephemeral and self-healing; it is never written to the causal op
|
|
6
|
+
* log. That makes the *transport* a free choice, and this helper picks it by
|
|
7
|
+
* intent rather than hardcoding a hub:
|
|
8
|
+
*
|
|
9
|
+
* - no `relayUrl` → {@link BroadcastChannelTransport}: cross-tab, $0, no
|
|
10
|
+
* socket, works with the network killed. This is the free / local tier and
|
|
11
|
+
* the default. (Telos principle 7: kill the network, presence across tabs
|
|
12
|
+
* still works — you just stop seeing remote peers.)
|
|
13
|
+
* - `relayUrl` set → {@link DurableObjectRelayTransport}: a hosted relay room.
|
|
14
|
+
* This opens a socket, so per the ecosystem economics it is a *paid* tier.
|
|
15
|
+
* - `transport` → bring your own (tests, or an Iroh gossip transport at
|
|
16
|
+
* Boulder 2) — the escape hatch that keeps the seam honest.
|
|
17
|
+
*
|
|
18
|
+
* Frameworks consume this inside their room hooks, e.g. Svelte:
|
|
19
|
+
*
|
|
20
|
+
* import { createRoom } from 'trellis/svelte';
|
|
21
|
+
* import { joinPresence } from 'trellis/realtime';
|
|
22
|
+
*
|
|
23
|
+
* const { presence, others, destroy } = createRoom(() =>
|
|
24
|
+
* joinPresence({ peerId, room: 'doc:42', initialPresence: { name, color } }),
|
|
25
|
+
* );
|
|
26
|
+
*/
|
|
27
|
+
import { BroadcastChannelTransport } from './broadcast-channel-transport.js';
|
|
28
|
+
import { DurableObjectRelayTransport } from './durable-object-relay-transport.js';
|
|
29
|
+
import { RealtimeRoom } from './room.js';
|
|
30
|
+
import type { PresenceState, RealtimeTransport } from './types.js';
|
|
31
|
+
export interface PresenceOptions<P extends PresenceState = PresenceState> {
|
|
32
|
+
/** Local peer identity (stable per tab/device). */
|
|
33
|
+
peerId: string;
|
|
34
|
+
/** Logical room — peers sharing it see each other. */
|
|
35
|
+
room: string;
|
|
36
|
+
/** Initial local presence (name, color, cursor, …). */
|
|
37
|
+
initialPresence?: P;
|
|
38
|
+
/**
|
|
39
|
+
* Hosted relay base URL. When set, presence syncs cross-device through the
|
|
40
|
+
* relay (paid tier). When omitted, presence stays local/cross-tab (free).
|
|
41
|
+
*/
|
|
42
|
+
relayUrl?: string;
|
|
43
|
+
/** Auth token for the hosted relay. */
|
|
44
|
+
auth?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Explicit transport — overrides the `relayUrl`/local selection entirely.
|
|
47
|
+
* Use for tests or an alternative transport (e.g. future Iroh gossip).
|
|
48
|
+
*/
|
|
49
|
+
transport?: RealtimeTransport;
|
|
50
|
+
/** Heartbeat interval (ms). Default 2000 (see {@link RealtimeRoom}). */
|
|
51
|
+
heartbeatMs?: number;
|
|
52
|
+
/** Peer expiry after no heartbeat (ms). Default 6000. */
|
|
53
|
+
timeoutMs?: number;
|
|
54
|
+
/** Injectable clock for tests. */
|
|
55
|
+
now?: () => number;
|
|
56
|
+
/** Injectable WebSocket (hosted relay) for tests / non-browser hosts. */
|
|
57
|
+
WebSocketImpl?: ConstructorParameters<typeof DurableObjectRelayTransport>[0]['WebSocketImpl'];
|
|
58
|
+
/** Injectable BroadcastChannel (local) for tests / non-browser hosts. */
|
|
59
|
+
BroadcastChannelImpl?: ConstructorParameters<typeof BroadcastChannelTransport>[0]['BroadcastChannelImpl'];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Select the presence transport for the given options without joining a room.
|
|
63
|
+
* Exposed so callers can inspect or wrap the choice; most code should use
|
|
64
|
+
* {@link joinPresence}.
|
|
65
|
+
*/
|
|
66
|
+
export declare function createPresenceTransport(opts: PresenceOptions): RealtimeTransport;
|
|
67
|
+
/**
|
|
68
|
+
* Join a presence room with a transport chosen by intent (local vs hosted).
|
|
69
|
+
* Returns a {@link RealtimeRoom}; pair it with a framework room hook
|
|
70
|
+
* (`createRoom` / `useRoom`) for reactive presence + broadcast.
|
|
71
|
+
*/
|
|
72
|
+
export declare function joinPresence<P extends PresenceState = PresenceState>(opts: PresenceOptions<P>): RealtimeRoom<P>;
|
|
73
|
+
//# sourceMappingURL=presence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../src/realtime/presence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa;IACtE,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,eAAe,CAAC,EAAE,CAAC,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,yEAAyE;IACzE,aAAa,CAAC,EAAE,qBAAqB,CACnC,OAAO,2BAA2B,CACnC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IACtB,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,qBAAqB,CAC1C,OAAO,yBAAyB,CACjC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,eAAe,GACpB,iBAAiB,CAgBnB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAClE,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GACvB,YAAY,CAAC,CAAC,CAAC,CAQjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory persistence for a WebSocket relay hub (demo / dev).
|
|
3
|
+
*
|
|
4
|
+
* Retains durable-enough session state: latest presence per peer, chat tail,
|
|
5
|
+
* and collaborative text (snapshot preferred, else op tail). Not the VCS op
|
|
6
|
+
* log — reset when the relay process stops.
|
|
7
|
+
*/
|
|
8
|
+
import type { RealtimeMessage } from './types.js';
|
|
9
|
+
export declare const DEFAULT_MAX_CHAT = 200;
|
|
10
|
+
export declare const DEFAULT_MAX_TEXT_OPS = 2000;
|
|
11
|
+
export interface RelayPersistenceOptions {
|
|
12
|
+
maxChat?: number;
|
|
13
|
+
maxTextOps?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Records relay traffic and builds ordered replay batches for newcomers.
|
|
17
|
+
*/
|
|
18
|
+
export declare class RelayPersistence {
|
|
19
|
+
private maxChat;
|
|
20
|
+
private maxTextOps;
|
|
21
|
+
private presence;
|
|
22
|
+
/** Chat is a grow-only set keyed by {@link chatKey} — dedup on record. */
|
|
23
|
+
private chatLog;
|
|
24
|
+
private chatKeys;
|
|
25
|
+
private textSnapshot;
|
|
26
|
+
private textOps;
|
|
27
|
+
constructor(opts?: RelayPersistenceOptions);
|
|
28
|
+
/** Record an inbound client message (skip `hello` / `replay`). */
|
|
29
|
+
record(message: RealtimeMessage): void;
|
|
30
|
+
/** Ordered messages to replay to a peer that just connected. */
|
|
31
|
+
buildReplay(): RealtimeMessage[];
|
|
32
|
+
getPresenceCount(): number;
|
|
33
|
+
getChatCount(): number;
|
|
34
|
+
hasTextSnapshot(): boolean;
|
|
35
|
+
private recordBroadcast;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=relay-persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-persistence.d.ts","sourceRoot":"","sources":["../../src/realtime/relay-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AA4BzC,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAkC;IAClD,0EAA0E;IAC1E,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,OAAO,CAAsB;gBAEzB,IAAI,GAAE,uBAA4B;IAK9C,kEAAkE;IAClE,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAoBtC,gEAAgE;IAChE,WAAW,IAAI,eAAe,EAAE;IAmBhC,gBAAgB,IAAI,MAAM;IAI1B,YAAY,IAAI,MAAM;IAItB,eAAe,IAAI,OAAO;IAI1B,OAAO,CAAC,eAAe;CA2BxB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/realtime/relay-persistence.ts
|
|
2
|
+
var DEFAULT_MAX_CHAT = 200;
|
|
3
|
+
var DEFAULT_MAX_TEXT_OPS = 2e3;
|
|
4
|
+
function chatKey(msg) {
|
|
5
|
+
return msg.id ?? `${msg.from}:${msg.ts}`;
|
|
6
|
+
}
|
|
7
|
+
function tieKey(msg) {
|
|
8
|
+
if (msg.t === "msg") return chatKey(msg);
|
|
9
|
+
if (msg.t === "presence" || msg.t === "bye") return msg.from;
|
|
10
|
+
return "";
|
|
11
|
+
}
|
|
12
|
+
function messageTs(msg) {
|
|
13
|
+
if (msg.t === "presence" || msg.t === "bye" || msg.t === "msg") {
|
|
14
|
+
return msg.ts;
|
|
15
|
+
}
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
var RelayPersistence = class {
|
|
19
|
+
maxChat;
|
|
20
|
+
maxTextOps;
|
|
21
|
+
presence = /* @__PURE__ */ new Map();
|
|
22
|
+
/** Chat is a grow-only set keyed by {@link chatKey} — dedup on record. */
|
|
23
|
+
chatLog = [];
|
|
24
|
+
chatKeys = /* @__PURE__ */ new Set();
|
|
25
|
+
textSnapshot = null;
|
|
26
|
+
textOps = [];
|
|
27
|
+
constructor(opts = {}) {
|
|
28
|
+
this.maxChat = opts.maxChat ?? DEFAULT_MAX_CHAT;
|
|
29
|
+
this.maxTextOps = opts.maxTextOps ?? DEFAULT_MAX_TEXT_OPS;
|
|
30
|
+
}
|
|
31
|
+
/** Record an inbound client message (skip `hello` / `replay`). */
|
|
32
|
+
record(message) {
|
|
33
|
+
if (message.v !== 1) return;
|
|
34
|
+
switch (message.t) {
|
|
35
|
+
case "hello":
|
|
36
|
+
return;
|
|
37
|
+
case "replay":
|
|
38
|
+
return;
|
|
39
|
+
case "presence":
|
|
40
|
+
this.presence.set(message.from, message);
|
|
41
|
+
return;
|
|
42
|
+
case "bye":
|
|
43
|
+
this.presence.delete(message.from);
|
|
44
|
+
return;
|
|
45
|
+
case "msg":
|
|
46
|
+
this.recordBroadcast(message);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Ordered messages to replay to a peer that just connected. */
|
|
51
|
+
buildReplay() {
|
|
52
|
+
const out = [
|
|
53
|
+
...this.presence.values(),
|
|
54
|
+
...this.chatLog
|
|
55
|
+
];
|
|
56
|
+
if (this.textSnapshot) {
|
|
57
|
+
out.push(this.textSnapshot);
|
|
58
|
+
} else {
|
|
59
|
+
out.push(...this.textOps);
|
|
60
|
+
}
|
|
61
|
+
out.sort((a, b) => {
|
|
62
|
+
const dt = messageTs(a) - messageTs(b);
|
|
63
|
+
if (dt !== 0) return dt;
|
|
64
|
+
return tieKey(a).localeCompare(tieKey(b));
|
|
65
|
+
});
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
getPresenceCount() {
|
|
69
|
+
return this.presence.size;
|
|
70
|
+
}
|
|
71
|
+
getChatCount() {
|
|
72
|
+
return this.chatLog.length;
|
|
73
|
+
}
|
|
74
|
+
hasTextSnapshot() {
|
|
75
|
+
return this.textSnapshot !== null;
|
|
76
|
+
}
|
|
77
|
+
recordBroadcast(message) {
|
|
78
|
+
if (message.channel === "chat" && message.event === "message") {
|
|
79
|
+
const key = chatKey(message);
|
|
80
|
+
if (this.chatKeys.has(key)) return;
|
|
81
|
+
this.chatKeys.add(key);
|
|
82
|
+
this.chatLog.push(message);
|
|
83
|
+
if (this.chatLog.length > this.maxChat) {
|
|
84
|
+
const evicted = this.chatLog.splice(0, this.chatLog.length - this.maxChat);
|
|
85
|
+
for (const m of evicted) this.chatKeys.delete(chatKey(m));
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (message.channel === "text" && message.event === "state") {
|
|
90
|
+
this.textSnapshot = message;
|
|
91
|
+
this.textOps = [];
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (message.channel === "text" && message.event === "op") {
|
|
95
|
+
if (this.textSnapshot) return;
|
|
96
|
+
this.textOps.push(message);
|
|
97
|
+
if (this.textOps.length > this.maxTextOps) {
|
|
98
|
+
this.textOps.splice(0, this.textOps.length - this.maxTextOps);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
export {
|
|
104
|
+
DEFAULT_MAX_CHAT,
|
|
105
|
+
DEFAULT_MAX_TEXT_OPS,
|
|
106
|
+
RelayPersistence
|
|
107
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trellis Realtime — Relay Hub (server side)
|
|
3
|
+
*
|
|
4
|
+
* The server counterpart to {@link WebSocketRelayTransport}: a dumb broadcast
|
|
5
|
+
* mesh that fans every inbound frame out to all *other* connected peers, with
|
|
6
|
+
* optional in-memory replay ({@link RelayPersistence}) so a late joiner catches
|
|
7
|
+
* up on presence / chat tail / text state.
|
|
8
|
+
*
|
|
9
|
+
* This is intentionally NOT {@link RealtimeRoom}. `RealtimeRoom` is a *client*
|
|
10
|
+
* abstraction — one peer's view of a room (its own presence + observed peers).
|
|
11
|
+
* The relay holds no presence of its own; it only moves bytes between peers and
|
|
12
|
+
* remembers enough to replay. Keep the two roles distinct: clients run
|
|
13
|
+
* `RealtimeRoom`, the server runs a relay.
|
|
14
|
+
*
|
|
15
|
+
* Room-scoped: peers are fanned out (and replayed) only to others in the *same*
|
|
16
|
+
* room. The room is taken from the upgrade path — `${path}/{room}` — matching
|
|
17
|
+
* {@link DurableObjectRelayTransport}'s `${url}/{room}` convention (and the
|
|
18
|
+
* reference Durable Object worker, which maps one object per room). A bare
|
|
19
|
+
* connection to `path` lands in the `'default'` room. This makes the bundled
|
|
20
|
+
* relay a faithful local stand-in for the hosted DO: distinct rooms stay
|
|
21
|
+
* isolated, so `joinPresence({ relayUrl })` Just Works against it.
|
|
22
|
+
*
|
|
23
|
+
* Node-only (uses `node:http` + the optional `ws` package). Exposed through
|
|
24
|
+
* `trellis/server`, never `trellis/realtime` (which is browser-bundled).
|
|
25
|
+
*
|
|
26
|
+
* import { createServer } from 'node:http';
|
|
27
|
+
* import { attachRealtimeRelay } from 'trellis/server';
|
|
28
|
+
*
|
|
29
|
+
* const server = createServer(handler);
|
|
30
|
+
* await attachRealtimeRelay(server, { path: '/rt' });
|
|
31
|
+
* server.listen(8231);
|
|
32
|
+
* // client: joinPresence({ relayUrl: 'ws://localhost:8231/rt', room: 'doc:42' })
|
|
33
|
+
* // → connects to ws://localhost:8231/rt/doc:42
|
|
34
|
+
*
|
|
35
|
+
* @module trellis/server
|
|
36
|
+
*/
|
|
37
|
+
import type { Server as HttpServer } from 'node:http';
|
|
38
|
+
import { RelayPersistence } from '../realtime/relay-persistence.js';
|
|
39
|
+
export interface RealtimeRelayOptions {
|
|
40
|
+
/**
|
|
41
|
+
* Base WebSocket upgrade path this relay claims. Default `/rt`. The relay
|
|
42
|
+
* accepts `path` (→ room `'default'`) and `${path}/{room}` (→ that room);
|
|
43
|
+
* other upgrade paths are left untouched so it can coexist with path-scoped
|
|
44
|
+
* WebSocket handlers.
|
|
45
|
+
*/
|
|
46
|
+
path?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Per-room replay store factory for late joiners. A fresh store is created
|
|
49
|
+
* the first time a room is seen. Pass `false` to disable replay entirely
|
|
50
|
+
* (pure fan-out). Default: `() => new RelayPersistence()`.
|
|
51
|
+
*/
|
|
52
|
+
persistence?: false | (() => RelayPersistence);
|
|
53
|
+
/**
|
|
54
|
+
* Grace window (ms) before replay is delivered to a new connection when no
|
|
55
|
+
* `hello` frame arrives first (UI mounting subscribers can race the socket).
|
|
56
|
+
* Default 250.
|
|
57
|
+
*/
|
|
58
|
+
replayGraceMs?: number;
|
|
59
|
+
/** Injectable `ws` WebSocketServer ctor for tests. */
|
|
60
|
+
WebSocketServerImpl?: unknown;
|
|
61
|
+
}
|
|
62
|
+
export interface RealtimeRelay {
|
|
63
|
+
/** Connected peers — across all rooms, or in `room` when given. */
|
|
64
|
+
clientCount(room?: string): number;
|
|
65
|
+
/** Currently active room ids (rooms drop when their last peer leaves). */
|
|
66
|
+
rooms(): string[];
|
|
67
|
+
/** The replay store for `room`, or `null` when replay is disabled. */
|
|
68
|
+
persistenceFor(room: string): RelayPersistence | null;
|
|
69
|
+
/** Close every peer socket and tear down the WS server. */
|
|
70
|
+
close(): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Mount a realtime relay on an existing HTTP server. Only handles upgrades on
|
|
74
|
+
* `opts.path`; other upgrade paths are left untouched, so this can coexist with
|
|
75
|
+
* other WebSocket handlers (e.g. the graph-subscription socket) **provided
|
|
76
|
+
* those handlers are themselves path-scoped**.
|
|
77
|
+
*/
|
|
78
|
+
export declare function attachRealtimeRelay(server: HttpServer, opts?: RealtimeRelayOptions): Promise<RealtimeRelay>;
|
|
79
|
+
export interface StandaloneRealtimeRelayOptions extends RealtimeRelayOptions {
|
|
80
|
+
/** Port to bind. Default 8231. Use 0 for an OS-assigned ephemeral port. */
|
|
81
|
+
port?: number;
|
|
82
|
+
/** Host to bind. Default `0.0.0.0`. */
|
|
83
|
+
hostname?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface StandaloneRealtimeRelay extends RealtimeRelay {
|
|
86
|
+
/** The bound port (resolved, so `port: 0` reports the real ephemeral port). */
|
|
87
|
+
port: number;
|
|
88
|
+
/** The underlying HTTP server (health check on `/`, 404 otherwise). */
|
|
89
|
+
server: HttpServer;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Spin up a standalone relay hub on its own HTTP server. The HTTP surface is a
|
|
93
|
+
* health endpoint only (`200` on `/`, `404` elsewhere); the relay lives on the
|
|
94
|
+
* WebSocket upgrade path. For embedding in an existing app server, use
|
|
95
|
+
* {@link attachRealtimeRelay} instead.
|
|
96
|
+
*
|
|
97
|
+
* const relay = await createRealtimeRelay({ port: 8231 });
|
|
98
|
+
* // ws://localhost:8231/rt → room 'default'
|
|
99
|
+
* // ws://localhost:8231/rt/doc:42 → room 'doc:42' (isolated fan-out)
|
|
100
|
+
* await relay.close();
|
|
101
|
+
*/
|
|
102
|
+
export declare function createRealtimeRelay(opts?: StandaloneRealtimeRelayOptions): Promise<StandaloneRealtimeRelay>;
|
|
103
|
+
//# sourceMappingURL=relay-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-server.d.ts","sourceRoot":"","sources":["../../src/realtime/relay-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAmB,MAAM,WAAW,CAAC;AAEvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAapE,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,WAAW,CAAC,EAAE,KAAK,GAAG,CAAC,MAAM,gBAAgB,CAAC,CAAC;IAC/C;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,0EAA0E;IAC1E,KAAK,IAAI,MAAM,EAAE,CAAC;IAClB,sEAAsE;IACtE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACtD,2DAA2D;IAC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAmBD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,oBAAyB,GAC9B,OAAO,CAAC,aAAa,CAAC,CA2IxB;AAED,MAAM,WAAW,8BAA+B,SAAQ,oBAAoB;IAC1E,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAwB,SAAQ,aAAa;IAC5D,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,GAAE,8BAAmC,GACxC,OAAO,CAAC,uBAAuB,CAAC,CA+BlC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RealtimeRoom — presence + broadcast over a {@link RealtimeTransport}.
|
|
3
|
+
*
|
|
4
|
+
* const room = RealtimeRoom.join({
|
|
5
|
+
* transport: new BroadcastChannelTransport({ id, channel: 'demo' }),
|
|
6
|
+
* initialPresence: { name: 'Ada', color: '#6d5bfa' },
|
|
7
|
+
* });
|
|
8
|
+
*
|
|
9
|
+
* room.onPresence((peers) => renderAvatars(peers));
|
|
10
|
+
* room.setPresence({ cursor: { x, y } });
|
|
11
|
+
* room.on('chat', (e) => appendMessage(e.payload));
|
|
12
|
+
* room.broadcast('chat', 'message', { text: 'hi' });
|
|
13
|
+
*
|
|
14
|
+
* Presence is heartbeat-based: peers re-announce on an interval and are pruned
|
|
15
|
+
* after a timeout. Transports with explicit teardown (MemoryHub) also emit an
|
|
16
|
+
* immediate `bye` on {@link RealtimeRoom.leave}.
|
|
17
|
+
*/
|
|
18
|
+
import { Signal } from '../client/reactive.js';
|
|
19
|
+
import type { BroadcastEvent, PresencePeer, PresenceState, RealtimeMessage, RealtimeTransport } from './types.js';
|
|
20
|
+
export interface RealtimeRoomOptions<P extends PresenceState> {
|
|
21
|
+
transport: RealtimeTransport;
|
|
22
|
+
/** Initial presence for the local peer. */
|
|
23
|
+
initialPresence?: P;
|
|
24
|
+
/** Heartbeat interval (ms). Default 2000. Set 0 to disable timers. */
|
|
25
|
+
heartbeatMs?: number;
|
|
26
|
+
/** Peer expiry after no heartbeat (ms). Default 6000. */
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
/** Injectable clock for tests. Default `Date.now`. */
|
|
29
|
+
now?: () => number;
|
|
30
|
+
}
|
|
31
|
+
type BroadcastHandler = (event: BroadcastEvent) => void;
|
|
32
|
+
export declare class RealtimeRoom<P extends PresenceState = PresenceState> {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
private transport;
|
|
35
|
+
private myState;
|
|
36
|
+
private peers;
|
|
37
|
+
/** Sender timestamps from presence messages (not local lastSeen). */
|
|
38
|
+
private presenceTsByPeer;
|
|
39
|
+
private channelHandlers;
|
|
40
|
+
private _presence;
|
|
41
|
+
private now;
|
|
42
|
+
private heartbeatMs;
|
|
43
|
+
private timeoutMs;
|
|
44
|
+
private heartbeatTimer?;
|
|
45
|
+
private unsubscribe;
|
|
46
|
+
private closed;
|
|
47
|
+
private pendingReplay;
|
|
48
|
+
/** Ids of broadcasts already delivered — keeps replay idempotent (G-Set). */
|
|
49
|
+
private seenMsgIds;
|
|
50
|
+
private constructor();
|
|
51
|
+
/** Join a room and announce presence. */
|
|
52
|
+
static join<P extends PresenceState = PresenceState>(opts: RealtimeRoomOptions<P>): RealtimeRoom<P>;
|
|
53
|
+
/** The local peer id. */
|
|
54
|
+
get selfId(): string;
|
|
55
|
+
/** Current local presence state. */
|
|
56
|
+
getSelfState(): P;
|
|
57
|
+
/** Merge a partial update into local presence and broadcast it. */
|
|
58
|
+
setPresence(partial: Partial<P>): void;
|
|
59
|
+
/** Replace local presence wholesale and broadcast it. */
|
|
60
|
+
replacePresence(state: P): void;
|
|
61
|
+
/** All peers including self (self first). */
|
|
62
|
+
getPresence(): PresencePeer<P>[];
|
|
63
|
+
/** Peers excluding self. */
|
|
64
|
+
getOthers(): PresencePeer<P>[];
|
|
65
|
+
/** Subscribe to presence changes. Called immediately with current peers. */
|
|
66
|
+
onPresence(cb: (peers: PresencePeer<P>[]) => void): () => void;
|
|
67
|
+
/** Reactive presence signal (for framework adapters). */
|
|
68
|
+
get presenceSignal(): Signal<PresencePeer<P>[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Fire-and-forget broadcast to all other peers on a channel. Returns the
|
|
71
|
+
* stable message id assigned to this broadcast — persist it alongside an
|
|
72
|
+
* optimistic local render so an echoed copy (relay replay, reconnect) is
|
|
73
|
+
* deduplicated by id rather than re-rendered.
|
|
74
|
+
*/
|
|
75
|
+
broadcast(channel: string, event: string, payload: unknown): string;
|
|
76
|
+
private newMsgId;
|
|
77
|
+
/** Subscribe to broadcasts on a channel. Returns an unsubscribe fn. */
|
|
78
|
+
on(channel: string, handler: BroadcastHandler): () => void;
|
|
79
|
+
/**
|
|
80
|
+
* Apply a relay replay batch (chat history, text snapshot, presence).
|
|
81
|
+
* Used when reconnecting to a hub with {@link RelayPersistence}.
|
|
82
|
+
*/
|
|
83
|
+
replay(messages: RealtimeMessage[]): void;
|
|
84
|
+
/** Announce departure and tear down. */
|
|
85
|
+
leave(): void;
|
|
86
|
+
private handle;
|
|
87
|
+
private flushPendingReplay;
|
|
88
|
+
private hasActiveSubscribers;
|
|
89
|
+
private integrateRemote;
|
|
90
|
+
private upsertPeer;
|
|
91
|
+
private announceHello;
|
|
92
|
+
private announcePresence;
|
|
93
|
+
private startHeartbeat;
|
|
94
|
+
private pruneExpired;
|
|
95
|
+
private recomputePresence;
|
|
96
|
+
}
|
|
97
|
+
export {};
|
|
98
|
+
//# sourceMappingURL=room.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../src/realtime/room.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,aAAa;IAC1D,SAAS,EAAE,iBAAiB,CAAC;IAC7B,2CAA2C;IAC3C,eAAe,CAAC,EAAE,CAAC,CAAC;IACpB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,KAAK,gBAAgB,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;AAExD,qBAAa,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa;IAC/D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,OAAO,CAAI;IACnB,OAAO,CAAC,KAAK,CAAsC;IACnD,qEAAqE;IACrE,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,GAAG,CAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAC,CAAiC;IACxD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAkC;IACvD,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAAqB;IAEvC,OAAO;IAYP,yCAAyC;IACzC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EACjD,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC3B,YAAY,CAAC,CAAC,CAAC;IAYlB,yBAAyB;IACzB,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,oCAAoC;IACpC,YAAY,IAAI,CAAC;IAIjB,mEAAmE;IACnE,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAMtC,yDAAyD;IACzD,eAAe,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAM/B,6CAA6C;IAC7C,WAAW,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE;IAIhC,4BAA4B;IAC5B,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE;IAI9B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI;IAM9D,yDAAyD;IACzD,IAAI,cAAc,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAE9C;IAMD;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM;IAiBnE,OAAO,CAAC,QAAQ;IAQhB,uEAAuE;IACvE,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAiB1D;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,IAAI;IAMzC,wCAAwC;IACxC,KAAK,IAAI,IAAI;IAoBb,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,eAAe;IA6CvB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,iBAAiB;CAY1B"}
|