trellis 3.1.34 → 3.2.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/CHANGELOG.md +16 -5
- package/README.md +19 -2
- package/bin/trellis.mjs +2 -75
- package/dist/better-sqlite-backend-2P4F6AOJ.js +209 -0
- package/dist/{better-sqlite-backend-ahx5p0br.js → better-sqlite-backend-PII64VE6.js} +37 -25
- package/dist/better-sqlite-backend-VUBVQ7SN.js +209 -0
- package/dist/better-sqlite-backend-Y3AQN65E.js +159 -0
- package/dist/better-sqlite-backend-Y3M7DXOX.js +159 -0
- package/dist/boot-middleware-FJDGVUM4.js +9 -0
- package/dist/boot-middleware-MHLHFCUC.js +9 -0
- package/dist/boot-middleware-MLJUTLUM.js +9 -0
- package/dist/boot-middleware-ZZPDZNYR.js +9 -0
- package/dist/{index-wncptktd.js → chunk-276LKLZR.js} +126 -59
- package/dist/chunk-2BRTCEHB.js +143 -0
- package/dist/chunk-2CX5UCRV.js +111 -0
- package/dist/chunk-2ESYSVXG.js +48 -0
- package/dist/{index-yp88he8n.js → chunk-2I5JU73Y.js} +88 -64
- package/dist/{index-w5wccer3.js → chunk-2UNSRRNB.js} +10 -5
- package/dist/{index-4wxa8xz4.js → chunk-335UEHQR.js} +158 -22
- package/dist/chunk-36VSSTL7.js +357 -0
- package/dist/chunk-3ETIIPPB.js +1077 -0
- package/dist/chunk-3GDRZTAW.js +45 -0
- package/dist/chunk-44FFQKQX.js +142 -0
- package/dist/chunk-4CF2L46N.js +29 -0
- package/dist/chunk-4HYPLFJD.js +150 -0
- package/dist/chunk-4XIVMVHC.js +361 -0
- package/dist/chunk-5CINODKT.js +41 -0
- package/dist/chunk-5ESGWJ5L.js +45 -0
- package/dist/chunk-5FGLQGMF.js +1676 -0
- package/dist/chunk-5IQZFITY.js +357 -0
- package/dist/{index-wt8rz4gn.js → chunk-5JWFAQDW.js} +41 -23
- package/dist/{index-7pjz3tsy.js → chunk-62UHTVU3.js} +50 -16
- package/dist/{index-h32txmxe.js → chunk-66UJQT2I.js} +6 -13
- package/dist/chunk-6CTA6MCE.js +340 -0
- package/dist/{index-4cdr7x2x.js → chunk-6RNNVOAS.js} +178 -109
- package/dist/chunk-6X23PZ6H.js +969 -0
- package/dist/chunk-7C7LL6MB.js +315 -0
- package/dist/chunk-7F4HM3JG.js +394 -0
- package/dist/chunk-7KJ7T4D3.js +910 -0
- package/dist/chunk-7QQQNUB5.js +92 -0
- package/dist/{index-53f3b8p8.js → chunk-7QWJBS72.js} +210 -165
- package/dist/chunk-7R36OZK3.js +957 -0
- package/dist/chunk-7UPKCOHE.js +946 -0
- package/dist/chunk-7WQGTFVJ.js +7434 -0
- package/dist/chunk-A3BONW34.js +35 -0
- package/dist/chunk-AHMDVHBL.js +141 -0
- package/dist/chunk-AW6A4OZY.js +171 -0
- package/dist/chunk-B3ZIFA2O.js +2240 -0
- package/dist/chunk-BJ5EKCJ5.js +458 -0
- package/dist/chunk-BJ7EZ7FP.js +145 -0
- package/dist/chunk-BQBUVMRN.js +171 -0
- package/dist/chunk-BRGYDO7D.js +223 -0
- package/dist/chunk-BXSTJVE3.js +67 -0
- package/dist/chunk-C5KPSEDN.js +359 -0
- package/dist/chunk-CCTNYTUC.js +940 -0
- package/dist/chunk-CYQ2OVD2.js +35 -0
- package/dist/chunk-DDAK7YOE.js +299 -0
- package/dist/chunk-DRILKBY6.js +965 -0
- package/dist/chunk-DXE24HNN.js +45 -0
- package/dist/chunk-E7ICUNW7.js +945 -0
- package/dist/chunk-EAL2PUOE.js +10022 -0
- package/dist/chunk-ELT7MLZB.js +109 -0
- package/dist/chunk-EO3J7GRP.js +0 -0
- package/dist/chunk-EWEIRF6G.js +171 -0
- package/dist/chunk-F5VDGQJC.js +120 -0
- package/dist/chunk-FCPL3IEQ.js +98 -0
- package/dist/{index-nq520y6k.js → chunk-FDPKYSV7.js} +43 -31
- package/dist/chunk-FES3TC24.js +171 -0
- package/dist/chunk-FF36CQHZ.js +61 -0
- package/dist/chunk-FKQO5A3H.js +35 -0
- package/dist/chunk-FOWKR5TW.js +129 -0
- package/dist/chunk-FZVCXDYW.js +150 -0
- package/dist/chunk-G3XIHPSQ.js +361 -0
- package/dist/chunk-GD5QJXSS.js +98 -0
- package/dist/chunk-GFZCJ4EH.js +108 -0
- package/dist/chunk-GKJLYLVU.js +359 -0
- package/dist/chunk-GLM4HGN4.js +55 -0
- package/dist/chunk-GNXHXNVQ.js +113 -0
- package/dist/chunk-GSR6ILTM.js +277 -0
- package/dist/chunk-GWRIMRSX.js +45 -0
- package/dist/chunk-H72UW2HJ.js +45 -0
- package/dist/chunk-HGI74PXB.js +7417 -0
- package/dist/chunk-HGRA37LO.js +145 -0
- package/dist/chunk-HO4TURXW.js +1078 -0
- package/dist/chunk-HXSRQO3L.js +145 -0
- package/dist/chunk-IG2X2BVO.js +373 -0
- package/dist/chunk-IIJVDD54.js +373 -0
- package/dist/chunk-IUWVEEOX.js +145 -0
- package/dist/chunk-IX4BBOIT.js +394 -0
- package/dist/{index-yhwjgfvj.js → chunk-IXU4RMQM.js} +67 -60
- package/dist/chunk-J3WYZO3Q.js +211 -0
- package/dist/{index-vkpkfwhq.js → chunk-J6OUIION.js} +234 -194
- package/dist/{index-xzym9w0m.js → chunk-JA7AIHRK.js} +12 -7
- package/dist/chunk-JUEMDWLU.js +233 -0
- package/dist/chunk-K46RNFDE.js +171 -0
- package/dist/chunk-KAGU2XMY.js +359 -0
- package/dist/chunk-KCVYJNVX.js +394 -0
- package/dist/chunk-KFQGP6VL.js +33 -0
- package/dist/chunk-KKDRMIV6.js +419 -0
- package/dist/chunk-KQ4A2D2P.js +910 -0
- package/dist/chunk-KSU2GW22.js +958 -0
- package/dist/chunk-KYLIQ3YI.js +399 -0
- package/dist/chunk-KZYJJIRN.js +946 -0
- package/dist/chunk-LFOX744K.js +96 -0
- package/dist/{index-rv1p47gp.js → chunk-LHOVJEWR.js} +2756 -2307
- package/dist/{index-h9e2efx4.js → chunk-LNUIGRDZ.js} +71 -55
- package/dist/chunk-LOPXTPF3.js +120 -0
- package/dist/chunk-LZR3VIFU.js +907 -0
- package/dist/chunk-MBNBTJCR.js +394 -0
- package/dist/chunk-MCKGQKYU.js +15 -0
- package/dist/{index-skhn0agf.js → chunk-MLC5BUYO.js} +19 -20
- package/dist/chunk-MPXUVGT3.js +104 -0
- package/dist/chunk-MU6EOS6F.js +0 -0
- package/dist/chunk-MWRQ2TXT.js +357 -0
- package/dist/{index-nzb3am4f.js → chunk-NO73OK2I.js} +43 -21
- package/dist/chunk-NPE2YJHK.js +394 -0
- package/dist/{index-xhcp6xrn.js → chunk-NSDXU6QX.js} +654 -500
- package/dist/chunk-NXIRDSZ6.js +145 -0
- package/dist/chunk-NZWFNHCS.js +407 -0
- package/dist/chunk-O2AV5WMN.js +48 -0
- package/dist/{index-h7zxhhhh.js → chunk-OB4CMMX6.js} +46 -38
- package/dist/chunk-OBKU74FU.js +7411 -0
- package/dist/chunk-OQNDWRDE.js +145 -0
- package/dist/chunk-OVWAJMB6.js +394 -0
- package/dist/chunk-PDHLBTTD.js +45 -0
- package/dist/chunk-PEQNRKLG.js +210 -0
- package/dist/chunk-QERIS7QY.js +7403 -0
- package/dist/chunk-QHA2DM3C.js +373 -0
- package/dist/chunk-QLM4HSYC.js +45 -0
- package/dist/chunk-RSWUFTO2.js +857 -0
- package/dist/chunk-S2OT3TQJ.js +283 -0
- package/dist/chunk-S5PHSN5K.js +907 -0
- package/dist/chunk-SIAA4J6H.js +21 -0
- package/dist/chunk-SPSPV5BC.js +390 -0
- package/dist/chunk-SQBNLUIA.js +171 -0
- package/dist/chunk-STLN6A6B.js +355 -0
- package/dist/chunk-TCKXSOBP.js +123 -0
- package/dist/chunk-U7HV7GU2.js +17 -0
- package/dist/chunk-UBGUDMUV.js +59 -0
- package/dist/chunk-UGZHOGRA.js +39 -0
- package/dist/chunk-UICF66FS.js +359 -0
- package/dist/chunk-UK3EQREE.js +1078 -0
- package/dist/chunk-UPKPURVY.js +394 -0
- package/dist/chunk-URC74VCN.js +959 -0
- package/dist/chunk-USEINYUL.js +12 -0
- package/dist/{index-bmyt7k8n.js → chunk-UZRUP7QW.js} +12 -4
- package/dist/chunk-V3G7Q3QQ.js +102 -0
- package/dist/chunk-VDAKEOML.js +857 -0
- package/dist/chunk-VUJ6SA55.js +303 -0
- package/dist/chunk-VUJQLIML.js +141 -0
- package/dist/chunk-VWKLKLYB.js +267 -0
- package/dist/chunk-VYC3RZMK.js +277 -0
- package/dist/chunk-WMERMSWI.js +154 -0
- package/dist/chunk-WMR777PO.js +2213 -0
- package/dist/{index-n9f2qyh5.js → chunk-X46IECAC.js} +55 -33
- package/dist/chunk-X5FLTRUB.js +517 -0
- package/dist/chunk-X762XWVC.js +419 -0
- package/dist/chunk-XEN3OEYY.js +2234 -0
- package/dist/chunk-XMQ7G77X.js +260 -0
- package/dist/chunk-XZQ66K7A.js +124 -0
- package/dist/{index-w7ng765c.js → chunk-YCM7ZYEZ.js} +102 -49
- package/dist/chunk-YY3GF7DH.js +7411 -0
- package/dist/chunk-ZE5R3H4C.js +907 -0
- package/dist/chunk-ZHVI7BQN.js +1077 -0
- package/dist/chunk-ZMN5LUB7.js +7411 -0
- package/dist/chunk-ZUV4MD5U.js +94 -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.map +1 -1
- package/dist/cli/index.js +2338 -6190
- 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.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-KMY6RRK3.js} +8 -9
- package/dist/config-PFTP67TR.js +19 -0
- package/dist/config-VDMK2DUJ.js +19 -0
- 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 +168 -101
- 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 +69 -56
- package/dist/db/inspector.js +11 -19
- package/dist/decisions/index.js +9 -10
- package/dist/deploy-66EC752W.js +9 -0
- package/dist/deploy-SO7AFK6L.js +9 -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-7GXBM4IT.js +7 -0
- package/dist/engine-NSR6BIF7.js +7 -0
- package/dist/engine.d.ts +32 -12
- package/dist/engine.d.ts.map +1 -1
- package/dist/factory-2P64OC7M.js +34 -0
- package/dist/factory-YP4ZZK5K.js +34 -0
- package/dist/import-AJLYHFIA.js +10 -0
- package/dist/import-UZEKXU3B.js +10 -0
- package/dist/index.js +102 -93
- package/dist/launch-explorer-AI6L2AWJ.js +91 -0
- package/dist/launch-explorer-HZ4ZJA4X.js +95 -0
- package/dist/links/index.js +24 -26
- 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-GJL3CVGN.js} +14 -15
- package/dist/query-MBJSK3EB.js +31 -0
- package/dist/query-TJHEVSKL.js +31 -0
- package/dist/query-WUIKOHPE.js +524 -0
- package/dist/query-XYLTJYSA.js +31 -0
- 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-BLJZ6KF6.js +224 -0
- package/dist/{remote-manager-xvbg4230.js → remote-manager-BPYE46SI.js} +24 -15
- package/dist/remote-manager-FMESEAFA.js +224 -0
- package/dist/remote-manager-K2WZ5RHY.js +223 -0
- package/dist/remote-manager-SG545WNY.js +224 -0
- package/dist/remote-manager-SG5PQKCH.js +224 -0
- package/dist/remote-manager-WGP6MIQZ.js +224 -0
- 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 +45 -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/sdk-3KBB3E6V.js +16 -0
- package/dist/sdk-4ZQO6UTU.js +16 -0
- package/dist/sdk-6JA6GV3G.js +16 -0
- package/dist/sdk-6VTP5UTZ.js +16 -0
- package/dist/sdk-7VS6TYCD.js +16 -0
- package/dist/sdk-HQ3FTLRT.js +16 -0
- package/dist/sdk-HZ7NU3XE.js +15 -0
- package/dist/sdk-KBQE2OXT.js +16 -0
- package/dist/sdk-LZ7W3EEY.js +9 -0
- package/dist/sdk-MSCDZ7JU.js +15 -0
- package/dist/sdk-WNZOGO3S.js +15 -0
- package/dist/sdk-YLV33ZCW.js +9 -0
- package/dist/sdk-ZSUD2LLJ.js +16 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +69 -61
- package/dist/server/node-adapter.js +5 -104
- package/dist/server/realtime.d.ts +10 -2
- package/dist/server/realtime.d.ts.map +1 -1
- package/dist/server/server.d.ts +7 -16
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/sprites.d.ts.map +1 -1
- package/dist/server/tenancy.d.ts.map +1 -1
- package/dist/server-AFXFFBWA.js +11 -0
- package/dist/server-AGHC4VUL.js +11 -0
- package/dist/server-BOH7M4TT.js +13 -0
- package/dist/server-DBUY2KY5.js +11 -0
- package/dist/server-GWBQJPRG.js +11 -0
- package/dist/server-IGBIIJSF.js +13 -0
- package/dist/server-JZZFULVU.js +11 -0
- package/dist/server-L5XAF4M5.js +11 -0
- package/dist/server-NYFUHANA.js +12 -0
- package/dist/server-OABUB2LO.js +12 -0
- package/dist/server-P2CKZWWV.js +12 -0
- package/dist/{sprites-vc4qbrp1.js → sprites-RU3E4XQN.js} +6 -7
- package/dist/sprites-XVSMQLSI.js +15 -0
- package/dist/sql-wasm-FORCZFHZ.js +2148 -0
- package/dist/sql-wasm-JZH76RLO.js +2148 -0
- package/dist/sqljs-backend-CJQOIQYE.js +266 -0
- package/dist/sqljs-backend-KWXBUDUO.js +266 -0
- package/dist/state-demo.bundle.js +1033 -0
- 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-CBWYEVUB.js +11 -0
- package/dist/tenancy-FO6WVYFN.js +13 -0
- package/dist/tenancy-FWDBESMX.js +14 -0
- package/dist/tenancy-HGPIS5QA.js +13 -0
- package/dist/tenancy-HXFALA37.js +14 -0
- package/dist/tenancy-OP34NFFS.js +14 -0
- package/dist/tenancy-S676GLID.js +14 -0
- package/dist/tenancy-V7ARWNNV.js +14 -0
- package/dist/tenancy-ZDN4GXK5.js +13 -0
- package/dist/tenancy-ZT5VMY7B.js +14 -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/{vm-config-6xhsj6b3.js → vm-config-JI4OXKDQ.js} +9 -10
- package/dist/vm-config-YZRJ3KUB.js +21 -0
- 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 +118 -16
- 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-y6a4kj0p.js +0 -43
- 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,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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RealtimeText — a compact RGA-style sequence CRDT for collaborative text.
|
|
3
|
+
*
|
|
4
|
+
* Each character is a node with a globally-unique id (`<lamport>@<peerId>`) and
|
|
5
|
+
* an `after` pointer to the node it follows. Concurrent inserts sharing an
|
|
6
|
+
* anchor are ordered deterministically (higher lamport first, peer id as
|
|
7
|
+
* tiebreak), so all replicas converge regardless of delivery order. Deletes are
|
|
8
|
+
* tombstones, making them idempotent and commutative.
|
|
9
|
+
*
|
|
10
|
+
* This is intentionally minimal — enough for a genuine multiplayer editor demo
|
|
11
|
+
* without the weight of a full production CRDT (no block compaction, GC, or
|
|
12
|
+
* rich formatting).
|
|
13
|
+
*/
|
|
14
|
+
import type { RealtimeRoom } from './room.js';
|
|
15
|
+
export interface TextNode {
|
|
16
|
+
id: string;
|
|
17
|
+
ch: string;
|
|
18
|
+
after: string | null;
|
|
19
|
+
deleted: boolean;
|
|
20
|
+
}
|
|
21
|
+
export type TextOp = {
|
|
22
|
+
op: 'ins';
|
|
23
|
+
id: string;
|
|
24
|
+
ch: string;
|
|
25
|
+
after: string | null;
|
|
26
|
+
} | {
|
|
27
|
+
op: 'del';
|
|
28
|
+
id: string;
|
|
29
|
+
};
|
|
30
|
+
export interface RealtimeTextOptions {
|
|
31
|
+
peerId: string;
|
|
32
|
+
/** Optional room binding for automatic op + state sync. */
|
|
33
|
+
room?: RealtimeRoom;
|
|
34
|
+
/** Broadcast channel name when bound to a room. Default `text`. */
|
|
35
|
+
channel?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare class RealtimeText {
|
|
38
|
+
private nodes;
|
|
39
|
+
private counter;
|
|
40
|
+
private peerId;
|
|
41
|
+
private listeners;
|
|
42
|
+
private room?;
|
|
43
|
+
private channel;
|
|
44
|
+
private unsubscribe?;
|
|
45
|
+
constructor(opts: RealtimeTextOptions);
|
|
46
|
+
/** Materialized visible text. */
|
|
47
|
+
toString(): string;
|
|
48
|
+
/** Current length of visible text. */
|
|
49
|
+
get length(): number;
|
|
50
|
+
/** Insert a string at a visible index. Broadcasts ops when room-bound. */
|
|
51
|
+
insert(index: number, str: string): TextOp[];
|
|
52
|
+
/** Delete `count` visible characters starting at `index`. */
|
|
53
|
+
delete(index: number, count?: number): TextOp[];
|
|
54
|
+
/** Apply a single remote op. Returns true if the document changed. */
|
|
55
|
+
applyOp(op: TextOp): boolean;
|
|
56
|
+
/** Apply a batch of remote ops, emitting once. */
|
|
57
|
+
applyOps(ops: TextOp[]): void;
|
|
58
|
+
/** Snapshot of all nodes (including tombstones) for state sync. */
|
|
59
|
+
getNodes(): TextNode[];
|
|
60
|
+
/** Merge a remote snapshot of nodes. */
|
|
61
|
+
mergeNodes(nodes: TextNode[]): void;
|
|
62
|
+
/** Subscribe to text changes. Returns an unsubscribe fn. */
|
|
63
|
+
onChange(cb: (text: string) => void): () => void;
|
|
64
|
+
/** Detach room bindings. */
|
|
65
|
+
dispose(): void;
|
|
66
|
+
private onRemote;
|
|
67
|
+
private publish;
|
|
68
|
+
private visibleNodes;
|
|
69
|
+
private nextId;
|
|
70
|
+
private bumpCounter;
|
|
71
|
+
private emit;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/realtime/text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,MAAM,GACd;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9B,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuBD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,IAAI,CAAC,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAa;gBAErB,IAAI,EAAE,mBAAmB;IAerC,iCAAiC;IACjC,QAAQ,IAAI,MAAM;IAMlB,sCAAsC;IACtC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,0EAA0E;IAC1E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAmB5C,6DAA6D;IAC7D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE;IAsB1C,sEAAsE;IACtE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAmB5B,kDAAkD;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAQ7B,mEAAmE;IACnE,QAAQ,IAAI,QAAQ,EAAE;IAItB,wCAAwC;IACxC,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI;IAgBnC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAOhD,4BAA4B;IAC5B,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,IAAI;CAUb"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trellis Realtime — Ephemeral Presence & Broadcast Types
|
|
3
|
+
*
|
|
4
|
+
* Distinct from the persisted VCS op log: realtime messages are ephemeral,
|
|
5
|
+
* mesh-broadcast, and never written to the causal history. This is the right
|
|
6
|
+
* home for high-frequency, disposable signals like cursors and presence, plus
|
|
7
|
+
* fire-and-forget broadcast (chat, live text edits).
|
|
8
|
+
*
|
|
9
|
+
* The transport is a broadcast mesh: `send` delivers a message to every other
|
|
10
|
+
* peer sharing the channel. Senders never receive their own messages.
|
|
11
|
+
*/
|
|
12
|
+
export declare const REALTIME_PROTOCOL: 1;
|
|
13
|
+
/** Arbitrary per-peer presence state (name, avatar, color, cursor, …). */
|
|
14
|
+
export type PresenceState = Record<string, unknown>;
|
|
15
|
+
export interface PresencePeer<P extends PresenceState = PresenceState> {
|
|
16
|
+
/** Peer/client identity. */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Latest published presence state. */
|
|
19
|
+
state: P;
|
|
20
|
+
/** Epoch ms of the last presence heartbeat we saw. */
|
|
21
|
+
lastSeen: number;
|
|
22
|
+
/** True for the local peer. */
|
|
23
|
+
self: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** A received broadcast on a channel. */
|
|
26
|
+
export interface BroadcastEvent {
|
|
27
|
+
from: string;
|
|
28
|
+
channel: string;
|
|
29
|
+
event: string;
|
|
30
|
+
payload: unknown;
|
|
31
|
+
ts: number;
|
|
32
|
+
/**
|
|
33
|
+
* Stable message identity. Assigned by the sender and carried unchanged to
|
|
34
|
+
* every replica, so dedup is order-independent (a grow-only set). Present on
|
|
35
|
+
* all broadcasts emitted by {@link RealtimeRoom.broadcast}; may be absent on
|
|
36
|
+
* legacy frames.
|
|
37
|
+
*/
|
|
38
|
+
id?: string;
|
|
39
|
+
}
|
|
40
|
+
export type RealtimeMessage<P extends PresenceState = PresenceState> = {
|
|
41
|
+
v: 1;
|
|
42
|
+
t: 'hello';
|
|
43
|
+
from: string;
|
|
44
|
+
} | {
|
|
45
|
+
v: 1;
|
|
46
|
+
t: 'presence';
|
|
47
|
+
from: string;
|
|
48
|
+
state: P;
|
|
49
|
+
ts: number;
|
|
50
|
+
} | {
|
|
51
|
+
v: 1;
|
|
52
|
+
t: 'bye';
|
|
53
|
+
from: string;
|
|
54
|
+
ts: number;
|
|
55
|
+
} | {
|
|
56
|
+
v: 1;
|
|
57
|
+
t: 'msg';
|
|
58
|
+
from: string;
|
|
59
|
+
channel: string;
|
|
60
|
+
event: string;
|
|
61
|
+
payload: unknown;
|
|
62
|
+
ts: number;
|
|
63
|
+
/** Stable per-message id (dedup key for grow-only replay). */
|
|
64
|
+
id?: string;
|
|
65
|
+
}
|
|
66
|
+
/** Relay welcome: re-deliver persisted session state to a new connection. */
|
|
67
|
+
| {
|
|
68
|
+
v: 1;
|
|
69
|
+
t: 'replay';
|
|
70
|
+
from: string;
|
|
71
|
+
messages: RealtimeMessage<P>[];
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Broadcast mesh transport. Implementations: {@link MemoryHub} (in-process /
|
|
75
|
+
* tests / side-by-side panes), {@link BroadcastChannelTransport} (serverless
|
|
76
|
+
* cross-tab in one browser), and {@link WebSocketRelayTransport} (relay-backed
|
|
77
|
+
* cross-browser rooms).
|
|
78
|
+
*/
|
|
79
|
+
export interface RealtimeTransport {
|
|
80
|
+
/** Local peer identity on this transport. */
|
|
81
|
+
readonly id: string;
|
|
82
|
+
/** Broadcast a message to all other peers. Never echoes to the sender. */
|
|
83
|
+
send(message: RealtimeMessage): void;
|
|
84
|
+
/** Register an inbound message handler. Returns an unsubscribe fn. */
|
|
85
|
+
onMessage(handler: (message: RealtimeMessage) => void): () => void;
|
|
86
|
+
/** Tear down the transport. */
|
|
87
|
+
close(): void;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,iBAAiB,EAAG,CAAU,CAAC;AAE5C,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa;IACnE,4BAA4B;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,uCAAuC;IACvC,KAAK,EAAE,CAAC,CAAC;IACT,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,yCAAyC;AACzC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAC/D;IAAE,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC5C;IACE,CAAC,EAAE,CAAC,CAAC;IACL,CAAC,EAAE,KAAK,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AACH,6EAA6E;GAC3E;IACE,CAAC,EAAE,CAAC,CAAC;IACL,CAAC,EAAE,QAAQ,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;CAChC,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,sEAAsE;IACtE,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACnE,+BAA+B;IAC/B,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser transport that relays {@link RealtimeMessage} frames through a
|
|
3
|
+
* shared WebSocket hub (demo server or custom relay). Unlike
|
|
4
|
+
* {@link BroadcastChannelTransport}, this works across different browsers on
|
|
5
|
+
* the same origin.
|
|
6
|
+
*/
|
|
7
|
+
import type { RealtimeMessage, RealtimeTransport } from './types.js';
|
|
8
|
+
export interface WebSocketRelayTransportOptions {
|
|
9
|
+
/** Local peer identity. */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Hub URL, e.g. `ws://localhost:8231/rt`. */
|
|
12
|
+
url: string;
|
|
13
|
+
/** Injectable WebSocket for tests. */
|
|
14
|
+
WebSocketImpl?: typeof WebSocket;
|
|
15
|
+
}
|
|
16
|
+
export declare class WebSocketRelayTransport implements RealtimeTransport {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
private ws;
|
|
19
|
+
private handlers;
|
|
20
|
+
private closed;
|
|
21
|
+
private pending;
|
|
22
|
+
constructor(opts: WebSocketRelayTransportOptions);
|
|
23
|
+
send(message: RealtimeMessage): void;
|
|
24
|
+
onMessage(handler: (message: RealtimeMessage) => void): () => void;
|
|
25
|
+
close(): void;
|
|
26
|
+
private flushPending;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=websocket-relay-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-relay-transport.d.ts","sourceRoot":"","sources":["../../src/realtime/websocket-relay-transport.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,8BAA8B;IAC7C,2BAA2B;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,aAAa,CAAC,EAAE,OAAO,SAAS,CAAC;CAClC;AAED,qBAAa,uBAAwB,YAAW,iBAAiB;IAC/D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,QAAQ,CAAiD;IACjE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAyB;gBAE5B,IAAI,EAAE,8BAA8B;IAgChD,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAUpC,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlE,KAAK,IAAI,IAAI;IAYb,OAAO,CAAC,YAAY;CAOrB"}
|