dropspace 0.0.0-stage → 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 +17 -2
- package/dist/automerge/index.d.ts +103 -0
- package/dist/automerge/index.d.ts.map +1 -0
- package/dist/automerge/index.js +394 -0
- package/dist/automerge/index.js.map +1 -0
- package/dist/client/channel.d.ts +131 -0
- package/dist/client/channel.d.ts.map +1 -0
- package/dist/client/channel.js +566 -0
- package/dist/client/channel.js.map +1 -0
- package/dist/client/client.d.ts +310 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +1176 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/events.d.ts +14 -0
- package/dist/client/events.d.ts.map +1 -0
- package/dist/client/events.js +71 -0
- package/dist/client/events.js.map +1 -0
- package/dist/client/identity.d.ts +89 -0
- package/dist/client/identity.d.ts.map +1 -0
- package/dist/client/identity.js +274 -0
- package/dist/client/identity.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/peer-connection.d.ts +182 -0
- package/dist/client/peer-connection.d.ts.map +1 -0
- package/dist/client/peer-connection.js +593 -0
- package/dist/client/peer-connection.js.map +1 -0
- package/dist/client/peer-selection.d.ts +70 -0
- package/dist/client/peer-selection.d.ts.map +1 -0
- package/dist/client/peer-selection.js +193 -0
- package/dist/client/peer-selection.js.map +1 -0
- package/dist/client/storage.d.ts +118 -0
- package/dist/client/storage.d.ts.map +1 -0
- package/dist/client/storage.js +463 -0
- package/dist/client/storage.js.map +1 -0
- package/dist/files/index.d.ts +136 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +701 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/sha256.d.ts +24 -0
- package/dist/files/sha256.d.ts.map +1 -0
- package/dist/files/sha256.js +133 -0
- package/dist/files/sha256.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/envelope.d.ts +61 -0
- package/dist/protocol/envelope.d.ts.map +1 -0
- package/dist/protocol/envelope.js +260 -0
- package/dist/protocol/envelope.js.map +1 -0
- package/dist/protocol/framing.d.ts +56 -0
- package/dist/protocol/framing.d.ts.map +1 -0
- package/dist/protocol/framing.js +93 -0
- package/dist/protocol/framing.js.map +1 -0
- package/dist/protocol/index.d.ts +3 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +3 -0
- package/dist/protocol/index.js.map +1 -0
- package/fixtures/envelopes.json +132 -0
- package/package.json +43 -4
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare const WIRE_MAGIC_BYTE = 213;
|
|
2
|
+
export declare enum WireFrameType {
|
|
3
|
+
CONTROL_JSON = 1,
|
|
4
|
+
MESSAGE_JSON = 2,
|
|
5
|
+
MESSAGE_BINARY = 3,
|
|
6
|
+
TRANSFER_CONTROL = 4,
|
|
7
|
+
TRANSFER_CHUNK = 5,
|
|
8
|
+
CRDT_SYNC = 6,
|
|
9
|
+
HUB_RELAY = 7
|
|
10
|
+
}
|
|
11
|
+
export type AckSemantics = "received" | "persisted" | "processed";
|
|
12
|
+
export interface WireFrameHeader {
|
|
13
|
+
messageId: string;
|
|
14
|
+
channel: string;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
chunkIndex?: number;
|
|
17
|
+
totalChunks?: number;
|
|
18
|
+
totalByteLength?: number;
|
|
19
|
+
ackRequired?: boolean;
|
|
20
|
+
ackMode?: AckSemantics;
|
|
21
|
+
correlationId?: string;
|
|
22
|
+
/** File transfer specific fields */
|
|
23
|
+
transferId?: string;
|
|
24
|
+
byteOffset?: number;
|
|
25
|
+
chunkHash?: string;
|
|
26
|
+
/** CRDT specific fields */
|
|
27
|
+
documentId?: string;
|
|
28
|
+
/** Hub relay specific fields */
|
|
29
|
+
sourceDeviceId?: string;
|
|
30
|
+
targetDeviceId?: string;
|
|
31
|
+
spaceId?: string;
|
|
32
|
+
hopCount?: number;
|
|
33
|
+
maxHops?: number;
|
|
34
|
+
/** Custom metadata */
|
|
35
|
+
meta?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
export interface DecodedWireFrame {
|
|
38
|
+
frameType: WireFrameType;
|
|
39
|
+
header: WireFrameHeader;
|
|
40
|
+
payload: Uint8Array;
|
|
41
|
+
}
|
|
42
|
+
export declare const MAX_HEADER_BYTES: number;
|
|
43
|
+
export declare const DEFAULT_MAX_FRAME_PAYLOAD_BYTES: number;
|
|
44
|
+
/**
|
|
45
|
+
* Binary frame layout:
|
|
46
|
+
* Byte 0: WIRE_MAGIC_BYTE (0xD5)
|
|
47
|
+
* Byte 1: WireFrameType (0x01 .. 0x07)
|
|
48
|
+
* Bytes 2..5: Header byte length (uint32 big-endian)
|
|
49
|
+
* Bytes 6..(6 + headerLen - 1): UTF-8 JSON encoded WireFrameHeader
|
|
50
|
+
* Remaining bytes: Raw binary payload (Uint8Array)
|
|
51
|
+
*/
|
|
52
|
+
export declare function encodeWireFrame(frameType: WireFrameType, header: WireFrameHeader, payload?: Uint8Array): Uint8Array;
|
|
53
|
+
export declare function decodeWireFrame(raw: Uint8Array | ArrayBuffer): DecodedWireFrame;
|
|
54
|
+
export declare function encodeJsonPayload(value: unknown): Uint8Array;
|
|
55
|
+
export declare function decodeJsonPayload<T = unknown>(payload: Uint8Array): T;
|
|
56
|
+
//# 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;AAEpC,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;AAKD,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAC1C,eAAO,MAAM,+BAA+B,QAAY,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,UAA8B,GACtC,UAAU,CA+BZ;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,WAAW,GAAG,gBAAgB,CA4D/E;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,93 @@
|
|
|
1
|
+
import { ProtocolValidationError } from "./envelope.js";
|
|
2
|
+
export const WIRE_MAGIC_BYTE = 0xd5;
|
|
3
|
+
export var WireFrameType;
|
|
4
|
+
(function (WireFrameType) {
|
|
5
|
+
WireFrameType[WireFrameType["CONTROL_JSON"] = 1] = "CONTROL_JSON";
|
|
6
|
+
WireFrameType[WireFrameType["MESSAGE_JSON"] = 2] = "MESSAGE_JSON";
|
|
7
|
+
WireFrameType[WireFrameType["MESSAGE_BINARY"] = 3] = "MESSAGE_BINARY";
|
|
8
|
+
WireFrameType[WireFrameType["TRANSFER_CONTROL"] = 4] = "TRANSFER_CONTROL";
|
|
9
|
+
WireFrameType[WireFrameType["TRANSFER_CHUNK"] = 5] = "TRANSFER_CHUNK";
|
|
10
|
+
WireFrameType[WireFrameType["CRDT_SYNC"] = 6] = "CRDT_SYNC";
|
|
11
|
+
WireFrameType[WireFrameType["HUB_RELAY"] = 7] = "HUB_RELAY";
|
|
12
|
+
})(WireFrameType || (WireFrameType = {}));
|
|
13
|
+
const textEncoder = new TextEncoder();
|
|
14
|
+
const textDecoder = new TextDecoder();
|
|
15
|
+
export const MAX_HEADER_BYTES = 16 * 1024; // 16 KiB header limit
|
|
16
|
+
export const DEFAULT_MAX_FRAME_PAYLOAD_BYTES = 64 * 1024; // 64 KiB safe WebRTC DataChannel chunk size
|
|
17
|
+
/**
|
|
18
|
+
* Binary frame layout:
|
|
19
|
+
* Byte 0: WIRE_MAGIC_BYTE (0xD5)
|
|
20
|
+
* Byte 1: WireFrameType (0x01 .. 0x07)
|
|
21
|
+
* Bytes 2..5: Header byte length (uint32 big-endian)
|
|
22
|
+
* Bytes 6..(6 + headerLen - 1): UTF-8 JSON encoded WireFrameHeader
|
|
23
|
+
* Remaining bytes: Raw binary payload (Uint8Array)
|
|
24
|
+
*/
|
|
25
|
+
export function encodeWireFrame(frameType, header, payload = new Uint8Array(0)) {
|
|
26
|
+
if (!header.messageId || typeof header.messageId !== "string") {
|
|
27
|
+
throw new ProtocolValidationError("WireFrameHeader requires messageId", "header.messageId");
|
|
28
|
+
}
|
|
29
|
+
if (!header.channel || typeof header.channel !== "string") {
|
|
30
|
+
throw new ProtocolValidationError("WireFrameHeader requires channel", "header.channel");
|
|
31
|
+
}
|
|
32
|
+
const headerBytes = textEncoder.encode(JSON.stringify(header));
|
|
33
|
+
if (headerBytes.byteLength > MAX_HEADER_BYTES) {
|
|
34
|
+
throw new ProtocolValidationError(`WireFrameHeader exceeds ${MAX_HEADER_BYTES} bytes`, "header", "MESSAGE_TOO_LARGE");
|
|
35
|
+
}
|
|
36
|
+
const totalLength = 6 + headerBytes.byteLength + payload.byteLength;
|
|
37
|
+
const buffer = new Uint8Array(totalLength);
|
|
38
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
39
|
+
view.setUint8(0, WIRE_MAGIC_BYTE);
|
|
40
|
+
view.setUint8(1, frameType);
|
|
41
|
+
view.setUint32(2, headerBytes.byteLength, false);
|
|
42
|
+
buffer.set(headerBytes, 6);
|
|
43
|
+
if (payload.byteLength > 0) {
|
|
44
|
+
buffer.set(payload, 6 + headerBytes.byteLength);
|
|
45
|
+
}
|
|
46
|
+
return buffer;
|
|
47
|
+
}
|
|
48
|
+
export function decodeWireFrame(raw) {
|
|
49
|
+
const bytes = raw instanceof Uint8Array ? raw : new Uint8Array(raw);
|
|
50
|
+
if (bytes.byteLength < 6) {
|
|
51
|
+
throw new ProtocolValidationError(`Wire frame too short (${bytes.byteLength} bytes, minimum 6)`, "frame");
|
|
52
|
+
}
|
|
53
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
54
|
+
const magic = view.getUint8(0);
|
|
55
|
+
if (magic !== WIRE_MAGIC_BYTE) {
|
|
56
|
+
throw new ProtocolValidationError(`Invalid wire frame magic byte: 0x${magic.toString(16)}`, "magic");
|
|
57
|
+
}
|
|
58
|
+
const frameType = view.getUint8(1);
|
|
59
|
+
if (frameType < WireFrameType.CONTROL_JSON || frameType > WireFrameType.HUB_RELAY) {
|
|
60
|
+
throw new ProtocolValidationError(`Unknown wire frame type: 0x${frameType.toString(16)}`, "frameType");
|
|
61
|
+
}
|
|
62
|
+
const headerLength = view.getUint32(2, false);
|
|
63
|
+
if (headerLength > MAX_HEADER_BYTES || 6 + headerLength > bytes.byteLength) {
|
|
64
|
+
throw new ProtocolValidationError(`Invalid wire frame header length: ${headerLength}`, "headerLength");
|
|
65
|
+
}
|
|
66
|
+
const headerSlice = bytes.subarray(6, 6 + headerLength);
|
|
67
|
+
let header;
|
|
68
|
+
try {
|
|
69
|
+
header = JSON.parse(textDecoder.decode(headerSlice));
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
throw new ProtocolValidationError("Malformed JSON in wire frame header", "header");
|
|
73
|
+
}
|
|
74
|
+
if (typeof header !== "object" ||
|
|
75
|
+
header === null ||
|
|
76
|
+
typeof header.messageId !== "string" ||
|
|
77
|
+
typeof header.channel !== "string") {
|
|
78
|
+
throw new ProtocolValidationError("Wire frame header missing messageId or channel", "header");
|
|
79
|
+
}
|
|
80
|
+
const payload = bytes.subarray(6 + headerLength);
|
|
81
|
+
return {
|
|
82
|
+
frameType,
|
|
83
|
+
header,
|
|
84
|
+
payload,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export function encodeJsonPayload(value) {
|
|
88
|
+
return textEncoder.encode(JSON.stringify(value));
|
|
89
|
+
}
|
|
90
|
+
export function decodeJsonPayload(payload) {
|
|
91
|
+
return JSON.parse(textDecoder.decode(payload));
|
|
92
|
+
}
|
|
93
|
+
//# 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 @@
|
|
|
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 @@
|
|
|
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,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dropspace",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
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
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"fixtures",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./client": {
|
|
20
|
+
"types": "./dist/client/index.d.ts",
|
|
21
|
+
"import": "./dist/client/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./files": {
|
|
24
|
+
"types": "./dist/files/index.d.ts",
|
|
25
|
+
"import": "./dist/files/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./automerge": {
|
|
28
|
+
"types": "./dist/automerge/index.d.ts",
|
|
29
|
+
"import": "./dist/automerge/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./protocol": {
|
|
32
|
+
"types": "./dist/protocol/index.d.ts",
|
|
33
|
+
"import": "./dist/protocol/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./fixtures/envelopes.json": "./fixtures/envelopes.json"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@automerge/automerge": "^2.2.8"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|