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 +21 -11
- package/package.json +1 -1
- package/src/database.ts +33 -20
- package/src/types.ts +4 -2
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
|
-
|
|
4769
|
-
|
|
4770
|
-
if (
|
|
4768
|
+
let stopped = false;
|
|
4769
|
+
const poll = async () => {
|
|
4770
|
+
if (stopped)
|
|
4771
4771
|
return;
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
const
|
|
4776
|
-
|
|
4777
|
-
|
|
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
|
-
|
|
4780
|
-
|
|
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
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
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
184
|
+
on: (callback: (row: AugmentedEntity<S>) => void | Promise<void>, options?: { interval?: number }) => () => void;
|
|
183
185
|
_tableName: string;
|
|
184
186
|
readonly _schema?: S;
|
|
185
187
|
};
|