@feltdb/core 0.11.3 → 0.11.4

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.
@@ -1,5 +1,6 @@
1
1
  import { FreshnessContractViolation } from './freshness.js';
2
2
  import { decideTransaction, embeddedResult, EmbeddedTransactionRejected, } from './embedded-transaction.js';
3
+ import { EmbeddedQueryEngine } from './embedded-query.js';
3
4
  /** Durable browser runtime. Every mutation resolves only after its IndexedDB transaction commits. */
4
5
  export class IndexedDbJsDb {
5
6
  database;
@@ -305,6 +306,33 @@ export class IndexedDbJsDb {
305
306
  return { success: false, error: String(error) };
306
307
  }
307
308
  }
309
+ /**
310
+ * Browser bounded-query fallback. IndexedDB schema indexes are static, so a
311
+ * dynamically declared FeltDB index is not claimed here until it has a
312
+ * durable object-store representation. The fallback stays correct and its
313
+ * plan truthfully reports a full scan.
314
+ */
315
+ async authority_query(query) {
316
+ const db = await this.database;
317
+ const rows = await new Promise((resolve, reject) => {
318
+ const request = db.transaction('rows').objectStore('rows').openCursor();
319
+ const output = [];
320
+ request.onsuccess = () => {
321
+ const cursor = request.result;
322
+ if (!cursor)
323
+ return resolve(output);
324
+ if (String(cursor.key).startsWith(`${query.collection}:`))
325
+ output.push([String(cursor.key), cursor.value]);
326
+ cursor.continue();
327
+ };
328
+ request.onerror = () => reject(request.error);
329
+ });
330
+ return new EmbeddedQueryEngine(() => rows).execute(query);
331
+ }
332
+ explain_query(query) {
333
+ return { plan: 'full-scan', reason: 'no compatible durable IndexedDB index', order: [...(query.orderBy ?? []).map(value => `${value.field} ${value.direction.toUpperCase()}`), 'id ASC'].join(', '), limit: query.limit, cursor: Boolean(query.cursor) };
334
+ }
335
+ rebuild_indexes() { }
308
336
  async request(storeName, create) {
309
337
  const db = await this.database;
310
338
  return new Promise((resolve, reject) => { const request = create(db.transaction(storeName).objectStore(storeName)); request.onsuccess = () => resolve(request.result); request.onerror = () => reject(request.error); });
@@ -1,6 +1,7 @@
1
1
  import type { JsDb } from './feltdb.js';
2
2
  import { type FreshnessCapability, type Revision } from './freshness.js';
3
3
  import type { AtomicTransactionRequest, AtomicTransactionResult } from './transaction.js';
4
+ import type { AuthorityQueryRequest } from './http-db.js';
4
5
  interface JsResult {
5
6
  success: boolean;
6
7
  data?: string;
@@ -25,6 +26,8 @@ export declare class MemoryJsDb implements JsDb {
25
26
  private readonly revisionState;
26
27
  private readonly peers;
27
28
  private readonly applied;
29
+ private readonly queryEngine;
30
+ private indexedRevision;
28
31
  constructor(namespace: string);
29
32
  private event;
30
33
  /**
@@ -59,6 +62,11 @@ export declare class MemoryJsDb implements JsDb {
59
62
  item?: any;
60
63
  }>;
61
64
  query(capability: string): JsResult;
65
+ authority_query<T = Record<string, unknown>>(query: AuthorityQueryRequest): Promise<import("./http-db.js").AuthorityQueryPage<T> & {
66
+ stats: import("./embedded-query.js").EmbeddedQueryStats;
67
+ }>;
68
+ explain_query(query: AuthorityQueryRequest): import("./embedded-query.js").EmbeddedQueryExplanation;
69
+ rebuild_indexes(): void;
62
70
  get_capability_records(capability: string): JsResult;
63
71
  execute_op(): JsResult;
64
72
  sync_info(): JsResult;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-db.d.ts","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-db.d.ts","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"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"}
package/dist/memory-db.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { FreshnessContractViolation } from './freshness.js';
2
2
  import { decideTransaction, embeddedResult, EmbeddedTransactionRejected, } from './embedded-transaction.js';
3
+ import { EmbeddedQueryEngine } from './embedded-query.js';
3
4
  const namespaces = new Map();
4
5
  const revisions = new Map();
5
6
  function namespaceRevision(namespace) {
@@ -19,6 +20,8 @@ export class MemoryJsDb {
19
20
  revisionState;
20
21
  peers = new Set();
21
22
  applied = new Set();
23
+ queryEngine;
24
+ indexedRevision;
22
25
  constructor(namespace) {
23
26
  let rows = namespaces.get(namespace);
24
27
  if (!rows) {
@@ -28,12 +31,16 @@ export class MemoryJsDb {
28
31
  this.rows = rows;
29
32
  this.revisionState = namespaceRevision(namespace);
30
33
  this.origin = `memory:${namespace}`;
34
+ this.queryEngine = new EmbeddedQueryEngine(() => this.rows.entries());
35
+ this.indexedRevision = this.revisionState.value;
31
36
  }
32
37
  event(collection, key, type, value) {
33
38
  this.sequence += 1;
34
39
  this.revisionState.value += 1;
35
40
  const timestamp = Date.now();
36
41
  this.events.push({ sequence: this.sequence, collection, key, type, value, timestamp, origin: this.origin, id: `${this.origin}:${timestamp}:${this.sequence}` });
42
+ this.queryEngine.apply(key, type === 'put' ? this.rows.get(key) : undefined);
43
+ this.indexedRevision = this.revisionState.value;
37
44
  }
38
45
  /**
39
46
  * Commit several operations atomically.
@@ -146,6 +153,15 @@ export class MemoryJsDb {
146
153
  .map(([, value]) => value);
147
154
  return { success: true, data: JSON.stringify(values) };
148
155
  }
156
+ async authority_query(query) {
157
+ if (this.indexedRevision !== this.revisionState.value) {
158
+ this.queryEngine.rebuild();
159
+ this.indexedRevision = this.revisionState.value;
160
+ }
161
+ return this.queryEngine.execute(query);
162
+ }
163
+ explain_query(query) { return this.queryEngine.explain(query); }
164
+ rebuild_indexes() { this.queryEngine.rebuild(); this.indexedRevision = this.revisionState.value; }
149
165
  get_capability_records(capability) {
150
166
  return this.query(capability);
151
167
  }
@@ -219,6 +235,9 @@ export class MemoryJsDb {
219
235
  this.rows.delete(operation.key);
220
236
  else
221
237
  this.rows.set(operation.key, operation.value);
238
+ this.queryEngine.apply(operation.key, operation.type === 'delete' ? undefined : operation.value);
239
+ this.revisionState.value += 1;
240
+ this.indexedRevision = this.revisionState.value;
222
241
  applied++;
223
242
  }
224
243
  else