dropspace 0.0.0-stage → 0.1.1

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.
Files changed (67) hide show
  1. package/README.md +17 -2
  2. package/dist/automerge/index.d.ts +108 -0
  3. package/dist/automerge/index.d.ts.map +1 -0
  4. package/dist/automerge/index.js +437 -0
  5. package/dist/automerge/index.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +372 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/client/channel.d.ts +153 -0
  11. package/dist/client/channel.d.ts.map +1 -0
  12. package/dist/client/channel.js +704 -0
  13. package/dist/client/channel.js.map +1 -0
  14. package/dist/client/client.d.ts +376 -0
  15. package/dist/client/client.d.ts.map +1 -0
  16. package/dist/client/client.js +1421 -0
  17. package/dist/client/client.js.map +1 -0
  18. package/dist/client/events.d.ts +14 -0
  19. package/dist/client/events.d.ts.map +1 -0
  20. package/dist/client/events.js +71 -0
  21. package/dist/client/events.js.map +1 -0
  22. package/dist/client/identity.d.ts +89 -0
  23. package/dist/client/identity.d.ts.map +1 -0
  24. package/dist/client/identity.js +274 -0
  25. package/dist/client/identity.js.map +1 -0
  26. package/dist/client/index.d.ts +8 -0
  27. package/dist/client/index.d.ts.map +1 -0
  28. package/dist/client/index.js +8 -0
  29. package/dist/client/index.js.map +1 -0
  30. package/dist/client/peer-connection.d.ts +190 -0
  31. package/dist/client/peer-connection.d.ts.map +1 -0
  32. package/dist/client/peer-connection.js +647 -0
  33. package/dist/client/peer-connection.js.map +1 -0
  34. package/dist/client/peer-selection.d.ts +70 -0
  35. package/dist/client/peer-selection.d.ts.map +1 -0
  36. package/dist/client/peer-selection.js +193 -0
  37. package/dist/client/peer-selection.js.map +1 -0
  38. package/dist/client/storage.d.ts +118 -0
  39. package/dist/client/storage.d.ts.map +1 -0
  40. package/dist/client/storage.js +463 -0
  41. package/dist/client/storage.js.map +1 -0
  42. package/dist/files/index.d.ts +140 -0
  43. package/dist/files/index.d.ts.map +1 -0
  44. package/dist/files/index.js +751 -0
  45. package/dist/files/index.js.map +1 -0
  46. package/dist/files/sha256.d.ts +24 -0
  47. package/dist/files/sha256.d.ts.map +1 -0
  48. package/dist/files/sha256.js +147 -0
  49. package/dist/files/sha256.js.map +1 -0
  50. package/dist/index.d.ts +4 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +4 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/protocol/envelope.d.ts +61 -0
  55. package/dist/protocol/envelope.d.ts.map +1 -0
  56. package/dist/protocol/envelope.js +268 -0
  57. package/dist/protocol/envelope.js.map +1 -0
  58. package/dist/protocol/framing.d.ts +69 -0
  59. package/dist/protocol/framing.d.ts.map +1 -0
  60. package/dist/protocol/framing.js +145 -0
  61. package/dist/protocol/framing.js.map +1 -0
  62. package/dist/protocol/index.d.ts +3 -0
  63. package/dist/protocol/index.d.ts.map +1 -0
  64. package/dist/protocol/index.js +3 -0
  65. package/dist/protocol/index.js.map +1 -0
  66. package/fixtures/envelopes.json +132 -0
  67. package/package.json +51 -4
@@ -0,0 +1,69 @@
1
+ export declare const WIRE_MAGIC_BYTE = 213;
2
+ export declare const WIRE_PREFIX_BYTES = 6;
3
+ export declare enum WireFrameType {
4
+ CONTROL_JSON = 1,
5
+ MESSAGE_JSON = 2,
6
+ MESSAGE_BINARY = 3,
7
+ TRANSFER_CONTROL = 4,
8
+ TRANSFER_CHUNK = 5,
9
+ CRDT_SYNC = 6,
10
+ HUB_RELAY = 7
11
+ }
12
+ export type AckSemantics = "received" | "persisted" | "processed";
13
+ export interface WireFrameHeader {
14
+ messageId: string;
15
+ channel: string;
16
+ timestamp: number;
17
+ chunkIndex?: number;
18
+ totalChunks?: number;
19
+ totalByteLength?: number;
20
+ ackRequired?: boolean;
21
+ ackMode?: AckSemantics;
22
+ correlationId?: string;
23
+ /** File transfer specific fields */
24
+ transferId?: string;
25
+ byteOffset?: number;
26
+ chunkHash?: string;
27
+ /** CRDT specific fields */
28
+ documentId?: string;
29
+ /** Hub relay specific fields */
30
+ sourceDeviceId?: string;
31
+ targetDeviceId?: string;
32
+ spaceId?: string;
33
+ hopCount?: number;
34
+ maxHops?: number;
35
+ /** Custom metadata */
36
+ meta?: Record<string, unknown>;
37
+ }
38
+ export interface DecodedWireFrame {
39
+ frameType: WireFrameType;
40
+ header: WireFrameHeader;
41
+ payload: Uint8Array;
42
+ }
43
+ export interface EncodeWireFrameOptions {
44
+ /** Maximum allowed total frame size in bytes (prefix + header + payload). Defaults to 64 KiB. */
45
+ maxTotalFrameBytes?: number;
46
+ }
47
+ export interface DecodeWireFrameOptions {
48
+ /** Maximum allowed total frame size in bytes when decoding. Defaults to 256 KiB. */
49
+ maxTotalFrameBytes?: number;
50
+ }
51
+ export declare const MAX_HEADER_BYTES: number;
52
+ export declare const DEFAULT_MAX_TOTAL_FRAME_BYTES: number;
53
+ export declare const DEFAULT_MAX_FRAME_PAYLOAD_BYTES: number;
54
+ export declare const MAX_DECODE_FRAME_BYTES: number;
55
+ /**
56
+ * Binary frame layout:
57
+ * Byte 0: WIRE_MAGIC_BYTE (0xD5)
58
+ * Byte 1: WireFrameType (0x01 .. 0x07)
59
+ * Bytes 2..5: Header byte length (uint32 big-endian)
60
+ * Bytes 6..(6 + headerLen - 1): UTF-8 JSON encoded WireFrameHeader
61
+ * Remaining bytes: Raw binary payload (Uint8Array)
62
+ *
63
+ * totalFrameBytes = WIRE_PREFIX_BYTES (6) + encodedHeaderBytes + payloadBytes
64
+ */
65
+ export declare function encodeWireFrame(frameType: WireFrameType, header: WireFrameHeader, payload?: Uint8Array, options?: EncodeWireFrameOptions): Uint8Array;
66
+ export declare function decodeWireFrame(raw: Uint8Array | ArrayBuffer, options?: DecodeWireFrameOptions): DecodedWireFrame;
67
+ export declare function encodeJsonPayload(value: unknown): Uint8Array;
68
+ export declare function decodeJsonPayload<T = unknown>(payload: Uint8Array): T;
69
+ //# sourceMappingURL=framing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framing.d.ts","sourceRoot":"","sources":["../../src/protocol/framing.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,MAAO,CAAC;AACpC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,oBAAY,aAAa;IACvB,YAAY,IAAO;IACnB,YAAY,IAAO;IACnB,cAAc,IAAO;IACrB,gBAAgB,IAAO;IACvB,cAAc,IAAO;IACrB,SAAS,IAAO;IAChB,SAAS,IAAO;CACjB;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,iGAAiG;IACjG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,oFAAoF;IACpF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAKD,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAC1C,eAAO,MAAM,6BAA6B,QAAY,CAAC;AACvD,eAAO,MAAM,+BAA+B,QAAY,CAAC;AACzD,eAAO,MAAM,sBAAsB,QAAa,CAAC;AA+CjD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,UAA8B,EACvC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,UAAU,CA+CZ;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,UAAU,GAAG,WAAW,EAC7B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,gBAAgB,CA+ElB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAE5D;AAED,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,CAAC,CAErE"}
@@ -0,0 +1,145 @@
1
+ import { ProtocolValidationError } from "./envelope.js";
2
+ export const WIRE_MAGIC_BYTE = 0xd5;
3
+ export const WIRE_PREFIX_BYTES = 6;
4
+ export var WireFrameType;
5
+ (function (WireFrameType) {
6
+ WireFrameType[WireFrameType["CONTROL_JSON"] = 1] = "CONTROL_JSON";
7
+ WireFrameType[WireFrameType["MESSAGE_JSON"] = 2] = "MESSAGE_JSON";
8
+ WireFrameType[WireFrameType["MESSAGE_BINARY"] = 3] = "MESSAGE_BINARY";
9
+ WireFrameType[WireFrameType["TRANSFER_CONTROL"] = 4] = "TRANSFER_CONTROL";
10
+ WireFrameType[WireFrameType["TRANSFER_CHUNK"] = 5] = "TRANSFER_CHUNK";
11
+ WireFrameType[WireFrameType["CRDT_SYNC"] = 6] = "CRDT_SYNC";
12
+ WireFrameType[WireFrameType["HUB_RELAY"] = 7] = "HUB_RELAY";
13
+ })(WireFrameType || (WireFrameType = {}));
14
+ const textEncoder = new TextEncoder();
15
+ const textDecoder = new TextDecoder("utf-8", { fatal: true });
16
+ export const MAX_HEADER_BYTES = 16 * 1024; // 16 KiB header limit
17
+ export const DEFAULT_MAX_TOTAL_FRAME_BYTES = 64 * 1024; // 64 KiB safe WebRTC SCTP baseline
18
+ export const DEFAULT_MAX_FRAME_PAYLOAD_BYTES = 48 * 1024; // 48 KiB payload leaves room for prefix + header within 64 KiB
19
+ export const MAX_DECODE_FRAME_BYTES = 256 * 1024; // 256 KiB max incoming frame guard
20
+ function validateFrameTypeSpecificHeader(frameType, header) {
21
+ if (typeof header.timestamp !== "number" || !Number.isFinite(header.timestamp)) {
22
+ throw new ProtocolValidationError("Wire frame header requires finite numeric timestamp", "header.timestamp");
23
+ }
24
+ if (frameType === WireFrameType.TRANSFER_CHUNK) {
25
+ if (!header.transferId || typeof header.transferId !== "string") {
26
+ throw new ProtocolValidationError("TRANSFER_CHUNK frame requires header.transferId", "header.transferId");
27
+ }
28
+ if (typeof header.byteOffset !== "number" ||
29
+ !Number.isFinite(header.byteOffset) ||
30
+ header.byteOffset < 0) {
31
+ throw new ProtocolValidationError("TRANSFER_CHUNK frame requires non-negative header.byteOffset", "header.byteOffset");
32
+ }
33
+ }
34
+ else if (frameType === WireFrameType.CRDT_SYNC) {
35
+ if (!header.documentId || typeof header.documentId !== "string") {
36
+ throw new ProtocolValidationError("CRDT_SYNC frame requires header.documentId", "header.documentId");
37
+ }
38
+ }
39
+ else if (frameType === WireFrameType.HUB_RELAY) {
40
+ if (!header.targetDeviceId || typeof header.targetDeviceId !== "string") {
41
+ throw new ProtocolValidationError("HUB_RELAY frame requires header.targetDeviceId", "header.targetDeviceId");
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * Binary frame layout:
47
+ * Byte 0: WIRE_MAGIC_BYTE (0xD5)
48
+ * Byte 1: WireFrameType (0x01 .. 0x07)
49
+ * Bytes 2..5: Header byte length (uint32 big-endian)
50
+ * Bytes 6..(6 + headerLen - 1): UTF-8 JSON encoded WireFrameHeader
51
+ * Remaining bytes: Raw binary payload (Uint8Array)
52
+ *
53
+ * totalFrameBytes = WIRE_PREFIX_BYTES (6) + encodedHeaderBytes + payloadBytes
54
+ */
55
+ export function encodeWireFrame(frameType, header, payload = new Uint8Array(0), options) {
56
+ if (frameType < WireFrameType.CONTROL_JSON || frameType > WireFrameType.HUB_RELAY) {
57
+ throw new ProtocolValidationError(`Unknown wire frame type: 0x${Number(frameType).toString(16)}`, "frameType");
58
+ }
59
+ if (!header.messageId || typeof header.messageId !== "string") {
60
+ throw new ProtocolValidationError("WireFrameHeader requires messageId", "header.messageId");
61
+ }
62
+ if (!header.channel || typeof header.channel !== "string") {
63
+ throw new ProtocolValidationError("WireFrameHeader requires channel", "header.channel");
64
+ }
65
+ validateFrameTypeSpecificHeader(frameType, header);
66
+ const headerBytes = textEncoder.encode(JSON.stringify(header));
67
+ if (headerBytes.byteLength > MAX_HEADER_BYTES) {
68
+ throw new ProtocolValidationError(`WireFrameHeader exceeds ${MAX_HEADER_BYTES} bytes`, "header", "MESSAGE_TOO_LARGE");
69
+ }
70
+ const totalLength = WIRE_PREFIX_BYTES + headerBytes.byteLength + payload.byteLength;
71
+ const maxTotal = options?.maxTotalFrameBytes ?? DEFAULT_MAX_TOTAL_FRAME_BYTES;
72
+ if (totalLength > maxTotal) {
73
+ throw new ProtocolValidationError(`Wire frame total size (${totalLength} bytes) exceeds limit (${maxTotal} bytes)`, "frame", "MESSAGE_TOO_LARGE");
74
+ }
75
+ const buffer = new Uint8Array(totalLength);
76
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
77
+ view.setUint8(0, WIRE_MAGIC_BYTE);
78
+ view.setUint8(1, frameType);
79
+ view.setUint32(2, headerBytes.byteLength, false);
80
+ buffer.set(headerBytes, WIRE_PREFIX_BYTES);
81
+ if (payload.byteLength > 0) {
82
+ buffer.set(payload, WIRE_PREFIX_BYTES + headerBytes.byteLength);
83
+ }
84
+ return buffer;
85
+ }
86
+ export function decodeWireFrame(raw, options) {
87
+ const bytes = raw instanceof Uint8Array ? raw : new Uint8Array(raw);
88
+ const maxTotal = options?.maxTotalFrameBytes ?? MAX_DECODE_FRAME_BYTES;
89
+ if (bytes.byteLength > maxTotal) {
90
+ throw new ProtocolValidationError(`Wire frame size (${bytes.byteLength} bytes) exceeds limit (${maxTotal} bytes)`, "frame", "MESSAGE_TOO_LARGE");
91
+ }
92
+ if (bytes.byteLength < WIRE_PREFIX_BYTES) {
93
+ throw new ProtocolValidationError(`Wire frame too short (${bytes.byteLength} bytes, minimum ${WIRE_PREFIX_BYTES})`, "frame");
94
+ }
95
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
96
+ const magic = view.getUint8(0);
97
+ if (magic !== WIRE_MAGIC_BYTE) {
98
+ throw new ProtocolValidationError(`Invalid wire frame magic byte: 0x${magic.toString(16)}`, "magic");
99
+ }
100
+ const frameType = view.getUint8(1);
101
+ if (frameType < WireFrameType.CONTROL_JSON || frameType > WireFrameType.HUB_RELAY) {
102
+ throw new ProtocolValidationError(`Unknown wire frame type: 0x${frameType.toString(16)}`, "frameType");
103
+ }
104
+ const headerLength = view.getUint32(2, false);
105
+ if (headerLength === 0 || headerLength > MAX_HEADER_BYTES || WIRE_PREFIX_BYTES + headerLength > bytes.byteLength) {
106
+ throw new ProtocolValidationError(`Invalid wire frame header length: ${headerLength}`, "headerLength");
107
+ }
108
+ const headerSlice = bytes.subarray(WIRE_PREFIX_BYTES, WIRE_PREFIX_BYTES + headerLength);
109
+ let headerJson;
110
+ try {
111
+ headerJson = textDecoder.decode(headerSlice);
112
+ }
113
+ catch {
114
+ throw new ProtocolValidationError("Invalid UTF-8 in wire frame header", "header");
115
+ }
116
+ let header;
117
+ try {
118
+ header = JSON.parse(headerJson);
119
+ }
120
+ catch {
121
+ throw new ProtocolValidationError("Malformed JSON in wire frame header", "header");
122
+ }
123
+ if (typeof header !== "object" ||
124
+ header === null ||
125
+ typeof header.messageId !== "string" ||
126
+ header.messageId.length === 0 ||
127
+ typeof header.channel !== "string" ||
128
+ header.channel.length === 0) {
129
+ throw new ProtocolValidationError("Wire frame header missing messageId or channel", "header");
130
+ }
131
+ validateFrameTypeSpecificHeader(frameType, header);
132
+ const payload = bytes.subarray(WIRE_PREFIX_BYTES + headerLength);
133
+ return {
134
+ frameType,
135
+ header,
136
+ payload,
137
+ };
138
+ }
139
+ export function encodeJsonPayload(value) {
140
+ return textEncoder.encode(JSON.stringify(value));
141
+ }
142
+ export function decodeJsonPayload(payload) {
143
+ return JSON.parse(textDecoder.decode(payload));
144
+ }
145
+ //# sourceMappingURL=framing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framing.js","sourceRoot":"","sources":["../../src/protocol/framing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from "./envelope.js";
2
+ export * from "./framing.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/protocol/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./envelope.js";
2
+ export * from "./framing.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/protocol/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,132 @@
1
+ {
2
+ "valid": [
3
+ {
4
+ "name": "auth_authenticate_v1",
5
+ "envelope": {
6
+ "protocolVersion": 1,
7
+ "type": "auth.authenticate",
8
+ "requestId": "req-auth-001",
9
+ "payload": {
10
+ "sessionToken": "tok_live_987654321",
11
+ "deviceLabel": "MacBook Pro",
12
+ "capabilities": ["messaging", "files", "crdt"]
13
+ }
14
+ }
15
+ },
16
+ {
17
+ "name": "webrtc_offer_with_generation",
18
+ "envelope": {
19
+ "protocolVersion": 1,
20
+ "type": "webrtc.offer",
21
+ "requestId": "req-offer-01",
22
+ "sessionId": "sess-001",
23
+ "connectionId": "conn-abc-123",
24
+ "generation": 2,
25
+ "spaceId": "space-main",
26
+ "senderDeviceId": "dev-alice",
27
+ "targetDeviceId": "dev-bob",
28
+ "payload": {
29
+ "sdp": "v=0\r\no=- 4611731400430051336 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n",
30
+ "tieBreaker": "dev-alice"
31
+ }
32
+ }
33
+ },
34
+ {
35
+ "name": "webrtc_ice_candidate_v1",
36
+ "envelope": {
37
+ "protocolVersion": 1,
38
+ "type": "webrtc.ice_candidate",
39
+ "connectionId": "conn-abc-123",
40
+ "generation": 2,
41
+ "spaceId": "space-main",
42
+ "senderDeviceId": "dev-alice",
43
+ "targetDeviceId": "dev-bob",
44
+ "payload": {
45
+ "candidate": "candidate:842163049 1 udp 1677729535 192.168.1.10 54321 typ srflx",
46
+ "sdpMid": "0",
47
+ "sdpMLineIndex": 0
48
+ }
49
+ }
50
+ },
51
+ {
52
+ "name": "pairing_awaiting_approval_v1",
53
+ "envelope": {
54
+ "protocolVersion": 1,
55
+ "type": "pairing.awaiting_approval",
56
+ "spaceId": "space-main",
57
+ "targetDeviceId": "dev-alice",
58
+ "payload": {
59
+ "pairingId": "pair-101",
60
+ "claimerDeviceId": "dev-bob",
61
+ "claimerLabel": "Bob's iPad",
62
+ "claimerFingerprint": "sha256:abcdef0123456789",
63
+ "claimerAlgorithm": "ECDSA_P256_SHA256",
64
+ "requestedPermissions": ["connect", "messaging", "files"]
65
+ }
66
+ }
67
+ },
68
+ {
69
+ "name": "revocation_notice_v1",
70
+ "envelope": {
71
+ "protocolVersion": 1,
72
+ "type": "revocation.notice",
73
+ "spaceId": "space-main",
74
+ "payload": {
75
+ "revokedDeviceId": "dev-bob",
76
+ "pairingId": "pair-101",
77
+ "revokedByDeviceId": "dev-alice",
78
+ "revokedAt": 1762956000000,
79
+ "reason": "User revoked device access"
80
+ }
81
+ }
82
+ }
83
+ ],
84
+ "invalid": [
85
+ {
86
+ "name": "wrong_protocol_version",
87
+ "expectedCode": "UNSUPPORTED_PROTOCOL_VERSION",
88
+ "envelope": {
89
+ "protocolVersion": 2,
90
+ "type": "heartbeat.ping",
91
+ "payload": { "clientTime": 1000 }
92
+ }
93
+ },
94
+ {
95
+ "name": "unknown_message_type",
96
+ "expectedCode": "INVALID_ENVELOPE",
97
+ "envelope": {
98
+ "protocolVersion": 1,
99
+ "type": "unknown.custom_event",
100
+ "payload": {}
101
+ }
102
+ },
103
+ {
104
+ "name": "offer_missing_generation",
105
+ "expectedCode": "INVALID_ENVELOPE",
106
+ "envelope": {
107
+ "protocolVersion": 1,
108
+ "type": "webrtc.offer",
109
+ "connectionId": "conn-abc-123",
110
+ "targetDeviceId": "dev-bob",
111
+ "payload": {
112
+ "sdp": "v=0..."
113
+ }
114
+ }
115
+ },
116
+ {
117
+ "name": "negative_generation",
118
+ "expectedCode": "INVALID_ENVELOPE",
119
+ "envelope": {
120
+ "protocolVersion": 1,
121
+ "type": "webrtc.answer",
122
+ "connectionId": "conn-abc-123",
123
+ "generation": -1,
124
+ "targetDeviceId": "dev-bob",
125
+ "payload": {
126
+ "sdp": "v=0..."
127
+ }
128
+ }
129
+ }
130
+ ]
131
+ }
132
+
package/package.json CHANGED
@@ -1,6 +1,53 @@
1
1
  {
2
2
  "name": "dropspace",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "End-to-end encrypted peer-to-peer rooms, resumable file transfers, and Automerge CRDT sync over WebRTC & WebSocket.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "dropspace": "./dist/cli.js"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "fixtures",
15
+ "README.md"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ },
22
+ "./client": {
23
+ "types": "./dist/client/index.d.ts",
24
+ "import": "./dist/client/index.js"
25
+ },
26
+ "./files": {
27
+ "types": "./dist/files/index.d.ts",
28
+ "import": "./dist/files/index.js"
29
+ },
30
+ "./automerge": {
31
+ "types": "./dist/automerge/index.d.ts",
32
+ "import": "./dist/automerge/index.js"
33
+ },
34
+ "./protocol": {
35
+ "types": "./dist/protocol/index.d.ts",
36
+ "import": "./dist/protocol/index.js"
37
+ },
38
+ "./fixtures/envelopes.json": "./fixtures/envelopes.json"
39
+ },
40
+ "dependencies": {
41
+ "@automerge/automerge": "^2.2.8",
42
+ "ws": "^8.18.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^20.17.0",
46
+ "@types/ws": "^8.5.13"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.json",
50
+ "typecheck": "tsc -p tsconfig.json --noEmit"
51
+ }
52
+ }
53
+