sqlite-zod-orm 3.5.0 → 3.5.1

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
@@ -4765,19 +4765,29 @@ class _Database {
4765
4765
  const maxRow = this.db.query(`SELECT MAX(id) as _max FROM "${entityName}"`).get();
4766
4766
  let lastMaxId = maxRow?._max ?? 0;
4767
4767
  let lastRevision = this._getRevision(entityName);
4768
- const timer = setInterval(() => {
4769
- const currentRevision = this._getRevision(entityName);
4770
- if (currentRevision === lastRevision)
4768
+ let stopped = false;
4769
+ const poll = async () => {
4770
+ if (stopped)
4771
4771
  return;
4772
- lastRevision = currentRevision;
4773
- const newRows = this.db.query(`SELECT * FROM "${entityName}" WHERE id > ? ORDER BY id ASC`).all(lastMaxId);
4774
- for (const rawRow of newRows) {
4775
- const entity = this._attachMethods(entityName, transformFromStorage(rawRow, this.schemas[entityName]));
4776
- callback(entity);
4777
- lastMaxId = rawRow.id;
4772
+ const currentRevision = this._getRevision(entityName);
4773
+ if (currentRevision !== lastRevision) {
4774
+ lastRevision = currentRevision;
4775
+ const newRows = this.db.query(`SELECT * FROM "${entityName}" WHERE id > ? ORDER BY id ASC`).all(lastMaxId);
4776
+ for (const rawRow of newRows) {
4777
+ if (stopped)
4778
+ return;
4779
+ const entity = this._attachMethods(entityName, transformFromStorage(rawRow, this.schemas[entityName]));
4780
+ await callback(entity);
4781
+ lastMaxId = rawRow.id;
4782
+ }
4778
4783
  }
4779
- }, interval);
4780
- return () => clearInterval(timer);
4784
+ if (!stopped)
4785
+ setTimeout(poll, interval);
4786
+ };
4787
+ setTimeout(poll, interval);
4788
+ return () => {
4789
+ stopped = true;
4790
+ };
4781
4791
  }
4782
4792
  insert(entityName, data) {
4783
4793
  const schema = this.schemas[entityName];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlite-zod-orm",
3
- "version": "3.5.0",
3
+ "version": "3.5.1",
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",
package/src/database.ts CHANGED
@@ -151,7 +151,7 @@ class _Database<Schemas extends SchemaMap> {
151
151
  */
152
152
  public _createOnStream(
153
153
  entityName: string,
154
- callback: (row: any) => void,
154
+ callback: (row: any) => void | Promise<void>,
155
155
  options?: { interval?: number },
156
156
  ): () => void {
157
157
  const { interval = 500 } = options ?? {};
@@ -160,30 +160,43 @@ class _Database<Schemas extends SchemaMap> {
160
160
  const maxRow = this.db.query(`SELECT MAX(id) as _max FROM "${entityName}"`).get() as any;
161
161
  let lastMaxId: number = maxRow?._max ?? 0;
162
162
  let lastRevision: string = this._getRevision(entityName);
163
+ let stopped = false;
164
+
165
+ // Self-scheduling async loop: guarantees strict ordering
166
+ // - Each callback (sync or async) completes before the next row is emitted
167
+ // - Next poll only starts after the current batch is fully processed
168
+ const poll = async () => {
169
+ if (stopped) return;
163
170
 
164
- const timer = setInterval(() => {
165
171
  // Fast check: did anything change?
166
172
  const currentRevision = this._getRevision(entityName);
167
- if (currentRevision === lastRevision) return;
168
- lastRevision = currentRevision;
169
-
170
- // Fetch new rows since watermark
171
- const newRows = this.db.query(
172
- `SELECT * FROM "${entityName}" WHERE id > ? ORDER BY id ASC`
173
- ).all(lastMaxId) as any[];
174
-
175
- for (const rawRow of newRows) {
176
- // Hydrate with entity methods and schema transforms
177
- const entity = this._attachMethods(
178
- entityName,
179
- transformFromStorage(rawRow, this.schemas[entityName]!)
180
- );
181
- callback(entity);
182
- lastMaxId = rawRow.id;
173
+ if (currentRevision !== lastRevision) {
174
+ lastRevision = currentRevision;
175
+
176
+ // Fetch new rows since watermark
177
+ const newRows = this.db.query(
178
+ `SELECT * FROM "${entityName}" WHERE id > ? ORDER BY id ASC`
179
+ ).all(lastMaxId) as any[];
180
+
181
+ for (const rawRow of newRows) {
182
+ if (stopped) return; // bail if unsubscribed mid-batch
183
+ const entity = this._attachMethods(
184
+ entityName,
185
+ transformFromStorage(rawRow, this.schemas[entityName]!)
186
+ );
187
+ await callback(entity); // await async callbacks
188
+ lastMaxId = rawRow.id;
189
+ }
183
190
  }
184
- }, interval);
185
191
 
186
- return () => clearInterval(timer);
192
+ // Schedule next poll only after this one is done
193
+ if (!stopped) setTimeout(poll, interval);
194
+ };
195
+
196
+ // Start the loop
197
+ setTimeout(poll, interval);
198
+
199
+ return () => { stopped = true; };
187
200
  }
188
201
 
189
202
  // ===========================================================================
package/src/types.ts CHANGED
@@ -146,9 +146,10 @@ export type NavEntityAccessor<
146
146
  /**
147
147
  * Stream new rows one at a time, in insertion order.
148
148
  * Only emits rows inserted AFTER subscription starts.
149
+ * Callbacks are awaited — strict ordering guaranteed even with async handlers.
149
150
  * @returns Unsubscribe function.
150
151
  */
151
- on: (callback: (row: NavEntity<S, R, Table>) => void, options?: { interval?: number }) => () => void;
152
+ on: (callback: (row: NavEntity<S, R, Table>) => void | Promise<void>, options?: { interval?: number }) => () => void;
152
153
  _tableName: string;
153
154
  readonly _schema?: S[Table & keyof S];
154
155
  };
@@ -177,9 +178,10 @@ export type EntityAccessor<S extends z.ZodType<any>> = {
177
178
  /**
178
179
  * Stream new rows one at a time, in insertion order.
179
180
  * Only emits rows inserted AFTER subscription starts.
181
+ * Callbacks are awaited — strict ordering guaranteed even with async handlers.
180
182
  * @returns Unsubscribe function.
181
183
  */
182
- on: (callback: (row: AugmentedEntity<S>) => void, options?: { interval?: number }) => () => void;
184
+ on: (callback: (row: AugmentedEntity<S>) => void | Promise<void>, options?: { interval?: number }) => () => void;
183
185
  _tableName: string;
184
186
  readonly _schema?: S;
185
187
  };