sqlite-zod-orm 3.7.2 → 3.7.3

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.js CHANGED
@@ -361,18 +361,25 @@ class QueryBuilder {
361
361
  subscribe(callback, options = {}) {
362
362
  const { interval = this.defaultPollInterval, immediate = true } = options;
363
363
  const fingerprintSQL = this.buildFingerprintSQL();
364
- let lastFingerprint = null;
364
+ let lastCount = null;
365
+ let lastMax = null;
366
+ let lastInMemoryRev = null;
365
367
  let stopped = false;
366
368
  const poll = async () => {
367
369
  if (stopped)
368
370
  return;
369
371
  try {
372
+ const rev = this.revisionGetter?.() ?? "0";
373
+ const inMemoryChanged = rev !== lastInMemoryRev;
374
+ lastInMemoryRev = rev;
370
375
  const fpRows = this.executor(fingerprintSQL.sql, fingerprintSQL.params, true);
371
376
  const fpRow = fpRows[0];
372
- const rev = this.revisionGetter?.() ?? "0";
373
- const currentFingerprint = `${fpRow?._cnt ?? 0}:${fpRow?._max ?? 0}:${rev}`;
374
- if (currentFingerprint !== lastFingerprint) {
375
- lastFingerprint = currentFingerprint;
377
+ const cnt = fpRow?._cnt ?? 0;
378
+ const max = fpRow?._max ?? 0;
379
+ const fpChanged = cnt !== lastCount || max !== lastMax;
380
+ lastCount = cnt;
381
+ lastMax = max;
382
+ if (inMemoryChanged || fpChanged) {
376
383
  const rows = this.all();
377
384
  await callback(rows);
378
385
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlite-zod-orm",
3
- "version": "3.7.2",
3
+ "version": "3.7.3",
4
4
  "description": "Type-safe SQLite ORM for Bun — Zod schemas, fluent queries, auto relationships, zero SQL",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -507,23 +507,38 @@ export class QueryBuilder<T extends Record<string, any>> {
507
507
 
508
508
  // Build the fingerprint SQL (COUNT + MAX(id)) using the same WHERE
509
509
  const fingerprintSQL = this.buildFingerprintSQL();
510
- let lastFingerprint: string | null = null;
510
+ let lastCount: number | null = null;
511
+ let lastMax: number | null = null;
512
+ let lastInMemoryRev: string | null = null;
511
513
  let stopped = false;
512
514
 
513
515
  const poll = async () => {
514
516
  if (stopped) return;
515
517
  try {
516
- // Run lightweight fingerprint check
517
- const fpRows = this.executor(fingerprintSQL.sql, fingerprintSQL.params, true);
518
- const fpRow = fpRows[0] as any;
519
- // Include revision in fingerprint (combines in-memory counter + PRAGMA data_version).
520
- // This detects ALL changes: same-process and cross-process.
518
+ // Two-signal change detection:
519
+ // 1. In-memory revision (table-specific) catches same-process writes
520
+ // 2. COUNT+MAX fingerprint (table-specific) catches cross-process inserts/deletes
521
+ //
522
+ // Note: cross-process UPDATEs that don't change count/max are only caught
523
+ // by PRAGMA data_version, which is database-wide. We accept this tradeoff
524
+ // to avoid re-querying on writes to OTHER tables.
521
525
  const rev = this.revisionGetter?.() ?? '0';
522
- const currentFingerprint = `${fpRow?._cnt ?? 0}:${fpRow?._max ?? 0}:${rev}`;
523
526
 
524
- if (currentFingerprint !== lastFingerprint) {
525
- lastFingerprint = currentFingerprint;
526
- // Fingerprint changed → re-execute the full query
527
+ // Fast path: in-memory revision changed → our CRUD wrote to this table
528
+ const inMemoryChanged = rev !== lastInMemoryRev;
529
+ lastInMemoryRev = rev;
530
+
531
+ // Check table-specific fingerprint (COUNT + MAX(id))
532
+ const fpRows = this.executor(fingerprintSQL.sql, fingerprintSQL.params, true);
533
+ const fpRow = fpRows[0] as any;
534
+ const cnt = fpRow?._cnt ?? 0;
535
+ const max = fpRow?._max ?? 0;
536
+ const fpChanged = cnt !== lastCount || max !== lastMax;
537
+ lastCount = cnt;
538
+ lastMax = max;
539
+
540
+ // Fire callback only if THIS table actually changed
541
+ if (inMemoryChanged || fpChanged) {
527
542
  const rows = this.all();
528
543
  await callback(rows);
529
544
  }