firebase-contract 0.1.0-rc.16 → 0.1.0-rc.2

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 (111) hide show
  1. package/README.md +60 -249
  2. package/dist/lib/_internal/compiler/compiler.d.ts +4 -11
  3. package/dist/lib/_internal/compiler/compiler.d.ts.map +1 -1
  4. package/dist/lib/_internal/compiler/compiler.js +26 -296
  5. package/dist/lib/_internal/generators/api/api-dto-generator.d.ts +5 -0
  6. package/dist/lib/_internal/generators/api/api-dto-generator.d.ts.map +1 -1
  7. package/dist/lib/_internal/generators/api/api-dto-generator.js +14 -29
  8. package/dist/lib/_internal/generators/api/api-types-generator.d.ts +5 -0
  9. package/dist/lib/_internal/generators/api/api-types-generator.d.ts.map +1 -1
  10. package/dist/lib/_internal/generators/api/api-types-generator.js +22 -38
  11. package/dist/lib/_internal/generators/api/api-validation-generator.d.ts +4 -0
  12. package/dist/lib/_internal/generators/api/api-validation-generator.d.ts.map +1 -1
  13. package/dist/lib/_internal/generators/api/api-validation-generator.js +9 -38
  14. package/dist/lib/_internal/generators/api/task-payload-generator.d.ts +6 -0
  15. package/dist/lib/_internal/generators/api/task-payload-generator.d.ts.map +1 -1
  16. package/dist/lib/_internal/generators/api/task-payload-generator.js +19 -33
  17. package/dist/lib/_internal/generators/config/config-generator.d.ts.map +1 -1
  18. package/dist/lib/_internal/generators/config/config-generator.js +1 -2
  19. package/dist/lib/_internal/generators/data-connect/adapter-generator.d.ts.map +1 -1
  20. package/dist/lib/_internal/generators/data-connect/adapter-generator.js +1 -2
  21. package/dist/lib/_internal/generators/data-connect/graphql-generator.d.ts +7 -0
  22. package/dist/lib/_internal/generators/data-connect/graphql-generator.d.ts.map +1 -1
  23. package/dist/lib/_internal/generators/data-connect/graphql-generator.js +5 -7
  24. package/dist/lib/_internal/generators/data-connect/operations-generator.d.ts +7 -0
  25. package/dist/lib/_internal/generators/data-connect/operations-generator.d.ts.map +1 -1
  26. package/dist/lib/_internal/generators/data-connect/operations-generator.js +8 -9
  27. package/dist/lib/_internal/generators/firestore/firestore-projection-generator.d.ts.map +1 -1
  28. package/dist/lib/_internal/generators/firestore/firestore-projection-generator.js +23 -9
  29. package/dist/lib/_internal/generators/firestore/firestore-split-generator.d.ts +1 -1
  30. package/dist/lib/_internal/generators/firestore/firestore-split-generator.d.ts.map +1 -1
  31. package/dist/lib/_internal/generators/firestore/firestore-split-generator.js +48 -71
  32. package/dist/lib/_internal/generators/firestore/firestore-type-generator.d.ts.map +1 -1
  33. package/dist/lib/_internal/generators/firestore/firestore-type-generator.js +1 -2
  34. package/dist/lib/_internal/generators/generator.d.ts +0 -38
  35. package/dist/lib/_internal/generators/generator.d.ts.map +1 -1
  36. package/dist/lib/_internal/generators/generator.js +1 -7
  37. package/dist/lib/_internal/generators/id/id-codec-generator.d.ts.map +1 -1
  38. package/dist/lib/_internal/generators/id/id-codec-generator.js +1 -2
  39. package/dist/lib/_internal/generators/index.d.ts +5 -2
  40. package/dist/lib/_internal/generators/index.d.ts.map +1 -1
  41. package/dist/lib/_internal/generators/index.js +15 -4
  42. package/dist/lib/_internal/generators/sql/sql-migration-generator.d.ts +1 -2
  43. package/dist/lib/_internal/generators/sql/sql-migration-generator.d.ts.map +1 -1
  44. package/dist/lib/_internal/generators/sql/sql-migration-generator.js +5 -13
  45. package/dist/lib/_internal/generators/support/header.d.ts.map +1 -1
  46. package/dist/lib/_internal/generators/support/header.js +0 -2
  47. package/dist/lib/_internal/generators/support/naming.d.ts +0 -1
  48. package/dist/lib/_internal/generators/support/naming.d.ts.map +1 -1
  49. package/dist/lib/_internal/generators/support/naming.js +0 -3
  50. package/dist/lib/_internal/generators/support/split.d.ts +1 -1
  51. package/dist/lib/_internal/generators/support/split.d.ts.map +1 -1
  52. package/dist/lib/_internal/generators/support/split.js +2 -3
  53. package/dist/lib/_internal/generators/typescript/typescript-generator.d.ts +1 -2
  54. package/dist/lib/_internal/generators/typescript/typescript-generator.d.ts.map +1 -1
  55. package/dist/lib/_internal/generators/typescript/typescript-generator.js +79 -14
  56. package/dist/lib/_internal/generators/typescript/typescript-split-generator.d.ts +1 -1
  57. package/dist/lib/_internal/generators/typescript/typescript-split-generator.d.ts.map +1 -1
  58. package/dist/lib/_internal/generators/typescript/typescript-split-generator.js +85 -6
  59. package/dist/lib/_internal/generators/union/union-generator.d.ts.map +1 -1
  60. package/dist/lib/_internal/generators/union/union-generator.js +1 -2
  61. package/dist/lib/_internal/generators/zod/zod-generator.d.ts +1 -2
  62. package/dist/lib/_internal/generators/zod/zod-generator.d.ts.map +1 -1
  63. package/dist/lib/_internal/generators/zod/zod-generator.js +56 -13
  64. package/dist/lib/_internal/generators/zod/zod-split-generator.d.ts +1 -1
  65. package/dist/lib/_internal/generators/zod/zod-split-generator.d.ts.map +1 -1
  66. package/dist/lib/_internal/generators/zod/zod-split-generator.js +57 -6
  67. package/dist/lib/_internal/ir/build-ir.d.ts.map +1 -1
  68. package/dist/lib/_internal/ir/build-ir.js +8 -95
  69. package/dist/lib/_internal/ir/ir.d.ts +5 -20
  70. package/dist/lib/_internal/ir/ir.d.ts.map +1 -1
  71. package/dist/lib/_internal/ir/ir.js +0 -1
  72. package/dist/lib/_internal/parser/parse.d.ts +3 -5
  73. package/dist/lib/_internal/parser/parse.d.ts.map +1 -1
  74. package/dist/lib/_internal/parser/parse.js +31 -297
  75. package/dist/lib/_internal/parser/raw-document.d.ts +9 -64
  76. package/dist/lib/_internal/parser/raw-document.d.ts.map +1 -1
  77. package/dist/lib/_internal/resolver/import-resolver.js +1 -1
  78. package/dist/lib/_internal/validation/rules.d.ts +0 -39
  79. package/dist/lib/_internal/validation/rules.d.ts.map +1 -1
  80. package/dist/lib/_internal/validation/rules.js +1 -133
  81. package/dist/lib/cli/commands/generate.d.ts.map +1 -1
  82. package/dist/lib/cli/commands/generate.js +5 -7
  83. package/dist/lib/cli/commands/index.d.ts.map +1 -1
  84. package/dist/lib/cli/commands/index.js +0 -2
  85. package/dist/lib/cli/commands/init.d.ts.map +1 -1
  86. package/dist/lib/cli/commands/init.js +16 -5
  87. package/dist/lib/cli/config.d.ts +2 -3
  88. package/dist/lib/cli/config.d.ts.map +1 -1
  89. package/dist/lib/cli/config.js +0 -3
  90. package/package.json +1 -1
  91. package/dist/lib/_internal/compiler/header-vars.d.ts +0 -41
  92. package/dist/lib/_internal/compiler/header-vars.d.ts.map +0 -1
  93. package/dist/lib/_internal/compiler/header-vars.js +0 -117
  94. package/dist/lib/_internal/generators/support/jsdoc.d.ts +0 -3
  95. package/dist/lib/_internal/generators/support/jsdoc.d.ts.map +0 -1
  96. package/dist/lib/_internal/generators/support/jsdoc.js +0 -9
  97. package/dist/lib/_internal/generators/support/split-variant.d.ts +0 -9
  98. package/dist/lib/_internal/generators/support/split-variant.d.ts.map +0 -1
  99. package/dist/lib/_internal/generators/support/split-variant.js +0 -13
  100. package/dist/lib/_internal/generators/support/templates.d.ts +0 -36
  101. package/dist/lib/_internal/generators/support/templates.d.ts.map +0 -1
  102. package/dist/lib/_internal/generators/support/templates.js +0 -50
  103. package/dist/lib/_internal/generators/typescript/render.d.ts +0 -15
  104. package/dist/lib/_internal/generators/typescript/render.d.ts.map +0 -1
  105. package/dist/lib/_internal/generators/typescript/render.js +0 -92
  106. package/dist/lib/_internal/generators/zod/render.d.ts +0 -12
  107. package/dist/lib/_internal/generators/zod/render.d.ts.map +0 -1
  108. package/dist/lib/_internal/generators/zod/render.js +0 -59
  109. package/dist/lib/cli/commands/where.d.ts +0 -3
  110. package/dist/lib/cli/commands/where.d.ts.map +0 -1
  111. package/dist/lib/cli/commands/where.js +0 -57
package/README.md CHANGED
@@ -10,7 +10,7 @@ From one contract, generate:
10
10
  - **Zod** validation schemas
11
11
  - **Data Connect** GraphQL schema (`@table`, keys, directives), query/mutation
12
12
  operations (routed per connector), and `Any`↔logical adapters
13
- - **Firestore** projection schemas (denormalized read model; shared field groups via fragments)
13
+ - **Firestore** projection schemas (denormalized read model with `_meta_`)
14
14
  - **API** request/response types, request-validation Zod, and class-validator DTOs
15
15
  - **Cloud Task / Pub/Sub** payload envelopes + delivery constants
16
16
  - **SQL migrations** for constraints Data Connect can't express (composite FKs,
@@ -32,101 +32,35 @@ Provides the `firebase-contract` (alias `fbc`) CLI and a programmatic API.
32
32
  ```bash
33
33
  fbc init # scaffold contract.yml + firebase-contract.json
34
34
  fbc validate # parse, resolve imports, semantically validate
35
- fbc generate # run every generator declared across the contract graph
35
+ fbc generate # run every `generate:` target declared in the contract graph
36
36
  fbc inspect # print the normalized IR (debugging)
37
- fbc where <Name> # locate the yml defining a type (logical / gqlName / fsName / table)
38
37
  ```
39
38
 
40
39
  ### One-command generation
41
40
 
42
- Each contract file declares the generators it uses in a top-level
43
- `generators:` block — a name plus an output template. Declaring a
44
- **document-scoped** generator (typescript, zod, …) runs it once for
45
- that yml; **api-scoped** generators (api-types, api-validation, api-dto,
46
- task-payloads) run for the entries that opt in (see below):
47
-
48
- ```yaml
49
- # contract.yml (root)
50
- project:
51
- aliases:
52
- "#contracts/*": libs/contracts/src/* # out templates may target aliases
53
- generators:
54
- - { generator: typescript, out: "#contracts", split: true }
55
- - { generator: api-types, out: "#contracts/api-types/{api-name}" }
56
- imports:
57
- - ./apps/shop/data-connect/schema.yml
58
- ```
41
+ Each contract file can declare its own outputs in a `generate:` section —
42
+ out dirs are relative to that yml file:
59
43
 
60
44
  ```yaml
61
45
  # apps/shop/data-connect/schema.yml
62
- generators:
63
- - { generator: data-connect-graphql, out: src, split: true }
64
- - { generator: sql-migrations, out: . }
46
+ generate:
47
+ - { out: src, generators: [data-connect-graphql-split] }
48
+ - { out: ., generators: [sql-migrations] }
65
49
  ```
66
50
 
67
- - `out` resolves relative to the declaring yml; `#alias/...` prefixes resolve
68
- through the **root** yml's `project.aliases` (relative to the root).
69
- - Api-scoped templates may use `{api-name}` (kebab-cased name) and `{path}`
70
- (REST path with `{param}` segments dropped).
71
- - Entries reference declarations by name — nearest first (same yml → root).
72
-
73
- #### Output settings: `file`, `split`, `options`, `header`
74
-
75
- Every declaration (and any entry-level application) can reshape the output —
76
- the defaults reproduce each generator's built-in layout, so omitting them
77
- changes nothing:
78
-
79
51
  ```yaml
80
- generators:
81
- - generator: api-dto
82
- out: "src/entries/{path}/dto"
83
- file: "{api-name}.dto.ts" # file-name template (default shown)
84
- split: true # one file per api (api-dto's default)
85
- - generator: api-types
86
- out: "#contracts/api-types"
87
- file: "{api-name}.types.ts" # override the bundled default with per-api files
88
- split: true
89
- options:
90
- typesImport: "../types" # where `import type { … } from '…'` points
91
- - generator: typescript
92
- out: "#contracts"
93
- file: models.ts # rename a single-file/barrel output
94
- split: true # document scope: per-table split layout
52
+ # contract.yml (root)
53
+ generate:
54
+ - out: libs/contracts/src
55
+ generators: [typescript-split, zod-split, firestore-split, id-codecs]
56
+ imports:
57
+ - ./apps/shop/data-connect/schema.yml
95
58
  ```
96
59
 
97
- - **`file`** — output file name. Api scope: a template (`{api-name}`/`{path}`
98
- allowed when `split: true`). Document scope: renames the single output file,
99
- or the barrel of a split layout.
100
- - **`split`** — api scope: `true` emits one file per api (the `file` template
101
- must contain a placeholder), `false` bundles everything into one `file`.
102
- Document scope: `true` selects the generator's per-item split layout
103
- (typescript, zod, firestore, data-connect-graphql, data-connect-operations)
104
- and errors for generators without one.
105
- - **`options`** — free-form string map passed through to the generator.
106
- Currently: `typesImport` (api-types, task-payloads, data-connect-operations)
107
- overrides the types import path. For api-types and task-payloads this is
108
- normally unnecessary: when the option is absent and a `typescript` generator
109
- is declared (nearest-first: same yml → root), the import specifier is derived
110
- automatically as the relative path from the output file to the declared
111
- barrel — moving or renaming the barrel (`out` / `file`) re-derives it. An
112
- explicit `typesImport` always wins; without a typescript declaration the
113
- generator's built-in default (`./types`) applies.
114
- - **`header`** — per-generator banner override: `default` for the built-in
115
- AUTO-GENERATED banner, any text for a custom comment, `""` to suppress the
116
- banner for this generator. Wins over the contract-level `header:` and the
117
- CLI `--header` flag.
118
- - Defaults per generator: `api-types` → `api-types.ts` bundled, `api-validation`
119
- → `api-validation.ts` bundled, `task-payloads` → `task-payloads.ts` bundled,
120
- `api-dto` → `{api-name}.dto.ts` split.
121
- - Entry-level settings override the declaration, which overrides the
122
- generator's default (same nearest-first rule as `out`).
123
-
124
- `fbc generate contract.yml` materializes **all** declared outputs across the
125
- whole import graph in one run. Passing `-o`/`-g` switches to single-target mode
126
- (`fbc generate <entry> -o <dir> -g typescript,zod`). `firebase-contract.json`
127
- holds only a default `entry` — output routing lives in the yml `generators:`
128
- declarations, so a config file can never silently override them.
129
-
60
+ `fbc generate contract.yml` then materializes **all** targets across the whole
61
+ import graph in one run. Passing `-o`/`-g` switches to single-target mode
62
+ (`fbc generate <entry> -o <dir> -g typescript,zod`), and
63
+ `firebase-contract.json` (`entry`, `outDir`, `generators`) can hold defaults.
130
64
 
131
65
  ### Generated-file headers
132
66
 
@@ -141,34 +75,6 @@ fbc generate --header "Managed by fbc" # custom text (multi-line ok)
141
75
  header: default # or any text; the CLI --header flag wins
142
76
  ```
143
77
 
144
- Header text (contract `header:`, per-generator `header`, CLI `--header`)
145
- supports `${...}` template variables:
146
-
147
- | Variable | Value |
148
- | --- | --- |
149
- | `${rootContractPath}` | entry (root) yml path, relative to the root yml's directory |
150
- | `${currentContractPath}` | the yml the output is generated from |
151
- | `${allContractPath}` | import chain root → current, joined with ` -> ` |
152
- | `${generatedAt}` | date the file was **first** generated (carried over on regenerate) |
153
- | `${updatedAt}` | date the content **last changed** |
154
-
155
- A regenerate that produces identical content keeps both dates and reproduces
156
- the file byte-for-byte, so `--check` stays drift-free; when content changes,
157
- `generatedAt` is carried over from the existing file and only `updatedAt`
158
- moves. Date tokens accept an optional format — `${updatedAt:yyyy-mm-dd HH:mm:ss}`
159
- — with runs `yyyy`/`yy`, `MM`, `dd`, `HH`, `ss`, and `mm` meaning month before
160
- any hour token / minute after one (both `yyyy-mm-dd` and `HH:mm` read
161
- naturally). Default: `yyyy-MM-dd`.
162
-
163
- The `default` banner includes the source and dates:
164
-
165
- ```
166
- // AUTO-GENERATED by firebase-contract. Do not edit by hand.
167
- // Source: ${currentContractPath}
168
- // Generated: ${generatedAt} / Updated: ${updatedAt}
169
- // Regenerate with: fbc generate
170
- ```
171
-
172
78
  Comment syntax adapts per file type (`//` for TS, `#` for GraphQL/YAML-ish,
173
79
  `--` for SQL).
174
80
 
@@ -182,33 +88,8 @@ in other contracts (relative paths or npm packages). Imports are resolved
182
88
  transitively with cycle/duplicate detection and diamond dedup, so you can split
183
89
  a large contract across files that mirror your repo layout.
184
90
 
185
- **Type names are globally unique.** The namespace is flat across the whole
186
- import graph: defining the same name twice — same kind (`DUPLICATE_DEFINITION`)
187
- or across kinds/derived identifiers, e.g. an enum and a model both named
188
- `Status`, or two enums whose `CONSTANT_CASE` consts collide (`NAME_COLLISION`)
189
- — aborts generation. Uniqueness is enforced per output namespace with its
190
- *effective* names, so `fsName`/`gqlName` renames legitimately reuse a name in a
191
- different output: GraphQL names are checked per `data-connect-graphql` scope
192
- (services may map distinct logical names onto the same gqlName), and the
193
- firestore module is checked under `fsName ?? name` alongside doc names. A bare
194
- type reference therefore always resolves to exactly one definition — use
195
- `fbc where <Name>` to find it.
196
-
197
- **Unknown keys are errors.** Every key the parser does not consume is an
198
- `UNKNOWN_KEY` error (all reported in one pass), never silently dropped — a
199
- typo like `optionnal:` must not quietly turn into a required field. There is
200
- no `version:` field: nothing consumes one, so accepting it would only fake a
201
- compatibility mechanism that does not exist.
202
-
203
- **Out-of-vocabulary values are errors too.** A value outside a field's fixed
204
- set is `INVALID_VALUE` rather than a silent coercion: `auth: PUBILC` does not
205
- quietly become `NO_ACCESS`, `dir: Dsec` does not become `ASC`, and a mistyped
206
- `action` / `single` / `keyArg` / `style.*` is not dropped. The one exception is
207
- `where.op`, which is warned (`UNKNOWN_WHERE_OP`) not errored — it is emitted
208
- verbatim into GraphQL and the recognized-operator list may lag Data Connect, so
209
- a typo is surfaced without rejecting a valid-but-unlisted operator.
210
-
211
91
  ```yaml
92
+ version: 1
212
93
  imports:
213
94
  - ./apps/shop/data-connect/schema.yml
214
95
  - some-shared-package/contract.yml
@@ -245,10 +126,8 @@ export type ProductStatusKey = keyof typeof PRODUCT_STATUS
245
126
  export type ProductStatus = (typeof PRODUCT_STATUS)[ProductStatusKey]
246
127
  ```
247
128
 
248
- For a plain `'OPEN' | 'DONE' | 'DISABLED'` union instead, construct the
249
- TypeScript generator with `enumStyle: 'union'` via the programmatic API
250
- (`createTypeScriptGenerator({ enumStyle: 'union' })`). This is a build-time
251
- generator option, not a YAML contract field.
129
+ Pass `enumStyle: 'union'` to the TypeScript generator for a plain
130
+ `'OPEN' | 'DONE' | 'DISABLED'` union instead.
252
131
 
253
132
  ## Models
254
133
 
@@ -417,13 +296,11 @@ name as long as their connector sets don't overlap.
417
296
 
418
297
  ## API endpoints
419
298
 
420
- Model application endpoints in three kind-implied sections — `apis:` (https /
421
- callable, keyed by REST path), `tasks:` (Cloud Tasks), and `events:` (Pub/Sub).
422
- The api-scoped generators — request/response types (`api-types`),
423
- request-validation Zod (`api-validation`), class-validator DTOs (`api-dto`),
424
- and payload contracts (`task-payloads`) — run for the entries that opt in via
425
- the section `defaults` or the entry's own `generators:`. A payload references a
426
- model or declares inline fields; a void response maps to `void`.
299
+ Model application endpoints (Cloud Task / callable / https / pubsub). Generates
300
+ request/response types (`api-types`), request-validation Zod (`api-validation`),
301
+ class-validator DTOs (`api-dto`), and — for `task`/`pubsub` — payload contracts
302
+ (`task-payloads`). A payload references a model or declares inline fields; a void
303
+ response maps to `void`.
427
304
 
428
305
  ```yaml
429
306
  envelopes:
@@ -433,10 +310,9 @@ envelopes:
433
310
  opId: string
434
311
  enqueuedAt: int
435
312
 
436
- tasks: # Cloud Tasks (kind implied)
437
- defaults:
438
- generators: [task-payloads] # section default: applies to entries below
313
+ apis:
439
314
  createCatalog:
315
+ kind: task # product | callable | https | pubsub
440
316
  envelope: RetryTaskPayload # wraps the product data
441
317
  maxAttempts: 3
442
318
  request:
@@ -446,31 +322,17 @@ tasks: # Cloud Tasks (kind implied)
446
322
  response:
447
323
  void: true
448
324
 
449
- events: # Pub/Sub (kind implied)
450
325
  generateAiResponse:
326
+ kind: pubsub
451
327
  topic: ai-review-generate-response
452
328
  timeoutSeconds: 540
453
- generators: [task-payloads]
454
-
455
- apis: # https/callable, keyed by REST path
456
- defaults:
457
- generators: [api-types, api-validation]
458
- /shops/{slug}:
459
- operationId: getShopBySlug
460
- kind: callable # https (default) | callable
329
+
330
+ getShopBySlug:
331
+ kind: callable
461
332
  request: { fields: { slug: { type: string, nonempty: true } } }
462
333
  response: { model: Shop }
463
- generators: # entry-level wins over section defaults;
464
- - api-types # an inline out overrides the declared template
465
- - { generator: api-dto, out: "src/entries/{path}" }
466
334
  ```
467
335
 
468
- Generator application resolves in two tiers — the section `defaults`
469
- (`apis:/tasks:/events:` → `defaults.generators`) and the entry's own
470
- `generators:` (which replaces the defaults). `apis:` keys must be REST paths
471
- (`/...` or `METHOD /...` so the same route can appear once per verb) with an
472
- `operationId`; tasks and Pub/Sub events live in their own sections.
473
-
474
336
  For `createCatalog` this yields `CreateCatalogTaskData`, `CreateCatalogTaskPayload =
475
337
  RetryTaskPayload<CreateCatalogTaskData>`, and `CREATE_CATALOG_MAX_ATTEMPTS`, plus the
476
338
  request types, Zod schema, and DTO.
@@ -483,9 +345,9 @@ reality automatically:
483
345
 
484
346
  - **relations → resolved string ids** (`ownerUser` → `ownerUserId: z.string()`)
485
347
  - **timestamps → `z.date()`**, optional fields → `.nullable()`
348
+ - a **`_meta_`** consistency envelope is attached (opt out with `meta: false`)
486
349
  - `pick` / `omit` select which base fields survive
487
350
  - inline `fields` add denormalized data (flattened DAG edges, stringified JSON)
488
- - `extends: [<fragment>…]` splices shared fields in (see **Fragments** below)
489
351
 
490
352
  ```yaml
491
353
  firestore:
@@ -503,13 +365,10 @@ firestore:
503
365
  ```
504
366
 
505
367
  Emits Zod schemas + inferred types, mirroring a hand-written Firestore schema
506
- library. (`firestore-types` is the zero-config entry point for projects that
507
- have not written projections yet: it re-types *every* model with the Firestore
508
- `Timestamp`, no `firestore:` section needed. Once you declare projections,
509
- prefer the `firestore` generator — it is the one that understands
510
- pick/omit/fsName/denormalized fields.)
368
+ library. (The simpler `firestore-types` generator just re-types *every* model
369
+ with the Firestore `Timestamp` and does not denormalize.)
511
370
 
512
- With `firestore` + `split: true`, fields whose Zod chain is **identical** to the Data
371
+ With `firestore-split`, fields whose Zod chain is **identical** to the Data
513
372
  Connect schema are reused via `.pick()` — only representation changes are
514
373
  restated:
515
374
 
@@ -519,6 +378,7 @@ export const ShopSchema = DcShopSchema.pick({
519
378
  }).extend({
520
379
  createdAt: z.date(),
521
380
  updatedAt: z.date().nullable(),
381
+ _meta_: _Meta_Schema,
522
382
  })
523
383
  ```
524
384
 
@@ -535,50 +395,6 @@ Additional projection options:
535
395
  - FS-only enums render as frozen consts (`REVIEW_STATE` + `ReviewStateSchema`),
536
396
  co-located with the first projection that references them
537
397
 
538
- ### Fragments (`fragments:` + `extends:`)
539
-
540
- A **fragment** is a named group of fields declared once and spliced into
541
- consumers via `extends: [<name>…]` — the way to share a common field across
542
- many projections (a consistency `_meta_` envelope, audit columns, …) without a
543
- tool-imposed convention. The fragment field's name, type, and which docs carry
544
- it are all yours.
545
-
546
- The value objects a fragment references can be **pinned** to a fixed split
547
- output via `out` (+ optional `file`) on the model declaration. A pinned value
548
- object is *placement-scoped*: emitted only at that location (dependency-ordered,
549
- with an `index.ts` barrel), imported by consumers via that directory, and
550
- excluded from the default `typescript`/`zod` barrels — so it lives purely in the
551
- firestore output. This is what lets a shared envelope sit under `firestore/_/`.
552
-
553
- ```yaml
554
- models:
555
- MetaOp:
556
- out: firestore/_ # → firestore/_/_meta_.ts (+ firestore/_/index.ts)
557
- file: _meta_.ts
558
- fields:
559
- id: { type: string }
560
- Meta:
561
- out: firestore/_
562
- file: _meta_.ts
563
- fields:
564
- scope: { type: float, nullable: true }
565
- op: { type: MetaOp, nullable: true }
566
-
567
- fragments:
568
- meta:
569
- fields:
570
- _meta_: { type: Meta }
571
-
572
- firestore:
573
- Shop:
574
- from: Shop
575
- extends: [meta] # appends `_meta_: MetaSchema` (imported from './_')
576
- ```
577
-
578
- `extends` referencing a fragment that is not declared is an `UNKNOWN_FRAGMENT`
579
- error, not a silent no-op — a typo like `extends: [metaa]` fails generation
580
- rather than quietly dropping the shared fields.
581
-
582
398
  ## Discriminated unions
583
399
 
584
400
  ```yaml
@@ -630,19 +446,14 @@ project:
630
446
  idCodec:
631
447
  minLength: 8
632
448
  alphabet: <your-shuffled-sqids-alphabet>
633
- aliases:
634
- "#contracts/*": libs/contracts/src/*
635
449
  ```
636
450
 
637
451
  - `services` (`name`/`database`) feed the `FIRESTORE_DATABASES` constants in the
638
- split `firestore` barrel.
452
+ `firestore-split` barrel.
639
453
  - `idCodec` pins the Sqids settings as a contract constant; when present, the
640
454
  `id-codecs` generator also emits a self-contained `id-core.ts` (the
641
455
  encode/decode primitives), so nothing about id encoding lives outside the
642
456
  contract.
643
- - `aliases` maps `#alias/...` out-template prefixes to paths relative to the
644
- **root** yml, so imported contracts can target shared libs without relative
645
- path gymnastics (longest prefix wins).
646
457
  - `codebases` / service `location` + `connectors` are consumed by the optional
647
458
  `config` generator (preview), which emits per-service `dataconnect.yaml`,
648
459
  per-connector `connector.yaml`, and the `FIRESTORE_DATABASES` /
@@ -654,32 +465,32 @@ project:
654
465
 
655
466
  # Generators
656
467
 
657
- | name | scope | output | notes |
658
- | ------------------------ | -------- | ----------------------------- | ------------------------------------------------------ |
659
- | `typescript` | document | `types.ts`; `split: true` → `types/<table>.ts` + barrel | interfaces + const/union enums; split co-locates enums/embedded objects per table |
660
- | `zod` | document | `schemas.ts`; `split: true` → `schemas/<table>.ts` + barrel | `z.object` schemas (constraints, `z.lazy` model refs) |
661
- | `data-connect-graphql` | document | `schema.gql`; `split: true` → `schema/<table>.gql` | `type … @table(name, key)`; `@col`/`@unique`/`@index`/`@default` |
662
- | `data-connect-operations`| document | `<connector>/operations.gql` + `.ts`; `split: true` → `<connector>/operations/<entity>/{queries,mutations}.gql` | queries/mutations (where ops, orderBy, limit, aggregate, exprs, inc), per connector; split matches the real Data Connect repo layout |
663
- | `data-connect-adapter` | document | `data-connect-adapters.ts` | convert `Any` rows ⇄ logical types |
664
- | `firestore-types` | document | `firestore-types.ts` | naive TS types with Firestore `Timestamp` (all models) |
665
- | `firestore` | document | `firestore.ts`; `split: true` → `firestore/<collection>.ts` + barrel | Firestore projection Zod schemas (derived, denormalized); `extends` fragments, pinned value objects under their `out` (e.g. `firestore/_/`), DC-schema `.pick()` reuse, `FIRESTORE_DATABASES` constants in the barrel |
666
- | `api-types` | api | `api-types.ts` | endpoint request/response types |
667
- | `api-validation` | api | `api-validation.ts` | endpoint request-validation Zod |
668
- | `api-dto` | api | `<operation>.dto.ts` per api | class-validator DTO classes (NestJS `dto/` convention) |
669
- | `task-payloads` | api | `task-payloads.ts` | envelopes + `*TaskData`/`*TaskPayload` + constants |
670
- | `sql-migrations` | document | `migrations/constraints.sql` | composite FK / CHECK / index SQL — idempotent (`IF NOT EXISTS` / `duplicate_object` guard), safe to re-apply whole |
671
- | `id-codecs` | document | `id-codecs.ts` (+ `id-core.ts`) | typed per-entity id encode/decode wrappers; emits the Sqids primitives when `project.idCodec` is set |
672
- | `unions` | document | `unions.ts` | Zod discriminated unions + TS union types |
673
- | `config` | document | `dataconnect.yaml`, `connector.yaml`, `constants.ts` | DC configs + sync constants (preview — see [Project config](#project-config)) |
468
+ | name | output | notes |
469
+ | ------------------------ | ----------------------------- | ------------------------------------------------------ |
470
+ | `typescript` | `types.ts` | interfaces + const/union enums |
471
+ | `typescript-split` | `types/<table>.ts` + `types.ts` barrel | one file per table; enums/embedded objects co-located |
472
+ | `zod` | `schemas.ts` | `z.object` schemas (constraints, `z.lazy` model refs) |
473
+ | `zod-split` | `schemas/<table>.ts` + `schemas.ts` barrel | split variant of `zod` |
474
+ | `data-connect-graphql` | `schema.gql` | `type … @table(name, key)`; `@col`/`@unique`/`@index`/`@default` |
475
+ | `data-connect-graphql-split` | `schema/<table>.gql` | same schema, one file per table (enums co-located) |
476
+ | `data-connect-operations`| `<connector>/operations.gql` + `.ts` | queries/mutations (where ops, orderBy, limit, aggregate, exprs, inc), per connector |
477
+ | `data-connect-operations-split` | `<connector>/operations/<entity>/{queries,mutations}.gql` | real Data Connect repo layout; shared types stay in `typescript`/`zod` outputs |
478
+ | `data-connect-adapter` | `data-connect-adapters.ts` | convert `Any` rows ⇄ logical types |
479
+ | `firestore-types` | `firestore-types.ts` | naive TS types with Firestore `Timestamp` (all models) |
480
+ | `firestore` | `firestore.ts` | Firestore projection Zod schemas (derived, denormalized) |
481
+ | `firestore-split` | `firestore/<collection>.ts` + `firestore.ts` barrel | one file per projection; `_meta_` under `firestore/_/`; DC-schema `.pick()` reuse; `FIRESTORE_DATABASES` constants in the barrel |
482
+ | `api-types` | `api-types.ts` | endpoint request/response types |
483
+ | `api-validation` | `api-validation.ts` | endpoint request-validation Zod |
484
+ | `api-dto` | `api-dtos.ts` | class-validator DTO classes |
485
+ | `task-payloads` | `task-payloads.ts` | envelopes + `*TaskData`/`*TaskPayload` + constants |
486
+ | `sql-migrations` | `migrations/constraints.sql` | composite FK / CHECK / index SQL |
487
+ | `id-codecs` | `id-codecs.ts` (+ `id-core.ts`) | typed per-entity id encode/decode wrappers; emits the Sqids primitives when `project.idCodec` is set |
488
+ | `unions` | `unions.ts` | Zod discriminated unions + TS union types |
489
+ | `config` | `dataconnect.yaml`, `connector.yaml`, `constants.ts` | DC configs + sync constants (preview — see [Project config](#project-config)) |
674
490
 
675
491
  Each generator emits nothing when its section is absent, so a small contract
676
492
  produces a small output. Select a subset with `-g`.
677
493
 
678
- **Scope** decides how a `generators:` declaration takes effect: `document`
679
- generators run once for the yml that declares them; `api` generators run only
680
- for the entries that apply them (section `defaults.generators` → entry
681
- `generators:`, entry wins).
682
-
683
494
  ### The `Any` boundary
684
495
 
685
496
  Data Connect stores JSON and embedded objects as the `Any` scalar, erasing the
@@ -707,7 +518,7 @@ const result = generate('contract.yml', {
707
518
  write: true,
708
519
  })
709
520
 
710
- // Every generator declared across the import graph:
521
+ // Every `generate:` target declared across the import graph:
711
522
  const all = generateAll('contract.yml', { write: true })
712
523
  ```
713
524
 
@@ -4,7 +4,6 @@ import { RawContract } from '../parser/raw-document.js';
4
4
  import { ModuleLoader } from '../resolver/module-loader.js';
5
5
  import { GeneratedFile, GeneratorContext } from '../generators/generator.js';
6
6
  import { GeneratorRegistry } from '../generators/registry.js';
7
- import { HeaderPathVars } from './header-vars.js';
8
7
  export interface CompileOptions {
9
8
  /** Override module loading (defaults to the file system). */
10
9
  loader?: ModuleLoader;
@@ -30,10 +29,6 @@ export interface GenerateOptions extends CompileOptions {
30
29
  /** When true, write the generated files to disk. */
31
30
  write?: boolean;
32
31
  context?: GeneratorContext;
33
- /** Header `${...}` path values; defaults to entry-only (root = current = entry). */
34
- headerVars?: HeaderPathVars;
35
- /** Clock for `${generatedAt}`/`${updatedAt}` stamping (tests); defaults to now. */
36
- now?: Date;
37
32
  }
38
33
  export interface GenerateTargetResult {
39
34
  /** The contract file that declared this target. */
@@ -48,18 +43,16 @@ export interface GenerateAllResult {
48
43
  ok: boolean;
49
44
  }
50
45
  /**
51
- * Run every generator declared across the entry contract and its (transitive)
52
- * imports — the one-command flow: each contract file declares its generators
53
- * (`generators:` + section defaults / entry applications) and
54
- * `fbc generate <root>` materializes all of them. Output dirs resolve relative
55
- * to the declaring yml (or the root yml for `#alias/...` templates).
46
+ * Run every `generate:` target declared across the entry contract and its
47
+ * (transitive) imports — the one-command flow: each contract file states where
48
+ * its own outputs go, and `fbc generate <root>` materializes all of them.
49
+ * Output dirs resolve relative to the declaring yml file.
56
50
  */
57
51
  export declare const generateAll: (entryPath: string, options?: {
58
52
  registry?: GeneratorRegistry;
59
53
  write?: boolean;
60
54
  context?: GeneratorContext;
61
55
  loader?: ModuleLoader;
62
- now?: Date;
63
56
  }) => GenerateAllResult;
64
57
  export interface FileDrift {
65
58
  /** Files whose on-disk content differs from the generated content. */
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../src/lib/_internal/compiler/compiler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAA;AAEhE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAU,WAAW,EAAqC,MAAM,2BAA2B,CAAA;AAElG,OAAO,EAAkB,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAI3E,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAI5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAEL,cAAc,EAGf,MAAM,kBAAkB,CAAA;AAEzB,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,EAAE,CAAA;IACN,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,WAAW,MAAM,EAAE,UAAS,cAAmB,KAAG,aAkBzE,CAAA;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,oFAAoF;IACpF,UAAU,CAAC,EAAE,cAAc,CAAA;IAC3B,mFAAmF;IACnF,GAAG,CAAC,EAAE,IAAI,CAAA;CACX;AAED,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,aAAa,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,oBAAoB,EAAE,CAAA;IAC/B,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,EAAE,EAAE,OAAO,CAAA;CACZ;AAyOD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GACtB,WAAW,MAAM,EACjB,UAAS;IACP,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,GAAG,CAAC,EAAE,IAAI,CAAA;CACN,KACL,iBA0FF,CAAA;AAED,MAAM,WAAW,SAAS;IACxB,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,mEAAmE;IACnE,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,aAAa,EAAE,KAAG,SAUlD,CAAA;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,EAAE,CAAA;IACN,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,oFAAoF;IACpF,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,0DAA0D;IAC1D,EAAE,EAAE,OAAO,CAAA;CACZ;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM,EAAE,SAAS,eAAe,KAAG,cAgEtE,CAAA"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../src/lib/_internal/compiler/compiler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAoB,MAAM,mBAAmB,CAAA;AAEhE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAEvD,OAAO,EAAkB,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAG3E,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAE5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE7D,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,EAAE,CAAA;IACN,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,WAAW,MAAM,EAAE,UAAS,cAAmB,KAAG,aAUzE,CAAA;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,MAAM,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,aAAa,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,oBAAoB,EAAE,CAAA;IAC/B,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,EAAE,EAAE,OAAO,CAAA;CACZ;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,WAAW,MAAM,EACjB,UAAS;IAAE,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAA;CAAO,KACjH,iBA8BF,CAAA;AAED,MAAM,WAAW,SAAS;IACxB,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,mEAAmE;IACnE,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,aAAa,EAAE,KAAG,SAUlD,CAAA;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,EAAE,CAAA;IACN,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,oFAAoF;IACpF,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,0DAA0D;IAC1D,EAAE,EAAE,OAAO,CAAA;CACZ;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,WAAW,MAAM,EAAE,SAAS,eAAe,KAAG,cAuCtE,CAAA"}