@peers-app/peers-sdk 0.14.0 → 0.15.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/dist/context/data-context.d.ts +4 -4
- package/dist/context/data-context.js +1 -1
- package/dist/context/index.d.ts +3 -3
- package/dist/context/index.js +4 -0
- package/dist/context/user-context-singleton.js +13 -14
- package/dist/context/user-context.d.ts +4 -4
- package/dist/context/user-context.js +48 -31
- package/dist/data/assistants.d.ts +1 -1
- package/dist/data/assistants.js +35 -24
- package/dist/data/change-tracking.d.ts +8 -8
- package/dist/data/change-tracking.js +45 -39
- package/dist/data/channels.js +5 -5
- package/dist/data/data-locks.d.ts +2 -2
- package/dist/data/data-locks.js +21 -23
- package/dist/data/data-locks.test.js +73 -75
- package/dist/data/device-sync-info.d.ts +1 -1
- package/dist/data/device-sync-info.js +4 -4
- package/dist/data/devices.d.ts +1 -1
- package/dist/data/devices.js +9 -12
- package/dist/data/embeddings.js +14 -11
- package/dist/data/files/file-read-stream.d.ts +2 -2
- package/dist/data/files/file-read-stream.js +23 -14
- package/dist/data/files/file-write-stream.d.ts +2 -2
- package/dist/data/files/file-write-stream.js +8 -8
- package/dist/data/files/file.types.d.ts +2 -2
- package/dist/data/files/file.types.js +17 -11
- package/dist/data/files/files.d.ts +6 -6
- package/dist/data/files/files.js +17 -19
- package/dist/data/files/files.test.js +213 -214
- package/dist/data/files/index.d.ts +4 -4
- package/dist/data/files/index.js +4 -4
- package/dist/data/group-member-roles.js +2 -2
- package/dist/data/group-members.d.ts +5 -5
- package/dist/data/group-members.js +27 -18
- package/dist/data/group-members.test.js +73 -73
- package/dist/data/group-permissions.d.ts +3 -3
- package/dist/data/group-permissions.js +13 -11
- package/dist/data/group-share.d.ts +2 -2
- package/dist/data/group-share.js +29 -24
- package/dist/data/groups.d.ts +4 -4
- package/dist/data/groups.js +27 -19
- package/dist/data/groups.test.js +44 -44
- package/dist/data/index.d.ts +6 -6
- package/dist/data/index.js +6 -6
- package/dist/data/knowledge/peer-types.js +9 -9
- package/dist/data/messages.d.ts +5 -5
- package/dist/data/messages.js +43 -30
- package/dist/data/orm/client-proxy.data-source.d.ts +4 -4
- package/dist/data/orm/client-proxy.data-source.js +10 -12
- package/dist/data/orm/cursor.d.ts +1 -1
- package/dist/data/orm/cursor.js +2 -2
- package/dist/data/orm/cursor.test.js +92 -93
- package/dist/data/orm/data-query.d.ts +3 -3
- package/dist/data/orm/data-query.js +24 -18
- package/dist/data/orm/data-query.mongo.d.ts +1 -1
- package/dist/data/orm/data-query.mongo.js +49 -51
- package/dist/data/orm/data-query.mongo.test.js +173 -204
- package/dist/data/orm/data-query.sqlite.d.ts +1 -1
- package/dist/data/orm/data-query.sqlite.js +84 -73
- package/dist/data/orm/data-query.sqlite.test.js +164 -176
- package/dist/data/orm/data-query.test.js +216 -224
- package/dist/data/orm/decorators.js +3 -3
- package/dist/data/orm/dependency-injection.test.js +53 -56
- package/dist/data/orm/doc.d.ts +4 -4
- package/dist/data/orm/doc.js +17 -21
- package/dist/data/orm/event-registry.d.ts +1 -1
- package/dist/data/orm/event-registry.test.js +16 -16
- package/dist/data/orm/factory.d.ts +2 -2
- package/dist/data/orm/factory.js +33 -33
- package/dist/data/orm/index.d.ts +10 -10
- package/dist/data/orm/index.js +10 -10
- package/dist/data/orm/multi-cursors.d.ts +1 -1
- package/dist/data/orm/multi-cursors.js +6 -6
- package/dist/data/orm/multi-cursors.test.js +152 -144
- package/dist/data/orm/sql.data-source.d.ts +7 -7
- package/dist/data/orm/sql.data-source.js +88 -93
- package/dist/data/orm/sql.data-source.test.js +109 -101
- package/dist/data/orm/subscribable.data-source.d.ts +4 -4
- package/dist/data/orm/subscribable.data-source.js +5 -5
- package/dist/data/orm/table-container-events.test.js +34 -26
- package/dist/data/orm/table-container.d.ts +6 -6
- package/dist/data/orm/table-container.js +33 -21
- package/dist/data/orm/table-container.test.js +64 -53
- package/dist/data/orm/table-definitions.system.d.ts +3 -3
- package/dist/data/orm/table-definitions.system.js +3 -3
- package/dist/data/orm/table-definitions.type.d.ts +5 -5
- package/dist/data/orm/table-dependencies.d.ts +2 -2
- package/dist/data/orm/table.d.ts +5 -5
- package/dist/data/orm/table.event-source.test.js +105 -115
- package/dist/data/orm/table.js +35 -34
- package/dist/data/orm/types.d.ts +3 -3
- package/dist/data/orm/types.js +26 -25
- package/dist/data/orm/types.test.js +166 -92
- package/dist/data/package-permissions.d.ts +1 -1
- package/dist/data/package-permissions.js +2 -2
- package/dist/data/package-version-permissions.d.ts +1 -1
- package/dist/data/package-version-permissions.js +2 -2
- package/dist/data/package-versions.d.ts +9 -9
- package/dist/data/package-versions.js +47 -33
- package/dist/data/packages.d.ts +2 -2
- package/dist/data/packages.js +36 -18
- package/dist/data/packages.utils.d.ts +2 -2
- package/dist/data/packages.utils.js +4 -4
- package/dist/data/persistent-vars.d.ts +15 -15
- package/dist/data/persistent-vars.js +165 -154
- package/dist/data/table-definitions-table.d.ts +5 -5
- package/dist/data/table-definitions-table.js +13 -12
- package/dist/data/tool-tests.js +6 -6
- package/dist/data/tools.js +29 -19
- package/dist/data/user-permissions.d.ts +1 -1
- package/dist/data/user-permissions.js +5 -5
- package/dist/data/user-permissions.test.js +90 -88
- package/dist/data/user-trust-levels.js +10 -10
- package/dist/data/users.d.ts +4 -4
- package/dist/data/users.js +16 -15
- package/dist/data/voice-messages.d.ts +2 -2
- package/dist/data/voice-messages.js +13 -13
- package/dist/data/welcome-modal.pvar.js +3 -1
- package/dist/data/workflow-logs.js +26 -18
- package/dist/data/workflow-runs.d.ts +6 -6
- package/dist/data/workflow-runs.js +70 -44
- package/dist/data/workflows.d.ts +2 -2
- package/dist/data/workflows.js +7 -9
- package/dist/device/binary-peer-connection-v2.d.ts +7 -7
- package/dist/device/binary-peer-connection-v2.js +32 -28
- package/dist/device/binary-peer-connection-v2.test.js +80 -67
- package/dist/device/binary-peer-connection.d.ts +7 -7
- package/dist/device/binary-peer-connection.js +29 -28
- package/dist/device/binary-peer-connection.test.js +35 -31
- package/dist/device/connection.d.ts +5 -5
- package/dist/device/connection.js +59 -48
- package/dist/device/connection.test.js +74 -68
- package/dist/device/device-election.d.ts +2 -2
- package/dist/device/device-election.js +25 -20
- package/dist/device/device-election.test.js +35 -36
- package/dist/device/device.d.ts +2 -2
- package/dist/device/device.js +10 -4
- package/dist/device/device.test.js +16 -17
- package/dist/device/get-trust-level-fn.d.ts +2 -2
- package/dist/device/get-trust-level-fn.js +22 -11
- package/dist/device/get-trust-level-fn.test.js +58 -58
- package/dist/device/socket-io-binary-peer.d.ts +1 -1
- package/dist/device/socket-io-binary-peer.js +16 -13
- package/dist/device/socket.type.d.ts +2 -2
- package/dist/device/streamed-socket.d.ts +2 -2
- package/dist/device/streamed-socket.js +8 -8
- package/dist/device/streamed-socket.test.js +40 -40
- package/dist/device/tx-encoding.test.js +77 -77
- package/dist/events.d.ts +1 -1
- package/dist/events.js +5 -2
- package/dist/group-invite/group-invite.js +110 -19
- package/dist/group-invite/group-invite.pvars.d.ts +2 -2
- package/dist/group-invite/group-invite.pvars.js +21 -13
- package/dist/group-invite/group-invite.types.d.ts +1 -1
- package/dist/group-invite/index.d.ts +3 -3
- package/dist/group-invite/index.js +1 -1
- package/dist/index.d.ts +25 -24
- package/dist/index.js +30 -25
- package/dist/keys.d.ts +3 -3
- package/dist/keys.js +31 -30
- package/dist/keys.test.js +69 -61
- package/dist/logging/console-logger.d.ts +1 -1
- package/dist/logging/console-logger.js +35 -40
- package/dist/logging/console-logger.test.js +115 -115
- package/dist/logging/console-logs.table.d.ts +3 -3
- package/dist/logging/console-logs.table.js +28 -23
- package/dist/mentions.js +16 -12
- package/dist/observable.d.ts +2 -2
- package/dist/observable.js +15 -9
- package/dist/observable.test.js +47 -47
- package/dist/package-loader/get-require.js +3 -4
- package/dist/package-loader/package-loader.d.ts +2 -2
- package/dist/package-loader/package-loader.js +52 -34
- package/dist/peers-ui/peers-ui.d.ts +2 -2
- package/dist/peers-ui/peers-ui.js +2 -4
- package/dist/peers-ui/peers-ui.types.d.ts +3 -3
- package/dist/peers-ui/peers-ui.types.js +0 -1
- package/dist/rpc-types.d.ts +61 -59
- package/dist/rpc-types.js +61 -55
- package/dist/serial-json.d.ts +1 -1
- package/dist/serial-json.js +50 -43
- package/dist/serial-json.test.js +22 -22
- package/dist/system-ids.js +8 -8
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/tools-factory.d.ts +1 -1
- package/dist/tools/tools-factory.js +2 -2
- package/dist/types/assistant-runner-args.d.ts +3 -3
- package/dist/types/peer-device.d.ts +1 -1
- package/dist/types/peers-package.d.ts +3 -3
- package/dist/types/workflow-logger.d.ts +1 -1
- package/dist/types/workflow-run-context.d.ts +4 -4
- package/dist/types/workflow.d.ts +4 -4
- package/dist/types/workflow.js +27 -14
- package/dist/types/zod-types.d.ts +2 -1
- package/dist/types/zod-types.js +9 -3
- package/dist/user-connect/connection-code.d.ts +1 -1
- package/dist/user-connect/connection-code.js +7 -7
- package/dist/user-connect/connection-code.test.js +106 -106
- package/dist/user-connect/index.d.ts +3 -3
- package/dist/user-connect/index.js +1 -1
- package/dist/user-connect/user-connect.pvars.js +13 -11
- package/dist/user-connect/user-connect.types.d.ts +3 -3
- package/dist/users.query.d.ts +2 -2
- package/dist/users.query.js +40 -30
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +34 -32
- package/dist/utils.test.js +12 -8
- package/dist/workflow-log-formatter.d.ts +1 -1
- package/dist/workflow-log-formatter.js +17 -18
- package/package.json +14 -8
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tx_encoding_1 = require("./tx-encoding");
|
|
4
3
|
const msgpack_1 = require("@msgpack/msgpack");
|
|
5
4
|
const serial_json_1 = require("../serial-json");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const tx_encoding_1 = require("./tx-encoding");
|
|
6
|
+
describe("tx-encode-decode", () => {
|
|
7
|
+
describe("txEncode and txDecode", () => {
|
|
8
|
+
it("should encode and decode simple objects", () => {
|
|
9
9
|
const testObj = {
|
|
10
|
-
name:
|
|
10
|
+
name: "test",
|
|
11
11
|
number: 42,
|
|
12
12
|
bool: true,
|
|
13
|
-
str:
|
|
13
|
+
str: "hello world",
|
|
14
14
|
};
|
|
15
15
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
16
16
|
expect(encoded).toBeInstanceOf(Uint8Array);
|
|
@@ -18,51 +18,51 @@ describe('tx-encode-decode', () => {
|
|
|
18
18
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
19
19
|
expect(decoded).toEqual(testObj);
|
|
20
20
|
});
|
|
21
|
-
it(
|
|
22
|
-
const testArray = [1, 2, 3,
|
|
21
|
+
it("should encode and decode arrays", () => {
|
|
22
|
+
const testArray = [1, 2, 3, "four", { five: 5 }];
|
|
23
23
|
const encoded = (0, tx_encoding_1.txEncode)(testArray);
|
|
24
24
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
25
25
|
expect(decoded).toEqual(testArray);
|
|
26
26
|
});
|
|
27
|
-
it(
|
|
27
|
+
it("should encode and decode nested objects", () => {
|
|
28
28
|
const testObj = {
|
|
29
29
|
level1: {
|
|
30
30
|
level2: {
|
|
31
31
|
level3: {
|
|
32
|
-
value:
|
|
33
|
-
number: 123
|
|
32
|
+
value: "deep nested value",
|
|
33
|
+
number: 123,
|
|
34
34
|
},
|
|
35
|
-
array: [1, 2, 3]
|
|
36
|
-
}
|
|
37
|
-
}
|
|
35
|
+
array: [1, 2, 3],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
38
|
};
|
|
39
39
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
40
40
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
41
41
|
expect(decoded).toEqual(testObj);
|
|
42
42
|
});
|
|
43
|
-
it(
|
|
43
|
+
it("should encode and decode special types (dates, etc.)", () => {
|
|
44
44
|
const testObj = {
|
|
45
|
-
date: new Date(
|
|
45
|
+
date: new Date("2023-01-01T00:00:00.000Z"),
|
|
46
46
|
nan: NaN,
|
|
47
47
|
infinity: Infinity,
|
|
48
48
|
negInfinity: -Infinity,
|
|
49
49
|
undef: undefined,
|
|
50
|
-
nullVal: null
|
|
50
|
+
nullVal: null,
|
|
51
51
|
};
|
|
52
52
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
53
53
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
54
54
|
expect(decoded.date).toBeInstanceOf(Date);
|
|
55
|
-
expect(decoded.date.toISOString()).toBe(
|
|
55
|
+
expect(decoded.date.toISOString()).toBe("2023-01-01T00:00:00.000Z");
|
|
56
56
|
expect(Number.isNaN(decoded.nan)).toBe(true);
|
|
57
57
|
expect(decoded.infinity).toBe(Infinity);
|
|
58
58
|
expect(decoded.negInfinity).toBe(-Infinity);
|
|
59
59
|
expect(decoded.undef).toBeUndefined();
|
|
60
60
|
expect(decoded.nullVal).toBeNull();
|
|
61
61
|
});
|
|
62
|
-
it(
|
|
62
|
+
it("should encode and decode Uint8Array", () => {
|
|
63
63
|
const testObj = {
|
|
64
64
|
data: new Uint8Array([72, 101, 108, 108, 111]),
|
|
65
|
-
metadata: { size: 5 }
|
|
65
|
+
metadata: { size: 5 },
|
|
66
66
|
};
|
|
67
67
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
68
68
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
@@ -70,37 +70,37 @@ describe('tx-encode-decode', () => {
|
|
|
70
70
|
expect(decoded.data).toEqual(testObj.data);
|
|
71
71
|
expect(decoded.metadata).toEqual(testObj.metadata);
|
|
72
72
|
});
|
|
73
|
-
it(
|
|
73
|
+
it("should encode and decode Buffer", () => {
|
|
74
74
|
const testObj = {
|
|
75
|
-
buffer: Buffer.from(
|
|
76
|
-
name:
|
|
75
|
+
buffer: Buffer.from("Hello Buffer"),
|
|
76
|
+
name: "test",
|
|
77
77
|
};
|
|
78
78
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
79
79
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
80
80
|
expect(Buffer.isBuffer(decoded.buffer)).toBe(true);
|
|
81
81
|
expect(decoded.buffer).toEqual(testObj.buffer);
|
|
82
|
-
expect(decoded.name).toBe(
|
|
82
|
+
expect(decoded.name).toBe("test");
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
|
-
describe(
|
|
86
|
-
it(
|
|
87
|
-
const smallObj = { message:
|
|
85
|
+
describe("compression threshold", () => {
|
|
86
|
+
it("should not compress small payloads (< 1024 bytes)", () => {
|
|
87
|
+
const smallObj = { message: "small" };
|
|
88
88
|
const encoded = (0, tx_encoding_1.txEncode)(smallObj);
|
|
89
89
|
// First byte is the flag
|
|
90
90
|
expect(encoded[0]).toBe(0); // flag = 0 means not compressed
|
|
91
91
|
});
|
|
92
|
-
it(
|
|
92
|
+
it("should compress large payloads (> 1024 bytes)", () => {
|
|
93
93
|
// Create an object that will exceed 8KB when msgpack-encoded
|
|
94
94
|
// msgpack is more compact than JSON, so we need significantly more data
|
|
95
95
|
// A string of 20,000 chars is roughly 20KB in JSON, but msgpack uses length prefix + bytes
|
|
96
96
|
// So we need even more to ensure msgpack encoding exceeds 8KB
|
|
97
97
|
const largeObj = {
|
|
98
|
-
data:
|
|
98
|
+
data: "x".repeat(30000),
|
|
99
99
|
array: Array.from({ length: 1000 }, (_, i) => ({
|
|
100
100
|
id: i,
|
|
101
101
|
value: `item ${i} with some extra text to make it larger and ensure we exceed the threshold`,
|
|
102
|
-
nested: { prop: `nested value ${i}` }
|
|
103
|
-
}))
|
|
102
|
+
nested: { prop: `nested value ${i}` },
|
|
103
|
+
})),
|
|
104
104
|
};
|
|
105
105
|
const encoded = (0, tx_encoding_1.txEncode)(largeObj);
|
|
106
106
|
// Verify the encoded size (without flag byte) exceeds 8KB threshold
|
|
@@ -112,12 +112,12 @@ describe('tx-encode-decode', () => {
|
|
|
112
112
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
113
113
|
expect(decoded).toEqual(largeObj);
|
|
114
114
|
});
|
|
115
|
-
it(
|
|
115
|
+
it("should have smaller encoded size for large compressible data", () => {
|
|
116
116
|
// Create data that exceeds 8KB when msgpack-encoded and compresses well
|
|
117
117
|
// Use data with some repetition but also enough variety to ensure msgpack size is large
|
|
118
118
|
const largeRepetitiveObj = {
|
|
119
|
-
data:
|
|
120
|
-
values: Array.from({ length: 5000 }, (_, i) => `item ${i} with some text that repeats to create compressible data pattern`)
|
|
119
|
+
data: "repeat ".repeat(10000), // Highly repetitive string - will compress well
|
|
120
|
+
values: Array.from({ length: 5000 }, (_, i) => `item ${i} with some text that repeats to create compressible data pattern`),
|
|
121
121
|
};
|
|
122
122
|
// First, verify the msgpack-encoded size exceeds 8KB threshold
|
|
123
123
|
const noCycles = (0, serial_json_1.toJSON)(largeRepetitiveObj);
|
|
@@ -134,98 +134,98 @@ describe('tx-encode-decode', () => {
|
|
|
134
134
|
expect(decoded).toEqual(largeRepetitiveObj);
|
|
135
135
|
});
|
|
136
136
|
});
|
|
137
|
-
describe(
|
|
138
|
-
it(
|
|
137
|
+
describe("error handling", () => {
|
|
138
|
+
it("should throw error on empty payload", () => {
|
|
139
139
|
const emptyPayload = new Uint8Array(0);
|
|
140
|
-
expect(() => (0, tx_encoding_1.txDecode)(emptyPayload)).toThrow(
|
|
140
|
+
expect(() => (0, tx_encoding_1.txDecode)(emptyPayload)).toThrow("Empty payload");
|
|
141
141
|
});
|
|
142
|
-
it(
|
|
142
|
+
it("should throw error on unknown flag", () => {
|
|
143
143
|
// Create a payload with an invalid flag (2)
|
|
144
144
|
const invalidPayload = new Uint8Array([2, 0, 0, 0]);
|
|
145
|
-
expect(() => (0, tx_encoding_1.txDecode)(invalidPayload)).toThrow(
|
|
145
|
+
expect(() => (0, tx_encoding_1.txDecode)(invalidPayload)).toThrow("Unknown tx flag: 2");
|
|
146
146
|
});
|
|
147
|
-
it(
|
|
147
|
+
it("should throw error on unknown flag (255)", () => {
|
|
148
148
|
const invalidPayload = new Uint8Array([255, 0, 0, 0]);
|
|
149
|
-
expect(() => (0, tx_encoding_1.txDecode)(invalidPayload)).toThrow(
|
|
149
|
+
expect(() => (0, tx_encoding_1.txDecode)(invalidPayload)).toThrow("Unknown tx flag: 255");
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
|
-
describe(
|
|
153
|
-
it(
|
|
152
|
+
describe("round-trip consistency", () => {
|
|
153
|
+
it("should handle empty objects", () => {
|
|
154
154
|
const emptyObj = {};
|
|
155
155
|
const encoded = (0, tx_encoding_1.txEncode)(emptyObj);
|
|
156
156
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
157
157
|
expect(decoded).toEqual(emptyObj);
|
|
158
158
|
});
|
|
159
|
-
it(
|
|
159
|
+
it("should handle empty arrays", () => {
|
|
160
160
|
const emptyArray = [];
|
|
161
161
|
const encoded = (0, tx_encoding_1.txEncode)(emptyArray);
|
|
162
162
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
163
163
|
expect(decoded).toEqual(emptyArray);
|
|
164
164
|
});
|
|
165
|
-
it(
|
|
165
|
+
it("should handle strings with special characters", () => {
|
|
166
166
|
const testObj = {
|
|
167
|
-
emoji:
|
|
168
|
-
unicode:
|
|
169
|
-
special:
|
|
170
|
-
quotes: 'He said "hello"'
|
|
167
|
+
emoji: "🚀🎉",
|
|
168
|
+
unicode: "Hello 世界",
|
|
169
|
+
special: "line1\nline2\ttab",
|
|
170
|
+
quotes: 'He said "hello"',
|
|
171
171
|
};
|
|
172
172
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
173
173
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
174
174
|
expect(decoded).toEqual(testObj);
|
|
175
175
|
});
|
|
176
|
-
it(
|
|
176
|
+
it("should handle very large numbers", () => {
|
|
177
177
|
const testObj = {
|
|
178
178
|
maxSafeInt: Number.MAX_SAFE_INTEGER,
|
|
179
179
|
minSafeInt: Number.MIN_SAFE_INTEGER,
|
|
180
180
|
large: 9007199254740991,
|
|
181
|
-
small: -9007199254740991
|
|
181
|
+
small: -9007199254740991,
|
|
182
182
|
};
|
|
183
183
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
184
184
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
185
185
|
expect(decoded).toEqual(testObj);
|
|
186
186
|
});
|
|
187
|
-
it(
|
|
187
|
+
it("should handle mixed type arrays", () => {
|
|
188
188
|
const testArray = [
|
|
189
189
|
1,
|
|
190
|
-
|
|
190
|
+
"string",
|
|
191
191
|
true,
|
|
192
192
|
null,
|
|
193
193
|
undefined,
|
|
194
|
-
{ obj:
|
|
194
|
+
{ obj: "value" },
|
|
195
195
|
[1, 2, 3],
|
|
196
|
-
new Date(
|
|
197
|
-
new Uint8Array([1, 2, 3])
|
|
196
|
+
new Date("2023-01-01"),
|
|
197
|
+
new Uint8Array([1, 2, 3]),
|
|
198
198
|
];
|
|
199
199
|
const encoded = (0, tx_encoding_1.txEncode)(testArray);
|
|
200
200
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
201
201
|
expect(decoded[0]).toBe(1);
|
|
202
|
-
expect(decoded[1]).toBe(
|
|
202
|
+
expect(decoded[1]).toBe("string");
|
|
203
203
|
expect(decoded[2]).toBe(true);
|
|
204
204
|
expect(decoded[3]).toBeNull();
|
|
205
205
|
expect(decoded[4]).toBeUndefined();
|
|
206
|
-
expect(decoded[5]).toEqual({ obj:
|
|
206
|
+
expect(decoded[5]).toEqual({ obj: "value" });
|
|
207
207
|
expect(decoded[6]).toEqual([1, 2, 3]);
|
|
208
208
|
expect(decoded[7]).toBeInstanceOf(Date);
|
|
209
209
|
expect(decoded[8]).toBeInstanceOf(Uint8Array);
|
|
210
210
|
expect(decoded[8]).toEqual(new Uint8Array([1, 2, 3]));
|
|
211
211
|
});
|
|
212
|
-
it(
|
|
212
|
+
it("should handle objects with circular references removed by toJSON", () => {
|
|
213
213
|
// toJSON handles circular references, so this should work
|
|
214
|
-
const obj = { name:
|
|
214
|
+
const obj = { name: "test" };
|
|
215
215
|
obj.self = obj; // circular reference
|
|
216
216
|
const encoded = (0, tx_encoding_1.txEncode)(obj);
|
|
217
217
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
218
218
|
// The circular reference should be handled by toJSON/fromJSON
|
|
219
|
-
expect(decoded).toHaveProperty(
|
|
220
|
-
expect(decoded).toHaveProperty(
|
|
219
|
+
expect(decoded).toHaveProperty("name", "test");
|
|
220
|
+
expect(decoded).toHaveProperty("self");
|
|
221
221
|
expect(decoded.self).toBe(decoded); // self-reference restored
|
|
222
222
|
});
|
|
223
|
-
it(
|
|
223
|
+
it("should preserve data integrity across multiple encode/decode cycles", () => {
|
|
224
224
|
const original = {
|
|
225
225
|
id: 123,
|
|
226
|
-
name:
|
|
226
|
+
name: "multi-cycle test",
|
|
227
227
|
data: new Uint8Array([1, 2, 3, 4, 5]),
|
|
228
|
-
timestamp: new Date(
|
|
228
|
+
timestamp: new Date("2023-06-15T12:00:00.000Z"),
|
|
229
229
|
};
|
|
230
230
|
// Encode and decode multiple times
|
|
231
231
|
let current = original;
|
|
@@ -239,43 +239,43 @@ describe('tx-encode-decode', () => {
|
|
|
239
239
|
expect(current.timestamp).toEqual(original.timestamp);
|
|
240
240
|
});
|
|
241
241
|
});
|
|
242
|
-
describe(
|
|
243
|
-
it(
|
|
244
|
-
const testObj = { test:
|
|
242
|
+
describe("payload structure", () => {
|
|
243
|
+
it("should have flag byte as first byte", () => {
|
|
244
|
+
const testObj = { test: "value" };
|
|
245
245
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
246
246
|
// First byte should be 0 or 1
|
|
247
247
|
expect(encoded[0]).toBeGreaterThanOrEqual(0);
|
|
248
248
|
expect(encoded[0]).toBeLessThanOrEqual(1);
|
|
249
249
|
});
|
|
250
|
-
it(
|
|
251
|
-
const testObj = { test:
|
|
250
|
+
it("should have body after flag byte", () => {
|
|
251
|
+
const testObj = { test: "value" };
|
|
252
252
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
253
253
|
// Should have at least 2 bytes (flag + body)
|
|
254
254
|
expect(encoded.length).toBeGreaterThan(1);
|
|
255
255
|
});
|
|
256
256
|
});
|
|
257
|
-
describe(
|
|
258
|
-
it(
|
|
257
|
+
describe("edge cases", () => {
|
|
258
|
+
it("should handle objects at exactly 1024 bytes threshold", () => {
|
|
259
259
|
// Create an object that when msgpack-encoded is very close to 1024 bytes
|
|
260
260
|
// This is tricky to get exact, so we just verify it works
|
|
261
261
|
const testObj = {
|
|
262
|
-
data:
|
|
262
|
+
data: "x".repeat(1000),
|
|
263
263
|
};
|
|
264
264
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
265
265
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
|
266
266
|
expect(decoded).toEqual(testObj);
|
|
267
267
|
});
|
|
268
|
-
it(
|
|
268
|
+
it("should handle primitive values", () => {
|
|
269
269
|
expect((0, tx_encoding_1.txDecode)((0, tx_encoding_1.txEncode)(42))).toBe(42);
|
|
270
|
-
expect((0, tx_encoding_1.txDecode)((0, tx_encoding_1.txEncode)(
|
|
270
|
+
expect((0, tx_encoding_1.txDecode)((0, tx_encoding_1.txEncode)("string"))).toBe("string");
|
|
271
271
|
expect((0, tx_encoding_1.txDecode)((0, tx_encoding_1.txEncode)(true))).toBe(true);
|
|
272
272
|
expect((0, tx_encoding_1.txDecode)((0, tx_encoding_1.txEncode)(false))).toBe(false);
|
|
273
273
|
expect((0, tx_encoding_1.txDecode)((0, tx_encoding_1.txEncode)(null))).toBe(null);
|
|
274
274
|
});
|
|
275
|
-
it(
|
|
275
|
+
it("should handle objects with only undefined values", () => {
|
|
276
276
|
const testObj = {
|
|
277
277
|
a: undefined,
|
|
278
|
-
b: undefined
|
|
278
|
+
b: undefined,
|
|
279
279
|
};
|
|
280
280
|
const encoded = (0, tx_encoding_1.txEncode)(testObj);
|
|
281
281
|
const decoded = (0, tx_encoding_1.txDecode)(encoded);
|
package/dist/events.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IEventData } from "./rpc-types";
|
|
1
|
+
import { type IEventData } from "./rpc-types";
|
|
2
2
|
export type IEventFilter = (event: IEventData) => boolean;
|
|
3
3
|
export type IEventHandler<T = any> = (eventData: IEventData<T>) => boolean | void | Promise<boolean> | Promise<void>;
|
|
4
4
|
export interface ISubscription {
|
package/dist/events.js
CHANGED
|
@@ -6,7 +6,7 @@ exports.subscribeDebounce = subscribeDebounce;
|
|
|
6
6
|
exports.emit = emit;
|
|
7
7
|
exports.unionEvents = unionEvents;
|
|
8
8
|
const rpc_types_1 = require("./rpc-types");
|
|
9
|
-
const unitTests = process.env.NODE_ENV ===
|
|
9
|
+
const unitTests = process.env.NODE_ENV === "test";
|
|
10
10
|
const subscriptions = [];
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
12
|
function subscribe(nameOrFilter, handler) {
|
|
@@ -65,7 +65,10 @@ async function emit(event, dontPropagate) {
|
|
|
65
65
|
// );
|
|
66
66
|
// }
|
|
67
67
|
if (!(dontPropagate || unitTests)) {
|
|
68
|
-
matchedHandlerPromises.push(rpc_types_1.rpcClientCalls.emitEvent(event).catch((err) => {
|
|
68
|
+
matchedHandlerPromises.push(rpc_types_1.rpcClientCalls.emitEvent(event).catch((err) => {
|
|
69
|
+
console.error(`Error while propagating event to client`, err);
|
|
70
|
+
return false;
|
|
71
|
+
}));
|
|
69
72
|
}
|
|
70
73
|
const results = await Promise.all(matchedHandlerPromises);
|
|
71
74
|
// if any handlers returned false (or errored), return false, otherwise return true
|
|
@@ -21,19 +21,110 @@ const keys_1 = require("../keys");
|
|
|
21
21
|
* Using common, easy-to-spell words.
|
|
22
22
|
*/
|
|
23
23
|
const WORD_LIST = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
"apple",
|
|
25
|
+
"banana",
|
|
26
|
+
"cherry",
|
|
27
|
+
"date",
|
|
28
|
+
"elder",
|
|
29
|
+
"fig",
|
|
30
|
+
"grape",
|
|
31
|
+
"honey",
|
|
32
|
+
"iris",
|
|
33
|
+
"jade",
|
|
34
|
+
"kiwi",
|
|
35
|
+
"lemon",
|
|
36
|
+
"mango",
|
|
37
|
+
"nectar",
|
|
38
|
+
"olive",
|
|
39
|
+
"peach",
|
|
40
|
+
"quince",
|
|
41
|
+
"rose",
|
|
42
|
+
"sugar",
|
|
43
|
+
"tulip",
|
|
44
|
+
"umber",
|
|
45
|
+
"violet",
|
|
46
|
+
"willow",
|
|
47
|
+
"yarrow",
|
|
48
|
+
"zebra",
|
|
49
|
+
"amber",
|
|
50
|
+
"blaze",
|
|
51
|
+
"coral",
|
|
52
|
+
"dusk",
|
|
53
|
+
"ember",
|
|
54
|
+
"frost",
|
|
55
|
+
"glow",
|
|
56
|
+
"haze",
|
|
57
|
+
"ivory",
|
|
58
|
+
"jewel",
|
|
59
|
+
"karma",
|
|
60
|
+
"lunar",
|
|
61
|
+
"maple",
|
|
62
|
+
"nova",
|
|
63
|
+
"opal",
|
|
64
|
+
"prism",
|
|
65
|
+
"quest",
|
|
66
|
+
"river",
|
|
67
|
+
"storm",
|
|
68
|
+
"terra",
|
|
69
|
+
"ultra",
|
|
70
|
+
"vivid",
|
|
71
|
+
"winter",
|
|
72
|
+
"azure",
|
|
73
|
+
"brave",
|
|
74
|
+
"calm",
|
|
75
|
+
"dawn",
|
|
76
|
+
"echo",
|
|
77
|
+
"fern",
|
|
78
|
+
"gentle",
|
|
79
|
+
"harbor",
|
|
80
|
+
"island",
|
|
81
|
+
"jungle",
|
|
82
|
+
"kindle",
|
|
83
|
+
"light",
|
|
84
|
+
"meadow",
|
|
85
|
+
"night",
|
|
86
|
+
"ocean",
|
|
87
|
+
"piano",
|
|
88
|
+
"quiet",
|
|
89
|
+
"rain",
|
|
90
|
+
"silk",
|
|
91
|
+
"tide",
|
|
92
|
+
"unity",
|
|
93
|
+
"velvet",
|
|
94
|
+
"wave",
|
|
95
|
+
"zenith",
|
|
96
|
+
"arch",
|
|
97
|
+
"beam",
|
|
98
|
+
"cloud",
|
|
99
|
+
"drift",
|
|
100
|
+
"earth",
|
|
101
|
+
"flame",
|
|
102
|
+
"green",
|
|
103
|
+
"hill",
|
|
104
|
+
"ink",
|
|
105
|
+
"jazz",
|
|
106
|
+
"keen",
|
|
107
|
+
"lake",
|
|
108
|
+
"moon",
|
|
109
|
+
"nest",
|
|
110
|
+
"oak",
|
|
111
|
+
"peak",
|
|
112
|
+
"ruby",
|
|
113
|
+
"sand",
|
|
114
|
+
"tree",
|
|
115
|
+
"vine",
|
|
116
|
+
"wind",
|
|
117
|
+
"year",
|
|
118
|
+
"zone",
|
|
119
|
+
"bold",
|
|
120
|
+
"crisp",
|
|
121
|
+
"deep",
|
|
122
|
+
"fair",
|
|
123
|
+
"glad",
|
|
124
|
+
"warm",
|
|
125
|
+
"pure",
|
|
126
|
+
"safe",
|
|
127
|
+
"true",
|
|
37
128
|
];
|
|
38
129
|
/**
|
|
39
130
|
* Generate a random memorable passphrase.
|
|
@@ -49,7 +140,7 @@ function generateInvitePassword(wordCount = 4) {
|
|
|
49
140
|
const index = bytes[i] % WORD_LIST.length;
|
|
50
141
|
words.push(WORD_LIST[index]);
|
|
51
142
|
}
|
|
52
|
-
return words.join(
|
|
143
|
+
return words.join("-");
|
|
53
144
|
}
|
|
54
145
|
/**
|
|
55
146
|
* Derive a network alias from a password.
|
|
@@ -63,8 +154,8 @@ function deriveAliasFromPassword(password) {
|
|
|
63
154
|
const hash = (0, sha2_1.sha256)(new TextEncoder().encode(normalized));
|
|
64
155
|
// Convert first 4 bytes to 8-char hex string
|
|
65
156
|
const hexChars = Array.from(hash.slice(0, 4))
|
|
66
|
-
.map(b => b.toString(16).padStart(2,
|
|
67
|
-
.join(
|
|
157
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
158
|
+
.join("")
|
|
68
159
|
.toUpperCase();
|
|
69
160
|
return hexChars;
|
|
70
161
|
}
|
|
@@ -112,7 +203,7 @@ function decryptWithPassword(encrypted, password) {
|
|
|
112
203
|
const ciphertext = combined.slice(24);
|
|
113
204
|
const decrypted = nacl.secretbox.open(ciphertext, nonce, key);
|
|
114
205
|
if (!decrypted) {
|
|
115
|
-
throw new Error(
|
|
206
|
+
throw new Error("Decryption failed - invalid password or corrupted data");
|
|
116
207
|
}
|
|
117
208
|
return (0, tx_encoding_1.txDecode)(decrypted);
|
|
118
209
|
}
|
|
@@ -135,6 +226,6 @@ function isValidInvitePassword(password) {
|
|
|
135
226
|
function generateRequestId() {
|
|
136
227
|
const bytes = nacl.randomBytes(8);
|
|
137
228
|
return Array.from(bytes)
|
|
138
|
-
.map(b => b.toString(16).padStart(2,
|
|
139
|
-
.join(
|
|
229
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
230
|
+
.join("");
|
|
140
231
|
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* - Status messages for UI feedback
|
|
8
8
|
* - Action triggers (UI sets these, device layer reacts)
|
|
9
9
|
*/
|
|
10
|
-
import type {
|
|
11
|
-
import {
|
|
10
|
+
import type { GroupMemberRole } from "../data/group-member-roles";
|
|
11
|
+
import type { IGroupInviteListener, IGroupInviteListenerInfo, IGroupJoinRequest, IGroupJoinResult } from "./group-invite.types";
|
|
12
12
|
/**
|
|
13
13
|
* Active group invitation listeners.
|
|
14
14
|
* Key is groupId, value contains the password and alias being listened for.
|
|
@@ -20,40 +20,44 @@ const persistent_vars_1 = require("../data/persistent-vars");
|
|
|
20
20
|
*
|
|
21
21
|
* Used by admins who are waiting for join requests.
|
|
22
22
|
*/
|
|
23
|
-
exports.groupInviteListeners = (0, persistent_vars_1.deviceVar)(
|
|
23
|
+
exports.groupInviteListeners = (0, persistent_vars_1.deviceVar)("groupInviteListeners", { defaultValue: {} });
|
|
24
24
|
/**
|
|
25
25
|
* Pending join requests that need admin approval.
|
|
26
26
|
* Array of requests waiting to be approved or denied.
|
|
27
27
|
*
|
|
28
28
|
* These are shown to the admin in the group details UI.
|
|
29
29
|
*/
|
|
30
|
-
exports.groupInviteRequests = (0, persistent_vars_1.deviceVar)(
|
|
30
|
+
exports.groupInviteRequests = (0, persistent_vars_1.deviceVar)("groupInviteRequests", {
|
|
31
|
+
defaultValue: [],
|
|
32
|
+
});
|
|
31
33
|
/**
|
|
32
34
|
* Status message for the group invite UI (admin side).
|
|
33
35
|
* Used to show success/error messages to the user.
|
|
34
36
|
*/
|
|
35
|
-
exports.groupInviteStatus = (0, persistent_vars_1.deviceVar)(
|
|
37
|
+
exports.groupInviteStatus = (0, persistent_vars_1.deviceVar)("groupInviteStatus", { defaultValue: "" });
|
|
36
38
|
/**
|
|
37
39
|
* Status message for the join group UI (joiner side).
|
|
38
40
|
* Used to show discovery/join status to the user.
|
|
39
41
|
*/
|
|
40
|
-
exports.groupJoinStatus = (0, persistent_vars_1.deviceVar)(
|
|
42
|
+
exports.groupJoinStatus = (0, persistent_vars_1.deviceVar)("groupJoinStatus", { defaultValue: "" });
|
|
41
43
|
/**
|
|
42
44
|
* Results from discovering group listeners.
|
|
43
45
|
* Updated by the device layer after discovery completes.
|
|
44
46
|
*/
|
|
45
|
-
exports.groupInviteDiscoveryResult = (0, persistent_vars_1.deviceVar)(
|
|
47
|
+
exports.groupInviteDiscoveryResult = (0, persistent_vars_1.deviceVar)("groupInviteDiscoveryResult", { defaultValue: [] });
|
|
46
48
|
/**
|
|
47
49
|
* Result of joining a group.
|
|
48
50
|
* Updated by the device layer after join completes.
|
|
49
51
|
*/
|
|
50
|
-
exports.groupInviteJoinResult = (0, persistent_vars_1.deviceVar)(
|
|
52
|
+
exports.groupInviteJoinResult = (0, persistent_vars_1.deviceVar)("groupInviteJoinResult", {
|
|
53
|
+
defaultValue: null,
|
|
54
|
+
});
|
|
51
55
|
/**
|
|
52
56
|
* Responses to join requests, keyed by requestId.
|
|
53
57
|
* Written by processJoinRequest, read by handleJoinRequest.
|
|
54
58
|
* Entries are cleaned up after being read.
|
|
55
59
|
*/
|
|
56
|
-
exports.groupInviteResponses = (0, persistent_vars_1.deviceVar)(
|
|
60
|
+
exports.groupInviteResponses = (0, persistent_vars_1.deviceVar)("groupInviteResponses", { defaultValue: {} });
|
|
57
61
|
// ============================================================================
|
|
58
62
|
// ACTION TRIGGERS (UI sets these, device layer reacts)
|
|
59
63
|
// ============================================================================
|
|
@@ -62,31 +66,35 @@ exports.groupInviteResponses = (0, persistent_vars_1.deviceVar)('groupInviteResp
|
|
|
62
66
|
* Set by UI: { groupId, password }
|
|
63
67
|
* Device layer clears after processing.
|
|
64
68
|
*/
|
|
65
|
-
exports.groupInviteStartListening = (0, persistent_vars_1.deviceVar)(
|
|
69
|
+
exports.groupInviteStartListening = (0, persistent_vars_1.deviceVar)("groupInviteStartListening", { defaultValue: null });
|
|
66
70
|
/**
|
|
67
71
|
* Trigger to stop listening for invitations.
|
|
68
72
|
* Set by UI: groupId
|
|
69
73
|
* Device layer clears after processing.
|
|
70
74
|
*/
|
|
71
|
-
exports.groupInviteStopListening = (0, persistent_vars_1.deviceVar)(
|
|
75
|
+
exports.groupInviteStopListening = (0, persistent_vars_1.deviceVar)("groupInviteStopListening", {
|
|
76
|
+
defaultValue: null,
|
|
77
|
+
});
|
|
72
78
|
/**
|
|
73
79
|
* Trigger to discover groups with a password.
|
|
74
80
|
* Set by UI: password
|
|
75
81
|
* Device layer updates groupInviteDiscoveryResult and clears this.
|
|
76
82
|
*/
|
|
77
|
-
exports.groupInviteDiscover = (0, persistent_vars_1.deviceVar)(
|
|
83
|
+
exports.groupInviteDiscover = (0, persistent_vars_1.deviceVar)("groupInviteDiscover", {
|
|
84
|
+
defaultValue: null,
|
|
85
|
+
});
|
|
78
86
|
/**
|
|
79
87
|
* Trigger to send a join request.
|
|
80
88
|
* Set by UI: { listener, password }
|
|
81
89
|
* Device layer updates groupInviteJoinResult and clears this.
|
|
82
90
|
*/
|
|
83
|
-
exports.groupInviteSendRequest = (0, persistent_vars_1.deviceVar)(
|
|
91
|
+
exports.groupInviteSendRequest = (0, persistent_vars_1.deviceVar)("groupInviteSendRequest", { defaultValue: null });
|
|
84
92
|
/**
|
|
85
93
|
* Trigger to process (approve/deny) a join request.
|
|
86
94
|
* Set by UI: { requestId, approved, role }
|
|
87
95
|
* Device layer processes and clears this.
|
|
88
96
|
*/
|
|
89
|
-
exports.groupInviteProcessRequest = (0, persistent_vars_1.deviceVar)(
|
|
97
|
+
exports.groupInviteProcessRequest = (0, persistent_vars_1.deviceVar)("groupInviteProcessRequest", { defaultValue: null });
|
|
90
98
|
// ============================================================================
|
|
91
99
|
// AUTO-CLEANUP
|
|
92
100
|
// ============================================================================
|
|
@@ -119,7 +127,7 @@ exports.groupInviteRequests.loadingPromise.then(() => {
|
|
|
119
127
|
setInterval(() => {
|
|
120
128
|
const requests = (0, exports.groupInviteRequests)();
|
|
121
129
|
const now = Date.now();
|
|
122
|
-
const validRequests = requests.filter(req => {
|
|
130
|
+
const validRequests = requests.filter((req) => {
|
|
123
131
|
const receivedAt = new Date(req.receivedAt).getTime();
|
|
124
132
|
const elapsed = now - receivedAt;
|
|
125
133
|
return elapsed < 600_000; // Keep for 10 minutes
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This flow allows admins to invite new members to a group using a simple
|
|
5
5
|
* password. Multiple admins can listen for the same password simultaneously.
|
|
6
6
|
*/
|
|
7
|
-
import { GroupMemberRole } from
|
|
7
|
+
import type { GroupMemberRole } from "../data/group-member-roles";
|
|
8
8
|
/**
|
|
9
9
|
* Information about a group shared during the invitation flow.
|
|
10
10
|
*/
|