taladb 0.3.0 → 0.4.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/index.d.mts CHANGED
@@ -5,6 +5,26 @@ interface VectorIndexOptions {
5
5
  dimensions: number;
6
6
  /** Similarity metric. Defaults to `"cosine"`. */
7
7
  metric?: VectorMetric;
8
+ /**
9
+ * Index algorithm. Defaults to `"flat"` (exact brute-force).
10
+ * Use `"hnsw"` for approximate nearest-neighbour search — much faster on
11
+ * large collections at the cost of occasional missed results.
12
+ * Requires the `vector-hnsw` feature to be compiled in.
13
+ */
14
+ indexType?: 'flat' | 'hnsw';
15
+ /** HNSW connectivity parameter M (default 16). Higher = better recall, more memory. */
16
+ hnswM?: number;
17
+ /** HNSW build-time quality parameter ef_construction (default 200). */
18
+ hnswEfConstruction?: number;
19
+ }
20
+ /** Describes the indexes that exist on a collection. */
21
+ interface CollectionIndexInfo {
22
+ /** B-tree indexes (created with `createIndex`). */
23
+ btree: string[];
24
+ /** Full-text search indexes (created with `createFtsIndex`). */
25
+ fts: string[];
26
+ /** Vector indexes (created with `createVectorIndex`). */
27
+ vector: string[];
8
28
  }
9
29
  /** A single result returned by `Collection.findNearest`. */
10
30
  interface VectorSearchResult<T extends Document = Document> {
@@ -72,6 +92,25 @@ interface Collection<T extends Document = Document> {
72
92
  count(filter?: Filter<T>): Promise<number>;
73
93
  createIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
74
94
  dropIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
95
+ /**
96
+ * Create a full-text search index on a string field.
97
+ *
98
+ * Enables fast `{ field: { $contains: 'token' } }` queries using an
99
+ * inverted token index instead of a full collection scan.
100
+ *
101
+ * @example
102
+ * await notes.createFtsIndex('body');
103
+ */
104
+ createFtsIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
105
+ /** Drop a full-text search index. */
106
+ dropFtsIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
107
+ /**
108
+ * Return the indexes that currently exist on this collection.
109
+ *
110
+ * @example
111
+ * const { btree, fts, vector } = await notes.listIndexes();
112
+ */
113
+ listIndexes(): Promise<CollectionIndexInfo>;
75
114
  /**
76
115
  * Create a vector index on a numeric-array field.
77
116
  *
@@ -84,6 +123,14 @@ interface Collection<T extends Document = Document> {
84
123
  createVectorIndex(field: keyof Omit<T, '_id'> & string, options: VectorIndexOptions): Promise<void>;
85
124
  /** Drop a vector index. */
86
125
  dropVectorIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
126
+ /**
127
+ * Upgrade a flat vector index to HNSW in-place.
128
+ *
129
+ * After calling this, `findNearest` uses approximate nearest-neighbour
130
+ * search which is significantly faster on large collections.
131
+ * Requires the `vector-hnsw` feature to be compiled in; no-op otherwise.
132
+ */
133
+ upgradeVectorIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
87
134
  /**
88
135
  * Find the `topK` most similar documents to `vector` using a vector index.
89
136
  *
@@ -136,4 +183,4 @@ interface TalaDB {
136
183
  */
137
184
  declare function openDB(dbName?: string): Promise<TalaDB>;
138
185
 
139
- export { type Collection, type Document, type Filter, type TalaDB, type Update, type Value, type VectorIndexOptions, type VectorMetric, type VectorSearchResult, openDB };
186
+ export { type Collection, type CollectionIndexInfo, type Document, type Filter, type TalaDB, type Update, type Value, type VectorIndexOptions, type VectorMetric, type VectorSearchResult, openDB };
package/dist/index.d.ts CHANGED
@@ -5,6 +5,26 @@ interface VectorIndexOptions {
5
5
  dimensions: number;
6
6
  /** Similarity metric. Defaults to `"cosine"`. */
7
7
  metric?: VectorMetric;
8
+ /**
9
+ * Index algorithm. Defaults to `"flat"` (exact brute-force).
10
+ * Use `"hnsw"` for approximate nearest-neighbour search — much faster on
11
+ * large collections at the cost of occasional missed results.
12
+ * Requires the `vector-hnsw` feature to be compiled in.
13
+ */
14
+ indexType?: 'flat' | 'hnsw';
15
+ /** HNSW connectivity parameter M (default 16). Higher = better recall, more memory. */
16
+ hnswM?: number;
17
+ /** HNSW build-time quality parameter ef_construction (default 200). */
18
+ hnswEfConstruction?: number;
19
+ }
20
+ /** Describes the indexes that exist on a collection. */
21
+ interface CollectionIndexInfo {
22
+ /** B-tree indexes (created with `createIndex`). */
23
+ btree: string[];
24
+ /** Full-text search indexes (created with `createFtsIndex`). */
25
+ fts: string[];
26
+ /** Vector indexes (created with `createVectorIndex`). */
27
+ vector: string[];
8
28
  }
9
29
  /** A single result returned by `Collection.findNearest`. */
10
30
  interface VectorSearchResult<T extends Document = Document> {
@@ -72,6 +92,25 @@ interface Collection<T extends Document = Document> {
72
92
  count(filter?: Filter<T>): Promise<number>;
73
93
  createIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
74
94
  dropIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
95
+ /**
96
+ * Create a full-text search index on a string field.
97
+ *
98
+ * Enables fast `{ field: { $contains: 'token' } }` queries using an
99
+ * inverted token index instead of a full collection scan.
100
+ *
101
+ * @example
102
+ * await notes.createFtsIndex('body');
103
+ */
104
+ createFtsIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
105
+ /** Drop a full-text search index. */
106
+ dropFtsIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
107
+ /**
108
+ * Return the indexes that currently exist on this collection.
109
+ *
110
+ * @example
111
+ * const { btree, fts, vector } = await notes.listIndexes();
112
+ */
113
+ listIndexes(): Promise<CollectionIndexInfo>;
75
114
  /**
76
115
  * Create a vector index on a numeric-array field.
77
116
  *
@@ -84,6 +123,14 @@ interface Collection<T extends Document = Document> {
84
123
  createVectorIndex(field: keyof Omit<T, '_id'> & string, options: VectorIndexOptions): Promise<void>;
85
124
  /** Drop a vector index. */
86
125
  dropVectorIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
126
+ /**
127
+ * Upgrade a flat vector index to HNSW in-place.
128
+ *
129
+ * After calling this, `findNearest` uses approximate nearest-neighbour
130
+ * search which is significantly faster on large collections.
131
+ * Requires the `vector-hnsw` feature to be compiled in; no-op otherwise.
132
+ */
133
+ upgradeVectorIndex(field: keyof Omit<T, '_id'> & string): Promise<void>;
87
134
  /**
88
135
  * Find the `topK` most similar documents to `vector` using a vector index.
89
136
  *
@@ -136,4 +183,4 @@ interface TalaDB {
136
183
  */
137
184
  declare function openDB(dbName?: string): Promise<TalaDB>;
138
185
 
139
- export { type Collection, type Document, type Filter, type TalaDB, type Update, type Value, type VectorIndexOptions, type VectorMetric, type VectorSearchResult, openDB };
186
+ export { type Collection, type CollectionIndexInfo, type Document, type Filter, type TalaDB, type Update, type Value, type VectorIndexOptions, type VectorMetric, type VectorSearchResult, openDB };
package/dist/index.js CHANGED
@@ -67,11 +67,42 @@ var WorkerProxy = class {
67
67
  });
68
68
  }
69
69
  };
70
+ function makePoller(findFn, callback) {
71
+ let active = true;
72
+ let lastJson = "";
73
+ const poll = async () => {
74
+ if (!active) return;
75
+ try {
76
+ const docs = await findFn();
77
+ const json = JSON.stringify(docs);
78
+ if (json !== lastJson) {
79
+ lastJson = json;
80
+ callback(docs);
81
+ }
82
+ } catch {
83
+ }
84
+ if (active) setTimeout(poll, 300);
85
+ };
86
+ poll();
87
+ return () => {
88
+ active = false;
89
+ };
90
+ }
70
91
  async function createBrowserDB(dbName) {
71
92
  const workerUrl = new URL("@taladb/web/worker/taladb.worker.js", import_meta.url);
72
93
  const worker = new Worker(workerUrl, { type: "module", name: "taladb" });
73
94
  const proxy = new WorkerProxy(worker);
74
95
  await proxy.send("init", { dbName });
96
+ const nudgeCallbacks = /* @__PURE__ */ new Set();
97
+ let channel = null;
98
+ if (typeof BroadcastChannel !== "undefined") {
99
+ channel = new BroadcastChannel(`taladb:${dbName}`);
100
+ channel.onmessage = (e) => {
101
+ if (e.data === "taladb:changed") {
102
+ for (const nudge of nudgeCallbacks) nudge();
103
+ }
104
+ };
105
+ }
75
106
  function wrapCollection(name) {
76
107
  const s = JSON.stringify;
77
108
  return {
@@ -115,13 +146,26 @@ async function createBrowserDB(dbName) {
115
146
  }),
116
147
  createIndex: (field) => proxy.send("createIndex", { collection: name, field }),
117
148
  dropIndex: (field) => proxy.send("dropIndex", { collection: name, field }),
118
- createVectorIndex: (field, options) => proxy.send("createVectorIndex", {
119
- collection: name,
120
- field,
121
- dimensions: options.dimensions,
122
- metric: options.metric
123
- }),
149
+ createFtsIndex: (field) => proxy.send("createFtsIndex", { collection: name, field }),
150
+ dropFtsIndex: (field) => proxy.send("dropFtsIndex", { collection: name, field }),
151
+ createVectorIndex: (field, options) => {
152
+ if (options.indexType === "hnsw") return Promise.reject(new Error("HNSW vector indexes are not available in the browser (requires native threads). Use Node.js or React Native."));
153
+ return proxy.send("createVectorIndex", {
154
+ collection: name,
155
+ field,
156
+ dimensions: options.dimensions,
157
+ metric: options.metric,
158
+ indexType: null,
159
+ hnswM: null,
160
+ hnswEfConstruction: null
161
+ });
162
+ },
124
163
  dropVectorIndex: (field) => proxy.send("dropVectorIndex", { collection: name, field }),
164
+ upgradeVectorIndex: (_field) => Promise.reject(new Error("HNSW vector indexes are not available in the browser (requires native threads). Use Node.js or React Native.")),
165
+ listIndexes: async () => {
166
+ const json = await proxy.send("listIndexes", { collection: name });
167
+ return JSON.parse(json);
168
+ },
125
169
  findNearest: async (field, vector, topK, filter) => {
126
170
  const json = await proxy.send("findNearest", {
127
171
  collection: name,
@@ -134,9 +178,14 @@ async function createBrowserDB(dbName) {
134
178
  },
135
179
  subscribe: (filter, callback) => {
136
180
  let active = true;
137
- let lastJson = "";
181
+ let lastJson = "[]";
182
+ let timer = null;
138
183
  const poll = async () => {
139
184
  if (!active) return;
185
+ if (timer !== null) {
186
+ clearTimeout(timer);
187
+ timer = null;
188
+ }
140
189
  try {
141
190
  const json = await proxy.send("find", {
142
191
  collection: name,
@@ -148,11 +197,17 @@ async function createBrowserDB(dbName) {
148
197
  }
149
198
  } catch {
150
199
  }
151
- if (active) setTimeout(poll, 300);
200
+ if (active) timer = setTimeout(poll, 300);
152
201
  };
202
+ nudgeCallbacks.add(poll);
153
203
  poll();
154
204
  return () => {
155
205
  active = false;
206
+ nudgeCallbacks.delete(poll);
207
+ if (timer !== null) {
208
+ clearTimeout(timer);
209
+ timer = null;
210
+ }
156
211
  };
157
212
  }
158
213
  };
@@ -160,6 +215,7 @@ async function createBrowserDB(dbName) {
160
215
  return {
161
216
  collection: (name) => wrapCollection(name),
162
217
  close: async () => {
218
+ channel?.close();
163
219
  await proxy.send("close");
164
220
  worker.terminate();
165
221
  }
@@ -182,33 +238,20 @@ async function createNodeDB(dbName) {
182
238
  count: async (filter) => col.count(filter ?? null),
183
239
  createIndex: async (field) => col.createIndex(field),
184
240
  dropIndex: async (field) => col.dropIndex(field),
185
- createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null),
241
+ createFtsIndex: async (field) => col.createFtsIndex(field),
242
+ dropFtsIndex: async (field) => col.dropFtsIndex(field),
243
+ createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null, options.indexType ?? null, options.hnswM ?? null, options.hnswEfConstruction ?? null),
186
244
  dropVectorIndex: async (field) => col.dropVectorIndex(field),
245
+ upgradeVectorIndex: async (field) => col.upgradeVectorIndex(field),
246
+ listIndexes: async () => {
247
+ const json = col.listIndexes();
248
+ return JSON.parse(json);
249
+ },
187
250
  findNearest: async (field, vector, topK, filter) => {
188
251
  const raw = await col.findNearest(field, vector, topK, filter ?? null);
189
252
  return raw;
190
253
  },
191
- subscribe: (filter, callback) => {
192
- let active = true;
193
- let lastJson = "";
194
- const poll = async () => {
195
- if (!active) return;
196
- try {
197
- const docs = await col.find(filter ?? null);
198
- const json = JSON.stringify(docs);
199
- if (json !== lastJson) {
200
- lastJson = json;
201
- callback(docs);
202
- }
203
- } catch {
204
- }
205
- if (active) setTimeout(poll, 300);
206
- };
207
- poll();
208
- return () => {
209
- active = false;
210
- };
211
- }
254
+ subscribe: (filter, callback) => makePoller(async () => col.find(filter ?? null), callback)
212
255
  };
213
256
  }
214
257
  return {
@@ -239,33 +282,17 @@ async function createNativeDB(_dbName) {
239
282
  count: async (filter) => col.count(filter ?? {}),
240
283
  createIndex: async (field) => col.createIndex(field),
241
284
  dropIndex: async (field) => col.dropIndex(field),
242
- createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null),
285
+ createFtsIndex: async (field) => col.createFtsIndex(field),
286
+ dropFtsIndex: async (field) => col.dropFtsIndex(field),
287
+ createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null, options.indexType ?? null, options.hnswM ?? null, options.hnswEfConstruction ?? null),
243
288
  dropVectorIndex: async (field) => col.dropVectorIndex(field),
289
+ upgradeVectorIndex: async (field) => col.upgradeVectorIndex(field),
290
+ listIndexes: async () => JSON.parse(col.listIndexes()),
244
291
  findNearest: async (field, vector, topK, filter) => {
245
292
  const raw = col.findNearest(field, vector, topK, filter ?? null);
246
293
  return raw;
247
294
  },
248
- subscribe: (filter, callback) => {
249
- let active = true;
250
- let lastJson = "";
251
- const poll = () => {
252
- if (!active) return;
253
- try {
254
- const docs = col.find(filter ?? {});
255
- const json = JSON.stringify(docs);
256
- if (json !== lastJson) {
257
- lastJson = json;
258
- callback(docs);
259
- }
260
- } catch {
261
- }
262
- if (active) setTimeout(poll, 300);
263
- };
264
- poll();
265
- return () => {
266
- active = false;
267
- };
268
- }
295
+ subscribe: (filter, callback) => makePoller(async () => col.find(filter ?? {}), callback)
269
296
  };
270
297
  }
271
298
  return {
package/dist/index.mjs CHANGED
@@ -32,11 +32,42 @@ var WorkerProxy = class {
32
32
  });
33
33
  }
34
34
  };
35
+ function makePoller(findFn, callback) {
36
+ let active = true;
37
+ let lastJson = "";
38
+ const poll = async () => {
39
+ if (!active) return;
40
+ try {
41
+ const docs = await findFn();
42
+ const json = JSON.stringify(docs);
43
+ if (json !== lastJson) {
44
+ lastJson = json;
45
+ callback(docs);
46
+ }
47
+ } catch {
48
+ }
49
+ if (active) setTimeout(poll, 300);
50
+ };
51
+ poll();
52
+ return () => {
53
+ active = false;
54
+ };
55
+ }
35
56
  async function createBrowserDB(dbName) {
36
57
  const workerUrl = new URL("@taladb/web/worker/taladb.worker.js", import.meta.url);
37
58
  const worker = new Worker(workerUrl, { type: "module", name: "taladb" });
38
59
  const proxy = new WorkerProxy(worker);
39
60
  await proxy.send("init", { dbName });
61
+ const nudgeCallbacks = /* @__PURE__ */ new Set();
62
+ let channel = null;
63
+ if (typeof BroadcastChannel !== "undefined") {
64
+ channel = new BroadcastChannel(`taladb:${dbName}`);
65
+ channel.onmessage = (e) => {
66
+ if (e.data === "taladb:changed") {
67
+ for (const nudge of nudgeCallbacks) nudge();
68
+ }
69
+ };
70
+ }
40
71
  function wrapCollection(name) {
41
72
  const s = JSON.stringify;
42
73
  return {
@@ -80,13 +111,26 @@ async function createBrowserDB(dbName) {
80
111
  }),
81
112
  createIndex: (field) => proxy.send("createIndex", { collection: name, field }),
82
113
  dropIndex: (field) => proxy.send("dropIndex", { collection: name, field }),
83
- createVectorIndex: (field, options) => proxy.send("createVectorIndex", {
84
- collection: name,
85
- field,
86
- dimensions: options.dimensions,
87
- metric: options.metric
88
- }),
114
+ createFtsIndex: (field) => proxy.send("createFtsIndex", { collection: name, field }),
115
+ dropFtsIndex: (field) => proxy.send("dropFtsIndex", { collection: name, field }),
116
+ createVectorIndex: (field, options) => {
117
+ if (options.indexType === "hnsw") return Promise.reject(new Error("HNSW vector indexes are not available in the browser (requires native threads). Use Node.js or React Native."));
118
+ return proxy.send("createVectorIndex", {
119
+ collection: name,
120
+ field,
121
+ dimensions: options.dimensions,
122
+ metric: options.metric,
123
+ indexType: null,
124
+ hnswM: null,
125
+ hnswEfConstruction: null
126
+ });
127
+ },
89
128
  dropVectorIndex: (field) => proxy.send("dropVectorIndex", { collection: name, field }),
129
+ upgradeVectorIndex: (_field) => Promise.reject(new Error("HNSW vector indexes are not available in the browser (requires native threads). Use Node.js or React Native.")),
130
+ listIndexes: async () => {
131
+ const json = await proxy.send("listIndexes", { collection: name });
132
+ return JSON.parse(json);
133
+ },
90
134
  findNearest: async (field, vector, topK, filter) => {
91
135
  const json = await proxy.send("findNearest", {
92
136
  collection: name,
@@ -99,9 +143,14 @@ async function createBrowserDB(dbName) {
99
143
  },
100
144
  subscribe: (filter, callback) => {
101
145
  let active = true;
102
- let lastJson = "";
146
+ let lastJson = "[]";
147
+ let timer = null;
103
148
  const poll = async () => {
104
149
  if (!active) return;
150
+ if (timer !== null) {
151
+ clearTimeout(timer);
152
+ timer = null;
153
+ }
105
154
  try {
106
155
  const json = await proxy.send("find", {
107
156
  collection: name,
@@ -113,11 +162,17 @@ async function createBrowserDB(dbName) {
113
162
  }
114
163
  } catch {
115
164
  }
116
- if (active) setTimeout(poll, 300);
165
+ if (active) timer = setTimeout(poll, 300);
117
166
  };
167
+ nudgeCallbacks.add(poll);
118
168
  poll();
119
169
  return () => {
120
170
  active = false;
171
+ nudgeCallbacks.delete(poll);
172
+ if (timer !== null) {
173
+ clearTimeout(timer);
174
+ timer = null;
175
+ }
121
176
  };
122
177
  }
123
178
  };
@@ -125,6 +180,7 @@ async function createBrowserDB(dbName) {
125
180
  return {
126
181
  collection: (name) => wrapCollection(name),
127
182
  close: async () => {
183
+ channel?.close();
128
184
  await proxy.send("close");
129
185
  worker.terminate();
130
186
  }
@@ -147,33 +203,20 @@ async function createNodeDB(dbName) {
147
203
  count: async (filter) => col.count(filter ?? null),
148
204
  createIndex: async (field) => col.createIndex(field),
149
205
  dropIndex: async (field) => col.dropIndex(field),
150
- createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null),
206
+ createFtsIndex: async (field) => col.createFtsIndex(field),
207
+ dropFtsIndex: async (field) => col.dropFtsIndex(field),
208
+ createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null, options.indexType ?? null, options.hnswM ?? null, options.hnswEfConstruction ?? null),
151
209
  dropVectorIndex: async (field) => col.dropVectorIndex(field),
210
+ upgradeVectorIndex: async (field) => col.upgradeVectorIndex(field),
211
+ listIndexes: async () => {
212
+ const json = col.listIndexes();
213
+ return JSON.parse(json);
214
+ },
152
215
  findNearest: async (field, vector, topK, filter) => {
153
216
  const raw = await col.findNearest(field, vector, topK, filter ?? null);
154
217
  return raw;
155
218
  },
156
- subscribe: (filter, callback) => {
157
- let active = true;
158
- let lastJson = "";
159
- const poll = async () => {
160
- if (!active) return;
161
- try {
162
- const docs = await col.find(filter ?? null);
163
- const json = JSON.stringify(docs);
164
- if (json !== lastJson) {
165
- lastJson = json;
166
- callback(docs);
167
- }
168
- } catch {
169
- }
170
- if (active) setTimeout(poll, 300);
171
- };
172
- poll();
173
- return () => {
174
- active = false;
175
- };
176
- }
219
+ subscribe: (filter, callback) => makePoller(async () => col.find(filter ?? null), callback)
177
220
  };
178
221
  }
179
222
  return {
@@ -204,33 +247,17 @@ async function createNativeDB(_dbName) {
204
247
  count: async (filter) => col.count(filter ?? {}),
205
248
  createIndex: async (field) => col.createIndex(field),
206
249
  dropIndex: async (field) => col.dropIndex(field),
207
- createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null),
250
+ createFtsIndex: async (field) => col.createFtsIndex(field),
251
+ dropFtsIndex: async (field) => col.dropFtsIndex(field),
252
+ createVectorIndex: async (field, options) => col.createVectorIndex(field, options.dimensions, options.metric ?? null, options.indexType ?? null, options.hnswM ?? null, options.hnswEfConstruction ?? null),
208
253
  dropVectorIndex: async (field) => col.dropVectorIndex(field),
254
+ upgradeVectorIndex: async (field) => col.upgradeVectorIndex(field),
255
+ listIndexes: async () => JSON.parse(col.listIndexes()),
209
256
  findNearest: async (field, vector, topK, filter) => {
210
257
  const raw = col.findNearest(field, vector, topK, filter ?? null);
211
258
  return raw;
212
259
  },
213
- subscribe: (filter, callback) => {
214
- let active = true;
215
- let lastJson = "";
216
- const poll = () => {
217
- if (!active) return;
218
- try {
219
- const docs = col.find(filter ?? {});
220
- const json = JSON.stringify(docs);
221
- if (json !== lastJson) {
222
- lastJson = json;
223
- callback(docs);
224
- }
225
- } catch {
226
- }
227
- if (active) setTimeout(poll, 300);
228
- };
229
- poll();
230
- return () => {
231
- active = false;
232
- };
233
- }
260
+ subscribe: (filter, callback) => makePoller(async () => col.find(filter ?? {}), callback)
234
261
  };
235
262
  }
236
263
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taladb",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
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",