@firtoz/drizzle-utils 0.3.3 → 1.0.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/CHANGELOG.md +24 -0
- package/package.json +7 -3
- package/src/collection-utils.ts +42 -369
- package/src/index.ts +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @firtoz/drizzle-utils
|
|
2
2
|
|
|
3
|
+
## 1.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3) Thanks [@firtoz](https://github.com/firtoz)! - Refactor `SyncBackend`, `createSyncFunction`, and `createCollectionConfig` to delegate to generic (Drizzle-free) implementations from `@firtoz/db-helpers`. No public API changes.
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3), [`5c667ec`](https://github.com/firtoz/fullstack-toolkit/commit/5c667ecfce1ed4f22ccf9686ad37f00e7a4ecee3)]:
|
|
10
|
+
- @firtoz/db-helpers@2.0.0
|
|
11
|
+
|
|
12
|
+
## 1.0.0
|
|
13
|
+
|
|
14
|
+
### Major Changes
|
|
15
|
+
|
|
16
|
+
- [`3c7ce1d`](https://github.com/firtoz/fullstack-toolkit/commit/3c7ce1dbca5c5396386db9927ae7f5e19a562cf6) Thanks [@firtoz](https://github.com/firtoz)! - **Unified collection sync**
|
|
17
|
+
|
|
18
|
+
`CollectionUtils` now exposes `receiveSync(messages: SyncMessage<T>[])` instead of `pushExternalSync`. Canonical sync message type is `SyncMessage<T, TKey>` (`insert` | `update` | `delete` | `truncate`). `ExternalSyncEvent` / `ExternalSyncHandler` are internal only.
|
|
19
|
+
|
|
20
|
+
**Upgrade:** Replace `utils.pushExternalSync(events)` with `utils.receiveSync(messages)`. Import `SyncMessage` from `@firtoz/drizzle-utils` (or from `@firtoz/db-helpers`) and send per-mutation messages: `{ type: "insert", value }`, `{ type: "update", value, previousValue }`, `{ type: "delete", key }`, or `{ type: "truncate" }`. Stop using `ExternalSyncEvent` / `ExternalSyncHandler` in your code; they are no longer part of the public API. Generic sync types (`SyncMessage`, `CollectionUtils`) are now defined in `@firtoz/db-helpers` and re-exported here for backward compatibility.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [[`3c7ce1d`](https://github.com/firtoz/fullstack-toolkit/commit/3c7ce1dbca5c5396386db9927ae7f5e19a562cf6)]:
|
|
25
|
+
- @firtoz/db-helpers@1.0.0
|
|
26
|
+
|
|
3
27
|
## 0.3.3
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firtoz/drizzle-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Shared utilities and types for Drizzle-based packages",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"module": "./src/index.ts",
|
|
@@ -53,15 +53,19 @@
|
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@tanstack/db": ">=0.5.
|
|
56
|
+
"@tanstack/db": ">=0.5.33",
|
|
57
57
|
"drizzle-orm": ">=0.45.1",
|
|
58
58
|
"drizzle-valibot": ">=0.4.0",
|
|
59
59
|
"valibot": ">=1.0.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@tanstack/db": "^0.5.
|
|
62
|
+
"@tanstack/db": "^0.5.33",
|
|
63
63
|
"drizzle-orm": "^0.45.1",
|
|
64
64
|
"drizzle-valibot": "^0.4.2",
|
|
65
65
|
"valibot": "^1.2.0"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@firtoz/db-helpers": "^2.0.0",
|
|
69
|
+
"@firtoz/maybe-error": "^1.5.2"
|
|
66
70
|
}
|
|
67
71
|
}
|
package/src/collection-utils.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import type { CollectionUtils } from "@firtoz/db-helpers";
|
|
2
|
+
import {
|
|
3
|
+
type GenericBaseSyncConfig,
|
|
4
|
+
type GenericSyncBackend,
|
|
5
|
+
type GenericSyncFunctionResult,
|
|
6
|
+
createGenericSyncFunction,
|
|
7
|
+
createGenericCollectionConfig,
|
|
8
|
+
USE_DEDUPE as _USE_DEDUPE,
|
|
9
|
+
} from "@firtoz/db-helpers";
|
|
1
10
|
import { type Table, SQL, getTableColumns } from "drizzle-orm";
|
|
2
11
|
import type { BuildSchema } from "drizzle-valibot";
|
|
3
12
|
import { createInsertSchema } from "drizzle-valibot";
|
|
@@ -7,12 +16,8 @@ import type {
|
|
|
7
16
|
UtilsRecord,
|
|
8
17
|
CollectionConfig,
|
|
9
18
|
InferSchemaOutput,
|
|
10
|
-
SyncConfig,
|
|
11
|
-
SyncConfigRes,
|
|
12
19
|
SyncMode,
|
|
13
|
-
LoadSubsetOptions,
|
|
14
20
|
} from "@tanstack/db";
|
|
15
|
-
import { DeduplicatedLoadSubset } from "@tanstack/db";
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
23
|
* Utility type for branded IDs
|
|
@@ -87,374 +92,41 @@ export type InferCollectionFromTable<TTable extends Table> = Collection<
|
|
|
87
92
|
}
|
|
88
93
|
>;
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
// creates invalid expressions like not(or(isNull(...), not(isNull(...))))
|
|
92
|
-
// See: https://github.com/TanStack/db/issues/828
|
|
93
|
-
// TODO: Re-enable once the bug is fixed
|
|
94
|
-
export const USE_DEDUPE = false as boolean;
|
|
95
|
+
export const USE_DEDUPE = _USE_DEDUPE;
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
|
-
* Base configuration for sync lifecycle management
|
|
98
|
+
* Base configuration for sync lifecycle management.
|
|
99
|
+
* Extends the generic (Drizzle-free) config with a Drizzle table reference.
|
|
98
100
|
*/
|
|
99
|
-
export interface BaseSyncConfig<TTable extends Table>
|
|
100
|
-
|
|
101
|
-
* The Drizzle table definition
|
|
102
|
-
*/
|
|
101
|
+
export interface BaseSyncConfig<TTable extends Table>
|
|
102
|
+
extends GenericBaseSyncConfig {
|
|
103
103
|
table: TTable;
|
|
104
|
-
/**
|
|
105
|
-
* Promise that resolves when the database is ready
|
|
106
|
-
*/
|
|
107
|
-
readyPromise: Promise<void>;
|
|
108
|
-
/**
|
|
109
|
-
* Sync mode: 'eager' (immediate) or 'lazy' (on-demand)
|
|
110
|
-
*/
|
|
111
|
-
syncMode?: SyncMode;
|
|
112
|
-
/**
|
|
113
|
-
* Enable debug logging
|
|
114
|
-
*/
|
|
115
|
-
debug?: boolean;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Backend-specific implementations required for sync
|
|
120
|
-
*/
|
|
121
|
-
export interface SyncBackend<TTable extends Table> {
|
|
122
|
-
/**
|
|
123
|
-
* Initial data load - should call write() for each item
|
|
124
|
-
*/
|
|
125
|
-
initialLoad: () => Promise<Array<InferSchemaOutput<SelectSchema<TTable>>>>;
|
|
126
|
-
/**
|
|
127
|
-
* Load a subset of data based on query options
|
|
128
|
-
*/
|
|
129
|
-
loadSubset: (
|
|
130
|
-
options: LoadSubsetOptions,
|
|
131
|
-
) => Promise<Array<InferSchemaOutput<SelectSchema<TTable>>>>;
|
|
132
|
-
/**
|
|
133
|
-
* Handle insert mutations
|
|
134
|
-
*/
|
|
135
|
-
handleInsert: (
|
|
136
|
-
items: Array<InferSchemaOutput<SelectSchema<TTable>>>,
|
|
137
|
-
) => Promise<Array<InferSchemaOutput<SelectSchema<TTable>>>>;
|
|
138
|
-
/**
|
|
139
|
-
* Handle update mutations
|
|
140
|
-
*/
|
|
141
|
-
handleUpdate: (
|
|
142
|
-
mutations: Array<{
|
|
143
|
-
key: string;
|
|
144
|
-
changes: Partial<InferSchemaOutput<SelectSchema<TTable>>>;
|
|
145
|
-
original: InferSchemaOutput<SelectSchema<TTable>>;
|
|
146
|
-
}>,
|
|
147
|
-
) => Promise<Array<InferSchemaOutput<SelectSchema<TTable>>>>;
|
|
148
|
-
/**
|
|
149
|
-
* Handle delete mutations
|
|
150
|
-
*/
|
|
151
|
-
handleDelete: (
|
|
152
|
-
mutations: Array<{
|
|
153
|
-
key: string;
|
|
154
|
-
modified: InferSchemaOutput<SelectSchema<TTable>>;
|
|
155
|
-
original: InferSchemaOutput<SelectSchema<TTable>>;
|
|
156
|
-
}>,
|
|
157
|
-
) => Promise<void>;
|
|
158
|
-
/**
|
|
159
|
-
* Handle truncate (clear all data from store)
|
|
160
|
-
* Optional - if not provided, truncate util won't be available
|
|
161
|
-
*/
|
|
162
|
-
handleTruncate?: () => Promise<void>;
|
|
163
104
|
}
|
|
164
105
|
|
|
165
106
|
/**
|
|
166
|
-
*
|
|
107
|
+
* Backend-specific implementations required for sync.
|
|
108
|
+
* Drizzle-typed alias for GenericSyncBackend.
|
|
167
109
|
*/
|
|
168
|
-
export type
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
| { type: "delete"; items: T[] }
|
|
172
|
-
| { type: "truncate" };
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Handler for external sync events
|
|
176
|
-
*/
|
|
177
|
-
export type ExternalSyncHandler<T> = (event: ExternalSyncEvent<T>) => void;
|
|
110
|
+
export type SyncBackend<TTable extends Table> = GenericSyncBackend<
|
|
111
|
+
InferSchemaOutput<SelectSchema<TTable>>
|
|
112
|
+
>;
|
|
178
113
|
|
|
179
114
|
/**
|
|
180
|
-
*
|
|
115
|
+
* Return type for createSyncFunction.
|
|
116
|
+
* Drizzle-typed alias for GenericSyncFunctionResult.
|
|
181
117
|
*/
|
|
182
|
-
export
|
|
183
|
-
|
|
184
|
-
* Clear all data from the store (truncate).
|
|
185
|
-
* This clears the backend store and updates the local reactive store.
|
|
186
|
-
*/
|
|
187
|
-
truncate: () => Promise<void>;
|
|
188
|
-
/**
|
|
189
|
-
* Push external sync events to the collection.
|
|
190
|
-
* Use this when receiving sync messages from a proxy server or other external source.
|
|
191
|
-
*/
|
|
192
|
-
pushExternalSync: ExternalSyncHandler<T>;
|
|
193
|
-
}
|
|
118
|
+
export type SyncFunctionResult<TTable extends Table> =
|
|
119
|
+
GenericSyncFunctionResult<InferSchemaOutput<SelectSchema<TTable>>>;
|
|
194
120
|
|
|
195
121
|
/**
|
|
196
|
-
*
|
|
197
|
-
|
|
198
|
-
export type SyncFunctionResult<TTable extends Table> = {
|
|
199
|
-
sync: SyncConfig<InferSchemaOutput<SelectSchema<TTable>>, string>["sync"];
|
|
200
|
-
onInsert: CollectionConfig<
|
|
201
|
-
InferSchemaOutput<SelectSchema<TTable>>,
|
|
202
|
-
string,
|
|
203
|
-
// biome-ignore lint/suspicious/noExplicitAny: Schema type parameter needs to be flexible
|
|
204
|
-
any
|
|
205
|
-
>["onInsert"];
|
|
206
|
-
onUpdate: CollectionConfig<
|
|
207
|
-
InferSchemaOutput<SelectSchema<TTable>>,
|
|
208
|
-
string,
|
|
209
|
-
// biome-ignore lint/suspicious/noExplicitAny: Schema type parameter needs to be flexible
|
|
210
|
-
any
|
|
211
|
-
>["onUpdate"];
|
|
212
|
-
onDelete: CollectionConfig<
|
|
213
|
-
InferSchemaOutput<SelectSchema<TTable>>,
|
|
214
|
-
string,
|
|
215
|
-
// biome-ignore lint/suspicious/noExplicitAny: Schema type parameter needs to be flexible
|
|
216
|
-
any
|
|
217
|
-
>["onDelete"];
|
|
218
|
-
/**
|
|
219
|
-
* Collection utilities including truncate and external sync
|
|
220
|
-
*/
|
|
221
|
-
utils: CollectionUtils<InferSchemaOutput<SelectSchema<TTable>>>;
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Creates the sync function with common lifecycle management
|
|
122
|
+
* Creates the sync function with common lifecycle management.
|
|
123
|
+
* Delegates to the generic (Drizzle-free) implementation in @firtoz/db-helpers.
|
|
226
124
|
*/
|
|
227
125
|
export function createSyncFunction<TTable extends Table>(
|
|
228
126
|
config: BaseSyncConfig<TTable>,
|
|
229
127
|
backend: SyncBackend<TTable>,
|
|
230
128
|
): SyncFunctionResult<TTable> {
|
|
231
|
-
|
|
232
|
-
type CollectionType = CollectionConfig<
|
|
233
|
-
ItemType,
|
|
234
|
-
string,
|
|
235
|
-
// biome-ignore lint/suspicious/noExplicitAny: Schema type parameter needs to be flexible
|
|
236
|
-
any
|
|
237
|
-
>;
|
|
238
|
-
|
|
239
|
-
let insertListener: CollectionType["onInsert"];
|
|
240
|
-
let updateListener: CollectionType["onUpdate"];
|
|
241
|
-
let deleteListener: CollectionType["onDelete"];
|
|
242
|
-
|
|
243
|
-
// Captured sync functions for external sync
|
|
244
|
-
let syncBegin: (() => void) | null = null;
|
|
245
|
-
let syncWrite:
|
|
246
|
-
| ((op: { type: "insert" | "update" | "delete"; value: ItemType }) => void)
|
|
247
|
-
| null = null;
|
|
248
|
-
let syncCommit: (() => void) | null = null;
|
|
249
|
-
let syncTruncate: (() => void) | null = null;
|
|
250
|
-
|
|
251
|
-
const syncFn: SyncConfig<
|
|
252
|
-
InferSchemaOutput<SelectSchema<TTable>>,
|
|
253
|
-
string
|
|
254
|
-
>["sync"] = (params) => {
|
|
255
|
-
const { begin, write, commit, markReady, truncate } = params;
|
|
256
|
-
|
|
257
|
-
// Capture sync functions for external use
|
|
258
|
-
syncBegin = begin;
|
|
259
|
-
syncWrite = write;
|
|
260
|
-
syncCommit = commit;
|
|
261
|
-
syncTruncate = truncate;
|
|
262
|
-
|
|
263
|
-
const initialSync = async () => {
|
|
264
|
-
await config.readyPromise;
|
|
265
|
-
|
|
266
|
-
try {
|
|
267
|
-
const items = await backend.initialLoad();
|
|
268
|
-
|
|
269
|
-
begin();
|
|
270
|
-
|
|
271
|
-
for (const item of items) {
|
|
272
|
-
write({
|
|
273
|
-
type: "insert",
|
|
274
|
-
value: item,
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
commit();
|
|
279
|
-
} finally {
|
|
280
|
-
markReady();
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
if (config.syncMode === "eager" || !config.syncMode) {
|
|
285
|
-
initialSync();
|
|
286
|
-
} else {
|
|
287
|
-
markReady();
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
insertListener = async (params) => {
|
|
291
|
-
const results = await backend.handleInsert(
|
|
292
|
-
params.transaction.mutations.map((m) => m.modified),
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
begin();
|
|
296
|
-
for (const result of results) {
|
|
297
|
-
write({
|
|
298
|
-
type: "insert",
|
|
299
|
-
value: result,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
commit();
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
updateListener = async (params) => {
|
|
306
|
-
const results = await backend.handleUpdate(params.transaction.mutations);
|
|
307
|
-
|
|
308
|
-
begin();
|
|
309
|
-
for (const result of results) {
|
|
310
|
-
write({
|
|
311
|
-
type: "update",
|
|
312
|
-
value: result,
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
commit();
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
deleteListener = async (params) => {
|
|
319
|
-
await backend.handleDelete(params.transaction.mutations);
|
|
320
|
-
|
|
321
|
-
begin();
|
|
322
|
-
for (const item of params.transaction.mutations) {
|
|
323
|
-
write({
|
|
324
|
-
type: "delete",
|
|
325
|
-
value: item.modified,
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
commit();
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
const loadSubset = async (options: LoadSubsetOptions) => {
|
|
332
|
-
await config.readyPromise;
|
|
333
|
-
|
|
334
|
-
const items = await backend.loadSubset(options);
|
|
335
|
-
|
|
336
|
-
begin();
|
|
337
|
-
|
|
338
|
-
for (const item of items) {
|
|
339
|
-
write({
|
|
340
|
-
type: "insert",
|
|
341
|
-
value: item,
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
commit();
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
// Create deduplicated loadSubset wrapper to avoid redundant queries
|
|
349
|
-
let loadSubsetDedupe: DeduplicatedLoadSubset | null = null;
|
|
350
|
-
if (USE_DEDUPE) {
|
|
351
|
-
loadSubsetDedupe = new DeduplicatedLoadSubset({
|
|
352
|
-
loadSubset,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
return {
|
|
357
|
-
cleanup: () => {
|
|
358
|
-
insertListener = undefined;
|
|
359
|
-
updateListener = undefined;
|
|
360
|
-
deleteListener = undefined;
|
|
361
|
-
loadSubsetDedupe?.reset();
|
|
362
|
-
},
|
|
363
|
-
loadSubset: loadSubsetDedupe?.loadSubset ?? loadSubset,
|
|
364
|
-
} satisfies SyncConfigRes;
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
// External sync handler - allows pushing sync events from outside (e.g., proxy server)
|
|
368
|
-
const pushExternalSync: ExternalSyncHandler<ItemType> = (event) => {
|
|
369
|
-
if (!syncBegin || !syncWrite || !syncCommit || !syncTruncate) {
|
|
370
|
-
if (config.debug) {
|
|
371
|
-
console.warn(
|
|
372
|
-
"[pushExternalSync] Sync functions not initialized yet - event will be dropped",
|
|
373
|
-
event,
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
switch (event.type) {
|
|
380
|
-
case "insert":
|
|
381
|
-
syncBegin();
|
|
382
|
-
for (const item of event.items) {
|
|
383
|
-
syncWrite({ type: "insert", value: item });
|
|
384
|
-
}
|
|
385
|
-
syncCommit();
|
|
386
|
-
break;
|
|
387
|
-
case "update":
|
|
388
|
-
syncBegin();
|
|
389
|
-
for (const item of event.items) {
|
|
390
|
-
syncWrite({ type: "update", value: item });
|
|
391
|
-
}
|
|
392
|
-
syncCommit();
|
|
393
|
-
break;
|
|
394
|
-
case "delete":
|
|
395
|
-
syncBegin();
|
|
396
|
-
for (const item of event.items) {
|
|
397
|
-
syncWrite({ type: "delete", value: item });
|
|
398
|
-
}
|
|
399
|
-
syncCommit();
|
|
400
|
-
break;
|
|
401
|
-
case "truncate":
|
|
402
|
-
syncBegin();
|
|
403
|
-
syncTruncate();
|
|
404
|
-
syncCommit();
|
|
405
|
-
break;
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
// Create utils with truncate and external sync
|
|
410
|
-
const utils: CollectionUtils<ItemType> = {
|
|
411
|
-
truncate: async () => {
|
|
412
|
-
if (!backend.handleTruncate) {
|
|
413
|
-
throw new Error("Truncate not supported by this backend");
|
|
414
|
-
}
|
|
415
|
-
if (!syncBegin || !syncTruncate || !syncCommit) {
|
|
416
|
-
throw new Error(
|
|
417
|
-
"Sync functions not initialized - sync function may not have been called yet",
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
// Clear the backend store
|
|
421
|
-
await backend.handleTruncate();
|
|
422
|
-
// Update local reactive store (same pattern as insert/update/delete listeners)
|
|
423
|
-
syncBegin();
|
|
424
|
-
syncTruncate();
|
|
425
|
-
syncCommit();
|
|
426
|
-
},
|
|
427
|
-
pushExternalSync,
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
return {
|
|
431
|
-
sync: syncFn,
|
|
432
|
-
onInsert: async (params) => {
|
|
433
|
-
if (!insertListener) {
|
|
434
|
-
throw new Error(
|
|
435
|
-
"insertListener not initialized - sync function may not have been called yet",
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
return insertListener(params);
|
|
439
|
-
},
|
|
440
|
-
onUpdate: async (params) => {
|
|
441
|
-
if (!updateListener) {
|
|
442
|
-
throw new Error(
|
|
443
|
-
"updateListener not initialized - sync function may not have been called yet",
|
|
444
|
-
);
|
|
445
|
-
}
|
|
446
|
-
return updateListener(params);
|
|
447
|
-
},
|
|
448
|
-
onDelete: async (params) => {
|
|
449
|
-
if (!deleteListener) {
|
|
450
|
-
throw new Error(
|
|
451
|
-
"deleteListener not initialized - sync function may not have been called yet",
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
return deleteListener(params);
|
|
455
|
-
},
|
|
456
|
-
utils,
|
|
457
|
-
};
|
|
129
|
+
return createGenericSyncFunction(config, backend);
|
|
458
130
|
}
|
|
459
131
|
|
|
460
132
|
/**
|
|
@@ -562,8 +234,8 @@ export function createGetKeyFunction<TTable extends Table>() {
|
|
|
562
234
|
}
|
|
563
235
|
|
|
564
236
|
/**
|
|
565
|
-
* Base collection config factory
|
|
566
|
-
*
|
|
237
|
+
* Base collection config factory.
|
|
238
|
+
* Delegates to the generic (Drizzle-free) implementation in @firtoz/db-helpers.
|
|
567
239
|
*/
|
|
568
240
|
export function createCollectionConfig<
|
|
569
241
|
TTable extends Table,
|
|
@@ -603,18 +275,19 @@ export function createCollectionConfig<
|
|
|
603
275
|
schema: TSchema;
|
|
604
276
|
utils: CollectionUtils<InferSchemaOutput<SelectSchema<TTable>>>;
|
|
605
277
|
} {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
utils: config.syncResult.utils,
|
|
278
|
+
type TItem = InferSchemaOutput<SelectSchema<TTable>>;
|
|
279
|
+
type ReturnType = Omit<
|
|
280
|
+
CollectionConfig<
|
|
281
|
+
TItem,
|
|
282
|
+
string,
|
|
283
|
+
// biome-ignore lint/suspicious/noExplicitAny: Schema type parameter needs to be flexible
|
|
284
|
+
any
|
|
285
|
+
>,
|
|
286
|
+
"utils"
|
|
287
|
+
> & {
|
|
288
|
+
schema: TSchema;
|
|
289
|
+
utils: CollectionUtils<TItem>;
|
|
619
290
|
};
|
|
291
|
+
|
|
292
|
+
return createGenericCollectionConfig<TItem, TSchema>(config) as ReturnType;
|
|
620
293
|
}
|