taladb 0.8.0 → 0.8.2

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.
@@ -84,6 +84,7 @@ var WorkerProxy = class {
84
84
  constructor(port) {
85
85
  this.pending = /* @__PURE__ */ new Map();
86
86
  this.nextId = 1;
87
+ this.dead = null;
87
88
  this.port = port;
88
89
  this.port.onmessage = (e) => {
89
90
  const { id, result, error } = e.data;
@@ -97,12 +98,23 @@ var WorkerProxy = class {
97
98
  this.port.start?.();
98
99
  }
99
100
  send(op, args = {}) {
101
+ if (this.dead) return Promise.reject(this.dead);
100
102
  return new Promise((resolve, reject) => {
101
103
  const id = this.nextId++;
102
104
  this.pending.set(id, { resolve, reject });
103
105
  this.port.postMessage({ id, op, ...args });
104
106
  });
105
107
  }
108
+ /**
109
+ * Reject every in-flight request and refuse new ones. Called when the
110
+ * worker errors or is terminated — without this, pending promises would
111
+ * hang forever (awaiting callers deadlock).
112
+ */
113
+ abort(reason) {
114
+ this.dead = reason;
115
+ for (const [, p] of this.pending) p.reject(reason);
116
+ this.pending.clear();
117
+ }
106
118
  };
107
119
  function makePoller(findFn, callback) {
108
120
  let active = true;
@@ -129,6 +141,9 @@ async function createBrowserDB(dbName, config) {
129
141
  const workerUrl = new URL("@taladb/web/worker/taladb.worker.js", import.meta.url);
130
142
  const worker = new Worker(workerUrl, { type: "module", name: "taladb" });
131
143
  const proxy = new WorkerProxy(worker);
144
+ worker.onerror = (e) => {
145
+ proxy.abort(new Error(`taladb worker error: ${e.message ?? "unknown"}`));
146
+ };
132
147
  const configJson = config !== void 0 ? JSON.stringify(config) : void 0;
133
148
  await proxy.send("init", { dbName, configJson });
134
149
  const nudgeCallbacks = /* @__PURE__ */ new Set();
@@ -216,7 +231,7 @@ async function createBrowserDB(dbName, config) {
216
231
  },
217
232
  subscribe: (filter, callback) => {
218
233
  let active = true;
219
- let lastJson = "[]";
234
+ let lastJson = "";
220
235
  let timer = null;
221
236
  const poll = async () => {
222
237
  if (!active) return;
@@ -256,8 +271,12 @@ async function createBrowserDB(dbName, config) {
256
271
  compact: () => proxy.send("compact"),
257
272
  close: async () => {
258
273
  channel?.close();
259
- await proxy.send("close");
260
- worker.terminate();
274
+ try {
275
+ await proxy.send("close");
276
+ } finally {
277
+ worker.terminate();
278
+ proxy.abort(new Error("taladb worker closed"));
279
+ }
261
280
  }
262
281
  };
263
282
  }
@@ -268,14 +287,14 @@ async function createNodeDB(dbName, config) {
268
287
  function wrapCollection(name, opts) {
269
288
  const col = db.collection(name);
270
289
  const wrapped = {
271
- insert: async (doc) => col.insert(doc),
272
- insertMany: async (docs) => col.insertMany(docs),
273
- find: async (filter) => col.find(filter ?? null),
290
+ insert: async (doc) => col.insertAsync ? col.insertAsync(doc) : col.insert(doc),
291
+ insertMany: async (docs) => col.insertManyAsync ? col.insertManyAsync(docs) : col.insertMany(docs),
292
+ find: async (filter) => col.findAsync ? col.findAsync(filter ?? null) : col.find(filter ?? null),
274
293
  findOne: async (filter) => col.findOne(filter) ?? null,
275
- updateOne: async (filter, update) => col.updateOne(filter, update),
276
- updateMany: async (filter, update) => col.updateMany(filter, update),
277
- deleteOne: async (filter) => col.deleteOne(filter),
278
- deleteMany: async (filter) => col.deleteMany(filter),
294
+ updateOne: async (filter, update) => col.updateOneAsync ? col.updateOneAsync(filter, update) : col.updateOne(filter, update),
295
+ updateMany: async (filter, update) => col.updateManyAsync ? col.updateManyAsync(filter, update) : col.updateMany(filter, update),
296
+ deleteOne: async (filter) => col.deleteOneAsync ? col.deleteOneAsync(filter) : col.deleteOne(filter),
297
+ deleteMany: async (filter) => col.deleteManyAsync ? col.deleteManyAsync(filter) : col.deleteMany(filter),
279
298
  count: async (filter) => col.count(filter ?? null),
280
299
  createIndex: async (field) => col.createIndex(field),
281
300
  dropIndex: async (field) => col.dropIndex(field),
@@ -299,8 +318,8 @@ async function createNodeDB(dbName, config) {
299
318
  return {
300
319
  collection: (name, opts) => wrapCollection(name, opts),
301
320
  compact: async () => db.compact(),
302
- close: async () => {
303
- }
321
+ // Releases the native file handle/lock (no-op on older .node binaries).
322
+ close: async () => db.close?.()
304
323
  };
305
324
  }
306
325
  async function createNativeDB(_dbName) {
@@ -336,7 +355,9 @@ async function createNativeDB(_dbName) {
336
355
  },
337
356
  dropVectorIndex: async (field) => native.dropVectorIndex(name, field),
338
357
  upgradeVectorIndex: async (field) => native.upgradeVectorIndex(name, field),
339
- listIndexes: async () => ({}),
358
+ // The JSI HostObject does not expose index introspection yet; return a
359
+ // correctly-shaped empty result rather than `{}` cast to the interface.
360
+ listIndexes: async () => ({ btree: [], fts: [], vector: [] }),
340
361
  findNearest: async (field, vector, topK, filter) => {
341
362
  const raw = native.findNearest(name, field, vector, topK, filter ?? null);
342
363
  return raw;
package/dist/index.js CHANGED
@@ -179,6 +179,7 @@ var WorkerProxy = class {
179
179
  constructor(port) {
180
180
  this.pending = /* @__PURE__ */ new Map();
181
181
  this.nextId = 1;
182
+ this.dead = null;
182
183
  this.port = port;
183
184
  this.port.onmessage = (e) => {
184
185
  const { id, result, error } = e.data;
@@ -192,12 +193,23 @@ var WorkerProxy = class {
192
193
  this.port.start?.();
193
194
  }
194
195
  send(op, args = {}) {
196
+ if (this.dead) return Promise.reject(this.dead);
195
197
  return new Promise((resolve, reject) => {
196
198
  const id = this.nextId++;
197
199
  this.pending.set(id, { resolve, reject });
198
200
  this.port.postMessage({ id, op, ...args });
199
201
  });
200
202
  }
203
+ /**
204
+ * Reject every in-flight request and refuse new ones. Called when the
205
+ * worker errors or is terminated — without this, pending promises would
206
+ * hang forever (awaiting callers deadlock).
207
+ */
208
+ abort(reason) {
209
+ this.dead = reason;
210
+ for (const [, p] of this.pending) p.reject(reason);
211
+ this.pending.clear();
212
+ }
201
213
  };
202
214
  function makePoller(findFn, callback) {
203
215
  let active = true;
@@ -224,6 +236,9 @@ async function createBrowserDB(dbName, config) {
224
236
  const workerUrl = new URL("@taladb/web/worker/taladb.worker.js", import_meta.url);
225
237
  const worker = new Worker(workerUrl, { type: "module", name: "taladb" });
226
238
  const proxy = new WorkerProxy(worker);
239
+ worker.onerror = (e) => {
240
+ proxy.abort(new Error(`taladb worker error: ${e.message ?? "unknown"}`));
241
+ };
227
242
  const configJson = config !== void 0 ? JSON.stringify(config) : void 0;
228
243
  await proxy.send("init", { dbName, configJson });
229
244
  const nudgeCallbacks = /* @__PURE__ */ new Set();
@@ -311,7 +326,7 @@ async function createBrowserDB(dbName, config) {
311
326
  },
312
327
  subscribe: (filter, callback) => {
313
328
  let active = true;
314
- let lastJson = "[]";
329
+ let lastJson = "";
315
330
  let timer = null;
316
331
  const poll = async () => {
317
332
  if (!active) return;
@@ -351,8 +366,12 @@ async function createBrowserDB(dbName, config) {
351
366
  compact: () => proxy.send("compact"),
352
367
  close: async () => {
353
368
  channel?.close();
354
- await proxy.send("close");
355
- worker.terminate();
369
+ try {
370
+ await proxy.send("close");
371
+ } finally {
372
+ worker.terminate();
373
+ proxy.abort(new Error("taladb worker closed"));
374
+ }
356
375
  }
357
376
  };
358
377
  }
@@ -363,14 +382,14 @@ async function createNodeDB(dbName, config) {
363
382
  function wrapCollection(name, opts) {
364
383
  const col = db.collection(name);
365
384
  const wrapped = {
366
- insert: async (doc) => col.insert(doc),
367
- insertMany: async (docs) => col.insertMany(docs),
368
- find: async (filter) => col.find(filter ?? null),
385
+ insert: async (doc) => col.insertAsync ? col.insertAsync(doc) : col.insert(doc),
386
+ insertMany: async (docs) => col.insertManyAsync ? col.insertManyAsync(docs) : col.insertMany(docs),
387
+ find: async (filter) => col.findAsync ? col.findAsync(filter ?? null) : col.find(filter ?? null),
369
388
  findOne: async (filter) => col.findOne(filter) ?? null,
370
- updateOne: async (filter, update) => col.updateOne(filter, update),
371
- updateMany: async (filter, update) => col.updateMany(filter, update),
372
- deleteOne: async (filter) => col.deleteOne(filter),
373
- deleteMany: async (filter) => col.deleteMany(filter),
389
+ updateOne: async (filter, update) => col.updateOneAsync ? col.updateOneAsync(filter, update) : col.updateOne(filter, update),
390
+ updateMany: async (filter, update) => col.updateManyAsync ? col.updateManyAsync(filter, update) : col.updateMany(filter, update),
391
+ deleteOne: async (filter) => col.deleteOneAsync ? col.deleteOneAsync(filter) : col.deleteOne(filter),
392
+ deleteMany: async (filter) => col.deleteManyAsync ? col.deleteManyAsync(filter) : col.deleteMany(filter),
374
393
  count: async (filter) => col.count(filter ?? null),
375
394
  createIndex: async (field) => col.createIndex(field),
376
395
  dropIndex: async (field) => col.dropIndex(field),
@@ -394,8 +413,8 @@ async function createNodeDB(dbName, config) {
394
413
  return {
395
414
  collection: (name, opts) => wrapCollection(name, opts),
396
415
  compact: async () => db.compact(),
397
- close: async () => {
398
- }
416
+ // Releases the native file handle/lock (no-op on older .node binaries).
417
+ close: async () => db.close?.()
399
418
  };
400
419
  }
401
420
  async function createNativeDB(_dbName) {
@@ -431,7 +450,9 @@ async function createNativeDB(_dbName) {
431
450
  },
432
451
  dropVectorIndex: async (field) => native.dropVectorIndex(name, field),
433
452
  upgradeVectorIndex: async (field) => native.upgradeVectorIndex(name, field),
434
- listIndexes: async () => ({}),
453
+ // The JSI HostObject does not expose index introspection yet; return a
454
+ // correctly-shaped empty result rather than `{}` cast to the interface.
455
+ listIndexes: async () => ({ btree: [], fts: [], vector: [] }),
435
456
  findNearest: async (field, vector, topK, filter) => {
436
457
  const raw = native.findNearest(name, field, vector, topK, filter ?? null);
437
458
  return raw;
package/dist/index.mjs CHANGED
@@ -141,6 +141,7 @@ var WorkerProxy = class {
141
141
  constructor(port) {
142
142
  this.pending = /* @__PURE__ */ new Map();
143
143
  this.nextId = 1;
144
+ this.dead = null;
144
145
  this.port = port;
145
146
  this.port.onmessage = (e) => {
146
147
  const { id, result, error } = e.data;
@@ -154,12 +155,23 @@ var WorkerProxy = class {
154
155
  this.port.start?.();
155
156
  }
156
157
  send(op, args = {}) {
158
+ if (this.dead) return Promise.reject(this.dead);
157
159
  return new Promise((resolve, reject) => {
158
160
  const id = this.nextId++;
159
161
  this.pending.set(id, { resolve, reject });
160
162
  this.port.postMessage({ id, op, ...args });
161
163
  });
162
164
  }
165
+ /**
166
+ * Reject every in-flight request and refuse new ones. Called when the
167
+ * worker errors or is terminated — without this, pending promises would
168
+ * hang forever (awaiting callers deadlock).
169
+ */
170
+ abort(reason) {
171
+ this.dead = reason;
172
+ for (const [, p] of this.pending) p.reject(reason);
173
+ this.pending.clear();
174
+ }
163
175
  };
164
176
  function makePoller(findFn, callback) {
165
177
  let active = true;
@@ -186,6 +198,9 @@ async function createBrowserDB(dbName, config) {
186
198
  const workerUrl = new URL("@taladb/web/worker/taladb.worker.js", import.meta.url);
187
199
  const worker = new Worker(workerUrl, { type: "module", name: "taladb" });
188
200
  const proxy = new WorkerProxy(worker);
201
+ worker.onerror = (e) => {
202
+ proxy.abort(new Error(`taladb worker error: ${e.message ?? "unknown"}`));
203
+ };
189
204
  const configJson = config !== void 0 ? JSON.stringify(config) : void 0;
190
205
  await proxy.send("init", { dbName, configJson });
191
206
  const nudgeCallbacks = /* @__PURE__ */ new Set();
@@ -273,7 +288,7 @@ async function createBrowserDB(dbName, config) {
273
288
  },
274
289
  subscribe: (filter, callback) => {
275
290
  let active = true;
276
- let lastJson = "[]";
291
+ let lastJson = "";
277
292
  let timer = null;
278
293
  const poll = async () => {
279
294
  if (!active) return;
@@ -313,8 +328,12 @@ async function createBrowserDB(dbName, config) {
313
328
  compact: () => proxy.send("compact"),
314
329
  close: async () => {
315
330
  channel?.close();
316
- await proxy.send("close");
317
- worker.terminate();
331
+ try {
332
+ await proxy.send("close");
333
+ } finally {
334
+ worker.terminate();
335
+ proxy.abort(new Error("taladb worker closed"));
336
+ }
318
337
  }
319
338
  };
320
339
  }
@@ -325,14 +344,14 @@ async function createNodeDB(dbName, config) {
325
344
  function wrapCollection(name, opts) {
326
345
  const col = db.collection(name);
327
346
  const wrapped = {
328
- insert: async (doc) => col.insert(doc),
329
- insertMany: async (docs) => col.insertMany(docs),
330
- find: async (filter) => col.find(filter ?? null),
347
+ insert: async (doc) => col.insertAsync ? col.insertAsync(doc) : col.insert(doc),
348
+ insertMany: async (docs) => col.insertManyAsync ? col.insertManyAsync(docs) : col.insertMany(docs),
349
+ find: async (filter) => col.findAsync ? col.findAsync(filter ?? null) : col.find(filter ?? null),
331
350
  findOne: async (filter) => col.findOne(filter) ?? null,
332
- updateOne: async (filter, update) => col.updateOne(filter, update),
333
- updateMany: async (filter, update) => col.updateMany(filter, update),
334
- deleteOne: async (filter) => col.deleteOne(filter),
335
- deleteMany: async (filter) => col.deleteMany(filter),
351
+ updateOne: async (filter, update) => col.updateOneAsync ? col.updateOneAsync(filter, update) : col.updateOne(filter, update),
352
+ updateMany: async (filter, update) => col.updateManyAsync ? col.updateManyAsync(filter, update) : col.updateMany(filter, update),
353
+ deleteOne: async (filter) => col.deleteOneAsync ? col.deleteOneAsync(filter) : col.deleteOne(filter),
354
+ deleteMany: async (filter) => col.deleteManyAsync ? col.deleteManyAsync(filter) : col.deleteMany(filter),
336
355
  count: async (filter) => col.count(filter ?? null),
337
356
  createIndex: async (field) => col.createIndex(field),
338
357
  dropIndex: async (field) => col.dropIndex(field),
@@ -356,8 +375,8 @@ async function createNodeDB(dbName, config) {
356
375
  return {
357
376
  collection: (name, opts) => wrapCollection(name, opts),
358
377
  compact: async () => db.compact(),
359
- close: async () => {
360
- }
378
+ // Releases the native file handle/lock (no-op on older .node binaries).
379
+ close: async () => db.close?.()
361
380
  };
362
381
  }
363
382
  async function createNativeDB(_dbName) {
@@ -393,7 +412,9 @@ async function createNativeDB(_dbName) {
393
412
  },
394
413
  dropVectorIndex: async (field) => native.dropVectorIndex(name, field),
395
414
  upgradeVectorIndex: async (field) => native.upgradeVectorIndex(name, field),
396
- listIndexes: async () => ({}),
415
+ // The JSI HostObject does not expose index introspection yet; return a
416
+ // correctly-shaped empty result rather than `{}` cast to the interface.
417
+ listIndexes: async () => ({ btree: [], fts: [], vector: [] }),
397
418
  findNearest: async (field, vector, topK, filter) => {
398
419
  const raw = native.findNearest(name, field, vector, topK, filter ?? null);
399
420
  return raw;
@@ -84,6 +84,7 @@ var WorkerProxy = class {
84
84
  constructor(port) {
85
85
  this.pending = /* @__PURE__ */ new Map();
86
86
  this.nextId = 1;
87
+ this.dead = null;
87
88
  this.port = port;
88
89
  this.port.onmessage = (e) => {
89
90
  const { id, result, error } = e.data;
@@ -97,12 +98,23 @@ var WorkerProxy = class {
97
98
  this.port.start?.();
98
99
  }
99
100
  send(op, args = {}) {
101
+ if (this.dead) return Promise.reject(this.dead);
100
102
  return new Promise((resolve, reject) => {
101
103
  const id = this.nextId++;
102
104
  this.pending.set(id, { resolve, reject });
103
105
  this.port.postMessage({ id, op, ...args });
104
106
  });
105
107
  }
108
+ /**
109
+ * Reject every in-flight request and refuse new ones. Called when the
110
+ * worker errors or is terminated — without this, pending promises would
111
+ * hang forever (awaiting callers deadlock).
112
+ */
113
+ abort(reason) {
114
+ this.dead = reason;
115
+ for (const [, p] of this.pending) p.reject(reason);
116
+ this.pending.clear();
117
+ }
106
118
  };
107
119
  function makePoller(findFn, callback) {
108
120
  let active = true;
@@ -129,6 +141,9 @@ async function createBrowserDB(dbName, config) {
129
141
  const workerUrl = new URL("@taladb/web/worker/taladb.worker.js", "react-native://unreachable");
130
142
  const worker = new Worker(workerUrl, { type: "module", name: "taladb" });
131
143
  const proxy = new WorkerProxy(worker);
144
+ worker.onerror = (e) => {
145
+ proxy.abort(new Error(`taladb worker error: ${e.message ?? "unknown"}`));
146
+ };
132
147
  const configJson = config !== void 0 ? JSON.stringify(config) : void 0;
133
148
  await proxy.send("init", { dbName, configJson });
134
149
  const nudgeCallbacks = /* @__PURE__ */ new Set();
@@ -216,7 +231,7 @@ async function createBrowserDB(dbName, config) {
216
231
  },
217
232
  subscribe: (filter, callback) => {
218
233
  let active = true;
219
- let lastJson = "[]";
234
+ let lastJson = "";
220
235
  let timer = null;
221
236
  const poll = async () => {
222
237
  if (!active) return;
@@ -256,8 +271,12 @@ async function createBrowserDB(dbName, config) {
256
271
  compact: () => proxy.send("compact"),
257
272
  close: async () => {
258
273
  channel?.close();
259
- await proxy.send("close");
260
- worker.terminate();
274
+ try {
275
+ await proxy.send("close");
276
+ } finally {
277
+ worker.terminate();
278
+ proxy.abort(new Error("taladb worker closed"));
279
+ }
261
280
  }
262
281
  };
263
282
  }
@@ -268,14 +287,14 @@ async function createNodeDB(dbName, config) {
268
287
  function wrapCollection(name, opts) {
269
288
  const col = db.collection(name);
270
289
  const wrapped = {
271
- insert: async (doc) => col.insert(doc),
272
- insertMany: async (docs) => col.insertMany(docs),
273
- find: async (filter) => col.find(filter ?? null),
290
+ insert: async (doc) => col.insertAsync ? col.insertAsync(doc) : col.insert(doc),
291
+ insertMany: async (docs) => col.insertManyAsync ? col.insertManyAsync(docs) : col.insertMany(docs),
292
+ find: async (filter) => col.findAsync ? col.findAsync(filter ?? null) : col.find(filter ?? null),
274
293
  findOne: async (filter) => col.findOne(filter) ?? null,
275
- updateOne: async (filter, update) => col.updateOne(filter, update),
276
- updateMany: async (filter, update) => col.updateMany(filter, update),
277
- deleteOne: async (filter) => col.deleteOne(filter),
278
- deleteMany: async (filter) => col.deleteMany(filter),
294
+ updateOne: async (filter, update) => col.updateOneAsync ? col.updateOneAsync(filter, update) : col.updateOne(filter, update),
295
+ updateMany: async (filter, update) => col.updateManyAsync ? col.updateManyAsync(filter, update) : col.updateMany(filter, update),
296
+ deleteOne: async (filter) => col.deleteOneAsync ? col.deleteOneAsync(filter) : col.deleteOne(filter),
297
+ deleteMany: async (filter) => col.deleteManyAsync ? col.deleteManyAsync(filter) : col.deleteMany(filter),
279
298
  count: async (filter) => col.count(filter ?? null),
280
299
  createIndex: async (field) => col.createIndex(field),
281
300
  dropIndex: async (field) => col.dropIndex(field),
@@ -299,8 +318,8 @@ async function createNodeDB(dbName, config) {
299
318
  return {
300
319
  collection: (name, opts) => wrapCollection(name, opts),
301
320
  compact: async () => db.compact(),
302
- close: async () => {
303
- }
321
+ // Releases the native file handle/lock (no-op on older .node binaries).
322
+ close: async () => db.close?.()
304
323
  };
305
324
  }
306
325
  async function createNativeDB(_dbName) {
@@ -336,7 +355,9 @@ async function createNativeDB(_dbName) {
336
355
  },
337
356
  dropVectorIndex: async (field) => native.dropVectorIndex(name, field),
338
357
  upgradeVectorIndex: async (field) => native.upgradeVectorIndex(name, field),
339
- listIndexes: async () => ({}),
358
+ // The JSI HostObject does not expose index introspection yet; return a
359
+ // correctly-shaped empty result rather than `{}` cast to the interface.
360
+ listIndexes: async () => ({ btree: [], fts: [], vector: [] }),
340
361
  findNearest: async (field, vector, topK, filter) => {
341
362
  const raw = native.findNearest(name, field, vector, topK, filter ?? null);
342
363
  return raw;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taladb",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Local-first document and vector database for React, React Native, and Node.js",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",