@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.
Files changed (37) hide show
  1. package/dist/{create-servers-B3Ls46bx.d.cts → create-servers-CfLtucbQ.d.cts} +27 -3
  2. package/dist/{create-servers-CvVZnihM.d.ts → create-servers-xx0m3wwM.d.ts} +27 -3
  3. package/dist/history/index.cjs +1 -1
  4. package/dist/history/index.cjs.map +1 -1
  5. package/dist/history/index.d.cts +3 -4
  6. package/dist/history/index.d.ts +3 -4
  7. package/dist/history/index.js +1 -1
  8. package/dist/history/index.js.map +1 -1
  9. package/dist/{index-DGB3Oemk.d.ts → index-BvKyjs6k.d.cts} +11 -3
  10. package/dist/{index-Cw9b1crP.d.cts → index-Njwf8jvu.d.ts} +11 -3
  11. package/dist/index.cjs +93 -93
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +8 -8
  14. package/dist/index.d.ts +8 -8
  15. package/dist/index.js +93 -93
  16. package/dist/index.js.map +1 -1
  17. package/dist/{openapi-BEf4OuG9.d.ts → openapi-BHZ2XHgn.d.ts} +1 -1
  18. package/dist/{openapi-D8UTm0lu.d.cts → openapi-DXUE_MEP.d.cts} +1 -1
  19. package/dist/{read-DMvxeFCg.d.cts → read-D4xAmsbE.d.cts} +141 -13
  20. package/dist/{read-DMvxeFCg.d.ts → read-D4xAmsbE.d.ts} +141 -13
  21. package/dist/servers/admin/index.cjs +45 -45
  22. package/dist/servers/admin/index.cjs.map +1 -1
  23. package/dist/servers/admin/index.d.cts +3 -3
  24. package/dist/servers/admin/index.d.ts +3 -3
  25. package/dist/servers/admin/index.js +45 -45
  26. package/dist/servers/admin/index.js.map +1 -1
  27. package/dist/servers/crud/index.d.cts +5 -5
  28. package/dist/servers/crud/index.d.ts +5 -5
  29. package/dist/servers/index.cjs +88 -88
  30. package/dist/servers/index.cjs.map +1 -1
  31. package/dist/servers/index.d.cts +7 -7
  32. package/dist/servers/index.d.ts +7 -7
  33. package/dist/servers/index.js +88 -88
  34. package/dist/servers/index.js.map +1 -1
  35. package/dist/{types-CE1dws32.d.cts → types-C822D0dX.d.ts} +19 -18
  36. package/dist/{types-CjexXskS.d.ts → types-Z1Zy-2hs.d.cts} +19 -18
  37. package/package.json +5 -2
@@ -1,4 +1,4 @@
1
- import { s as CrudRepoRegistry, O as OpenAPISpecOptions } from './types-CjexXskS.js';
1
+ import { s as CrudRepoRegistry, O as OpenAPISpecOptions } from './types-C822D0dX.js';
2
2
 
3
3
  /**
4
4
  * OpenAPI 3.1 specification generator for the CRUD server.
@@ -1,4 +1,4 @@
1
- import { s as CrudRepoRegistry, O as OpenAPISpecOptions } from './types-CE1dws32.cjs';
1
+ import { s as CrudRepoRegistry, O as OpenAPISpecOptions } from './types-Z1Zy-2hs.cjs';
2
2
 
3
3
  /**
4
4
  * OpenAPI 3.1 specification generator for the CRUD server.
@@ -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 a Timestamp field (default name: `expiresAt`) at `now + days`.
115
- * You still need to enable the TTL policy on that field via gcloud / console.
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
- list: (...args: any[]) => Promise<HistoryEntry<T>[]>;
222
- raw: (...args: any[]) => Promise<Array<{
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
- byField: (...args: any[]) => Promise<HistoryEntry<T>[]>;
227
- byOperation: (...args: any[]) => Promise<HistoryEntry<T>[]>;
228
- recordManual: (...args: any[]) => Promise<HistoryEntry<T> | null>;
229
- } | null;
230
- type HistoryMethods<T> = NonNullable<ReturnType<typeof createHistoryMethods<T>>>;
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 HistoryMethods as a, type HistoryTriggersConfig 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 };
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 a Timestamp field (default name: `expiresAt`) at `now + days`.
115
- * You still need to enable the TTL policy on that field via gcloud / console.
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
- list: (...args: any[]) => Promise<HistoryEntry<T>[]>;
222
- raw: (...args: any[]) => Promise<Array<{
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
- byField: (...args: any[]) => Promise<HistoryEntry<T>[]>;
227
- byOperation: (...args: any[]) => Promise<HistoryEntry<T>[]>;
228
- recordManual: (...args: any[]) => Promise<HistoryEntry<T> | null>;
229
- } | null;
230
- type HistoryMethods<T> = NonNullable<ReturnType<typeof createHistoryMethods<T>>>;
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 HistoryMethods as a, type HistoryTriggersConfig 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 };
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 };