@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
|
@@ -3,15 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const SQLiteDB = require("better-sqlite3");
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const data_locks_1 = require("./data-locks");
|
|
6
|
+
const group_member_roles_1 = require("./group-member-roles");
|
|
6
7
|
const sql_data_source_1 = require("./orm/sql.data-source");
|
|
7
8
|
const types_1 = require("./orm/types");
|
|
8
|
-
const group_member_roles_1 = require("./group-member-roles");
|
|
9
9
|
class DBHarness {
|
|
10
10
|
_db = null;
|
|
11
11
|
get database() {
|
|
12
12
|
if (!this._db) {
|
|
13
|
-
this._db = new SQLiteDB(
|
|
14
|
-
this._db.pragma(
|
|
13
|
+
this._db = new SQLiteDB(":memory:");
|
|
14
|
+
this._db.pragma("journal_mode = WAL");
|
|
15
15
|
}
|
|
16
16
|
return this._db;
|
|
17
17
|
}
|
|
@@ -32,8 +32,8 @@ class DBHarness {
|
|
|
32
32
|
}
|
|
33
33
|
// Mock peer device for testing
|
|
34
34
|
class MockPeerDevice {
|
|
35
|
-
deviceId =
|
|
36
|
-
userId =
|
|
35
|
+
deviceId = "mock-device";
|
|
36
|
+
userId = "mock-user";
|
|
37
37
|
role = group_member_roles_1.GroupMemberRole.Owner;
|
|
38
38
|
connections = [];
|
|
39
39
|
changes = [];
|
|
@@ -42,7 +42,7 @@ class MockPeerDevice {
|
|
|
42
42
|
deviceId: `peer-${i}`,
|
|
43
43
|
latencyMs: 50,
|
|
44
44
|
errorRate: 0,
|
|
45
|
-
timestampLastApplied: Date.now()
|
|
45
|
+
timestampLastApplied: Date.now(),
|
|
46
46
|
}));
|
|
47
47
|
}
|
|
48
48
|
async getNetworkInfo() {
|
|
@@ -59,11 +59,11 @@ class MockPeerDevice {
|
|
|
59
59
|
async listChanges(query) {
|
|
60
60
|
if (!query)
|
|
61
61
|
return this.changes;
|
|
62
|
-
return this.changes.filter(change => change.tableName === query.tableName &&
|
|
62
|
+
return this.changes.filter((change) => change.tableName === query.tableName &&
|
|
63
63
|
change.recordId === query.recordId &&
|
|
64
64
|
change.op === query.op);
|
|
65
65
|
}
|
|
66
|
-
async notifyOfChanges(
|
|
66
|
+
async notifyOfChanges(_deviceId, _timestampLastApplied) {
|
|
67
67
|
// Mock implementation
|
|
68
68
|
}
|
|
69
69
|
async downloadFileChunk(_chunkHash) {
|
|
@@ -77,10 +77,10 @@ class MockPeerDevice {
|
|
|
77
77
|
addAcknowledgment(recordId, acknowledged) {
|
|
78
78
|
this.changes.push({
|
|
79
79
|
changeId: (0, utils_1.newid)(),
|
|
80
|
-
tableName:
|
|
80
|
+
tableName: "DataLocks",
|
|
81
81
|
recordId,
|
|
82
|
-
op:
|
|
83
|
-
path:
|
|
82
|
+
op: "set",
|
|
83
|
+
path: "/acknowledged",
|
|
84
84
|
value: acknowledged,
|
|
85
85
|
createdAt: Date.now(),
|
|
86
86
|
appliedAt: Date.now(),
|
|
@@ -91,14 +91,14 @@ class MockPeerDevice {
|
|
|
91
91
|
deviceId: `peer-${i}`,
|
|
92
92
|
latencyMs: 50,
|
|
93
93
|
errorRate: 0,
|
|
94
|
-
timestampLastApplied: Date.now()
|
|
94
|
+
timestampLastApplied: Date.now(),
|
|
95
95
|
}));
|
|
96
96
|
}
|
|
97
|
-
sendDeviceMessage(
|
|
98
|
-
throw new Error(
|
|
97
|
+
sendDeviceMessage(_message) {
|
|
98
|
+
throw new Error("Method not implemented.");
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
describe(
|
|
101
|
+
describe("data-locks.ts", () => {
|
|
102
102
|
const fiveMinutesMs = 5 * 60 * 1000;
|
|
103
103
|
jest.setTimeout(fiveMinutesMs);
|
|
104
104
|
let db;
|
|
@@ -106,30 +106,28 @@ describe('data-locks.ts', () => {
|
|
|
106
106
|
let dataLocksTable;
|
|
107
107
|
let mockPeerDevice;
|
|
108
108
|
const dataLocksTableMetaData = {
|
|
109
|
-
name:
|
|
110
|
-
primaryKeyName:
|
|
111
|
-
description:
|
|
109
|
+
name: "DataLocks",
|
|
110
|
+
primaryKeyName: "dataLockId",
|
|
111
|
+
description: "Data locks table to track exclusive write access to records in other tables.",
|
|
112
112
|
fields: (0, types_1.schemaToFields)(data_locks_1.dataLockSchema),
|
|
113
|
-
indexes: [
|
|
114
|
-
{ fields: ['recordId'] },
|
|
115
|
-
],
|
|
113
|
+
indexes: [{ fields: ["recordId"] }],
|
|
116
114
|
};
|
|
117
115
|
beforeAll(async () => {
|
|
118
116
|
db = new DBHarness();
|
|
119
117
|
dataSource = new sql_data_source_1.SQLDataSource(db, dataLocksTableMetaData);
|
|
120
118
|
const mockDataContextForRegistry = {
|
|
121
|
-
dataContextId:
|
|
119
|
+
dataContextId: "data-locks-test",
|
|
122
120
|
};
|
|
123
|
-
const { EventRegistry } = require(
|
|
121
|
+
const { EventRegistry } = require("./orm/event-registry");
|
|
124
122
|
const eventRegistry = new EventRegistry(mockDataContextForRegistry);
|
|
125
|
-
const
|
|
123
|
+
const _mockDataContext = {
|
|
126
124
|
dataSourceFactory: () => dataSource,
|
|
127
|
-
eventRegistry: eventRegistry
|
|
125
|
+
eventRegistry: eventRegistry,
|
|
128
126
|
};
|
|
129
127
|
const deps = {
|
|
130
128
|
dataSource,
|
|
131
129
|
eventRegistry,
|
|
132
|
-
schema: data_locks_1.dataLockSchema
|
|
130
|
+
schema: data_locks_1.dataLockSchema,
|
|
133
131
|
};
|
|
134
132
|
dataLocksTable = new data_locks_1.DataLocksTable(dataLocksTableMetaData, deps);
|
|
135
133
|
mockPeerDevice = new MockPeerDevice();
|
|
@@ -147,23 +145,23 @@ describe('data-locks.ts', () => {
|
|
|
147
145
|
}
|
|
148
146
|
mockPeerDevice.setConnectionCount(3);
|
|
149
147
|
});
|
|
150
|
-
describe(
|
|
151
|
-
describe(
|
|
152
|
-
it(
|
|
148
|
+
describe("DataLocksTable", () => {
|
|
149
|
+
describe("constructor", () => {
|
|
150
|
+
it("should create a DataLocksTable instance with default constants", () => {
|
|
153
151
|
expect(dataLocksTable.DEFAULT_LOCK_TIME_MS).toBe(300_000); // 5 minutes
|
|
154
152
|
expect(dataLocksTable.DEFAULT_TIMEOUT_MS).toBe(20_000); // 20 seconds
|
|
155
153
|
expect(dataLocksTable.DEAD_PERIOD_MS).toBe(10_000); // 10 seconds
|
|
156
154
|
});
|
|
157
|
-
it(
|
|
155
|
+
it("should have peerDevice property", () => {
|
|
158
156
|
expect(dataLocksTable.peerDevice).toBeDefined();
|
|
159
157
|
});
|
|
160
158
|
});
|
|
161
|
-
describe(
|
|
162
|
-
it(
|
|
163
|
-
const result = await dataLocksTable.getCurrentLock(
|
|
159
|
+
describe("getCurrentLock", () => {
|
|
160
|
+
it("should return undefined when no locks exist for recordId", async () => {
|
|
161
|
+
const result = await dataLocksTable.getCurrentLock("nonexistent-record");
|
|
164
162
|
expect(result).toBeUndefined();
|
|
165
163
|
});
|
|
166
|
-
it(
|
|
164
|
+
it("should return undefined when only expired locks exist", async () => {
|
|
167
165
|
const recordId = (0, utils_1.newid)();
|
|
168
166
|
const expiredLock = {
|
|
169
167
|
dataLockId: (0, utils_1.newid)(),
|
|
@@ -174,7 +172,7 @@ describe('data-locks.ts', () => {
|
|
|
174
172
|
const result = await dataLocksTable.getCurrentLock(recordId);
|
|
175
173
|
expect(result).toBeUndefined();
|
|
176
174
|
});
|
|
177
|
-
it(
|
|
175
|
+
it("should return the current valid lock", async () => {
|
|
178
176
|
const recordId = (0, utils_1.newid)();
|
|
179
177
|
const validLock = {
|
|
180
178
|
dataLockId: (0, utils_1.newid)(),
|
|
@@ -185,7 +183,7 @@ describe('data-locks.ts', () => {
|
|
|
185
183
|
const result = await dataLocksTable.getCurrentLock(recordId);
|
|
186
184
|
expect(result).toEqual(validLock);
|
|
187
185
|
});
|
|
188
|
-
it(
|
|
186
|
+
it("should return the earliest lock when multiple valid locks exist", async () => {
|
|
189
187
|
const recordId = (0, utils_1.newid)();
|
|
190
188
|
const lock1 = {
|
|
191
189
|
dataLockId: (0, utils_1.newid)(),
|
|
@@ -206,8 +204,8 @@ describe('data-locks.ts', () => {
|
|
|
206
204
|
expect(result?.dataLockId).toBe(firstLock.dataLockId);
|
|
207
205
|
});
|
|
208
206
|
});
|
|
209
|
-
describe(
|
|
210
|
-
it(
|
|
207
|
+
describe("releaseLock", () => {
|
|
208
|
+
it("should delete the lock from the database", async () => {
|
|
211
209
|
const lock = {
|
|
212
210
|
dataLockId: (0, utils_1.newid)(),
|
|
213
211
|
recordId: (0, utils_1.newid)(),
|
|
@@ -219,11 +217,11 @@ describe('data-locks.ts', () => {
|
|
|
219
217
|
expect(await dataLocksTable.get(lock.dataLockId)).toBeUndefined();
|
|
220
218
|
});
|
|
221
219
|
});
|
|
222
|
-
describe(
|
|
223
|
-
it(
|
|
220
|
+
describe("acquireLock", () => {
|
|
221
|
+
it("should acquire a lock when no existing locks", async () => {
|
|
224
222
|
const recordId = (0, utils_1.newid)();
|
|
225
223
|
// Mock sufficient acknowledgments for lock confirmation
|
|
226
|
-
const mockAcquireLock = jest.spyOn(dataLocksTable,
|
|
224
|
+
const mockAcquireLock = jest.spyOn(dataLocksTable, "acquireLock");
|
|
227
225
|
mockAcquireLock.mockImplementation(async () => {
|
|
228
226
|
const lock = {
|
|
229
227
|
dataLockId: (0, utils_1.newid)(),
|
|
@@ -239,11 +237,11 @@ describe('data-locks.ts', () => {
|
|
|
239
237
|
expect(result?.lockedUntil).toBeGreaterThan(Date.now());
|
|
240
238
|
mockAcquireLock.mockRestore();
|
|
241
239
|
});
|
|
242
|
-
it(
|
|
240
|
+
it("should use custom timeout and lock time", async () => {
|
|
243
241
|
const recordId = (0, utils_1.newid)();
|
|
244
242
|
const customTimeout = 5000;
|
|
245
243
|
const customLockTime = 120000;
|
|
246
|
-
const mockAcquireLock = jest.spyOn(dataLocksTable,
|
|
244
|
+
const mockAcquireLock = jest.spyOn(dataLocksTable, "acquireLock");
|
|
247
245
|
mockAcquireLock.mockImplementation(async (recordId, timeoutMs, lockTimeMs) => {
|
|
248
246
|
expect(timeoutMs).toBe(customTimeout);
|
|
249
247
|
expect(lockTimeMs).toBe(customLockTime);
|
|
@@ -257,8 +255,8 @@ describe('data-locks.ts', () => {
|
|
|
257
255
|
mockAcquireLock.mockRestore();
|
|
258
256
|
});
|
|
259
257
|
});
|
|
260
|
-
describe(
|
|
261
|
-
it(
|
|
258
|
+
describe("renewLock", () => {
|
|
259
|
+
it("should renew a valid lock", async () => {
|
|
262
260
|
const lock = {
|
|
263
261
|
dataLockId: (0, utils_1.newid)(),
|
|
264
262
|
recordId: (0, utils_1.newid)(),
|
|
@@ -267,13 +265,13 @@ describe('data-locks.ts', () => {
|
|
|
267
265
|
await dataLocksTable.insert(lock);
|
|
268
266
|
const originalLockedUntil = lock.lockedUntil;
|
|
269
267
|
// Small delay to ensure time difference
|
|
270
|
-
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
268
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
271
269
|
await sleep(10);
|
|
272
270
|
const renewedLock = await dataLocksTable.renewLock(lock, 120000);
|
|
273
271
|
expect(renewedLock).toBeDefined();
|
|
274
272
|
expect(renewedLock?.lockedUntil).toBeGreaterThan(originalLockedUntil);
|
|
275
273
|
});
|
|
276
|
-
it(
|
|
274
|
+
it("should reject renewal of expired lock", async () => {
|
|
277
275
|
const lock = {
|
|
278
276
|
dataLockId: (0, utils_1.newid)(),
|
|
279
277
|
recordId: (0, utils_1.newid)(),
|
|
@@ -283,7 +281,7 @@ describe('data-locks.ts', () => {
|
|
|
283
281
|
const result = await dataLocksTable.renewLock(lock);
|
|
284
282
|
expect(result).toBeUndefined();
|
|
285
283
|
});
|
|
286
|
-
it(
|
|
284
|
+
it("should reject renewal when lock is no longer current", async () => {
|
|
287
285
|
const recordId = (0, utils_1.newid)();
|
|
288
286
|
// getCurrentLock returns the lock with the lexicographically first dataLockId,
|
|
289
287
|
// so ensure newLockId sorts before oldLockId
|
|
@@ -305,8 +303,8 @@ describe('data-locks.ts', () => {
|
|
|
305
303
|
expect(result).toBeUndefined();
|
|
306
304
|
});
|
|
307
305
|
});
|
|
308
|
-
describe(
|
|
309
|
-
it(
|
|
306
|
+
describe("lockStatus", () => {
|
|
307
|
+
it("should return confirmed when sufficient acknowledgments", async () => {
|
|
310
308
|
const lock = {
|
|
311
309
|
dataLockId: (0, utils_1.newid)(),
|
|
312
310
|
recordId: (0, utils_1.newid)(),
|
|
@@ -318,9 +316,9 @@ describe('data-locks.ts', () => {
|
|
|
318
316
|
mockPeerDevice.addAcknowledgment(lock.dataLockId, Date.now() + 2);
|
|
319
317
|
mockPeerDevice.addAcknowledgment(lock.dataLockId, Date.now() + 3);
|
|
320
318
|
const status = await dataLocksTable.lockStatus(lock);
|
|
321
|
-
expect(status).toBe(
|
|
319
|
+
expect(status).toBe("confirmed");
|
|
322
320
|
});
|
|
323
|
-
it(
|
|
321
|
+
it("should return pending when insufficient acknowledgments", async () => {
|
|
324
322
|
const lock = {
|
|
325
323
|
dataLockId: (0, utils_1.newid)(),
|
|
326
324
|
recordId: (0, utils_1.newid)(),
|
|
@@ -329,9 +327,9 @@ describe('data-locks.ts', () => {
|
|
|
329
327
|
// Add insufficient acknowledgments (only 1, need 4)
|
|
330
328
|
mockPeerDevice.addAcknowledgment(lock.dataLockId, Date.now());
|
|
331
329
|
const status = await dataLocksTable.lockStatus(lock);
|
|
332
|
-
expect(status).toBe(
|
|
330
|
+
expect(status).toBe("pending");
|
|
333
331
|
});
|
|
334
|
-
it(
|
|
332
|
+
it("should calculate acknowledgments needed correctly for different network sizes", async () => {
|
|
335
333
|
const lock = {
|
|
336
334
|
dataLockId: (0, utils_1.newid)(),
|
|
337
335
|
recordId: (0, utils_1.newid)(),
|
|
@@ -342,13 +340,13 @@ describe('data-locks.ts', () => {
|
|
|
342
340
|
mockPeerDevice.addAcknowledgment(lock.dataLockId, Date.now());
|
|
343
341
|
mockPeerDevice.addAcknowledgment(lock.dataLockId, Date.now() + 1);
|
|
344
342
|
let status = await dataLocksTable.lockStatus(lock);
|
|
345
|
-
expect(status).toBe(
|
|
343
|
+
expect(status).toBe("confirmed");
|
|
346
344
|
// Test with 5 connections (need Math.ceil(5 * 0.7) + 1 = 5 acknowledgments)
|
|
347
345
|
mockPeerDevice.setConnectionCount(5);
|
|
348
346
|
status = await dataLocksTable.lockStatus(lock);
|
|
349
|
-
expect(status).toBe(
|
|
347
|
+
expect(status).toBe("pending"); // Still only 2 acknowledgments, need 5
|
|
350
348
|
});
|
|
351
|
-
it(
|
|
349
|
+
it("should throw error when peerDevice is not set", async () => {
|
|
352
350
|
const lock = {
|
|
353
351
|
dataLockId: (0, utils_1.newid)(),
|
|
354
352
|
recordId: (0, utils_1.newid)(),
|
|
@@ -356,41 +354,41 @@ describe('data-locks.ts', () => {
|
|
|
356
354
|
};
|
|
357
355
|
const originalPeerDevice = dataLocksTable.peerDevice;
|
|
358
356
|
dataLocksTable.peerDevice = undefined;
|
|
359
|
-
await expect(dataLocksTable.lockStatus(lock)).rejects.toThrow(
|
|
357
|
+
await expect(dataLocksTable.lockStatus(lock)).rejects.toThrow("Peer device not set for DataLocksTable");
|
|
360
358
|
dataLocksTable.peerDevice = originalPeerDevice;
|
|
361
359
|
});
|
|
362
360
|
});
|
|
363
361
|
});
|
|
364
|
-
describe(
|
|
365
|
-
it(
|
|
362
|
+
describe("dataLockSchema", () => {
|
|
363
|
+
it("should validate valid lock data", () => {
|
|
366
364
|
const validLock = {
|
|
367
365
|
dataLockId: (0, utils_1.newid)(),
|
|
368
|
-
recordId:
|
|
366
|
+
recordId: "test-record",
|
|
369
367
|
lockedUntil: Date.now() + 60000,
|
|
370
368
|
};
|
|
371
369
|
const result = data_locks_1.dataLockSchema.safeParse(validLock);
|
|
372
370
|
expect(result.success).toBe(true);
|
|
373
371
|
});
|
|
374
|
-
it(
|
|
372
|
+
it("should validate lock with acknowledgment", () => {
|
|
375
373
|
const validLock = {
|
|
376
374
|
dataLockId: (0, utils_1.newid)(),
|
|
377
|
-
recordId:
|
|
375
|
+
recordId: "test-record",
|
|
378
376
|
lockedUntil: Date.now() + 60000,
|
|
379
377
|
acknowledged: Date.now(),
|
|
380
378
|
};
|
|
381
379
|
const result = data_locks_1.dataLockSchema.safeParse(validLock);
|
|
382
380
|
expect(result.success).toBe(true);
|
|
383
381
|
});
|
|
384
|
-
it(
|
|
382
|
+
it("should reject invalid lock data", () => {
|
|
385
383
|
const invalidLock = {
|
|
386
384
|
dataLockId: 123, // Should be string
|
|
387
|
-
recordId:
|
|
388
|
-
lockedUntil:
|
|
385
|
+
recordId: "test-record",
|
|
386
|
+
lockedUntil: "invalid", // Should be number
|
|
389
387
|
};
|
|
390
388
|
const result = data_locks_1.dataLockSchema.safeParse(invalidLock);
|
|
391
389
|
expect(result.success).toBe(false);
|
|
392
390
|
});
|
|
393
|
-
it(
|
|
391
|
+
it("should reject missing required fields", () => {
|
|
394
392
|
const incompleteLock = {
|
|
395
393
|
dataLockId: (0, utils_1.newid)(),
|
|
396
394
|
// Missing recordId and lockedUntil
|
|
@@ -399,17 +397,17 @@ describe('data-locks.ts', () => {
|
|
|
399
397
|
expect(result.success).toBe(false);
|
|
400
398
|
});
|
|
401
399
|
});
|
|
402
|
-
describe(
|
|
403
|
-
it(
|
|
400
|
+
describe("DataLocks factory function", () => {
|
|
401
|
+
it("should return a DataLocksTable instance", () => {
|
|
404
402
|
// This is a simplified test - in practice you'd need to set up the factory properly
|
|
405
|
-
expect(typeof data_locks_1.DataLocks).toBe(
|
|
403
|
+
expect(typeof data_locks_1.DataLocks).toBe("function");
|
|
406
404
|
});
|
|
407
405
|
});
|
|
408
|
-
describe(
|
|
409
|
-
it(
|
|
406
|
+
describe("integration scenarios", () => {
|
|
407
|
+
it("should handle concurrent lock attempts", async () => {
|
|
410
408
|
const recordId = (0, utils_1.newid)();
|
|
411
409
|
// This is a simplified version - real concurrent testing would require more complex setup
|
|
412
|
-
const mockInsert = jest.spyOn(dataLocksTable,
|
|
410
|
+
const mockInsert = jest.spyOn(dataLocksTable, "insert");
|
|
413
411
|
let insertCount = 0;
|
|
414
412
|
mockInsert.mockImplementation(async (lock) => {
|
|
415
413
|
insertCount++;
|
|
@@ -425,7 +423,7 @@ describe('data-locks.ts', () => {
|
|
|
425
423
|
expect(insertCount).toBe(3);
|
|
426
424
|
mockInsert.mockRestore();
|
|
427
425
|
});
|
|
428
|
-
it(
|
|
426
|
+
it("should handle lock expiration cleanup", async () => {
|
|
429
427
|
const recordId = (0, utils_1.newid)();
|
|
430
428
|
const expiredLock = {
|
|
431
429
|
dataLockId: (0, utils_1.newid)(),
|
|
@@ -442,7 +440,7 @@ describe('data-locks.ts', () => {
|
|
|
442
440
|
const currentLock = await dataLocksTable.getCurrentLock(recordId);
|
|
443
441
|
expect(currentLock?.dataLockId).toBe(validLock.dataLockId);
|
|
444
442
|
});
|
|
445
|
-
it(
|
|
443
|
+
it("should handle multiple records with independent locks", async () => {
|
|
446
444
|
const record1 = (0, utils_1.newid)();
|
|
447
445
|
const record2 = (0, utils_1.newid)();
|
|
448
446
|
const lock1 = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { ITableMetaData } from "./orm";
|
|
3
2
|
import type { DataContext } from "../context/data-context";
|
|
3
|
+
import { type ITableMetaData } from "./orm";
|
|
4
4
|
export declare const deviceSyncInfoSchema: z.ZodObject<{
|
|
5
5
|
deviceId: z.ZodEffects<z.ZodString, string, string>;
|
|
6
6
|
timestampAppliedLast: z.ZodNumber;
|
|
@@ -3,18 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.deviceSyncInfoMetaData = exports.deviceSyncInfoSchema = void 0;
|
|
4
4
|
exports.DeviceSyncInfos = DeviceSyncInfos;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
+
const context_1 = require("../context");
|
|
6
7
|
const zod_types_1 = require("../types/zod-types");
|
|
7
8
|
const orm_1 = require("./orm");
|
|
8
|
-
const context_1 = require("../context");
|
|
9
9
|
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
10
10
|
exports.deviceSyncInfoSchema = zod_1.z.object({
|
|
11
11
|
deviceId: zod_types_1.zodPeerId,
|
|
12
12
|
timestampAppliedLast: zod_1.z.number(),
|
|
13
13
|
});
|
|
14
14
|
exports.deviceSyncInfoMetaData = {
|
|
15
|
-
name:
|
|
16
|
-
primaryKeyName:
|
|
17
|
-
description:
|
|
15
|
+
name: "DeviceSyncTracking",
|
|
16
|
+
primaryKeyName: "deviceId",
|
|
17
|
+
description: "Sync tracking table",
|
|
18
18
|
fields: (0, orm_1.schemaToFields)(exports.deviceSyncInfoSchema),
|
|
19
19
|
localOnly: true,
|
|
20
20
|
};
|
package/dist/data/devices.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { TrustLevel } from "../device/socket.type";
|
|
3
2
|
import type { DataContext } from "../context/data-context";
|
|
3
|
+
import { TrustLevel } from "../device/socket.type";
|
|
4
4
|
export declare const deviceSchema: z.ZodObject<{
|
|
5
5
|
deviceId: z.ZodEffects<z.ZodString, string, string>;
|
|
6
6
|
userId: z.ZodEffects<z.ZodString, string, string>;
|
package/dist/data/devices.js
CHANGED
|
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.thisDeviceId = exports.trustedServers = exports.deviceSchema = void 0;
|
|
4
4
|
exports.Devices = Devices;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
-
const types_1 = require("./orm/types");
|
|
7
|
-
const persistent_vars_1 = require("./persistent-vars");
|
|
8
6
|
const user_context_singleton_1 = require("../context/user-context-singleton");
|
|
9
|
-
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
10
7
|
const socket_type_1 = require("../device/socket.type");
|
|
11
8
|
const zod_types_1 = require("../types/zod-types");
|
|
9
|
+
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
10
|
+
const types_1 = require("./orm/types");
|
|
11
|
+
const persistent_vars_1 = require("./persistent-vars");
|
|
12
12
|
exports.deviceSchema = zod_1.z.object({
|
|
13
13
|
deviceId: zod_types_1.zodPeerId,
|
|
14
14
|
userId: zod_types_1.zodPeerId,
|
|
@@ -19,19 +19,16 @@ exports.deviceSchema = zod_1.z.object({
|
|
|
19
19
|
trustLevel: zod_1.z.nativeEnum(socket_type_1.TrustLevel),
|
|
20
20
|
});
|
|
21
21
|
const metaData = {
|
|
22
|
-
name:
|
|
23
|
-
description:
|
|
24
|
-
primaryKeyName:
|
|
22
|
+
name: "Devices",
|
|
23
|
+
description: "The Peer devices that this computer is aware of",
|
|
24
|
+
primaryKeyName: "deviceId",
|
|
25
25
|
fields: (0, types_1.schemaToFields)(exports.deviceSchema),
|
|
26
26
|
};
|
|
27
27
|
(0, table_definitions_system_1.registerSystemTableDefinition)(metaData, exports.deviceSchema);
|
|
28
28
|
function Devices(dataContext) {
|
|
29
29
|
return (0, user_context_singleton_1.getTableContainer)(dataContext).getTable(metaData, exports.deviceSchema);
|
|
30
30
|
}
|
|
31
|
-
exports.trustedServers = (0, persistent_vars_1.groupVar)(
|
|
32
|
-
defaultValue: [
|
|
33
|
-
'https://peers.app',
|
|
34
|
-
'https://peers-services.azurewebsites.net',
|
|
35
|
-
],
|
|
31
|
+
exports.trustedServers = (0, persistent_vars_1.groupVar)("trustedServers", {
|
|
32
|
+
defaultValue: ["https://peers.app", "https://peers-services.azurewebsites.net"],
|
|
36
33
|
});
|
|
37
|
-
exports.thisDeviceId = (0, persistent_vars_1.deviceVar)(
|
|
34
|
+
exports.thisDeviceId = (0, persistent_vars_1.deviceVar)("thisDeviceId");
|
package/dist/data/embeddings.js
CHANGED
|
@@ -3,29 +3,32 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.embeddingSchema = void 0;
|
|
4
4
|
exports.Embeddings = Embeddings;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
-
const zod_types_1 = require("../types/zod-types");
|
|
7
|
-
const types_1 = require("./orm/types");
|
|
8
6
|
const user_context_singleton_1 = require("../context/user-context-singleton");
|
|
7
|
+
const zod_types_1 = require("../types/zod-types");
|
|
9
8
|
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
9
|
+
const types_1 = require("./orm/types");
|
|
10
10
|
exports.embeddingSchema = zod_1.z.object({
|
|
11
11
|
embeddingId: zod_types_1.zodPeerId,
|
|
12
|
-
textHash: zod_1.z.string().describe(
|
|
13
|
-
embedding: zod_1.z.array(zod_1.z.number()).describe(
|
|
14
|
-
embeddingType: zod_1.z.string().describe(
|
|
15
|
-
metadata: zod_1.z
|
|
12
|
+
textHash: zod_1.z.string().describe("The hash of the text"),
|
|
13
|
+
embedding: zod_1.z.array(zod_1.z.number()).describe("The embedding of the text"),
|
|
14
|
+
embeddingType: zod_1.z.string().describe("The type of embedding used"),
|
|
15
|
+
metadata: zod_1.z
|
|
16
|
+
.object({
|
|
16
17
|
fkId: zod_1.z.string().optional(),
|
|
17
18
|
// fkTable: z.string().optional(),
|
|
18
19
|
// fkIdFieldName: z.string().optional(),
|
|
19
|
-
})
|
|
20
|
+
})
|
|
21
|
+
.catchall(zod_1.z.any())
|
|
22
|
+
.describe("Any metadata associated with the embedding"),
|
|
20
23
|
});
|
|
21
24
|
const metaData = {
|
|
22
|
-
name:
|
|
23
|
-
description:
|
|
24
|
-
primaryKeyName:
|
|
25
|
+
name: "Embeddings",
|
|
26
|
+
description: "The embeddings for some specific text",
|
|
27
|
+
primaryKeyName: "embeddingId",
|
|
25
28
|
fields: (0, types_1.schemaToFields)(exports.embeddingSchema),
|
|
26
29
|
indexes: [
|
|
27
30
|
{
|
|
28
|
-
fields: [
|
|
31
|
+
fields: ["textHash", "embeddingType"],
|
|
29
32
|
unique: true,
|
|
30
33
|
},
|
|
31
34
|
],
|
|
@@ -39,10 +39,11 @@ class FileReadStream {
|
|
|
39
39
|
}
|
|
40
40
|
async loadChunkByIndex(chunkIndex) {
|
|
41
41
|
await this.loadChunkHashes();
|
|
42
|
-
|
|
42
|
+
const chunkHashes = this.chunkHashes;
|
|
43
|
+
if (chunkIndex >= chunkHashes.length) {
|
|
43
44
|
throw new Error(`Chunk index ${chunkIndex} out of bounds`);
|
|
44
45
|
}
|
|
45
|
-
const chunkHash =
|
|
46
|
+
const chunkHash = chunkHashes[chunkIndex];
|
|
46
47
|
const ops = await (0, file_types_1.getFileOps)();
|
|
47
48
|
const chunkPath = `${file_types_1.CHUNKS_DIR}/${chunkHash}`;
|
|
48
49
|
let chunk;
|
|
@@ -68,16 +69,17 @@ class FileReadStream {
|
|
|
68
69
|
}
|
|
69
70
|
async preloadChunks() {
|
|
70
71
|
await this.loadChunkHashes();
|
|
72
|
+
const chunkHashes = this.chunkHashes;
|
|
71
73
|
// Start from current chunk and preload up to preloadChunksCount ahead
|
|
72
74
|
for (let offset = 0; offset < this.preloadChunksCount; offset++) {
|
|
73
75
|
const chunkIndex = this.currentChunkIndex + offset;
|
|
74
|
-
if (chunkIndex >=
|
|
76
|
+
if (chunkIndex >= chunkHashes.length) {
|
|
75
77
|
break; // No more chunks to preload
|
|
76
78
|
}
|
|
77
79
|
if (!this.chunkPromises.has(chunkIndex)) {
|
|
78
80
|
// Start preload but don't await it - let it happen in background
|
|
79
81
|
// Add error handling to prevent unhandled promise rejections
|
|
80
|
-
const safeChunkPromise = this.loadChunkByIndex(chunkIndex).catch(error => {
|
|
82
|
+
const safeChunkPromise = this.loadChunkByIndex(chunkIndex).catch((error) => {
|
|
81
83
|
// Re-throw so error is available when promise is consumed
|
|
82
84
|
throw error;
|
|
83
85
|
});
|
|
@@ -89,7 +91,8 @@ class FileReadStream {
|
|
|
89
91
|
}
|
|
90
92
|
async loadCurrentChunk() {
|
|
91
93
|
await this.preloadChunks();
|
|
92
|
-
|
|
94
|
+
const chunkHashes = this.chunkHashes;
|
|
95
|
+
if (this.currentChunkIndex >= chunkHashes.length) {
|
|
93
96
|
this.eof = true;
|
|
94
97
|
this.currentChunkBuffer = null;
|
|
95
98
|
this.chunkPromises.clear();
|
|
@@ -118,15 +121,16 @@ class FileReadStream {
|
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
// Read from current chunk
|
|
121
|
-
const
|
|
124
|
+
const buf = this.currentChunkBuffer;
|
|
125
|
+
const availableInChunk = buf.length - this.positionInChunk;
|
|
122
126
|
const bytesToRead = Math.min(remainingBytes, availableInChunk);
|
|
123
|
-
const chunkPortion =
|
|
127
|
+
const chunkPortion = buf.subarray(this.positionInChunk, this.positionInChunk + bytesToRead);
|
|
124
128
|
chunks.push(chunkPortion);
|
|
125
129
|
remainingBytes -= bytesToRead;
|
|
126
130
|
this.positionInChunk += bytesToRead;
|
|
127
131
|
this.totalPosition += bytesToRead;
|
|
128
132
|
// If we've consumed the entire chunk, move to next one
|
|
129
|
-
if (this.positionInChunk >=
|
|
133
|
+
if (this.positionInChunk >= buf.length) {
|
|
130
134
|
this.currentChunkIndex++;
|
|
131
135
|
this.currentChunkBuffer = null;
|
|
132
136
|
this.positionInChunk = 0;
|
|
@@ -137,12 +141,13 @@ class FileReadStream {
|
|
|
137
141
|
}
|
|
138
142
|
async seek(position) {
|
|
139
143
|
if (position < 0) {
|
|
140
|
-
throw new Error(
|
|
144
|
+
throw new Error("Seek position cannot be negative");
|
|
141
145
|
}
|
|
142
146
|
if (position > this.fileRecord.fileSize) {
|
|
143
|
-
throw new Error(
|
|
147
|
+
throw new Error("Seek position beyond file size");
|
|
144
148
|
}
|
|
145
149
|
await this.loadChunkHashes();
|
|
150
|
+
const chunkHashes = this.chunkHashes;
|
|
146
151
|
// Calculate which chunk contains the target position
|
|
147
152
|
const targetChunkIndex = Math.floor(position / file_types_1.FILE_CHUNK_SIZE);
|
|
148
153
|
const positionInTargetChunk = position % file_types_1.FILE_CHUNK_SIZE;
|
|
@@ -151,7 +156,7 @@ class FileReadStream {
|
|
|
151
156
|
this.totalPosition = position;
|
|
152
157
|
this.currentChunkBuffer = null; // Will be loaded on next read
|
|
153
158
|
// Only set EOF if we're seeking beyond the last chunk OR at the very end of the file
|
|
154
|
-
this.eof =
|
|
159
|
+
this.eof = targetChunkIndex >= chunkHashes.length || position >= this.fileRecord.fileSize;
|
|
155
160
|
this.chunkPromises.clear();
|
|
156
161
|
await this.preloadChunks();
|
|
157
162
|
}
|
|
@@ -176,7 +181,11 @@ class FileReadStream {
|
|
|
176
181
|
const chunks = [];
|
|
177
182
|
let chunk;
|
|
178
183
|
try {
|
|
179
|
-
while (
|
|
184
|
+
while (true) {
|
|
185
|
+
chunk = await this.read();
|
|
186
|
+
if (chunk === null) {
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
180
189
|
chunks.push(chunk);
|
|
181
190
|
}
|
|
182
191
|
return new Uint8Array(Buffer.concat(chunks));
|
|
@@ -185,8 +194,8 @@ class FileReadStream {
|
|
|
185
194
|
// Only return null for chunk-specific errors (not found, download failed)
|
|
186
195
|
// Rethrow other errors like index file issues
|
|
187
196
|
if (error instanceof Error &&
|
|
188
|
-
|
|
189
|
-
|
|
197
|
+
error.message.includes("Chunk") &&
|
|
198
|
+
(error.message.includes("not found") || error.message.includes("integrity check failed"))) {
|
|
190
199
|
return null;
|
|
191
200
|
}
|
|
192
201
|
throw error;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IFile, IFileInput } from
|
|
2
|
-
import type { FilesTable } from
|
|
1
|
+
import { type IFile, type IFileInput } from "./file.types";
|
|
2
|
+
import type { FilesTable } from "./files";
|
|
3
3
|
export declare class FileWriteStream {
|
|
4
4
|
private metadata;
|
|
5
5
|
private fileTable;
|