@weaveprotocol/core 0.1.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/README.md +1106 -0
- package/dist/elements/auth-styles.d.ts +18 -0
- package/dist/elements/auth-styles.d.ts.map +1 -0
- package/dist/elements/auth-styles.js +150 -0
- package/dist/elements/auth-styles.js.map +1 -0
- package/dist/elements/dom.d.ts +28 -0
- package/dist/elements/dom.d.ts.map +1 -0
- package/dist/elements/dom.js +74 -0
- package/dist/elements/dom.js.map +1 -0
- package/dist/elements/index.d.ts +13 -0
- package/dist/elements/index.d.ts.map +1 -0
- package/dist/elements/index.js +11 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/elements/weave-auth.d.ts +52 -0
- package/dist/elements/weave-auth.d.ts.map +1 -0
- package/dist/elements/weave-auth.js +427 -0
- package/dist/elements/weave-auth.js.map +1 -0
- package/dist/identity/account-store.d.ts +113 -0
- package/dist/identity/account-store.d.ts.map +1 -0
- package/dist/identity/account-store.js +305 -0
- package/dist/identity/account-store.js.map +1 -0
- package/dist/identity/account-vault.d.ts +199 -0
- package/dist/identity/account-vault.d.ts.map +1 -0
- package/dist/identity/account-vault.js +251 -0
- package/dist/identity/account-vault.js.map +1 -0
- package/dist/identity/agent-note.d.ts +19 -0
- package/dist/identity/agent-note.d.ts.map +1 -0
- package/dist/identity/agent-note.js +29 -0
- package/dist/identity/agent-note.js.map +1 -0
- package/dist/identity/crypto-p256.d.ts +7 -0
- package/dist/identity/crypto-p256.d.ts.map +1 -0
- package/dist/identity/crypto-p256.js +84 -0
- package/dist/identity/crypto-p256.js.map +1 -0
- package/dist/identity/device-key.d.ts +60 -0
- package/dist/identity/device-key.d.ts.map +1 -0
- package/dist/identity/device-key.js +103 -0
- package/dist/identity/device-key.js.map +1 -0
- package/dist/identity/did.d.ts +22 -0
- package/dist/identity/did.d.ts.map +1 -0
- package/dist/identity/did.js +37 -0
- package/dist/identity/did.js.map +1 -0
- package/dist/identity/folder-account.d.ts +65 -0
- package/dist/identity/folder-account.d.ts.map +1 -0
- package/dist/identity/folder-account.js +115 -0
- package/dist/identity/folder-account.js.map +1 -0
- package/dist/identity/identity-manager.d.ts +36 -0
- package/dist/identity/identity-manager.d.ts.map +1 -0
- package/dist/identity/identity-manager.js +115 -0
- package/dist/identity/identity-manager.js.map +1 -0
- package/dist/identity/index.d.ts +10 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +10 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/keys.d.ts +24 -0
- package/dist/identity/keys.d.ts.map +1 -0
- package/dist/identity/keys.js +38 -0
- package/dist/identity/keys.js.map +1 -0
- package/dist/identity/pairing.d.ts +83 -0
- package/dist/identity/pairing.d.ts.map +1 -0
- package/dist/identity/pairing.js +120 -0
- package/dist/identity/pairing.js.map +1 -0
- package/dist/identity/passkey-diagnostics.d.ts +54 -0
- package/dist/identity/passkey-diagnostics.d.ts.map +1 -0
- package/dist/identity/passkey-diagnostics.js +178 -0
- package/dist/identity/passkey-diagnostics.js.map +1 -0
- package/dist/identity/recovery-code.d.ts +50 -0
- package/dist/identity/recovery-code.d.ts.map +1 -0
- package/dist/identity/recovery-code.js +116 -0
- package/dist/identity/recovery-code.js.map +1 -0
- package/dist/identity/root-signer.d.ts +59 -0
- package/dist/identity/root-signer.d.ts.map +1 -0
- package/dist/identity/root-signer.js +44 -0
- package/dist/identity/root-signer.js.map +1 -0
- package/dist/identity/ucan.d.ts +164 -0
- package/dist/identity/ucan.d.ts.map +1 -0
- package/dist/identity/ucan.js +273 -0
- package/dist/identity/ucan.js.map +1 -0
- package/dist/identity/webauthn.d.ts +87 -0
- package/dist/identity/webauthn.d.ts.map +1 -0
- package/dist/identity/webauthn.js +155 -0
- package/dist/identity/webauthn.js.map +1 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/network/index.d.ts +17 -0
- package/dist/network/index.d.ts.map +1 -0
- package/dist/network/index.js +10 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/introductions.d.ts +85 -0
- package/dist/network/introductions.d.ts.map +1 -0
- package/dist/network/introductions.js +94 -0
- package/dist/network/introductions.js.map +1 -0
- package/dist/network/local-transport.d.ts +22 -0
- package/dist/network/local-transport.d.ts.map +1 -0
- package/dist/network/local-transport.js +55 -0
- package/dist/network/local-transport.js.map +1 -0
- package/dist/network/mesh.d.ts +31 -0
- package/dist/network/mesh.d.ts.map +1 -0
- package/dist/network/mesh.js +332 -0
- package/dist/network/mesh.js.map +1 -0
- package/dist/network/multi-signaling.d.ts +29 -0
- package/dist/network/multi-signaling.d.ts.map +1 -0
- package/dist/network/multi-signaling.js +125 -0
- package/dist/network/multi-signaling.js.map +1 -0
- package/dist/network/network-manager.d.ts +37 -0
- package/dist/network/network-manager.d.ts.map +1 -0
- package/dist/network/network-manager.js +64 -0
- package/dist/network/network-manager.js.map +1 -0
- package/dist/network/peer-auth.d.ts +98 -0
- package/dist/network/peer-auth.d.ts.map +1 -0
- package/dist/network/peer-auth.js +86 -0
- package/dist/network/peer-auth.js.map +1 -0
- package/dist/network/rtc-transport.d.ts +18 -0
- package/dist/network/rtc-transport.d.ts.map +1 -0
- package/dist/network/rtc-transport.js +149 -0
- package/dist/network/rtc-transport.js.map +1 -0
- package/dist/network/signaling.d.ts +40 -0
- package/dist/network/signaling.d.ts.map +1 -0
- package/dist/network/signaling.js +124 -0
- package/dist/network/signaling.js.map +1 -0
- package/dist/network/transport.d.ts +50 -0
- package/dist/network/transport.d.ts.map +1 -0
- package/dist/network/transport.js +13 -0
- package/dist/network/transport.js.map +1 -0
- package/dist/network/ws-transport.d.ts +42 -0
- package/dist/network/ws-transport.d.ts.map +1 -0
- package/dist/network/ws-transport.js +194 -0
- package/dist/network/ws-transport.js.map +1 -0
- package/dist/node/actions.d.ts +62 -0
- package/dist/node/actions.d.ts.map +1 -0
- package/dist/node/actions.js +500 -0
- package/dist/node/actions.js.map +1 -0
- package/dist/node/carrier.d.ts +85 -0
- package/dist/node/carrier.d.ts.map +1 -0
- package/dist/node/carrier.js +192 -0
- package/dist/node/carrier.js.map +1 -0
- package/dist/node/copy.d.ts +38 -0
- package/dist/node/copy.d.ts.map +1 -0
- package/dist/node/copy.js +53 -0
- package/dist/node/copy.js.map +1 -0
- package/dist/node/index.d.ts +16 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +11 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/node.d.ts +12 -0
- package/dist/node/node.d.ts.map +1 -0
- package/dist/node/node.js +872 -0
- package/dist/node/node.js.map +1 -0
- package/dist/node/space-runtime.d.ts +144 -0
- package/dist/node/space-runtime.d.ts.map +1 -0
- package/dist/node/space-runtime.js +1221 -0
- package/dist/node/space-runtime.js.map +1 -0
- package/dist/node/stores.d.ts +45 -0
- package/dist/node/stores.d.ts.map +1 -0
- package/dist/node/stores.js +31 -0
- package/dist/node/stores.js.map +1 -0
- package/dist/node/types.d.ts +508 -0
- package/dist/node/types.d.ts.map +1 -0
- package/dist/node/types.js +2 -0
- package/dist/node/types.js.map +1 -0
- package/dist/privacy/index.d.ts +4 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +4 -0
- package/dist/privacy/index.js.map +1 -0
- package/dist/privacy/key-distribution.d.ts +42 -0
- package/dist/privacy/key-distribution.d.ts.map +1 -0
- package/dist/privacy/key-distribution.js +50 -0
- package/dist/privacy/key-distribution.js.map +1 -0
- package/dist/privacy/privacy-guard.d.ts +24 -0
- package/dist/privacy/privacy-guard.d.ts.map +1 -0
- package/dist/privacy/privacy-guard.js +87 -0
- package/dist/privacy/privacy-guard.js.map +1 -0
- package/dist/privacy/space-encryption.d.ts +48 -0
- package/dist/privacy/space-encryption.d.ts.map +1 -0
- package/dist/privacy/space-encryption.js +61 -0
- package/dist/privacy/space-encryption.js.map +1 -0
- package/dist/query/engine.d.ts +27 -0
- package/dist/query/engine.d.ts.map +1 -0
- package/dist/query/engine.js +84 -0
- package/dist/query/engine.js.map +1 -0
- package/dist/query/filter.d.ts +15 -0
- package/dist/query/filter.d.ts.map +1 -0
- package/dist/query/filter.js +207 -0
- package/dist/query/filter.js.map +1 -0
- package/dist/query/types.d.ts +144 -0
- package/dist/query/types.d.ts.map +1 -0
- package/dist/query/types.js +22 -0
- package/dist/query/types.js.map +1 -0
- package/dist/react/context.d.ts +81 -0
- package/dist/react/context.d.ts.map +1 -0
- package/dist/react/context.js +95 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/index.d.ts +40 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +36 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/use-live.d.ts +16 -0
- package/dist/react/use-live.d.ts.map +1 -0
- package/dist/react/use-live.js +55 -0
- package/dist/react/use-live.js.map +1 -0
- package/dist/react/use-query.d.ts +17 -0
- package/dist/react/use-query.d.ts.map +1 -0
- package/dist/react/use-query.js +23 -0
- package/dist/react/use-query.js.map +1 -0
- package/dist/react/use-space.d.ts +29 -0
- package/dist/react/use-space.d.ts.map +1 -0
- package/dist/react/use-space.js +48 -0
- package/dist/react/use-space.js.map +1 -0
- package/dist/react/use-spaces.d.ts +19 -0
- package/dist/react/use-spaces.d.ts.map +1 -0
- package/dist/react/use-spaces.js +55 -0
- package/dist/react/use-spaces.js.map +1 -0
- package/dist/react/use-weave-auth.d.ts +10 -0
- package/dist/react/use-weave-auth.d.ts.map +1 -0
- package/dist/react/use-weave-auth.js +15 -0
- package/dist/react/use-weave-auth.js.map +1 -0
- package/dist/react/weave-auth.d.ts +17 -0
- package/dist/react/weave-auth.d.ts.map +1 -0
- package/dist/react/weave-auth.js +38 -0
- package/dist/react/weave-auth.js.map +1 -0
- package/dist/records/describe.d.ts +38 -0
- package/dist/records/describe.d.ts.map +1 -0
- package/dist/records/describe.js +101 -0
- package/dist/records/describe.js.map +1 -0
- package/dist/records/links.d.ts +14 -0
- package/dist/records/links.d.ts.map +1 -0
- package/dist/records/links.js +25 -0
- package/dist/records/links.js.map +1 -0
- package/dist/records/rules.d.ts +59 -0
- package/dist/records/rules.d.ts.map +1 -0
- package/dist/records/rules.js +118 -0
- package/dist/records/rules.js.map +1 -0
- package/dist/records/version.d.ts +54 -0
- package/dist/records/version.d.ts.map +1 -0
- package/dist/records/version.js +70 -0
- package/dist/records/version.js.map +1 -0
- package/dist/schema/collection-def.d.ts +96 -0
- package/dist/schema/collection-def.d.ts.map +1 -0
- package/dist/schema/collection-def.js +272 -0
- package/dist/schema/collection-def.js.map +1 -0
- package/dist/schema/expression.d.ts +69 -0
- package/dist/schema/expression.d.ts.map +1 -0
- package/dist/schema/expression.js +92 -0
- package/dist/schema/expression.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/schema-engine.d.ts +42 -0
- package/dist/schema/schema-engine.d.ts.map +1 -0
- package/dist/schema/schema-engine.js +36 -0
- package/dist/schema/schema-engine.js.map +1 -0
- package/dist/schema/signer.d.ts +27 -0
- package/dist/schema/signer.d.ts.map +1 -0
- package/dist/schema/signer.js +36 -0
- package/dist/schema/signer.js.map +1 -0
- package/dist/schemas/apps.d.ts +88 -0
- package/dist/schemas/apps.d.ts.map +1 -0
- package/dist/schemas/apps.js +168 -0
- package/dist/schemas/apps.js.map +1 -0
- package/dist/schemas/index.d.ts +410 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +208 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/screens.d.ts +67 -0
- package/dist/schemas/screens.d.ts.map +1 -0
- package/dist/schemas/screens.js +242 -0
- package/dist/schemas/screens.js.map +1 -0
- package/dist/session/agent-link.d.ts +79 -0
- package/dist/session/agent-link.d.ts.map +1 -0
- package/dist/session/agent-link.js +251 -0
- package/dist/session/agent-link.js.map +1 -0
- package/dist/session/auth.d.ts +233 -0
- package/dist/session/auth.d.ts.map +1 -0
- package/dist/session/auth.js +783 -0
- package/dist/session/auth.js.map +1 -0
- package/dist/session/connect.d.ts +211 -0
- package/dist/session/connect.d.ts.map +1 -0
- package/dist/session/connect.js +355 -0
- package/dist/session/connect.js.map +1 -0
- package/dist/session/connection.d.ts +70 -0
- package/dist/session/connection.d.ts.map +1 -0
- package/dist/session/connection.js +120 -0
- package/dist/session/connection.js.map +1 -0
- package/dist/session/credentials.d.ts +44 -0
- package/dist/session/credentials.d.ts.map +1 -0
- package/dist/session/credentials.js +60 -0
- package/dist/session/credentials.js.map +1 -0
- package/dist/session/index.d.ts +25 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +18 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/pairing.d.ts +59 -0
- package/dist/session/pairing.d.ts.map +1 -0
- package/dist/session/pairing.js +144 -0
- package/dist/session/pairing.js.map +1 -0
- package/dist/session/places.d.ts +62 -0
- package/dist/session/places.d.ts.map +1 -0
- package/dist/session/places.js +101 -0
- package/dist/session/places.js.map +1 -0
- package/dist/session/stay-signed-in.d.ts +37 -0
- package/dist/session/stay-signed-in.d.ts.map +1 -0
- package/dist/session/stay-signed-in.js +124 -0
- package/dist/session/stay-signed-in.js.map +1 -0
- package/dist/space/account-registry.d.ts +64 -0
- package/dist/space/account-registry.d.ts.map +1 -0
- package/dist/space/account-registry.js +66 -0
- package/dist/space/account-registry.js.map +1 -0
- package/dist/space/index.d.ts +3 -0
- package/dist/space/index.d.ts.map +1 -0
- package/dist/space/index.js +3 -0
- package/dist/space/index.js.map +1 -0
- package/dist/space/pass.d.ts +63 -0
- package/dist/space/pass.d.ts.map +1 -0
- package/dist/space/pass.js +54 -0
- package/dist/space/pass.js.map +1 -0
- package/dist/space/presets.d.ts +31 -0
- package/dist/space/presets.d.ts.map +1 -0
- package/dist/space/presets.js +24 -0
- package/dist/space/presets.js.map +1 -0
- package/dist/space/roles.d.ts +186 -0
- package/dist/space/roles.d.ts.map +1 -0
- package/dist/space/roles.js +500 -0
- package/dist/space/roles.js.map +1 -0
- package/dist/space/space-access.d.ts +80 -0
- package/dist/space/space-access.d.ts.map +1 -0
- package/dist/space/space-access.js +135 -0
- package/dist/space/space-access.js.map +1 -0
- package/dist/space/space-manager.d.ts +87 -0
- package/dist/space/space-manager.d.ts.map +1 -0
- package/dist/space/space-manager.js +187 -0
- package/dist/space/space-manager.js.map +1 -0
- package/dist/storage/directory-access.d.ts +78 -0
- package/dist/storage/directory-access.d.ts.map +1 -0
- package/dist/storage/directory-access.js +164 -0
- package/dist/storage/directory-access.js.map +1 -0
- package/dist/storage/encrypted-adapter.d.ts +49 -0
- package/dist/storage/encrypted-adapter.d.ts.map +1 -0
- package/dist/storage/encrypted-adapter.js +106 -0
- package/dist/storage/encrypted-adapter.js.map +1 -0
- package/dist/storage/folder-adapter.d.ts +105 -0
- package/dist/storage/folder-adapter.d.ts.map +1 -0
- package/dist/storage/folder-adapter.js +280 -0
- package/dist/storage/folder-adapter.js.map +1 -0
- package/dist/storage/folder-reconcile.d.ts +53 -0
- package/dist/storage/folder-reconcile.d.ts.map +1 -0
- package/dist/storage/folder-reconcile.js +65 -0
- package/dist/storage/folder-reconcile.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +9 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/indexeddb-adapter.d.ts +12 -0
- package/dist/storage/indexeddb-adapter.d.ts.map +1 -0
- package/dist/storage/indexeddb-adapter.js +190 -0
- package/dist/storage/indexeddb-adapter.js.map +1 -0
- package/dist/storage/mst.d.ts +121 -0
- package/dist/storage/mst.d.ts.map +1 -0
- package/dist/storage/mst.js +402 -0
- package/dist/storage/mst.js.map +1 -0
- package/dist/storage/storage-provider.d.ts +85 -0
- package/dist/storage/storage-provider.d.ts.map +1 -0
- package/dist/storage/storage-provider.js +220 -0
- package/dist/storage/storage-provider.js.map +1 -0
- package/dist/sync/anti-entropy.d.ts +49 -0
- package/dist/sync/anti-entropy.d.ts.map +1 -0
- package/dist/sync/anti-entropy.js +62 -0
- package/dist/sync/anti-entropy.js.map +1 -0
- package/dist/sync/index.d.ts +4 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +4 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/sync-engine.d.ts +71 -0
- package/dist/sync/sync-engine.d.ts.map +1 -0
- package/dist/sync/sync-engine.js +309 -0
- package/dist/sync/sync-engine.js.map +1 -0
- package/dist/sync/sync-messages.d.ts +75 -0
- package/dist/sync/sync-messages.d.ts.map +1 -0
- package/dist/sync/sync-messages.js +12 -0
- package/dist/sync/sync-messages.js.map +1 -0
- package/dist/types.d.ts +243 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/encoding.d.ts +63 -0
- package/dist/utils/encoding.d.ts.map +1 -0
- package/dist/utils/encoding.js +130 -0
- package/dist/utils/encoding.js.map +1 -0
- package/dist/utils/errors.d.ts +43 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +28 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/events.d.ts +19 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/utils/events.js +27 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/hash.d.ts +23 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +49 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/validation/capability-gate.d.ts +50 -0
- package/dist/validation/capability-gate.d.ts.map +1 -0
- package/dist/validation/capability-gate.js +71 -0
- package/dist/validation/capability-gate.js.map +1 -0
- package/dist/validation/crypto-gate.d.ts +16 -0
- package/dist/validation/crypto-gate.d.ts.map +1 -0
- package/dist/validation/crypto-gate.js +37 -0
- package/dist/validation/crypto-gate.js.map +1 -0
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +6 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/stateful-gate.d.ts +15 -0
- package/dist/validation/stateful-gate.d.ts.map +1 -0
- package/dist/validation/stateful-gate.js +50 -0
- package/dist/validation/stateful-gate.js.map +1 -0
- package/dist/validation/structural-gate.d.ts +18 -0
- package/dist/validation/structural-gate.d.ts.map +1 -0
- package/dist/validation/structural-gate.js +54 -0
- package/dist/validation/structural-gate.js.map +1 -0
- package/dist/validation/validation-engine.d.ts +28 -0
- package/dist/validation/validation-engine.d.ts.map +1 -0
- package/dist/validation/validation-engine.js +38 -0
- package/dist/validation/validation-engine.js.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { deserializeNode } from '../storage/mst.js';
|
|
2
|
+
import { cidFromBytes } from '../utils/hash.js';
|
|
3
|
+
import { createEmitter } from '../utils/events.js';
|
|
4
|
+
import { parseSyncMessage, SYNC_PROTOCOL_VERSION } from './sync-messages.js';
|
|
5
|
+
import { differingEntries, unknownChildren, verifyNode } from './anti-entropy.js';
|
|
6
|
+
/** At most this many records wait for what they depend on; the oldest give way */
|
|
7
|
+
const MAX_WAITING = 1000;
|
|
8
|
+
/** Collection definitions first, then records by version — what others depend on comes first */
|
|
9
|
+
const rank = (e) => (e?.collection === 'sys.collection' ? -1 : (e?.seq ?? 0));
|
|
10
|
+
/** Nodes asked for in one message. Nodes are small; this keeps round trips few. */
|
|
11
|
+
export const MAX_CIDS_PER_REQUEST = 64;
|
|
12
|
+
/** Records asked for in one message. */
|
|
13
|
+
export const MAX_IDS_PER_REQUEST = 200;
|
|
14
|
+
/** A real tree of a billion entries is about seven deep. Anything past this is hostile. */
|
|
15
|
+
const MAX_DEPTH = 32;
|
|
16
|
+
/** Nodes one walk may fetch before it is abandoned as runaway. */
|
|
17
|
+
const MAX_NODES_PER_WALK = 200_000;
|
|
18
|
+
/** A walk that has heard nothing for this long is given up on. */
|
|
19
|
+
const STALE_WALK_MS = 30_000;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a sync engine orchestrator.
|
|
22
|
+
* @param config Sync engine configuration.
|
|
23
|
+
* @returns A sync engine instance.
|
|
24
|
+
*/
|
|
25
|
+
export function createSyncEngine(config) {
|
|
26
|
+
const { storageProvider, sendToPeer, heartbeatInterval = 30000, validate } = config;
|
|
27
|
+
const peers = new Set();
|
|
28
|
+
const walks = new Map();
|
|
29
|
+
let intervalId = null;
|
|
30
|
+
let nextRequestId = 1;
|
|
31
|
+
const { on, off, emit } = createEmitter();
|
|
32
|
+
const stamp = (msg) => ({ v: SYNC_PROTOCOL_VERSION, ...msg });
|
|
33
|
+
const send = (peerId, msg) => sendToPeer(peerId, stamp(msg));
|
|
34
|
+
const broadcast = (msg) => {
|
|
35
|
+
for (const peer of peers)
|
|
36
|
+
sendToPeer(peer, stamp(msg));
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Commits an expression from a peer, but only if the gatekeeper allows it.
|
|
40
|
+
* @returns Whether the expression was accepted
|
|
41
|
+
*/
|
|
42
|
+
const admit = async (peerId, expression) => {
|
|
43
|
+
if (validate) {
|
|
44
|
+
const verdict = await validate(expression);
|
|
45
|
+
if (!verdict.valid) {
|
|
46
|
+
if (verdict.later) {
|
|
47
|
+
waiting.set(expression.id, { peerId, expression });
|
|
48
|
+
if (waiting.size > MAX_WAITING)
|
|
49
|
+
waiting.delete(waiting.keys().next().value);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
emit('rejected', peerId, expression, verdict.reason);
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
waiting.delete(expression.id);
|
|
58
|
+
await storageProvider.addExpression(expression);
|
|
59
|
+
emit('expression-received', expression);
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
62
|
+
/** Records that could not be judged yet — tried again whenever something new is admitted */
|
|
63
|
+
const waiting = new Map();
|
|
64
|
+
const retryWaiting = async () => {
|
|
65
|
+
let progressed = true;
|
|
66
|
+
while (progressed && waiting.size > 0) {
|
|
67
|
+
progressed = false;
|
|
68
|
+
for (const [id, held] of [...waiting]) {
|
|
69
|
+
waiting.delete(id);
|
|
70
|
+
if (await admit(held.peerId, held.expression))
|
|
71
|
+
progressed = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
// ─── The walk ──────────────────────────────────────────────────────
|
|
76
|
+
const finish = (peerId, walk) => {
|
|
77
|
+
walks.delete(peerId);
|
|
78
|
+
emit('synced', peerId);
|
|
79
|
+
if (walk.next !== null && walk.next !== walk.remoteRoot)
|
|
80
|
+
void pull(peerId, walk.next);
|
|
81
|
+
};
|
|
82
|
+
/** Sends whatever is queued, or moves on to records once the tree is done. */
|
|
83
|
+
const advance = (peerId, walk) => {
|
|
84
|
+
walk.touchedAt = Date.now();
|
|
85
|
+
while (walk.queue.length > 0) {
|
|
86
|
+
const batch = walk.queue.splice(0, MAX_CIDS_PER_REQUEST);
|
|
87
|
+
const id = nextRequestId++;
|
|
88
|
+
walk.nodeBatches.set(id, batch);
|
|
89
|
+
send(peerId, { type: 'node-request', id, cids: batch });
|
|
90
|
+
}
|
|
91
|
+
if (walk.nodeBatches.size > 0)
|
|
92
|
+
return;
|
|
93
|
+
// The tree is walked. Ask for the records it named that are not here.
|
|
94
|
+
if (walk.missing.size > 0 && walk.idBatches.size === 0) {
|
|
95
|
+
const ids = [...walk.missing];
|
|
96
|
+
walk.missing.clear();
|
|
97
|
+
for (let i = 0; i < ids.length; i += MAX_IDS_PER_REQUEST) {
|
|
98
|
+
const batch = ids.slice(i, i + MAX_IDS_PER_REQUEST);
|
|
99
|
+
const id = nextRequestId++;
|
|
100
|
+
walk.idBatches.set(id, batch);
|
|
101
|
+
send(peerId, { type: 'diff-request', id, missingIds: batch });
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (walk.idBatches.size === 0)
|
|
106
|
+
finish(peerId, walk);
|
|
107
|
+
};
|
|
108
|
+
/** Pulls a peer's tree, given its root. */
|
|
109
|
+
const pull = async (peerId, remoteRoot) => {
|
|
110
|
+
const current = walks.get(peerId);
|
|
111
|
+
if (current && Date.now() - current.touchedAt < STALE_WALK_MS) {
|
|
112
|
+
// One walk per peer at a time; a newer root is pulled when this one ends.
|
|
113
|
+
if (current.remoteRoot !== remoteRoot)
|
|
114
|
+
current.next = remoteRoot;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
walks.delete(peerId);
|
|
118
|
+
if (remoteRoot === null) {
|
|
119
|
+
emit('synced', peerId);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const localRoot = await storageProvider.getRootCid();
|
|
123
|
+
if (await storageProvider.getAdapter().has(remoteRoot)) {
|
|
124
|
+
// A tree this store holds, or has moved past: nothing to pull.
|
|
125
|
+
emit('synced', peerId);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const walk = {
|
|
129
|
+
remoteRoot,
|
|
130
|
+
localRoot,
|
|
131
|
+
depth: new Map([[remoteRoot, 0]]),
|
|
132
|
+
queue: [remoteRoot],
|
|
133
|
+
nodeBatches: new Map(),
|
|
134
|
+
missing: new Set(),
|
|
135
|
+
idBatches: new Map(),
|
|
136
|
+
fetched: 0,
|
|
137
|
+
touchedAt: Date.now(),
|
|
138
|
+
next: null,
|
|
139
|
+
};
|
|
140
|
+
walks.set(peerId, walk);
|
|
141
|
+
advance(peerId, walk);
|
|
142
|
+
};
|
|
143
|
+
const onNodes = async (peerId, requestId, nodes) => {
|
|
144
|
+
const walk = walks.get(peerId);
|
|
145
|
+
const batch = walk?.nodeBatches.get(requestId);
|
|
146
|
+
if (!walk || !batch)
|
|
147
|
+
return; // not ours, or already answered
|
|
148
|
+
const asked = new Set(batch);
|
|
149
|
+
const adapter = storageProvider.getAdapter();
|
|
150
|
+
for (const { cid, node: sent } of nodes) {
|
|
151
|
+
if (typeof cid !== 'string' || !asked.has(cid))
|
|
152
|
+
continue;
|
|
153
|
+
const node = await verifyNode(cid, sent);
|
|
154
|
+
if (!node)
|
|
155
|
+
continue; // malformed, or not the node that CID names
|
|
156
|
+
if (++walk.fetched > MAX_NODES_PER_WALK) {
|
|
157
|
+
walks.delete(peerId);
|
|
158
|
+
emit('error', new Error(`Sync with ${peerId} abandoned: more than ${MAX_NODES_PER_WALK} nodes`));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
for (const id of await differingEntries(adapter, walk.localRoot, node))
|
|
162
|
+
walk.missing.add(id);
|
|
163
|
+
const depth = walk.depth.get(cid) ?? 0;
|
|
164
|
+
if (depth >= MAX_DEPTH)
|
|
165
|
+
continue;
|
|
166
|
+
for (const child of await unknownChildren(adapter, node)) {
|
|
167
|
+
if (walk.depth.has(child))
|
|
168
|
+
continue; // already queued — a cycle, or a shared subtree
|
|
169
|
+
walk.depth.set(child, depth + 1);
|
|
170
|
+
walk.queue.push(child);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Asked-for nodes the peer did not send are simply not followed: a peer can
|
|
174
|
+
// legitimately have compacted a node away between its root and our request.
|
|
175
|
+
// Marked answered only now, so a reply processed alongside this one cannot
|
|
176
|
+
// decide the tree is finished while this one's children are still unqueued.
|
|
177
|
+
walk.nodeBatches.delete(requestId);
|
|
178
|
+
advance(peerId, walk);
|
|
179
|
+
};
|
|
180
|
+
const onRecords = async (peerId, requestId, expressions) => {
|
|
181
|
+
const walk = walks.get(peerId);
|
|
182
|
+
const asked = walk?.idBatches.get(requestId);
|
|
183
|
+
// Only records this node asked for are considered; anything else was not
|
|
184
|
+
// requested and is not taken on trust as a side effect.
|
|
185
|
+
const wanted = asked ? new Set(asked) : null;
|
|
186
|
+
// Definitions and first versions before what depends on them, so little has to wait.
|
|
187
|
+
const ordered = [...expressions].sort((a, b) => rank(a) - rank(b));
|
|
188
|
+
let admitted = false;
|
|
189
|
+
for (const expression of ordered) {
|
|
190
|
+
if (wanted?.has(expression?.id) && (await admit(peerId, expression)))
|
|
191
|
+
admitted = true;
|
|
192
|
+
}
|
|
193
|
+
if (admitted)
|
|
194
|
+
await retryWaiting();
|
|
195
|
+
if (!walk || !asked)
|
|
196
|
+
return;
|
|
197
|
+
walk.idBatches.delete(requestId);
|
|
198
|
+
advance(peerId, walk);
|
|
199
|
+
};
|
|
200
|
+
// ─── Serving ───────────────────────────────────────────────────────
|
|
201
|
+
const serveNodes = async (peerId, requestId, cids) => {
|
|
202
|
+
const adapter = storageProvider.getAdapter();
|
|
203
|
+
const nodes = [];
|
|
204
|
+
for (const cid of cids.slice(0, MAX_CIDS_PER_REQUEST)) {
|
|
205
|
+
if (typeof cid !== 'string')
|
|
206
|
+
continue;
|
|
207
|
+
const bytes = await adapter.get(cid);
|
|
208
|
+
// Only content-addressed tree nodes leave this store — never another key
|
|
209
|
+
// that happens to share the namespace.
|
|
210
|
+
if (bytes && (await cidFromBytes(bytes)) === cid)
|
|
211
|
+
nodes.push({ cid, node: deserializeNode(bytes) });
|
|
212
|
+
}
|
|
213
|
+
send(peerId, { type: 'node-response', id: requestId, nodes });
|
|
214
|
+
};
|
|
215
|
+
const serveRecords = async (peerId, requestId, ids) => {
|
|
216
|
+
const expressions = [];
|
|
217
|
+
for (const id of ids.slice(0, MAX_IDS_PER_REQUEST)) {
|
|
218
|
+
const expression = typeof id === 'string' ? await storageProvider.getExpression(id) : null;
|
|
219
|
+
if (expression)
|
|
220
|
+
expressions.push(expression);
|
|
221
|
+
}
|
|
222
|
+
// Always answered, even empty: the asker counts replies to know it is done.
|
|
223
|
+
send(peerId, { type: 'diff-response', id: requestId, expressions });
|
|
224
|
+
};
|
|
225
|
+
return {
|
|
226
|
+
start() {
|
|
227
|
+
if (intervalId !== null)
|
|
228
|
+
return;
|
|
229
|
+
intervalId = setInterval(async () => {
|
|
230
|
+
const rootCid = await storageProvider.getRootCid();
|
|
231
|
+
broadcast({ type: 'sync-request', rootCid });
|
|
232
|
+
}, heartbeatInterval);
|
|
233
|
+
},
|
|
234
|
+
stop() {
|
|
235
|
+
if (intervalId !== null) {
|
|
236
|
+
clearInterval(intervalId);
|
|
237
|
+
intervalId = null;
|
|
238
|
+
}
|
|
239
|
+
walks.clear();
|
|
240
|
+
},
|
|
241
|
+
async handleMessage(peerId, message) {
|
|
242
|
+
try {
|
|
243
|
+
const msg = parseSyncMessage(message);
|
|
244
|
+
if (!msg)
|
|
245
|
+
return; // malformed, or a protocol version this peer does not speak
|
|
246
|
+
switch (msg.type) {
|
|
247
|
+
case 'sync-request': {
|
|
248
|
+
const localRoot = await storageProvider.getRootCid();
|
|
249
|
+
const differs = localRoot !== msg.rootCid;
|
|
250
|
+
send(peerId, { type: 'sync-response', rootCid: localRoot, hasChanges: differs });
|
|
251
|
+
// They will pull ours from the response; we pull theirs.
|
|
252
|
+
if (differs)
|
|
253
|
+
await pull(peerId, msg.rootCid);
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
case 'sync-response': {
|
|
257
|
+
if (msg.hasChanges)
|
|
258
|
+
await pull(peerId, msg.rootCid);
|
|
259
|
+
else
|
|
260
|
+
emit('synced', peerId);
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
case 'node-request':
|
|
264
|
+
await serveNodes(peerId, msg.id, Array.isArray(msg.cids) ? msg.cids : []);
|
|
265
|
+
break;
|
|
266
|
+
case 'node-response':
|
|
267
|
+
await onNodes(peerId, msg.id, Array.isArray(msg.nodes) ? msg.nodes : []);
|
|
268
|
+
break;
|
|
269
|
+
case 'diff-request':
|
|
270
|
+
await serveRecords(peerId, msg.id, Array.isArray(msg.missingIds) ? msg.missingIds : []);
|
|
271
|
+
break;
|
|
272
|
+
case 'diff-response':
|
|
273
|
+
await onRecords(peerId, msg.id, Array.isArray(msg.expressions) ? msg.expressions : []);
|
|
274
|
+
break;
|
|
275
|
+
case 'push-update':
|
|
276
|
+
await admit(peerId, msg.expression);
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
emit('error', err);
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
notifyPeers(peerIds) {
|
|
285
|
+
storageProvider.getRootCid().then(rootCid => {
|
|
286
|
+
for (const peer of peerIds) {
|
|
287
|
+
if (peers.has(peer))
|
|
288
|
+
send(peer, { type: 'sync-request', rootCid });
|
|
289
|
+
}
|
|
290
|
+
}).catch(err => emit('error', err));
|
|
291
|
+
},
|
|
292
|
+
onLocalChange(expression) {
|
|
293
|
+
storageProvider.getRootCid().then(newRootCid => {
|
|
294
|
+
broadcast({ type: 'push-update', expression, newRootCid: newRootCid || '' });
|
|
295
|
+
}).catch(err => emit('error', err));
|
|
296
|
+
},
|
|
297
|
+
addPeer(peerId) {
|
|
298
|
+
peers.add(peerId);
|
|
299
|
+
},
|
|
300
|
+
removePeer(peerId) {
|
|
301
|
+
peers.delete(peerId);
|
|
302
|
+
// A dropped peer must not leave a half-finished walk holding memory.
|
|
303
|
+
walks.delete(peerId);
|
|
304
|
+
},
|
|
305
|
+
on,
|
|
306
|
+
off,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=sync-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../../src/sync/sync-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sync-messages
|
|
3
|
+
* What peers say to each other to reconcile a space.
|
|
4
|
+
*
|
|
5
|
+
* Messages are plain objects: they travel inside the network's own envelope,
|
|
6
|
+
* which is encoded once, rather than being encoded here and again there.
|
|
7
|
+
*
|
|
8
|
+
* Every message carries `v`. A peer drops a message whose version it does not
|
|
9
|
+
* speak rather than half-processing it: two versions that cannot reconcile
|
|
10
|
+
* should fail loudly, not leave a quiet partial sync.
|
|
11
|
+
*/
|
|
12
|
+
import type { Expression } from '../types.js';
|
|
13
|
+
export declare const SYNC_PROTOCOL_VERSION = 3;
|
|
14
|
+
type V = {
|
|
15
|
+
readonly v: typeof SYNC_PROTOCOL_VERSION;
|
|
16
|
+
};
|
|
17
|
+
export type SyncMessage = V & (
|
|
18
|
+
/** "My tree's root is this." Equal roots mean identical data. */
|
|
19
|
+
{
|
|
20
|
+
readonly type: 'sync-request';
|
|
21
|
+
readonly rootCid: string | null;
|
|
22
|
+
}
|
|
23
|
+
/** The answer: my root, and whether it differs from yours. */
|
|
24
|
+
| {
|
|
25
|
+
readonly type: 'sync-response';
|
|
26
|
+
readonly rootCid: string | null;
|
|
27
|
+
readonly hasChanges: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* "Send me these tree nodes." `id` is echoed in the reply: requests are
|
|
31
|
+
* served concurrently, so replies can arrive in any order.
|
|
32
|
+
*/
|
|
33
|
+
| {
|
|
34
|
+
readonly type: 'node-request';
|
|
35
|
+
readonly id: number;
|
|
36
|
+
readonly cids: ReadonlyArray<string>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Tree nodes, as objects. Unknown CIDs are left out, never an error. The
|
|
40
|
+
* receiver checks each against its CID by serializing it the one canonical
|
|
41
|
+
* way (`anti-entropy.ts`).
|
|
42
|
+
*/
|
|
43
|
+
| {
|
|
44
|
+
readonly type: 'node-response';
|
|
45
|
+
readonly id: number;
|
|
46
|
+
readonly nodes: ReadonlyArray<{
|
|
47
|
+
readonly cid: string;
|
|
48
|
+
readonly node: unknown;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/** "Send me these records." */
|
|
52
|
+
| {
|
|
53
|
+
readonly type: 'diff-request';
|
|
54
|
+
readonly id: number;
|
|
55
|
+
readonly missingIds: ReadonlyArray<string>;
|
|
56
|
+
} | {
|
|
57
|
+
readonly type: 'diff-response';
|
|
58
|
+
readonly id: number;
|
|
59
|
+
readonly expressions: ReadonlyArray<Expression>;
|
|
60
|
+
}
|
|
61
|
+
/** A record written just now, pushed without waiting for the next round. */
|
|
62
|
+
| {
|
|
63
|
+
readonly type: 'push-update';
|
|
64
|
+
readonly expression: Expression;
|
|
65
|
+
readonly newRootCid: string;
|
|
66
|
+
});
|
|
67
|
+
/** A message before the version is stamped on — what callers construct. */
|
|
68
|
+
export type SyncMessageBody = SyncMessage extends infer M ? (M extends V ? Omit<M, 'v'> : never) : never;
|
|
69
|
+
/**
|
|
70
|
+
* Checks that something a peer sent is a sync message this peer speaks.
|
|
71
|
+
* @returns The message, or null when it is malformed or from another protocol version.
|
|
72
|
+
*/
|
|
73
|
+
export declare function parseSyncMessage(value: unknown): SyncMessage | null;
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=sync-messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-messages.d.ts","sourceRoot":"","sources":["../../src/sync/sync-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,KAAK,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,EAAE,OAAO,qBAAqB,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,CAAC,GACzB;AACE,iEAAiE;AAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AACpE,8DAA8D;GAC5D;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAAE;AACnG;;;GAGG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE;AAC9F;;;;GAIG;GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CAAE;AAC1I,+BAA+B;GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,GAClG;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;CAAE;AAC1G,4EAA4E;GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CACjG,CAAC;AAEJ,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG,WAAW,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEzG;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAInE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const SYNC_PROTOCOL_VERSION = 3;
|
|
2
|
+
/**
|
|
3
|
+
* Checks that something a peer sent is a sync message this peer speaks.
|
|
4
|
+
* @returns The message, or null when it is malformed or from another protocol version.
|
|
5
|
+
*/
|
|
6
|
+
export function parseSyncMessage(value) {
|
|
7
|
+
const message = value;
|
|
8
|
+
if (!message || typeof message !== 'object' || message.v !== SYNC_PROTOCOL_VERSION || typeof message.type !== 'string')
|
|
9
|
+
return null;
|
|
10
|
+
return message;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=sync-messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-messages.js","sourceRoot":"","sources":["../../src/sync/sync-messages.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AA+BvC;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,MAAM,OAAO,GAAG,KAAoC,CAAC;IACrD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,qBAAqB,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACpI,OAAO,OAAsB,CAAC;AAChC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core protocol types used across all modules.
|
|
3
|
+
* @module types
|
|
4
|
+
*/
|
|
5
|
+
/** Crypto provider interface — abstraction over key algorithms for easy swapping */
|
|
6
|
+
export interface CryptoProvider {
|
|
7
|
+
readonly algorithm: string;
|
|
8
|
+
generateKeyPair(): Promise<CryptoKeyPairResult>;
|
|
9
|
+
/**
|
|
10
|
+
* Deterministically derives a key pair from seed bytes (same seed → same keys).
|
|
11
|
+
* Owns the whole KDF: callers pass the raw seed, at least 16 uniform bytes.
|
|
12
|
+
*/
|
|
13
|
+
deriveKeyPairFromSeed(seed: Uint8Array): Promise<CryptoKeyPairResult>;
|
|
14
|
+
sign(privateKey: CryptoKey, data: Uint8Array): Promise<Uint8Array>;
|
|
15
|
+
verify(publicKey: CryptoKey, signature: Uint8Array, data: Uint8Array): Promise<boolean>;
|
|
16
|
+
exportPublicKey(key: CryptoKey): Promise<Uint8Array>;
|
|
17
|
+
importPublicKey(bytes: Uint8Array): Promise<CryptoKey>;
|
|
18
|
+
importPrivateKey(bytes: Uint8Array): Promise<CryptoKey>;
|
|
19
|
+
}
|
|
20
|
+
export interface CryptoKeyPairResult {
|
|
21
|
+
readonly publicKey: CryptoKey;
|
|
22
|
+
readonly privateKey: CryptoKey;
|
|
23
|
+
}
|
|
24
|
+
/** Standard Schema v1 interface (https://standardschema.dev/) */
|
|
25
|
+
export interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
26
|
+
readonly '~standard': {
|
|
27
|
+
readonly version: 1;
|
|
28
|
+
readonly vendor: string;
|
|
29
|
+
readonly validate: (value: unknown) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;
|
|
30
|
+
readonly types?: {
|
|
31
|
+
readonly input: Input;
|
|
32
|
+
readonly output: Output;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Standard JSON Schema v1 (https://standardschema.dev/json-schema): a schema
|
|
38
|
+
* that can describe itself as JSON Schema — Zod 4.2+, ArkType 2.1.28+, and
|
|
39
|
+
* Valibot through `toStandardJsonSchema`. It is how a validator you already
|
|
40
|
+
* use becomes a definition a space can store.
|
|
41
|
+
*/
|
|
42
|
+
export interface StandardJSONSchemaV1<Input = unknown, Output = Input> {
|
|
43
|
+
readonly '~standard': {
|
|
44
|
+
readonly version: 1;
|
|
45
|
+
readonly vendor: string;
|
|
46
|
+
readonly types?: {
|
|
47
|
+
readonly input: Input;
|
|
48
|
+
readonly output: Output;
|
|
49
|
+
};
|
|
50
|
+
readonly jsonSchema: {
|
|
51
|
+
readonly input: (options: {
|
|
52
|
+
readonly target: string;
|
|
53
|
+
readonly libraryOptions?: Record<string, unknown>;
|
|
54
|
+
}) => Record<string, unknown>;
|
|
55
|
+
readonly output: (options: {
|
|
56
|
+
readonly target: string;
|
|
57
|
+
readonly libraryOptions?: Record<string, unknown>;
|
|
58
|
+
}) => Record<string, unknown>;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export type StandardSchemaResult<Output> = {
|
|
63
|
+
readonly value: Output;
|
|
64
|
+
readonly issues?: undefined;
|
|
65
|
+
} | {
|
|
66
|
+
readonly value?: undefined;
|
|
67
|
+
readonly issues: ReadonlyArray<StandardSchemaIssue>;
|
|
68
|
+
};
|
|
69
|
+
export interface StandardSchemaIssue {
|
|
70
|
+
readonly message: string;
|
|
71
|
+
readonly path?: ReadonlyArray<PropertyKey>;
|
|
72
|
+
}
|
|
73
|
+
/** What a record is about: another record in the same space, in a named role */
|
|
74
|
+
export interface Link {
|
|
75
|
+
/** The role: 'about', 'in', 'replyTo' — lower camel case */
|
|
76
|
+
readonly rel: string;
|
|
77
|
+
/** The key of the record it points at */
|
|
78
|
+
readonly to: string;
|
|
79
|
+
}
|
|
80
|
+
/** Expression — the atomic data unit */
|
|
81
|
+
export interface Expression<T = unknown> {
|
|
82
|
+
readonly id: string;
|
|
83
|
+
readonly author: string;
|
|
84
|
+
readonly collection: string;
|
|
85
|
+
readonly space?: string;
|
|
86
|
+
readonly createdAt: string;
|
|
87
|
+
readonly body: T;
|
|
88
|
+
readonly proof?: string;
|
|
89
|
+
/** The record's identity, stable across versions. Links point here. */
|
|
90
|
+
readonly key: string;
|
|
91
|
+
/** 0 for a record's first version; each later version is one more than the one it replaces */
|
|
92
|
+
readonly seq: number;
|
|
93
|
+
/** Id of the version this one replaces. Absent on seq 0. */
|
|
94
|
+
readonly prev?: string;
|
|
95
|
+
/** Id of the record's first version — who created it. Absent on seq 0. */
|
|
96
|
+
readonly genesis?: string;
|
|
97
|
+
/** Keep this version once it is superseded — set by the writer, from the collection's `history` */
|
|
98
|
+
readonly retain?: true;
|
|
99
|
+
/**
|
|
100
|
+
* The latest changes to the space's access history — roles, members,
|
|
101
|
+
* invites, revoked notes, collection definitions — its writer knew of. It
|
|
102
|
+
* is judged by who held what, and which definition was in force, as of
|
|
103
|
+
* those (`space/roles.ts`).
|
|
104
|
+
*/
|
|
105
|
+
readonly seen?: ReadonlyArray<string>;
|
|
106
|
+
/** This version deletes the record; its body is null */
|
|
107
|
+
readonly deleted?: true;
|
|
108
|
+
/**
|
|
109
|
+
* Links to other records. Signed with the rest. In a private space they are
|
|
110
|
+
* sealed inside the encrypted body instead, and this is absent.
|
|
111
|
+
*/
|
|
112
|
+
readonly links?: ReadonlyArray<Link>;
|
|
113
|
+
readonly signature: string;
|
|
114
|
+
}
|
|
115
|
+
export interface UnsignedExpression<T = unknown> {
|
|
116
|
+
readonly author: string;
|
|
117
|
+
readonly collection: string;
|
|
118
|
+
/** Space this belongs to — signed, so it cannot be replayed into another space */
|
|
119
|
+
readonly space?: string;
|
|
120
|
+
readonly createdAt: string;
|
|
121
|
+
readonly body: T;
|
|
122
|
+
/** Encoded UCAN proving the author may write this — signed along with the rest */
|
|
123
|
+
readonly proof?: string;
|
|
124
|
+
/** The record's identity, stable across versions. Links point here. */
|
|
125
|
+
readonly key: string;
|
|
126
|
+
/** 0 for a record's first version; each later version is one more than the one it replaces */
|
|
127
|
+
readonly seq: number;
|
|
128
|
+
/** Id of the version this one replaces. Absent on seq 0. */
|
|
129
|
+
readonly prev?: string;
|
|
130
|
+
/** Id of the record's first version — who created it. Absent on seq 0. */
|
|
131
|
+
readonly genesis?: string;
|
|
132
|
+
/** Keep this version once it is superseded — set by the writer, from the collection's `history` */
|
|
133
|
+
readonly retain?: true;
|
|
134
|
+
/**
|
|
135
|
+
* The latest changes to the space's access history — roles, members,
|
|
136
|
+
* invites, revoked notes, collection definitions — its writer knew of. It
|
|
137
|
+
* is judged by who held what, and which definition was in force, as of
|
|
138
|
+
* those (`space/roles.ts`).
|
|
139
|
+
*/
|
|
140
|
+
readonly seen?: ReadonlyArray<string>;
|
|
141
|
+
/** This version deletes the record; its body is null */
|
|
142
|
+
readonly deleted?: true;
|
|
143
|
+
/**
|
|
144
|
+
* Links to other records. Signed with the rest. In a private space they are
|
|
145
|
+
* sealed inside the encrypted body instead, and this is absent.
|
|
146
|
+
*/
|
|
147
|
+
readonly links?: ReadonlyArray<Link>;
|
|
148
|
+
}
|
|
149
|
+
/** Whether a space's contents are readable by anyone who has them */
|
|
150
|
+
export type SpaceVisibility = 'public' | 'private';
|
|
151
|
+
/** A role, as a space defines it — see `space/roles.ts` */
|
|
152
|
+
export interface SpaceRole {
|
|
153
|
+
/** Lower case, used as its key: `moderator` */
|
|
154
|
+
readonly name: string;
|
|
155
|
+
/** What people see: `Moderator` */
|
|
156
|
+
readonly title?: string;
|
|
157
|
+
/** Higher can change lower. Equal ranks are equals. */
|
|
158
|
+
readonly rank: number;
|
|
159
|
+
readonly permissions: ReadonlyArray<string>;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A space. Its id is the hash of what is fixed at creation — creator,
|
|
163
|
+
* visibility, starting roles, time, nonce and read key (`space/space-access.ts`)
|
|
164
|
+
* — so whoever hands over a space cannot change who started it or with which
|
|
165
|
+
* roles. `name` is a description, not part of that.
|
|
166
|
+
*/
|
|
167
|
+
export interface Space {
|
|
168
|
+
readonly id: string;
|
|
169
|
+
readonly visibility: SpaceVisibility;
|
|
170
|
+
/** The account that made it, holding `creatorRole` at the start */
|
|
171
|
+
readonly creator: string;
|
|
172
|
+
/** The roles it started with — later changed by records in `sys.role` */
|
|
173
|
+
readonly roles: ReadonlyArray<SpaceRole>;
|
|
174
|
+
readonly creatorRole: string;
|
|
175
|
+
readonly name: string;
|
|
176
|
+
readonly createdAt: string;
|
|
177
|
+
/** Random, so two spaces made alike still differ */
|
|
178
|
+
readonly nonce: string;
|
|
179
|
+
/** Private spaces: the public half of the read key, derived from the space key — what a node checks a reader against */
|
|
180
|
+
readonly readKey?: string;
|
|
181
|
+
readonly encryptionKeyId?: string;
|
|
182
|
+
}
|
|
183
|
+
/** Collection definition */
|
|
184
|
+
export interface CollectionDef {
|
|
185
|
+
readonly name: string;
|
|
186
|
+
readonly schema: StandardSchemaV1;
|
|
187
|
+
}
|
|
188
|
+
/** Peer info */
|
|
189
|
+
export interface PeerInfo {
|
|
190
|
+
readonly did: string;
|
|
191
|
+
readonly connectionId: string;
|
|
192
|
+
readonly connectedAt: string;
|
|
193
|
+
}
|
|
194
|
+
/** Sync state */
|
|
195
|
+
export interface SyncState {
|
|
196
|
+
readonly peerId: string;
|
|
197
|
+
readonly lastSyncedAt: string;
|
|
198
|
+
readonly remoteRoot: string;
|
|
199
|
+
}
|
|
200
|
+
/** Storage adapter interface */
|
|
201
|
+
export interface StorageAdapter {
|
|
202
|
+
get(key: string): Promise<Uint8Array | null>;
|
|
203
|
+
put(key: string, value: Uint8Array): Promise<void>;
|
|
204
|
+
delete(key: string): Promise<void>;
|
|
205
|
+
has(key: string): Promise<boolean>;
|
|
206
|
+
list(prefix?: string): Promise<string[]>;
|
|
207
|
+
/** Query expressions by collection */
|
|
208
|
+
queryExpressions(collection: string, limit?: number, cursor?: string): Promise<Expression[]>;
|
|
209
|
+
/** Store an expression */
|
|
210
|
+
putExpression(expression: Expression): Promise<void>;
|
|
211
|
+
/** Get an expression by ID */
|
|
212
|
+
getExpression(id: string): Promise<Expression | null>;
|
|
213
|
+
/** Delete an expression by ID */
|
|
214
|
+
deleteExpression(id: string): Promise<void>;
|
|
215
|
+
/** Batch operations */
|
|
216
|
+
batch(ops: ReadonlyArray<BatchOp>): Promise<void>;
|
|
217
|
+
close(): Promise<void>;
|
|
218
|
+
}
|
|
219
|
+
export type BatchOp = {
|
|
220
|
+
readonly type: 'put';
|
|
221
|
+
readonly key: string;
|
|
222
|
+
readonly value: Uint8Array;
|
|
223
|
+
} | {
|
|
224
|
+
readonly type: 'delete';
|
|
225
|
+
readonly key: string;
|
|
226
|
+
};
|
|
227
|
+
/** Network message envelope */
|
|
228
|
+
export interface NetworkMessage {
|
|
229
|
+
readonly type: string;
|
|
230
|
+
readonly from: string;
|
|
231
|
+
readonly payload: unknown;
|
|
232
|
+
}
|
|
233
|
+
/** Result type for operations that can fail */
|
|
234
|
+
export type Result<T, E = Error> = {
|
|
235
|
+
readonly ok: true;
|
|
236
|
+
readonly value: T;
|
|
237
|
+
} | {
|
|
238
|
+
readonly ok: false;
|
|
239
|
+
readonly error: E;
|
|
240
|
+
};
|
|
241
|
+
export declare const ok: <T>(value: T) => Result<T, never>;
|
|
242
|
+
export declare const err: <E>(error: E) => Result<never, E>;
|
|
243
|
+
//# sourceMappingURL=types.d.ts.map
|