@lpdjs/firestore-repo-service 2.4.3 → 2.6.2-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 (76) hide show
  1. package/README.md +92 -50
  2. package/dist/{create-servers-B9dTUhvR.d.cts → create-servers-B4GrBqdA.d.cts} +6 -6
  3. package/dist/{create-servers-BFhdPPeo.d.ts → create-servers-CVudVM8e.d.ts} +6 -6
  4. package/dist/{firebase-auth-D1APf9PA.d.cts → firebase-auth-Dpvrd8MP.d.cts} +13 -0
  5. package/dist/{firebase-auth-D1APf9PA.d.ts → firebase-auth-Dpvrd8MP.d.ts} +13 -0
  6. package/dist/history/index.cjs +1 -1
  7. package/dist/history/index.cjs.map +1 -1
  8. package/dist/history/index.d.cts +10 -4
  9. package/dist/history/index.d.ts +10 -4
  10. package/dist/history/index.js +1 -1
  11. package/dist/history/index.js.map +1 -1
  12. package/dist/{index-BxurOEz1.d.ts → index-DzO9MfNI.d.cts} +9 -2
  13. package/dist/{index-BmagC7uw.d.cts → index-oFhGCBrY.d.ts} +9 -2
  14. package/dist/index.cjs +84 -84
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +9 -9
  17. package/dist/index.d.ts +9 -9
  18. package/dist/index.js +84 -84
  19. package/dist/index.js.map +1 -1
  20. package/dist/{openapi-ML_1hTx2.d.cts → openapi-B2w5tVRR.d.cts} +1 -1
  21. package/dist/{openapi-DIoQV_yQ.d.ts → openapi-DB8bXZB-.d.ts} +1 -1
  22. package/dist/{queue-xMOZxY0M.d.cts → queue-B8YUTnBT.d.cts} +20 -5
  23. package/dist/{queue-CVchaGAh.d.ts → queue-DYmbVDu5.d.ts} +20 -5
  24. package/dist/{read-BSyLao3I.d.cts → read-CTWZjxyh.d.cts} +1 -1
  25. package/dist/{read-BSyLao3I.d.ts → read-CTWZjxyh.d.ts} +1 -1
  26. package/dist/servers/admin/index.cjs +48 -48
  27. package/dist/servers/admin/index.cjs.map +1 -1
  28. package/dist/servers/admin/index.d.cts +4 -4
  29. package/dist/servers/admin/index.d.ts +4 -4
  30. package/dist/servers/admin/index.js +48 -48
  31. package/dist/servers/admin/index.js.map +1 -1
  32. package/dist/servers/auth/index.cjs +25 -12
  33. package/dist/servers/auth/index.cjs.map +1 -1
  34. package/dist/servers/auth/index.d.cts +1 -1
  35. package/dist/servers/auth/index.d.ts +1 -1
  36. package/dist/servers/auth/index.js +25 -12
  37. package/dist/servers/auth/index.js.map +1 -1
  38. package/dist/servers/crud/index.cjs +2 -2
  39. package/dist/servers/crud/index.cjs.map +1 -1
  40. package/dist/servers/crud/index.d.cts +6 -6
  41. package/dist/servers/crud/index.d.ts +6 -6
  42. package/dist/servers/crud/index.js +2 -2
  43. package/dist/servers/crud/index.js.map +1 -1
  44. package/dist/servers/hono/cli.cjs +142 -53
  45. package/dist/servers/hono/cli.cjs.map +1 -1
  46. package/dist/servers/hono/cli.js +142 -53
  47. package/dist/servers/hono/cli.js.map +1 -1
  48. package/dist/servers/hono/index.cjs +5 -5
  49. package/dist/servers/hono/index.cjs.map +1 -1
  50. package/dist/servers/hono/index.d.cts +241 -24
  51. package/dist/servers/hono/index.d.ts +241 -24
  52. package/dist/servers/hono/index.js +5 -5
  53. package/dist/servers/hono/index.js.map +1 -1
  54. package/dist/servers/index.cjs +98 -98
  55. package/dist/servers/index.cjs.map +1 -1
  56. package/dist/servers/index.d.cts +9 -9
  57. package/dist/servers/index.d.ts +9 -9
  58. package/dist/servers/index.js +98 -98
  59. package/dist/servers/index.js.map +1 -1
  60. package/dist/sync/bigquery.cjs +3 -3
  61. package/dist/sync/bigquery.cjs.map +1 -1
  62. package/dist/sync/bigquery.d.cts +18 -2
  63. package/dist/sync/bigquery.d.ts +18 -2
  64. package/dist/sync/bigquery.js +3 -3
  65. package/dist/sync/bigquery.js.map +1 -1
  66. package/dist/sync/index.cjs +37 -37
  67. package/dist/sync/index.cjs.map +1 -1
  68. package/dist/sync/index.d.cts +5 -5
  69. package/dist/sync/index.d.ts +5 -5
  70. package/dist/sync/index.js +37 -37
  71. package/dist/sync/index.js.map +1 -1
  72. package/dist/{types-5vgXdUM2.d.ts → types-BHZ-Gk-s.d.ts} +71 -4
  73. package/dist/{types-ChzVPw4k.d.ts → types-FLGn8CAI.d.ts} +15 -1
  74. package/dist/{types-BtdC0Qhu.d.cts → types-GvexCqrq.d.cts} +71 -4
  75. package/dist/{types-BgIGWlR1.d.cts → types-wcX7xfdo.d.cts} +15 -1
  76. package/package.json +2 -2
@@ -1,8 +1,8 @@
1
- import { c as AuthUser, A as AuthExtension } from './firebase-auth-D1APf9PA.js';
1
+ import { c as AuthUser, A as AuthExtension } from './firebase-auth-Dpvrd8MP.js';
2
2
  import * as zod from 'zod';
3
3
  import { z } from 'zod';
4
4
  import { HttpsOptions } from 'firebase-functions/v2/https';
5
- import { a as HistoryConfigForModel, b as HistoryMethods } from './read-BSyLao3I.js';
5
+ import { d as HistoryConfigForModel, i as HistoryMethods } from './read-CTWZjxyh.js';
6
6
  import { DocumentReference, Firestore, DocumentSnapshot, WhereFilterOp, Query, CollectionReference, WriteBatch, Transaction } from 'firebase-admin/firestore';
7
7
 
8
8
  /**
@@ -533,6 +533,58 @@ type ConfiguredRepository<T extends RepositoryConfig<any, any, any, any, any, an
533
533
  history?: HistoryMethods<T["type"], Parameters<T["documentRef"]>>;
534
534
  };
535
535
 
536
+ /**
537
+ * Default security-headers middleware for the bundled HTTP servers.
538
+ *
539
+ * Addresses issues #12 (no security headers / clickjacking / cache leakage)
540
+ * and #13 (no CSP bounding the CDN origins loaded by the admin & login pages).
541
+ *
542
+ * The middleware is framework-agnostic: it only touches `res.setHeader`
543
+ * (present on Node's `ServerResponse` and the shims used by the admin/CRUD
544
+ * routers) and always calls `next()`.
545
+ */
546
+ type AnyReq = any;
547
+ type AnyRes = any;
548
+ type Next = () => void | Promise<void>;
549
+ /**
550
+ * Reasonable default Content-Security-Policy for the bundled **HTML** pages
551
+ * (admin UI + login). Allows the specific CDN origins the pages need and
552
+ * forbids framing entirely. `'unsafe-inline'`/`'unsafe-eval'` are required by
553
+ * the Tailwind browser build and the small inline bootstrap scripts.
554
+ */
555
+ declare const DEFAULT_HTML_CSP: string;
556
+ interface SecurityHeadersOptions {
557
+ /**
558
+ * Content-Security-Policy value. Pass a string to override, or `false` to
559
+ * omit the header entirely. Defaults to {@link DEFAULT_HTML_CSP} for HTML
560
+ * servers (admin/login) and is omitted for pure JSON APIs unless provided.
561
+ */
562
+ csp?: string | false;
563
+ /**
564
+ * `X-Frame-Options` value. Default `"DENY"`. Pass `false` to omit (e.g. when
565
+ * the app must be embedded in a trusted iframe — prefer a CSP
566
+ * `frame-ancestors` allowlist instead).
567
+ */
568
+ frameOptions?: string | false;
569
+ /** `Referrer-Policy` value. Default `"no-referrer"`. */
570
+ referrerPolicy?: string | false;
571
+ /**
572
+ * `Cache-Control` value. Default `"private, no-store"` to keep private data
573
+ * out of shared proxy caches. Pass `false` to leave caching to handlers.
574
+ */
575
+ cacheControl?: string | false;
576
+ }
577
+ /**
578
+ * Build a middleware that sets a baseline of security response headers.
579
+ *
580
+ * @example
581
+ * ```ts
582
+ * router.use(securityHeaders()); // HTML-safe defaults
583
+ * router.use(securityHeaders({ csp: false })); // JSON API (no CSP)
584
+ * ```
585
+ */
586
+ declare function securityHeaders(opts?: SecurityHeadersOptions): (_req: AnyReq, res: AnyRes, next: Next) => Promise<void>;
587
+
536
588
  /**
537
589
  * Options to control OpenAPI 3.1 spec generation for the CRUD server.
538
590
  * Defined here (rather than in `./openapi`) to avoid a circular import:
@@ -577,8 +629,9 @@ type IsAny<T> = 0 extends 1 & T ? true : false;
577
629
  * - `"create"` — field is accepted in create requests / create form
578
630
  * - `"mutable"` — field is accepted in update requests / edit form
579
631
  * - `"filterable"` — field can be used in query filters / filter bar
632
+ * - `"orderable"` — field can be used in `orderBy` / sort
580
633
  */
581
- type FieldRole = "create" | "mutable" | "filterable";
634
+ type FieldRole = "create" | "mutable" | "filterable" | "orderable";
582
635
  /**
583
636
  * Field paths on the model, **excluding** auto-managed system keys.
584
637
  * Falls back to `string` when `TRepo` is unresolved (`any`) so that plain
@@ -627,6 +680,10 @@ interface CrudRepoConfig<TRepo extends ConfiguredRepository<any> = ConfiguredRep
627
680
  * - `"create"` — field is accepted in create requests
628
681
  * - `"mutable"` — field is accepted in update requests (PUT/PATCH)
629
682
  * - `"filterable"` — field can be used in query filters
683
+ * - `"orderable"` — field can be used in `orderBy` / sort. When no field
684
+ * declares `"orderable"`, the `"filterable"` set is reused so existing
685
+ * configs keep sorting on their filterable fields (fail-closed: fields
686
+ * that are neither filterable nor orderable cannot be sorted on).
630
687
  *
631
688
  * If `fieldsConfig` is omitted, all non-system schema fields are allowed
632
689
  * for all roles, and all fields (including system keys) are filterable.
@@ -764,6 +821,8 @@ interface CrudRepoEntry {
764
821
  pageSize: number;
765
822
  /** Resolved from fieldsConfig: fields with role "filterable" */
766
823
  filterableFields?: string[];
824
+ /** Resolved from fieldsConfig: fields with role "orderable" (falls back to filterableFields) */
825
+ orderableFields?: string[];
767
826
  /** Resolved from fieldsConfig: fields with role "mutable" */
768
827
  mutableFields?: string[];
769
828
  /** Resolved from fieldsConfig: fields with role "create" */
@@ -832,6 +891,14 @@ interface CrudServerOptions<TRepos extends Record<string, ConfiguredRepository<a
832
891
  };
833
892
  /** Whether to parse JSON bodies. Default: true. */
834
893
  parseBody?: boolean;
894
+ /**
895
+ * Baseline security response headers (X-Frame-Options, nosniff,
896
+ * Referrer-Policy, Cache-Control, optional CSP). Enabled by default; for
897
+ * this JSON API the CSP is omitted unless you provide one (so the bundled
898
+ * `/__docs` UI keeps working). Pass an options object to customise or
899
+ * `false` to disable (issue #12).
900
+ */
901
+ securityHeaders?: SecurityHeadersOptions | false;
835
902
  /**
836
903
  * Authentication guard executed before every request.
837
904
  * - Pass an {@link AuthExtension} (e.g. result of `firebaseAuth({...})`) to
@@ -970,4 +1037,4 @@ interface QueryRequestBody {
970
1037
  })[];
971
1038
  }
972
1039
 
973
- export { type ApiResponse as A, type BasicAuthConfig as B, type ConfiguredRepository as C, type ExtractDocumentRefSignature as E, type FieldRole as F, type GetOptions as G, type IncludeConfigTyped as I, type ListResponseData as L, type Middleware as M, type OpenAPISpecOptions as O, type PaginationOptions as P, type QueryRequestBody as Q, type RepoFieldPath as R, type UserFieldPath as U, type WhereClause as W, type CrudServerOptions as a, type CrudRepoConfig as b, type CrudRepoEntry as c, type CrudRepoRegistry as d, type RepoRelationKeys as e, type RepositoryConfig as f, type FieldPath as g, type QueryOptions as h, type RelationConfig as i, type ExtractUpdateSignature as j, type GetResult as k, type RelationalKeys as l, createPaginationIterator as m, executePaginatedQuery as n, type PaginationResult as o, type GenerateGetMethods as p, type GenerateQueryMethods as q, type PaginationWithIncludeOptionsTyped as r, type PopulateOptionsTyped as s };
1040
+ export { type ApiResponse as A, type BasicAuthConfig as B, type ConfiguredRepository as C, DEFAULT_HTML_CSP as D, type ExtractDocumentRefSignature as E, type FieldRole as F, type GetOptions as G, type IncludeConfigTyped as I, type ListResponseData as L, type Middleware as M, type OpenAPISpecOptions as O, type PaginationOptions as P, type QueryRequestBody as Q, type RepoFieldPath as R, type SecurityHeadersOptions as S, type UserFieldPath as U, type WhereClause as W, type CrudServerOptions as a, type CrudRepoConfig as b, type CrudRepoEntry as c, type CrudRepoRegistry as d, type RepoRelationKeys as e, type RepositoryConfig as f, type FieldPath as g, type QueryOptions as h, type RelationConfig as i, type ExtractUpdateSignature as j, type GetResult as k, type RelationalKeys as l, createPaginationIterator as m, executePaginatedQuery as n, type PaginationResult as o, type GenerateGetMethods as p, type GenerateQueryMethods as q, type PaginationWithIncludeOptionsTyped as r, securityHeaders as s, type PopulateOptionsTyped as t };
@@ -1,4 +1,4 @@
1
- import { A as AuthExtension } from './firebase-auth-D1APf9PA.js';
1
+ import { A as AuthExtension } from './firebase-auth-Dpvrd8MP.js';
2
2
  import { onDocumentCreated, onDocumentUpdated, onDocumentDeleted } from 'firebase-functions/v2/firestore';
3
3
  import { onRequest, HttpsOptions } from 'firebase-functions/v2/https';
4
4
  import { onMessagePublished, PubSubOptions } from 'firebase-functions/v2/pubsub';
@@ -77,6 +77,14 @@ interface SyncEvent {
77
77
  * versions; the worker treats `undefined` as "always apply".
78
78
  */
79
79
  version?: number;
80
+ /**
81
+ * DLQ retry bookkeeping. Set by the worker when an event is re-published to
82
+ * the dead-letter topic after a flush failure. Used to cap retries of a
83
+ * poison message (see issue #09). Absent on first-time events.
84
+ */
85
+ attempts?: number;
86
+ /** Epoch millis of the first flush failure for this event (DLQ only). */
87
+ firstFailedAt?: number;
80
88
  }
81
89
  /**
82
90
  * Abstract SQL adapter that the sync worker calls.
@@ -240,6 +248,12 @@ interface SyncWorkerConfig<M = Record<string, any>> {
240
248
  autoMigrate?: boolean;
241
249
  /** PubSub topic prefix (default: "firestore-sync") */
242
250
  topicPrefix?: string;
251
+ /**
252
+ * Maximum number of times an event may be re-published to the dead-letter
253
+ * topic before it is dropped (poison-message cap). Default: 5. Set to 0 to
254
+ * disable the cap (events are re-published indefinitely). See issue #09.
255
+ */
256
+ maxDlqAttempts?: number;
243
257
  /**
244
258
  * Cloud Functions v2 options forwarded to `onMessagePublished()` for every
245
259
  * worker handler. Use to tune `concurrency`, `maxInstances`, `minInstances`,
@@ -1,8 +1,8 @@
1
- import { c as AuthUser, A as AuthExtension } from './firebase-auth-D1APf9PA.cjs';
1
+ import { c as AuthUser, A as AuthExtension } from './firebase-auth-Dpvrd8MP.cjs';
2
2
  import * as zod from 'zod';
3
3
  import { z } from 'zod';
4
4
  import { HttpsOptions } from 'firebase-functions/v2/https';
5
- import { a as HistoryConfigForModel, b as HistoryMethods } from './read-BSyLao3I.cjs';
5
+ import { d as HistoryConfigForModel, i as HistoryMethods } from './read-CTWZjxyh.cjs';
6
6
  import { DocumentReference, Firestore, DocumentSnapshot, WhereFilterOp, Query, CollectionReference, WriteBatch, Transaction } from 'firebase-admin/firestore';
7
7
 
8
8
  /**
@@ -533,6 +533,58 @@ type ConfiguredRepository<T extends RepositoryConfig<any, any, any, any, any, an
533
533
  history?: HistoryMethods<T["type"], Parameters<T["documentRef"]>>;
534
534
  };
535
535
 
536
+ /**
537
+ * Default security-headers middleware for the bundled HTTP servers.
538
+ *
539
+ * Addresses issues #12 (no security headers / clickjacking / cache leakage)
540
+ * and #13 (no CSP bounding the CDN origins loaded by the admin & login pages).
541
+ *
542
+ * The middleware is framework-agnostic: it only touches `res.setHeader`
543
+ * (present on Node's `ServerResponse` and the shims used by the admin/CRUD
544
+ * routers) and always calls `next()`.
545
+ */
546
+ type AnyReq = any;
547
+ type AnyRes = any;
548
+ type Next = () => void | Promise<void>;
549
+ /**
550
+ * Reasonable default Content-Security-Policy for the bundled **HTML** pages
551
+ * (admin UI + login). Allows the specific CDN origins the pages need and
552
+ * forbids framing entirely. `'unsafe-inline'`/`'unsafe-eval'` are required by
553
+ * the Tailwind browser build and the small inline bootstrap scripts.
554
+ */
555
+ declare const DEFAULT_HTML_CSP: string;
556
+ interface SecurityHeadersOptions {
557
+ /**
558
+ * Content-Security-Policy value. Pass a string to override, or `false` to
559
+ * omit the header entirely. Defaults to {@link DEFAULT_HTML_CSP} for HTML
560
+ * servers (admin/login) and is omitted for pure JSON APIs unless provided.
561
+ */
562
+ csp?: string | false;
563
+ /**
564
+ * `X-Frame-Options` value. Default `"DENY"`. Pass `false` to omit (e.g. when
565
+ * the app must be embedded in a trusted iframe — prefer a CSP
566
+ * `frame-ancestors` allowlist instead).
567
+ */
568
+ frameOptions?: string | false;
569
+ /** `Referrer-Policy` value. Default `"no-referrer"`. */
570
+ referrerPolicy?: string | false;
571
+ /**
572
+ * `Cache-Control` value. Default `"private, no-store"` to keep private data
573
+ * out of shared proxy caches. Pass `false` to leave caching to handlers.
574
+ */
575
+ cacheControl?: string | false;
576
+ }
577
+ /**
578
+ * Build a middleware that sets a baseline of security response headers.
579
+ *
580
+ * @example
581
+ * ```ts
582
+ * router.use(securityHeaders()); // HTML-safe defaults
583
+ * router.use(securityHeaders({ csp: false })); // JSON API (no CSP)
584
+ * ```
585
+ */
586
+ declare function securityHeaders(opts?: SecurityHeadersOptions): (_req: AnyReq, res: AnyRes, next: Next) => Promise<void>;
587
+
536
588
  /**
537
589
  * Options to control OpenAPI 3.1 spec generation for the CRUD server.
538
590
  * Defined here (rather than in `./openapi`) to avoid a circular import:
@@ -577,8 +629,9 @@ type IsAny<T> = 0 extends 1 & T ? true : false;
577
629
  * - `"create"` — field is accepted in create requests / create form
578
630
  * - `"mutable"` — field is accepted in update requests / edit form
579
631
  * - `"filterable"` — field can be used in query filters / filter bar
632
+ * - `"orderable"` — field can be used in `orderBy` / sort
580
633
  */
581
- type FieldRole = "create" | "mutable" | "filterable";
634
+ type FieldRole = "create" | "mutable" | "filterable" | "orderable";
582
635
  /**
583
636
  * Field paths on the model, **excluding** auto-managed system keys.
584
637
  * Falls back to `string` when `TRepo` is unresolved (`any`) so that plain
@@ -627,6 +680,10 @@ interface CrudRepoConfig<TRepo extends ConfiguredRepository<any> = ConfiguredRep
627
680
  * - `"create"` — field is accepted in create requests
628
681
  * - `"mutable"` — field is accepted in update requests (PUT/PATCH)
629
682
  * - `"filterable"` — field can be used in query filters
683
+ * - `"orderable"` — field can be used in `orderBy` / sort. When no field
684
+ * declares `"orderable"`, the `"filterable"` set is reused so existing
685
+ * configs keep sorting on their filterable fields (fail-closed: fields
686
+ * that are neither filterable nor orderable cannot be sorted on).
630
687
  *
631
688
  * If `fieldsConfig` is omitted, all non-system schema fields are allowed
632
689
  * for all roles, and all fields (including system keys) are filterable.
@@ -764,6 +821,8 @@ interface CrudRepoEntry {
764
821
  pageSize: number;
765
822
  /** Resolved from fieldsConfig: fields with role "filterable" */
766
823
  filterableFields?: string[];
824
+ /** Resolved from fieldsConfig: fields with role "orderable" (falls back to filterableFields) */
825
+ orderableFields?: string[];
767
826
  /** Resolved from fieldsConfig: fields with role "mutable" */
768
827
  mutableFields?: string[];
769
828
  /** Resolved from fieldsConfig: fields with role "create" */
@@ -832,6 +891,14 @@ interface CrudServerOptions<TRepos extends Record<string, ConfiguredRepository<a
832
891
  };
833
892
  /** Whether to parse JSON bodies. Default: true. */
834
893
  parseBody?: boolean;
894
+ /**
895
+ * Baseline security response headers (X-Frame-Options, nosniff,
896
+ * Referrer-Policy, Cache-Control, optional CSP). Enabled by default; for
897
+ * this JSON API the CSP is omitted unless you provide one (so the bundled
898
+ * `/__docs` UI keeps working). Pass an options object to customise or
899
+ * `false` to disable (issue #12).
900
+ */
901
+ securityHeaders?: SecurityHeadersOptions | false;
835
902
  /**
836
903
  * Authentication guard executed before every request.
837
904
  * - Pass an {@link AuthExtension} (e.g. result of `firebaseAuth({...})`) to
@@ -970,4 +1037,4 @@ interface QueryRequestBody {
970
1037
  })[];
971
1038
  }
972
1039
 
973
- export { type ApiResponse as A, type BasicAuthConfig as B, type ConfiguredRepository as C, type ExtractDocumentRefSignature as E, type FieldRole as F, type GetOptions as G, type IncludeConfigTyped as I, type ListResponseData as L, type Middleware as M, type OpenAPISpecOptions as O, type PaginationOptions as P, type QueryRequestBody as Q, type RepoFieldPath as R, type UserFieldPath as U, type WhereClause as W, type CrudServerOptions as a, type CrudRepoConfig as b, type CrudRepoEntry as c, type CrudRepoRegistry as d, type RepoRelationKeys as e, type RepositoryConfig as f, type FieldPath as g, type QueryOptions as h, type RelationConfig as i, type ExtractUpdateSignature as j, type GetResult as k, type RelationalKeys as l, createPaginationIterator as m, executePaginatedQuery as n, type PaginationResult as o, type GenerateGetMethods as p, type GenerateQueryMethods as q, type PaginationWithIncludeOptionsTyped as r, type PopulateOptionsTyped as s };
1040
+ export { type ApiResponse as A, type BasicAuthConfig as B, type ConfiguredRepository as C, DEFAULT_HTML_CSP as D, type ExtractDocumentRefSignature as E, type FieldRole as F, type GetOptions as G, type IncludeConfigTyped as I, type ListResponseData as L, type Middleware as M, type OpenAPISpecOptions as O, type PaginationOptions as P, type QueryRequestBody as Q, type RepoFieldPath as R, type SecurityHeadersOptions as S, type UserFieldPath as U, type WhereClause as W, type CrudServerOptions as a, type CrudRepoConfig as b, type CrudRepoEntry as c, type CrudRepoRegistry as d, type RepoRelationKeys as e, type RepositoryConfig as f, type FieldPath as g, type QueryOptions as h, type RelationConfig as i, type ExtractUpdateSignature as j, type GetResult as k, type RelationalKeys as l, createPaginationIterator as m, executePaginatedQuery as n, type PaginationResult as o, type GenerateGetMethods as p, type GenerateQueryMethods as q, type PaginationWithIncludeOptionsTyped as r, securityHeaders as s, type PopulateOptionsTyped as t };
@@ -1,4 +1,4 @@
1
- import { A as AuthExtension } from './firebase-auth-D1APf9PA.cjs';
1
+ import { A as AuthExtension } from './firebase-auth-Dpvrd8MP.cjs';
2
2
  import { onDocumentCreated, onDocumentUpdated, onDocumentDeleted } from 'firebase-functions/v2/firestore';
3
3
  import { onRequest, HttpsOptions } from 'firebase-functions/v2/https';
4
4
  import { onMessagePublished, PubSubOptions } from 'firebase-functions/v2/pubsub';
@@ -77,6 +77,14 @@ interface SyncEvent {
77
77
  * versions; the worker treats `undefined` as "always apply".
78
78
  */
79
79
  version?: number;
80
+ /**
81
+ * DLQ retry bookkeeping. Set by the worker when an event is re-published to
82
+ * the dead-letter topic after a flush failure. Used to cap retries of a
83
+ * poison message (see issue #09). Absent on first-time events.
84
+ */
85
+ attempts?: number;
86
+ /** Epoch millis of the first flush failure for this event (DLQ only). */
87
+ firstFailedAt?: number;
80
88
  }
81
89
  /**
82
90
  * Abstract SQL adapter that the sync worker calls.
@@ -240,6 +248,12 @@ interface SyncWorkerConfig<M = Record<string, any>> {
240
248
  autoMigrate?: boolean;
241
249
  /** PubSub topic prefix (default: "firestore-sync") */
242
250
  topicPrefix?: string;
251
+ /**
252
+ * Maximum number of times an event may be re-published to the dead-letter
253
+ * topic before it is dropped (poison-message cap). Default: 5. Set to 0 to
254
+ * disable the cap (events are re-published indefinitely). See issue #09.
255
+ */
256
+ maxDlqAttempts?: number;
243
257
  /**
244
258
  * Cloud Functions v2 options forwarded to `onMessagePublished()` for every
245
259
  * worker handler. Use to tune `concurrency`, `maxInstances`, `minInstances`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lpdjs/firestore-repo-service",
3
- "version": "2.4.3",
3
+ "version": "2.6.2-beta.0",
4
4
  "workspaces": [
5
5
  "test/functions"
6
6
  ],
@@ -135,7 +135,7 @@
135
135
  "LICENSE"
136
136
  ],
137
137
  "bin": {
138
- "frs-hono": "./dist/servers/hono/cli.js"
138
+ "frs": "./dist/servers/hono/cli.js"
139
139
  },
140
140
  "authors": [
141
141
  {