@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,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview WebRTC signaling over one WebSocket to a relay.
|
|
3
|
+
*
|
|
4
|
+
* One socket serves every room this peer is in: it joins and leaves rooms as
|
|
5
|
+
* spaces open and close, and joins them all again after a reconnect.
|
|
6
|
+
*/
|
|
7
|
+
import { createEmitter } from '../utils/events.js';
|
|
8
|
+
const SIGNAL_KINDS = new Set(['offer', 'answer', 'candidate']);
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new signaling client.
|
|
11
|
+
*
|
|
12
|
+
* @param url - The relay's WebSocket URL.
|
|
13
|
+
* @param did - The decentralized identifier of this peer.
|
|
14
|
+
* @returns The signaling client instance.
|
|
15
|
+
*/
|
|
16
|
+
export function createSignalingClient(url, did) {
|
|
17
|
+
let ws = null;
|
|
18
|
+
let connected = false;
|
|
19
|
+
let retryCount = 0;
|
|
20
|
+
const maxRetries = 5;
|
|
21
|
+
const maxBackoffMs = 30000;
|
|
22
|
+
let reconnectTimer = null;
|
|
23
|
+
const rooms = new Set();
|
|
24
|
+
const { on, off, emit } = createEmitter();
|
|
25
|
+
const sendMessage = (msg) => {
|
|
26
|
+
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
27
|
+
return;
|
|
28
|
+
ws.send(JSON.stringify({ ...msg, from: did }));
|
|
29
|
+
};
|
|
30
|
+
const connect = () => {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
|
|
33
|
+
resolve();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
ws = new WebSocket(url);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
reject(err);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
ws.onopen = () => {
|
|
44
|
+
connected = true;
|
|
45
|
+
retryCount = 0;
|
|
46
|
+
emit('connected');
|
|
47
|
+
for (const room of rooms)
|
|
48
|
+
sendMessage({ type: 'join', room });
|
|
49
|
+
resolve();
|
|
50
|
+
};
|
|
51
|
+
ws.onmessage = (event) => {
|
|
52
|
+
try {
|
|
53
|
+
const msg = JSON.parse(event.data);
|
|
54
|
+
if (SIGNAL_KINDS.has(msg.type))
|
|
55
|
+
emit('signal', msg);
|
|
56
|
+
else if (typeof msg.room !== 'string')
|
|
57
|
+
return;
|
|
58
|
+
else if (msg.type === 'join')
|
|
59
|
+
emit('peer-joined', msg.from, msg.room);
|
|
60
|
+
else if (msg.type === 'leave')
|
|
61
|
+
emit('peer-left', msg.from, msg.room);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
emit('error', err instanceof Error ? err : new Error(String(err)));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
ws.onerror = () => {
|
|
68
|
+
const error = new Error('WebSocket error occurred');
|
|
69
|
+
emit('error', error);
|
|
70
|
+
if (!connected) {
|
|
71
|
+
reject(error);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
ws.onclose = () => {
|
|
75
|
+
connected = false;
|
|
76
|
+
emit('disconnected');
|
|
77
|
+
if (retryCount < maxRetries) {
|
|
78
|
+
const backoff = Math.min(1000 * Math.pow(2, retryCount), maxBackoffMs);
|
|
79
|
+
retryCount++;
|
|
80
|
+
if (reconnectTimer) {
|
|
81
|
+
clearTimeout(reconnectTimer);
|
|
82
|
+
}
|
|
83
|
+
reconnectTimer = setTimeout(() => {
|
|
84
|
+
connect().catch(() => {
|
|
85
|
+
// Ignore promise rejection on reconnect attempt
|
|
86
|
+
});
|
|
87
|
+
}, backoff);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const disconnect = () => {
|
|
93
|
+
if (reconnectTimer) {
|
|
94
|
+
clearTimeout(reconnectTimer);
|
|
95
|
+
reconnectTimer = null;
|
|
96
|
+
}
|
|
97
|
+
retryCount = maxRetries; // Prevent reconnection
|
|
98
|
+
if (ws) {
|
|
99
|
+
ws.close();
|
|
100
|
+
ws = null;
|
|
101
|
+
}
|
|
102
|
+
connected = false;
|
|
103
|
+
rooms.clear();
|
|
104
|
+
};
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
connect,
|
|
107
|
+
disconnect,
|
|
108
|
+
join: (room) => {
|
|
109
|
+
if (rooms.has(room))
|
|
110
|
+
return;
|
|
111
|
+
rooms.add(room);
|
|
112
|
+
sendMessage({ type: 'join', room });
|
|
113
|
+
},
|
|
114
|
+
leave: (room) => {
|
|
115
|
+
if (rooms.delete(room))
|
|
116
|
+
sendMessage({ type: 'leave', room });
|
|
117
|
+
},
|
|
118
|
+
signal: (kind, targetDid, payload) => sendMessage({ type: kind, to: targetDid, payload }),
|
|
119
|
+
on,
|
|
120
|
+
off,
|
|
121
|
+
isConnected: () => connected,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=signaling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signaling.js","sourceRoot":"","sources":["../../src/network/signaling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview What the mesh and network managers need from any way of moving bytes
|
|
3
|
+
* between peers.
|
|
4
|
+
*
|
|
5
|
+
* Two kinds exist. A **signalled** transport (WebRTC) cannot open a connection
|
|
6
|
+
* on its own: an offer and an answer have to be carried to the other side by
|
|
7
|
+
* something else — a relay, or a peer already connected to both. An
|
|
8
|
+
* **unsignalled** one (a WebSocket to an always-on node, an in-memory fake in
|
|
9
|
+
* tests) just dials. The first kind is the mesh's (`mesh.ts`); the second, a
|
|
10
|
+
* network manager's (`network-manager.ts`).
|
|
11
|
+
*/
|
|
12
|
+
export type PeerTransportEvents = {
|
|
13
|
+
data: (peerId: string, data: Uint8Array) => void;
|
|
14
|
+
connected: (peerId: string) => void;
|
|
15
|
+
disconnected: (peerId: string) => void;
|
|
16
|
+
error: (peerId: string, error: Error) => void;
|
|
17
|
+
};
|
|
18
|
+
export interface PeerTransport {
|
|
19
|
+
/**
|
|
20
|
+
* Starts dialling, for a transport that reaches out on its own. Called by
|
|
21
|
+
* the network manager's `connect()`. A signalled transport has nothing to
|
|
22
|
+
* start — its connections begin with an offer.
|
|
23
|
+
*/
|
|
24
|
+
readonly connect?: () => Promise<void>;
|
|
25
|
+
readonly send: (peerId: string, data: Uint8Array) => void;
|
|
26
|
+
readonly close: (peerId: string) => void;
|
|
27
|
+
/** Closes every connection. Deliberate: a transport must not reconnect after it. */
|
|
28
|
+
readonly closeAll: () => void;
|
|
29
|
+
readonly on: <K extends keyof PeerTransportEvents>(event: K, callback: PeerTransportEvents[K]) => void;
|
|
30
|
+
readonly off: <K extends keyof PeerTransportEvents>(event: K, callback: PeerTransportEvents[K]) => void;
|
|
31
|
+
/**
|
|
32
|
+
* The certificates of one open connection's two ends, for binding the peer
|
|
33
|
+
* handshake to it (`peer-auth.ts`). Absent where the connection has none.
|
|
34
|
+
*/
|
|
35
|
+
readonly binding?: (peerId: string) => {
|
|
36
|
+
readonly local: string;
|
|
37
|
+
readonly remote: string;
|
|
38
|
+
} | null;
|
|
39
|
+
}
|
|
40
|
+
/** Receives the ICE candidates a connection discovers, to be carried to the other side. */
|
|
41
|
+
export type CandidateSink = (candidate: RTCIceCandidateInit) => void;
|
|
42
|
+
export interface SignalledTransport extends PeerTransport {
|
|
43
|
+
/** Opens a connection and returns the offer to carry to the peer. */
|
|
44
|
+
readonly createOffer: (peerId: string, onCandidate: CandidateSink) => Promise<RTCSessionDescriptionInit>;
|
|
45
|
+
/** Accepts a peer's offer and returns the answer to carry back. */
|
|
46
|
+
readonly handleOffer: (peerId: string, offer: RTCSessionDescriptionInit, onCandidate: CandidateSink) => Promise<RTCSessionDescriptionInit>;
|
|
47
|
+
readonly handleAnswer: (peerId: string, answer: RTCSessionDescriptionInit) => Promise<void>;
|
|
48
|
+
readonly addIceCandidate: (peerId: string, candidate: RTCIceCandidateInit) => Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/network/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACjD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1D,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACvG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACxG;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACnG;AAED,2FAA2F;AAC3F,MAAM,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAErE,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACzG,mEAAmE;IACnE,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,yBAAyB,EAAE,WAAW,EAAE,aAAa,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC3I,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F,QAAQ,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7F"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview What the mesh and network managers need from any way of moving bytes
|
|
3
|
+
* between peers.
|
|
4
|
+
*
|
|
5
|
+
* Two kinds exist. A **signalled** transport (WebRTC) cannot open a connection
|
|
6
|
+
* on its own: an offer and an answer have to be carried to the other side by
|
|
7
|
+
* something else — a relay, or a peer already connected to both. An
|
|
8
|
+
* **unsignalled** one (a WebSocket to an always-on node, an in-memory fake in
|
|
9
|
+
* tests) just dials. The first kind is the mesh's (`mesh.ts`); the second, a
|
|
10
|
+
* network manager's (`network-manager.ts`).
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/network/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A WebSocket to one always-on node, as a transport.
|
|
3
|
+
*
|
|
4
|
+
* Browsers cannot accept connections, but they can dial a node that has a DNS
|
|
5
|
+
* name and a TLS certificate — no relay, no offer and answer, and no TURN for
|
|
6
|
+
* peers that could not otherwise reach each other. The node appears as a
|
|
7
|
+
* single peer.
|
|
8
|
+
*
|
|
9
|
+
* The wire is deliberately plain — three text frames, then binary:
|
|
10
|
+
*
|
|
11
|
+
* 1. node → `{"type":"challenge","nonce":…,"did":…}`
|
|
12
|
+
* 2. client → `{"type":"hello","did":…,"nonce":…,"sig"?:…}`
|
|
13
|
+
* 3. node → `{"type":"welcome","did":…,"sig"?:…}`
|
|
14
|
+
* 4. binary frames either way, passed through untouched.
|
|
15
|
+
*
|
|
16
|
+
* With an authenticator both sides sign: the client proves the DID it gives
|
|
17
|
+
* is its own — and, for a private space, that it may read — and the node that
|
|
18
|
+
* the welcome comes from the node that sent the challenge (see `peer-auth.ts`).
|
|
19
|
+
*/
|
|
20
|
+
import type { PeerTransport } from './transport.js';
|
|
21
|
+
import { type ClientAuth } from './peer-auth.js';
|
|
22
|
+
export interface WebSocketTransportConfig {
|
|
23
|
+
/** `wss://node.example.com/peer` */
|
|
24
|
+
readonly url: string;
|
|
25
|
+
/** This side's DID, sent in the hello */
|
|
26
|
+
readonly did: string;
|
|
27
|
+
/** Redial after an unexpected close. Default true. */
|
|
28
|
+
readonly reconnect?: boolean;
|
|
29
|
+
/** Ceiling for the redial backoff. Default 30 s. */
|
|
30
|
+
readonly maxBackoffMs?: number;
|
|
31
|
+
/** Proves who this side is (and that it may read a private space), and checks the node's welcome. */
|
|
32
|
+
readonly authenticator?: ClientAuth | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a transport that holds one socket to one node, redialling it with
|
|
36
|
+
* backoff for as long as the transport is wanted.
|
|
37
|
+
*
|
|
38
|
+
* @param config - Where to dial, and as whom.
|
|
39
|
+
* @returns The transport; call `connect()` to start.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createWebSocketTransport(config: WebSocketTransportConfig): PeerTransport;
|
|
42
|
+
//# sourceMappingURL=ws-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-transport.d.ts","sourceRoot":"","sources":["../../src/network/ws-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAuB,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,wBAAwB;IACvC,oCAAoC;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,qGAAqG;IACrG,QAAQ,CAAC,aAAa,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;CAC5C;AAmBD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,GAAG,aAAa,CAmKxF"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A WebSocket to one always-on node, as a transport.
|
|
3
|
+
*
|
|
4
|
+
* Browsers cannot accept connections, but they can dial a node that has a DNS
|
|
5
|
+
* name and a TLS certificate — no relay, no offer and answer, and no TURN for
|
|
6
|
+
* peers that could not otherwise reach each other. The node appears as a
|
|
7
|
+
* single peer.
|
|
8
|
+
*
|
|
9
|
+
* The wire is deliberately plain — three text frames, then binary:
|
|
10
|
+
*
|
|
11
|
+
* 1. node → `{"type":"challenge","nonce":…,"did":…}`
|
|
12
|
+
* 2. client → `{"type":"hello","did":…,"nonce":…,"sig"?:…}`
|
|
13
|
+
* 3. node → `{"type":"welcome","did":…,"sig"?:…}`
|
|
14
|
+
* 4. binary frames either way, passed through untouched.
|
|
15
|
+
*
|
|
16
|
+
* With an authenticator both sides sign: the client proves the DID it gives
|
|
17
|
+
* is its own — and, for a private space, that it may read — and the node that
|
|
18
|
+
* the welcome comes from the node that sent the challenge (see `peer-auth.ts`).
|
|
19
|
+
*/
|
|
20
|
+
import { peerNonce } from './peer-auth.js';
|
|
21
|
+
import { createEmitter } from '../utils/events.js';
|
|
22
|
+
function parseFrame(data, type) {
|
|
23
|
+
if (typeof data !== 'string')
|
|
24
|
+
return null;
|
|
25
|
+
try {
|
|
26
|
+
const parsed = JSON.parse(data);
|
|
27
|
+
return parsed?.type === type && typeof parsed.did === 'string' && parsed.did.length > 0 ? parsed : null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates a transport that holds one socket to one node, redialling it with
|
|
35
|
+
* backoff for as long as the transport is wanted.
|
|
36
|
+
*
|
|
37
|
+
* @param config - Where to dial, and as whom.
|
|
38
|
+
* @returns The transport; call `connect()` to start.
|
|
39
|
+
*/
|
|
40
|
+
export function createWebSocketTransport(config) {
|
|
41
|
+
const reconnect = config.reconnect !== false;
|
|
42
|
+
const maxBackoffMs = config.maxBackoffMs ?? 30_000;
|
|
43
|
+
let ws = null;
|
|
44
|
+
/** The node's DID, once its hello has arrived */
|
|
45
|
+
let peerId = null;
|
|
46
|
+
/** Set by close/closeAll: an intentional shutdown must never be fought */
|
|
47
|
+
let stopped = false;
|
|
48
|
+
let retryCount = 0;
|
|
49
|
+
let reconnectTimer = null;
|
|
50
|
+
const { on, off, emit } = createEmitter();
|
|
51
|
+
const scheduleRedial = () => {
|
|
52
|
+
if (stopped || !reconnect || reconnectTimer)
|
|
53
|
+
return;
|
|
54
|
+
// Exponential, capped, with jitter so a node restart is not met by every
|
|
55
|
+
// client at the same instant.
|
|
56
|
+
const base = Math.min(1000 * 2 ** retryCount, maxBackoffMs);
|
|
57
|
+
const delay = base / 2 + Math.random() * (base / 2);
|
|
58
|
+
retryCount += 1;
|
|
59
|
+
reconnectTimer = setTimeout(() => {
|
|
60
|
+
reconnectTimer = null;
|
|
61
|
+
dial().catch(() => {
|
|
62
|
+
// The close handler schedules the next attempt.
|
|
63
|
+
});
|
|
64
|
+
}, delay);
|
|
65
|
+
};
|
|
66
|
+
const dial = () => new Promise((resolve, reject) => {
|
|
67
|
+
if (stopped) {
|
|
68
|
+
reject(new Error('Transport was closed'));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
let socket;
|
|
72
|
+
try {
|
|
73
|
+
socket = new WebSocket(config.url);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
77
|
+
scheduleRedial();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
ws = socket;
|
|
81
|
+
socket.binaryType = 'arraybuffer';
|
|
82
|
+
let settled = false;
|
|
83
|
+
let stage = 'challenge';
|
|
84
|
+
const ourNonce = peerNonce();
|
|
85
|
+
const authenticator = config.authenticator ?? null;
|
|
86
|
+
/** Who sent the challenge: the welcome must come from the same node */
|
|
87
|
+
let nodeDid = null;
|
|
88
|
+
const refuse = (reason) => {
|
|
89
|
+
const error = new Error(reason);
|
|
90
|
+
emit('error', config.url, error);
|
|
91
|
+
if (!settled) {
|
|
92
|
+
settled = true;
|
|
93
|
+
reject(error);
|
|
94
|
+
}
|
|
95
|
+
// Clients may only send 1000 or 3000–4999; 4002 mirrors 1002 "protocol error".
|
|
96
|
+
socket.close(4002, 'protocol error');
|
|
97
|
+
};
|
|
98
|
+
const handle = async (event) => {
|
|
99
|
+
if (stage === 'challenge') {
|
|
100
|
+
const challenge = parseFrame(event.data, 'challenge');
|
|
101
|
+
if (!challenge || typeof challenge.nonce !== 'string')
|
|
102
|
+
return refuse('Expected a challenge from the node');
|
|
103
|
+
nodeDid = challenge.did;
|
|
104
|
+
const proof = authenticator ? await authenticator.hello(config.did, nodeDid, challenge.nonce) : {};
|
|
105
|
+
socket.send(JSON.stringify({ type: 'hello', did: config.did, nonce: ourNonce, ...proof }));
|
|
106
|
+
stage = 'welcome';
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (stage === 'welcome') {
|
|
110
|
+
const welcome = parseFrame(event.data, 'welcome');
|
|
111
|
+
if (!welcome)
|
|
112
|
+
return refuse('Expected a welcome from the node');
|
|
113
|
+
const did = welcome.did;
|
|
114
|
+
if (authenticator && (did !== nodeDid || !(await authenticator.checkWelcome(did, ourNonce, welcome.sig)))) {
|
|
115
|
+
return refuse('The node could not prove it is the node that answered');
|
|
116
|
+
}
|
|
117
|
+
stage = 'open';
|
|
118
|
+
peerId = did;
|
|
119
|
+
retryCount = 0;
|
|
120
|
+
settled = true;
|
|
121
|
+
emit('connected', peerId);
|
|
122
|
+
resolve();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (event.data instanceof ArrayBuffer && peerId !== null) {
|
|
126
|
+
emit('data', peerId, new Uint8Array(event.data));
|
|
127
|
+
}
|
|
128
|
+
// Text after the welcome has no meaning in this protocol; ignore it.
|
|
129
|
+
};
|
|
130
|
+
// Frames are handled one at a time: the handshake awaits crypto, and a
|
|
131
|
+
// data frame must not overtake the welcome that opens the connection.
|
|
132
|
+
let queue = Promise.resolve();
|
|
133
|
+
socket.onmessage = (event) => {
|
|
134
|
+
queue = queue
|
|
135
|
+
.then(() => handle(event))
|
|
136
|
+
.catch((error) => refuse(error instanceof Error ? error.message : String(error)));
|
|
137
|
+
};
|
|
138
|
+
socket.onerror = () => {
|
|
139
|
+
const error = new Error(`WebSocket error on ${config.url}`);
|
|
140
|
+
emit('error', peerId ?? config.url, error);
|
|
141
|
+
if (!settled) {
|
|
142
|
+
settled = true;
|
|
143
|
+
reject(error);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
socket.onclose = () => {
|
|
147
|
+
if (ws === socket)
|
|
148
|
+
ws = null;
|
|
149
|
+
const wasConnected = peerId;
|
|
150
|
+
peerId = null;
|
|
151
|
+
if (wasConnected)
|
|
152
|
+
emit('disconnected', wasConnected);
|
|
153
|
+
if (!settled) {
|
|
154
|
+
settled = true;
|
|
155
|
+
reject(new Error(`Connection to ${config.url} closed before the handshake finished`));
|
|
156
|
+
}
|
|
157
|
+
scheduleRedial();
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
const connect = () => {
|
|
161
|
+
stopped = false;
|
|
162
|
+
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
|
|
163
|
+
return Promise.resolve();
|
|
164
|
+
}
|
|
165
|
+
return dial();
|
|
166
|
+
};
|
|
167
|
+
const send = (target, data) => {
|
|
168
|
+
if (!ws || ws.readyState !== WebSocket.OPEN || target !== peerId) {
|
|
169
|
+
throw new Error(`Not connected to ${target}`);
|
|
170
|
+
}
|
|
171
|
+
ws.send(data);
|
|
172
|
+
};
|
|
173
|
+
const closeAll = () => {
|
|
174
|
+
stopped = true;
|
|
175
|
+
if (reconnectTimer) {
|
|
176
|
+
clearTimeout(reconnectTimer);
|
|
177
|
+
reconnectTimer = null;
|
|
178
|
+
}
|
|
179
|
+
ws?.close(1000, 'closed');
|
|
180
|
+
};
|
|
181
|
+
return Object.freeze({
|
|
182
|
+
connect,
|
|
183
|
+
send,
|
|
184
|
+
// One socket, one peer: closing the peer closes the transport.
|
|
185
|
+
close: (target) => {
|
|
186
|
+
if (target === peerId)
|
|
187
|
+
closeAll();
|
|
188
|
+
},
|
|
189
|
+
closeAll,
|
|
190
|
+
on,
|
|
191
|
+
off,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=ws-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-transport.js","sourceRoot":"","sources":["../../src/network/ws-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node/actions
|
|
3
|
+
* The node's operations, described once so every front end can be generated
|
|
4
|
+
* from the same list.
|
|
5
|
+
*
|
|
6
|
+
* Each action has a name, a sentence saying what it does, a JSON Schema for its
|
|
7
|
+
* input and a function that runs it. That is exactly what a command line needs
|
|
8
|
+
* to parse flags, what an MCP server lists as tools, and what WebMCP's
|
|
9
|
+
* `registerTool` takes — so a CLI, an agent on the desktop and an agent in the
|
|
10
|
+
* browser all see the same operations with the same names.
|
|
11
|
+
*
|
|
12
|
+
* Inputs and outputs are plain JSON. Nothing here may return a key, a handle or
|
|
13
|
+
* a function.
|
|
14
|
+
*/
|
|
15
|
+
import type { P2PNode } from './types.js';
|
|
16
|
+
/** The subset of JSON Schema these inputs use */
|
|
17
|
+
export interface ActionSchema {
|
|
18
|
+
readonly type: 'object';
|
|
19
|
+
readonly properties: Readonly<Record<string, {
|
|
20
|
+
readonly type?: string;
|
|
21
|
+
readonly enum?: ReadonlyArray<string>;
|
|
22
|
+
readonly description?: string;
|
|
23
|
+
readonly items?: unknown;
|
|
24
|
+
}>>;
|
|
25
|
+
readonly required?: ReadonlyArray<string>;
|
|
26
|
+
readonly additionalProperties?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface NodeAction {
|
|
29
|
+
/** `[a-z_]+`, so it is a valid tool name everywhere */
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly description: string;
|
|
32
|
+
readonly input: ActionSchema;
|
|
33
|
+
/** Reads only. Agents may run these without asking; everything else changes data. */
|
|
34
|
+
readonly readOnly: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Returns something that grants access — an invite to a private space
|
|
37
|
+
* carries its key. A front end should confirm with a person before handing
|
|
38
|
+
* the result to anyone.
|
|
39
|
+
*/
|
|
40
|
+
readonly sensitive?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Removes or overwrites something, or brings in someone else's space. A
|
|
43
|
+
* front end should ask a person before an agent runs it: an agent reads
|
|
44
|
+
* records other people wrote, and one of them may be telling it what to do.
|
|
45
|
+
*/
|
|
46
|
+
readonly destructive?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Returns what other people wrote — record bodies, names, collection
|
|
49
|
+
* descriptions. Data for an agent to read, never instructions to follow.
|
|
50
|
+
*/
|
|
51
|
+
readonly peerContent?: boolean;
|
|
52
|
+
readonly run: (node: P2PNode, input: Record<string, unknown>) => Promise<unknown>;
|
|
53
|
+
}
|
|
54
|
+
export declare const NODE_ACTIONS: ReadonlyArray<NodeAction>;
|
|
55
|
+
/** Why an input does not fit an action's schema, or null when it does. */
|
|
56
|
+
export declare function checkActionInput(action: NodeAction, input: unknown): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Runs an action by name, checking its input first.
|
|
59
|
+
* @throws When the action is unknown or the input does not fit
|
|
60
|
+
*/
|
|
61
|
+
export declare function runAction(node: P2PNode, name: string, input?: unknown): Promise<unknown>;
|
|
62
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/node/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAO1C,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAC3B,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAC3I,CAAC;IACF,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACnF;AAkBD,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,UAAU,CAodjD,CAAC;AAEH,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAgBlF;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,OAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAMlG"}
|