@lpdjs/firestore-repo-service 2.2.7 → 2.2.9-beta.0
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/{create-servers-B3Ls46bx.d.cts → create-servers-CfLtucbQ.d.cts} +27 -3
- package/dist/{create-servers-CvVZnihM.d.ts → create-servers-xx0m3wwM.d.ts} +27 -3
- package/dist/history/index.cjs +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +3 -4
- package/dist/history/index.d.ts +3 -4
- package/dist/history/index.js +1 -1
- package/dist/history/index.js.map +1 -1
- package/dist/{index-DGB3Oemk.d.ts → index-BvKyjs6k.d.cts} +11 -3
- package/dist/{index-Cw9b1crP.d.cts → index-Njwf8jvu.d.ts} +11 -3
- package/dist/index.cjs +93 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +93 -93
- package/dist/index.js.map +1 -1
- package/dist/{openapi-BEf4OuG9.d.ts → openapi-BHZ2XHgn.d.ts} +1 -1
- package/dist/{openapi-D8UTm0lu.d.cts → openapi-DXUE_MEP.d.cts} +1 -1
- package/dist/{read-DMvxeFCg.d.cts → read-D4xAmsbE.d.cts} +141 -13
- package/dist/{read-DMvxeFCg.d.ts → read-D4xAmsbE.d.ts} +141 -13
- package/dist/servers/admin/index.cjs +45 -45
- package/dist/servers/admin/index.cjs.map +1 -1
- package/dist/servers/admin/index.d.cts +3 -3
- package/dist/servers/admin/index.d.ts +3 -3
- package/dist/servers/admin/index.js +45 -45
- package/dist/servers/admin/index.js.map +1 -1
- package/dist/servers/crud/index.d.cts +5 -5
- package/dist/servers/crud/index.d.ts +5 -5
- package/dist/servers/index.cjs +88 -88
- package/dist/servers/index.cjs.map +1 -1
- package/dist/servers/index.d.cts +7 -7
- package/dist/servers/index.d.ts +7 -7
- package/dist/servers/index.js +88 -88
- package/dist/servers/index.js.map +1 -1
- package/dist/{types-CE1dws32.d.cts → types-C822D0dX.d.ts} +19 -18
- package/dist/{types-CjexXskS.d.ts → types-Z1Zy-2hs.d.cts} +19 -18
- package/package.json +5 -2
|
@@ -111,11 +111,10 @@ interface HistoryConfigBase {
|
|
|
111
111
|
subcollection?: string;
|
|
112
112
|
/**
|
|
113
113
|
* Optional Firestore TTL configuration. When set, every written history doc
|
|
114
|
-
* gets
|
|
115
|
-
*
|
|
114
|
+
* gets an `expiresAt` Timestamp at `now + days`. You still need to enable
|
|
115
|
+
* the TTL policy on the `expiresAt` field via gcloud / console.
|
|
116
116
|
*/
|
|
117
117
|
ttl?: {
|
|
118
|
-
field?: string;
|
|
119
118
|
days: number;
|
|
120
119
|
};
|
|
121
120
|
}
|
|
@@ -191,7 +190,6 @@ interface HistoryTriggersConfig<M = Record<string, any>> {
|
|
|
191
190
|
/** Defaults applied to every repo unless overridden. */
|
|
192
191
|
defaults?: {
|
|
193
192
|
ttl?: {
|
|
194
|
-
field?: string;
|
|
195
193
|
days: number;
|
|
196
194
|
};
|
|
197
195
|
};
|
|
@@ -217,16 +215,146 @@ interface HistoryTriggersConfig<M = Record<string, any>> {
|
|
|
217
215
|
*/
|
|
218
216
|
declare function createHistoryMethods<T>(documentRef: (...args: any[]) => DocumentReference, systemKeys: string[], repoName: string, config: HistoryConfigForModel<T> & {
|
|
219
217
|
enabled: boolean;
|
|
220
|
-
}):
|
|
221
|
-
|
|
222
|
-
|
|
218
|
+
}): HistoryMethods<T> | null;
|
|
219
|
+
/**
|
|
220
|
+
* Public, strongly-typed surface of the `repo.history` namespace.
|
|
221
|
+
*
|
|
222
|
+
* Exposed on a repository **only when** `history.enabled: true` is set in
|
|
223
|
+
* its config. Reads from the entity's `history` subcollection (or the custom
|
|
224
|
+
* name set via `history.subcollection`) and normalises both schema versions
|
|
225
|
+
* (v1 = one doc per modified field, v2 = one doc per write) into a single
|
|
226
|
+
* {@link HistoryEntry} shape.
|
|
227
|
+
*
|
|
228
|
+
* ### Path arguments
|
|
229
|
+
*
|
|
230
|
+
* Every method's leading positional arguments mirror
|
|
231
|
+
* `Parameters<repo.documentRef>`, so the call signature stays consistent with
|
|
232
|
+
* the rest of the repo API:
|
|
233
|
+
*
|
|
234
|
+
* - **Top-level collection** (`documentRef: (db, docId) => …`)
|
|
235
|
+
* → `repo.history.list("doc_42", opts?)`
|
|
236
|
+
* - **Subcollection** (`documentRef: (db, parentId, docId) => …`)
|
|
237
|
+
* → `repo.history.list("parent_1", "doc_42", opts?)`
|
|
238
|
+
*
|
|
239
|
+
* The trailing options/payload argument keeps the same position whatever the
|
|
240
|
+
* depth of the path.
|
|
241
|
+
*
|
|
242
|
+
* ### Pagination
|
|
243
|
+
*
|
|
244
|
+
* `list` / `byField` / `byOperation` use real Firestore cursors via the
|
|
245
|
+
* `cursor` + `limit` options on {@link HistoryListOptions} — no in-memory
|
|
246
|
+
* slicing, safe for large histories.
|
|
247
|
+
*
|
|
248
|
+
* @example Basic read
|
|
249
|
+
* ```ts
|
|
250
|
+
* const entries = await repos.residences.history!.list("residence_123", {
|
|
251
|
+
* limit: 50,
|
|
252
|
+
* direction: "desc",
|
|
253
|
+
* });
|
|
254
|
+
* for (const e of entries) {
|
|
255
|
+
* console.log(e.historySetAt.toDate(), e.operation, e.meta.userId);
|
|
256
|
+
* }
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @example Filter by field (autocompleted on `keyof T`)
|
|
260
|
+
* ```ts
|
|
261
|
+
* const addressChanges = await repos.residences.history!.byField(
|
|
262
|
+
* "residence_123",
|
|
263
|
+
* "address",
|
|
264
|
+
* );
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @template T - The repository's model type. Field-name parameters
|
|
268
|
+
* (e.g. `byField`'s `K`) and `HistoryEntry<T>` payloads
|
|
269
|
+
* are derived from this.
|
|
270
|
+
* @template PathArgs - Tuple of path-segment args inherited from the repo's
|
|
271
|
+
* `documentRef`. Defaults to `[string]` (a single
|
|
272
|
+
* `docId`) when used standalone.
|
|
273
|
+
*
|
|
274
|
+
* @see {@link createHistoryMethods} - factory used internally by `createRepository`.
|
|
275
|
+
* @see {@link HistoryEntry} - normalised return shape.
|
|
276
|
+
* @see {@link HistoryListOptions} - pagination + filter options.
|
|
277
|
+
*/
|
|
278
|
+
interface HistoryMethods<T, PathArgs extends readonly unknown[] = [string]> {
|
|
279
|
+
/**
|
|
280
|
+
* List normalised history entries for a single document.
|
|
281
|
+
*
|
|
282
|
+
* Reads both v1 and v2 docs and folds v1 field-per-doc entries that share
|
|
283
|
+
* the same author + timestamp (±5 ms) into a single logical entry, so the
|
|
284
|
+
* caller never has to care about the storage version.
|
|
285
|
+
*
|
|
286
|
+
* @param args - `[...pathArgs, options?]`. `pathArgs` mirror the repo's
|
|
287
|
+
* `documentRef`. `options` accepts `limit`, `cursor`,
|
|
288
|
+
* `direction`, `fields`, `operations`.
|
|
289
|
+
* @returns Array of {@link HistoryEntry} ordered by `historySetAt`
|
|
290
|
+
* (`direction` defaults to `"desc"`).
|
|
291
|
+
*/
|
|
292
|
+
list(...args: [...PathArgs, HistoryListOptions<T>?]): Promise<HistoryEntry<T>[]>;
|
|
293
|
+
/**
|
|
294
|
+
* Escape hatch returning **raw** Firestore documents (v1 or v2) without
|
|
295
|
+
* normalisation. Use only when {@link list} doesn't expose the field you
|
|
296
|
+
* need (custom legacy fields, debugging, migrations).
|
|
297
|
+
*
|
|
298
|
+
* @param args - `[...pathArgs, options?]`. Supports the same pagination
|
|
299
|
+
* options as `list`, minus model-aware filters.
|
|
300
|
+
*/
|
|
301
|
+
raw(...args: [...PathArgs, HistoryRawListOptions?]): Promise<Array<{
|
|
223
302
|
id: string;
|
|
224
303
|
data: V1HistoryDoc | V2HistoryDoc;
|
|
225
304
|
}>>;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Convenience wrapper around {@link list} that only returns entries
|
|
307
|
+
* touching a specific field. Field name is checked against `keyof T` at
|
|
308
|
+
* compile time.
|
|
309
|
+
*
|
|
310
|
+
* @typeParam K - A literal key of the model `T`.
|
|
311
|
+
* @param args - `[...pathArgs, field, options?]`.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* await repos.users.history!.byField("user_42", "email");
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
byField<K extends keyof T & string>(...args: [...PathArgs, K, HistoryListOptions<T>?]): Promise<HistoryEntry<T>[]>;
|
|
319
|
+
/**
|
|
320
|
+
* Convenience wrapper around {@link list} filtering on the operation type.
|
|
321
|
+
*
|
|
322
|
+
* @param args - `[...pathArgs, operation, options?]` where `operation` is
|
|
323
|
+
* `"create" | "update" | "delete"`.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```ts
|
|
327
|
+
* await repos.residences.history!.byOperation("residence_123", "delete");
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
byOperation(...args: [...PathArgs, HistoryOperation, HistoryListOptions<T>?]): Promise<HistoryEntry<T>[]>;
|
|
331
|
+
/**
|
|
332
|
+
* Synchronously append a custom history entry, bypassing the trigger.
|
|
333
|
+
*
|
|
334
|
+
* Useful when:
|
|
335
|
+
* - You already have richer business context than the trigger can extract
|
|
336
|
+
* (e.g. inside an HTTP handler that knows the authenticated user).
|
|
337
|
+
* - You want to record an event that isn't a Firestore write (e.g.
|
|
338
|
+
* `meta.reason = "exported-to-pdf"`).
|
|
339
|
+
*
|
|
340
|
+
* Honours the same `include` / `exclude` / meta auto-exclusion rules as
|
|
341
|
+
* the trigger. Returns `null` when the diff is empty (no changes recorded).
|
|
342
|
+
*
|
|
343
|
+
* > ⚠️ Use sparingly — combining manual records with the trigger can
|
|
344
|
+
* > produce duplicate entries if both fire for the same write.
|
|
345
|
+
*
|
|
346
|
+
* @param args - `[...pathArgs, payload]` where `payload` is
|
|
347
|
+
* `{ operation, before?, after?, meta? }`.
|
|
348
|
+
*/
|
|
349
|
+
recordManual(...args: [
|
|
350
|
+
...PathArgs,
|
|
351
|
+
{
|
|
352
|
+
operation: HistoryOperation;
|
|
353
|
+
before?: T | null;
|
|
354
|
+
after?: T | null;
|
|
355
|
+
meta?: HistoryMeta;
|
|
356
|
+
}
|
|
357
|
+
]): Promise<HistoryEntry<T> | null>;
|
|
358
|
+
}
|
|
231
359
|
|
|
232
|
-
export { type HistoryConfigForModel as H, type V2HistoryDoc as V, type
|
|
360
|
+
export { type HistoryConfigForModel as H, type V2HistoryDoc as V, type HistoryTriggersConfig as a, type HistoryMethods as b, type HistoryOperation as c, type HistoryFieldChange as d, type HistoryMeta as e, type HistoryValueType as f, type V1HistoryDoc as g, type HistoryEntry as h, createHistoryMethods as i, type HistoryConfigBase as j, type HistoryFirestoreTriggersDep as k, type HistoryListOptions as l, type HistoryRawListOptions as m, type HistoryTriggerRepoOverride as n };
|
|
@@ -111,11 +111,10 @@ interface HistoryConfigBase {
|
|
|
111
111
|
subcollection?: string;
|
|
112
112
|
/**
|
|
113
113
|
* Optional Firestore TTL configuration. When set, every written history doc
|
|
114
|
-
* gets
|
|
115
|
-
*
|
|
114
|
+
* gets an `expiresAt` Timestamp at `now + days`. You still need to enable
|
|
115
|
+
* the TTL policy on the `expiresAt` field via gcloud / console.
|
|
116
116
|
*/
|
|
117
117
|
ttl?: {
|
|
118
|
-
field?: string;
|
|
119
118
|
days: number;
|
|
120
119
|
};
|
|
121
120
|
}
|
|
@@ -191,7 +190,6 @@ interface HistoryTriggersConfig<M = Record<string, any>> {
|
|
|
191
190
|
/** Defaults applied to every repo unless overridden. */
|
|
192
191
|
defaults?: {
|
|
193
192
|
ttl?: {
|
|
194
|
-
field?: string;
|
|
195
193
|
days: number;
|
|
196
194
|
};
|
|
197
195
|
};
|
|
@@ -217,16 +215,146 @@ interface HistoryTriggersConfig<M = Record<string, any>> {
|
|
|
217
215
|
*/
|
|
218
216
|
declare function createHistoryMethods<T>(documentRef: (...args: any[]) => DocumentReference, systemKeys: string[], repoName: string, config: HistoryConfigForModel<T> & {
|
|
219
217
|
enabled: boolean;
|
|
220
|
-
}):
|
|
221
|
-
|
|
222
|
-
|
|
218
|
+
}): HistoryMethods<T> | null;
|
|
219
|
+
/**
|
|
220
|
+
* Public, strongly-typed surface of the `repo.history` namespace.
|
|
221
|
+
*
|
|
222
|
+
* Exposed on a repository **only when** `history.enabled: true` is set in
|
|
223
|
+
* its config. Reads from the entity's `history` subcollection (or the custom
|
|
224
|
+
* name set via `history.subcollection`) and normalises both schema versions
|
|
225
|
+
* (v1 = one doc per modified field, v2 = one doc per write) into a single
|
|
226
|
+
* {@link HistoryEntry} shape.
|
|
227
|
+
*
|
|
228
|
+
* ### Path arguments
|
|
229
|
+
*
|
|
230
|
+
* Every method's leading positional arguments mirror
|
|
231
|
+
* `Parameters<repo.documentRef>`, so the call signature stays consistent with
|
|
232
|
+
* the rest of the repo API:
|
|
233
|
+
*
|
|
234
|
+
* - **Top-level collection** (`documentRef: (db, docId) => …`)
|
|
235
|
+
* → `repo.history.list("doc_42", opts?)`
|
|
236
|
+
* - **Subcollection** (`documentRef: (db, parentId, docId) => …`)
|
|
237
|
+
* → `repo.history.list("parent_1", "doc_42", opts?)`
|
|
238
|
+
*
|
|
239
|
+
* The trailing options/payload argument keeps the same position whatever the
|
|
240
|
+
* depth of the path.
|
|
241
|
+
*
|
|
242
|
+
* ### Pagination
|
|
243
|
+
*
|
|
244
|
+
* `list` / `byField` / `byOperation` use real Firestore cursors via the
|
|
245
|
+
* `cursor` + `limit` options on {@link HistoryListOptions} — no in-memory
|
|
246
|
+
* slicing, safe for large histories.
|
|
247
|
+
*
|
|
248
|
+
* @example Basic read
|
|
249
|
+
* ```ts
|
|
250
|
+
* const entries = await repos.residences.history!.list("residence_123", {
|
|
251
|
+
* limit: 50,
|
|
252
|
+
* direction: "desc",
|
|
253
|
+
* });
|
|
254
|
+
* for (const e of entries) {
|
|
255
|
+
* console.log(e.historySetAt.toDate(), e.operation, e.meta.userId);
|
|
256
|
+
* }
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @example Filter by field (autocompleted on `keyof T`)
|
|
260
|
+
* ```ts
|
|
261
|
+
* const addressChanges = await repos.residences.history!.byField(
|
|
262
|
+
* "residence_123",
|
|
263
|
+
* "address",
|
|
264
|
+
* );
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @template T - The repository's model type. Field-name parameters
|
|
268
|
+
* (e.g. `byField`'s `K`) and `HistoryEntry<T>` payloads
|
|
269
|
+
* are derived from this.
|
|
270
|
+
* @template PathArgs - Tuple of path-segment args inherited from the repo's
|
|
271
|
+
* `documentRef`. Defaults to `[string]` (a single
|
|
272
|
+
* `docId`) when used standalone.
|
|
273
|
+
*
|
|
274
|
+
* @see {@link createHistoryMethods} - factory used internally by `createRepository`.
|
|
275
|
+
* @see {@link HistoryEntry} - normalised return shape.
|
|
276
|
+
* @see {@link HistoryListOptions} - pagination + filter options.
|
|
277
|
+
*/
|
|
278
|
+
interface HistoryMethods<T, PathArgs extends readonly unknown[] = [string]> {
|
|
279
|
+
/**
|
|
280
|
+
* List normalised history entries for a single document.
|
|
281
|
+
*
|
|
282
|
+
* Reads both v1 and v2 docs and folds v1 field-per-doc entries that share
|
|
283
|
+
* the same author + timestamp (±5 ms) into a single logical entry, so the
|
|
284
|
+
* caller never has to care about the storage version.
|
|
285
|
+
*
|
|
286
|
+
* @param args - `[...pathArgs, options?]`. `pathArgs` mirror the repo's
|
|
287
|
+
* `documentRef`. `options` accepts `limit`, `cursor`,
|
|
288
|
+
* `direction`, `fields`, `operations`.
|
|
289
|
+
* @returns Array of {@link HistoryEntry} ordered by `historySetAt`
|
|
290
|
+
* (`direction` defaults to `"desc"`).
|
|
291
|
+
*/
|
|
292
|
+
list(...args: [...PathArgs, HistoryListOptions<T>?]): Promise<HistoryEntry<T>[]>;
|
|
293
|
+
/**
|
|
294
|
+
* Escape hatch returning **raw** Firestore documents (v1 or v2) without
|
|
295
|
+
* normalisation. Use only when {@link list} doesn't expose the field you
|
|
296
|
+
* need (custom legacy fields, debugging, migrations).
|
|
297
|
+
*
|
|
298
|
+
* @param args - `[...pathArgs, options?]`. Supports the same pagination
|
|
299
|
+
* options as `list`, minus model-aware filters.
|
|
300
|
+
*/
|
|
301
|
+
raw(...args: [...PathArgs, HistoryRawListOptions?]): Promise<Array<{
|
|
223
302
|
id: string;
|
|
224
303
|
data: V1HistoryDoc | V2HistoryDoc;
|
|
225
304
|
}>>;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Convenience wrapper around {@link list} that only returns entries
|
|
307
|
+
* touching a specific field. Field name is checked against `keyof T` at
|
|
308
|
+
* compile time.
|
|
309
|
+
*
|
|
310
|
+
* @typeParam K - A literal key of the model `T`.
|
|
311
|
+
* @param args - `[...pathArgs, field, options?]`.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* await repos.users.history!.byField("user_42", "email");
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
byField<K extends keyof T & string>(...args: [...PathArgs, K, HistoryListOptions<T>?]): Promise<HistoryEntry<T>[]>;
|
|
319
|
+
/**
|
|
320
|
+
* Convenience wrapper around {@link list} filtering on the operation type.
|
|
321
|
+
*
|
|
322
|
+
* @param args - `[...pathArgs, operation, options?]` where `operation` is
|
|
323
|
+
* `"create" | "update" | "delete"`.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```ts
|
|
327
|
+
* await repos.residences.history!.byOperation("residence_123", "delete");
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
byOperation(...args: [...PathArgs, HistoryOperation, HistoryListOptions<T>?]): Promise<HistoryEntry<T>[]>;
|
|
331
|
+
/**
|
|
332
|
+
* Synchronously append a custom history entry, bypassing the trigger.
|
|
333
|
+
*
|
|
334
|
+
* Useful when:
|
|
335
|
+
* - You already have richer business context than the trigger can extract
|
|
336
|
+
* (e.g. inside an HTTP handler that knows the authenticated user).
|
|
337
|
+
* - You want to record an event that isn't a Firestore write (e.g.
|
|
338
|
+
* `meta.reason = "exported-to-pdf"`).
|
|
339
|
+
*
|
|
340
|
+
* Honours the same `include` / `exclude` / meta auto-exclusion rules as
|
|
341
|
+
* the trigger. Returns `null` when the diff is empty (no changes recorded).
|
|
342
|
+
*
|
|
343
|
+
* > ⚠️ Use sparingly — combining manual records with the trigger can
|
|
344
|
+
* > produce duplicate entries if both fire for the same write.
|
|
345
|
+
*
|
|
346
|
+
* @param args - `[...pathArgs, payload]` where `payload` is
|
|
347
|
+
* `{ operation, before?, after?, meta? }`.
|
|
348
|
+
*/
|
|
349
|
+
recordManual(...args: [
|
|
350
|
+
...PathArgs,
|
|
351
|
+
{
|
|
352
|
+
operation: HistoryOperation;
|
|
353
|
+
before?: T | null;
|
|
354
|
+
after?: T | null;
|
|
355
|
+
meta?: HistoryMeta;
|
|
356
|
+
}
|
|
357
|
+
]): Promise<HistoryEntry<T> | null>;
|
|
358
|
+
}
|
|
231
359
|
|
|
232
|
-
export { type HistoryConfigForModel as H, type V2HistoryDoc as V, type
|
|
360
|
+
export { type HistoryConfigForModel as H, type V2HistoryDoc as V, type HistoryTriggersConfig as a, type HistoryMethods as b, type HistoryOperation as c, type HistoryFieldChange as d, type HistoryMeta as e, type HistoryValueType as f, type V1HistoryDoc as g, type HistoryEntry as h, createHistoryMethods as i, type HistoryConfigBase as j, type HistoryFirestoreTriggersDep as k, type HistoryListOptions as l, type HistoryRawListOptions as m, type HistoryTriggerRepoOverride as n };
|