firebase-contract 0.1.0-rc.15 → 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 +91 -274
  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 -32
  79. package/dist/lib/_internal/validation/rules.d.ts.map +1 -1
  80. package/dist/lib/_internal/validation/rules.js +0 -119
  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
@@ -281,24 +162,24 @@ models:
281
162
 
282
163
  | option | meaning |
283
164
  | ----------------------------------- | -------------------------------------------------------- |
284
- | `type` | document | scalar name, or an enum/model name |
285
- | `optional` | document | value may be absent (`field?`) |
286
- | `list` | document | value is an array of `type` |
287
- | `id` | document | marks the (single) primary identifier |
288
- | `unique` | document | field-level unique → `@unique` |
289
- | `relation` | document | model-typed field is a foreign-key relation (see below) |
290
- | `col` | document | Data Connect column dataType (Int64 PKs default to `bigserial`) |
291
- | `default` | document | `@default(expr: …)` on the DC column |
292
- | `literal` | document | pin to one literal value (union discriminant tags) |
293
- | `nullable` | document | value may be `null` (`.nullable()` / `\| null`) |
294
- | `description` | document | doc comment carried into generated output |
295
- | `jsdoc` | document | render the description as a JSDoc block (Firestore fields) |
165
+ | `type` | scalar name, or an enum/model name |
166
+ | `optional` | value may be absent (`field?`) |
167
+ | `list` | value is an array of `type` |
168
+ | `id` | marks the (single) primary identifier |
169
+ | `unique` | field-level unique → `@unique` |
170
+ | `relation` | model-typed field is a foreign-key relation (see below) |
171
+ | `col` | Data Connect column dataType (Int64 PKs default to `bigserial`) |
172
+ | `default` | `@default(expr: …)` on the DC column |
173
+ | `literal` | pin to one literal value (union discriminant tags) |
174
+ | `nullable` | value may be `null` (`.nullable()` / `\| null`) |
175
+ | `description` | doc comment carried into generated output |
176
+ | `jsdoc` | render the description as a JSDoc block (Firestore fields) |
296
177
  | **constraints** → | |
297
- | `min` / `max` | document | numeric bounds |
298
- | `minLength` / `maxLength` | document | string/array length bounds |
299
- | `nonempty` | document | non-empty string/array |
300
- | `pattern` | document | regex the string must match |
301
- | `email` / `url` | document | string format |
178
+ | `min` / `max` | numeric bounds |
179
+ | `minLength` / `maxLength` | string/array length bounds |
180
+ | `nonempty` | non-empty string/array |
181
+ | `pattern` | regex the string must match |
182
+ | `email` / `url` | string format |
302
183
 
303
184
  Constraints flow into the Zod schemas, the API request validation, and the
304
185
  class-validator DTOs.
@@ -307,14 +188,14 @@ class-validator DTOs.
307
188
 
308
189
  | option | meaning |
309
190
  | ------------ | ------------------------------------------------------------------ |
310
- | `key` | document | composite primary key field names (else the `id: true` field) |
311
- | `table` | document | table name override (default: snake_case pluralization) |
312
- | `gqlName` | document | GraphQL type name override |
313
- | `fsName` | document | Firestore-side rename (avoid collisions with table models) |
314
- | `directives` | document | `multi` = each type-level directive on its own line |
315
- | `footer` | document | trailing comment block after the closing `}` in the schema file |
316
- | `indexes` | document | composite `@index`/`@unique` (`{ fields, name?, unique?, expand? }` — `expand` renders args one per line) |
317
- | `sql` | document | raw SQL constraints (see [SQL migrations](#sql-migrations)) |
191
+ | `key` | composite primary key field names (else the `id: true` field) |
192
+ | `table` | table name override (default: snake_case pluralization) |
193
+ | `gqlName` | GraphQL type name override |
194
+ | `fsName` | Firestore-side rename (avoid collisions with table models) |
195
+ | `directives` | `multi` = each type-level directive on its own line |
196
+ | `footer` | trailing comment block after the closing `}` in the schema file |
197
+ | `indexes` | composite `@index`/`@unique` (`{ fields, name?, unique?, expand? }` — `expand` renders args one per line) |
198
+ | `sql` | raw SQL constraints (see [SQL migrations](#sql-migrations)) |
318
199
 
319
200
  ### Embedded vs relation
320
201
 
@@ -392,14 +273,14 @@ Everything below exists to reproduce real hand-written `.gql` files byte-for-byt
392
273
 
393
274
  | option | meaning |
394
275
  | --- | --- |
395
- | `gqlName` | document | rendered operation name (the yml key stays unique across services) |
396
- | `footer` | document | trailing `# …` comment block after the operation |
397
- | `raw` | document | emit the operation body verbatim (multi-model queries, `_or` keyset cursors — field checks are skipped) |
398
- | `single: id \| document | key` | single-row lookup (`product(id: $id)` / `product(key: { … })`) |
399
- | `keyArg` / `keyVars` | document | update/delete key argument form and variable renames |
400
- | `whereAnd: true` | document | render conditions as an `_and: [ … ]` array |
401
- | `entityDir` | document | override the `operations/<entity>/` output directory |
402
- | `style` | document | formatting hints: `signature`, `args`, `data`, `orderBy`, `auth`, `key`, `and`, `where` (`inline`/`multi`/`compact`/`bare`) |
276
+ | `gqlName` | rendered operation name (the yml key stays unique across services) |
277
+ | `footer` | trailing `# …` comment block after the operation |
278
+ | `raw` | emit the operation body verbatim (multi-model queries, `_or` keyset cursors — field checks are skipped) |
279
+ | `single: id \| key` | single-row lookup (`product(id: $id)` / `product(key: { … })`) |
280
+ | `keyArg` / `keyVars` | update/delete key argument form and variable renames |
281
+ | `whereAnd: true` | render conditions as an `_and: [ … ]` array |
282
+ | `entityDir` | override the `operations/<entity>/` output directory |
283
+ | `style` | formatting hints: `signature`, `args`, `data`, `orderBy`, `auth`, `key`, `and`, `where` (`inline`/`multi`/`compact`/`bare`) |
403
284
 
404
285
  Inputs support `var` (variable rename), `required` (override optionality),
405
286
  `literal` (fixed value, no variable), `flat` (write the FK column directly),
@@ -415,13 +296,11 @@ name as long as their connector sets don't overlap.
415
296
 
416
297
  ## API endpoints
417
298
 
418
- Model application endpoints in three kind-implied sections — `apis:` (https /
419
- callable, keyed by REST path), `tasks:` (Cloud Tasks), and `events:` (Pub/Sub).
420
- The api-scoped generators — request/response types (`api-types`),
421
- request-validation Zod (`api-validation`), class-validator DTOs (`api-dto`),
422
- and payload contracts (`task-payloads`) — run for the entries that opt in via
423
- the section `defaults` or the entry's own `generators:`. A payload references a
424
- 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`.
425
304
 
426
305
  ```yaml
427
306
  envelopes:
@@ -431,10 +310,9 @@ envelopes:
431
310
  opId: string
432
311
  enqueuedAt: int
433
312
 
434
- tasks: # Cloud Tasks (kind implied)
435
- defaults:
436
- generators: [task-payloads] # section default: applies to entries below
313
+ apis:
437
314
  createCatalog:
315
+ kind: task # product | callable | https | pubsub
438
316
  envelope: RetryTaskPayload # wraps the product data
439
317
  maxAttempts: 3
440
318
  request:
@@ -444,31 +322,17 @@ tasks: # Cloud Tasks (kind implied)
444
322
  response:
445
323
  void: true
446
324
 
447
- events: # Pub/Sub (kind implied)
448
325
  generateAiResponse:
326
+ kind: pubsub
449
327
  topic: ai-review-generate-response
450
328
  timeoutSeconds: 540
451
- generators: [task-payloads]
452
-
453
- apis: # https/callable, keyed by REST path
454
- defaults:
455
- generators: [api-types, api-validation]
456
- /shops/{slug}:
457
- operationId: getShopBySlug
458
- kind: callable # https (default) | callable
329
+
330
+ getShopBySlug:
331
+ kind: callable
459
332
  request: { fields: { slug: { type: string, nonempty: true } } }
460
333
  response: { model: Shop }
461
- generators: # entry-level wins over section defaults;
462
- - api-types # an inline out overrides the declared template
463
- - { generator: api-dto, out: "src/entries/{path}" }
464
334
  ```
465
335
 
466
- Generator application resolves in two tiers — the section `defaults`
467
- (`apis:/tasks:/events:` → `defaults.generators`) and the entry's own
468
- `generators:` (which replaces the defaults). `apis:` keys must be REST paths
469
- (`/...` or `METHOD /...` so the same route can appear once per verb) with an
470
- `operationId`; tasks and Pub/Sub events live in their own sections.
471
-
472
336
  For `createCatalog` this yields `CreateCatalogTaskData`, `CreateCatalogTaskPayload =
473
337
  RetryTaskPayload<CreateCatalogTaskData>`, and `CREATE_CATALOG_MAX_ATTEMPTS`, plus the
474
338
  request types, Zod schema, and DTO.
@@ -481,9 +345,9 @@ reality automatically:
481
345
 
482
346
  - **relations → resolved string ids** (`ownerUser` → `ownerUserId: z.string()`)
483
347
  - **timestamps → `z.date()`**, optional fields → `.nullable()`
348
+ - a **`_meta_`** consistency envelope is attached (opt out with `meta: false`)
484
349
  - `pick` / `omit` select which base fields survive
485
350
  - inline `fields` add denormalized data (flattened DAG edges, stringified JSON)
486
- - `extends: [<fragment>…]` splices shared fields in (see **Fragments** below)
487
351
 
488
352
  ```yaml
489
353
  firestore:
@@ -501,13 +365,10 @@ firestore:
501
365
  ```
502
366
 
503
367
  Emits Zod schemas + inferred types, mirroring a hand-written Firestore schema
504
- library. (`firestore-types` is the zero-config entry point for projects that
505
- have not written projections yet: it re-types *every* model with the Firestore
506
- `Timestamp`, no `firestore:` section needed. Once you declare projections,
507
- prefer the `firestore` generator — it is the one that understands
508
- 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.)
509
370
 
510
- 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
511
372
  Connect schema are reused via `.pick()` — only representation changes are
512
373
  restated:
513
374
 
@@ -517,6 +378,7 @@ export const ShopSchema = DcShopSchema.pick({
517
378
  }).extend({
518
379
  createdAt: z.date(),
519
380
  updatedAt: z.date().nullable(),
381
+ _meta_: _Meta_Schema,
520
382
  })
521
383
  ```
522
384
 
@@ -533,46 +395,6 @@ Additional projection options:
533
395
  - FS-only enums render as frozen consts (`REVIEW_STATE` + `ReviewStateSchema`),
534
396
  co-located with the first projection that references them
535
397
 
536
- ### Fragments (`fragments:` + `extends:`)
537
-
538
- A **fragment** is a named group of fields declared once and spliced into
539
- consumers via `extends: [<name>…]` — the way to share a common field across
540
- many projections (a consistency `_meta_` envelope, audit columns, …) without a
541
- tool-imposed convention. The fragment field's name, type, and which docs carry
542
- it are all yours.
543
-
544
- The value objects a fragment references can be **pinned** to a fixed split
545
- output via `out` (+ optional `file`) on the model declaration. A pinned value
546
- object is *placement-scoped*: emitted only at that location (dependency-ordered,
547
- with an `index.ts` barrel), imported by consumers via that directory, and
548
- excluded from the default `typescript`/`zod` barrels — so it lives purely in the
549
- firestore output. This is what lets a shared envelope sit under `firestore/_/`.
550
-
551
- ```yaml
552
- models:
553
- MetaOp:
554
- out: firestore/_ # → firestore/_/_meta_.ts (+ firestore/_/index.ts)
555
- file: _meta_.ts
556
- fields:
557
- id: { type: string }
558
- Meta:
559
- out: firestore/_
560
- file: _meta_.ts
561
- fields:
562
- scope: { type: float, nullable: true }
563
- op: { type: MetaOp, nullable: true }
564
-
565
- fragments:
566
- meta:
567
- fields:
568
- _meta_: { type: Meta }
569
-
570
- firestore:
571
- Shop:
572
- from: Shop
573
- extends: [meta] # appends `_meta_: MetaSchema` (imported from './_')
574
- ```
575
-
576
398
  ## Discriminated unions
577
399
 
578
400
  ```yaml
@@ -624,19 +446,14 @@ project:
624
446
  idCodec:
625
447
  minLength: 8
626
448
  alphabet: <your-shuffled-sqids-alphabet>
627
- aliases:
628
- "#contracts/*": libs/contracts/src/*
629
449
  ```
630
450
 
631
451
  - `services` (`name`/`database`) feed the `FIRESTORE_DATABASES` constants in the
632
- split `firestore` barrel.
452
+ `firestore-split` barrel.
633
453
  - `idCodec` pins the Sqids settings as a contract constant; when present, the
634
454
  `id-codecs` generator also emits a self-contained `id-core.ts` (the
635
455
  encode/decode primitives), so nothing about id encoding lives outside the
636
456
  contract.
637
- - `aliases` maps `#alias/...` out-template prefixes to paths relative to the
638
- **root** yml, so imported contracts can target shared libs without relative
639
- path gymnastics (longest prefix wins).
640
457
  - `codebases` / service `location` + `connectors` are consumed by the optional
641
458
  `config` generator (preview), which emits per-service `dataconnect.yaml`,
642
459
  per-connector `connector.yaml`, and the `FIRESTORE_DATABASES` /
@@ -648,32 +465,32 @@ project:
648
465
 
649
466
  # Generators
650
467
 
651
- | name | scope | output | notes |
652
- | ------------------------ | -------- | ----------------------------- | ------------------------------------------------------ |
653
- | `typescript` | document | `types.ts`; `split: true` → `types/<table>.ts` + barrel | interfaces + const/union enums; split co-locates enums/embedded objects per table |
654
- | `zod` | document | `schemas.ts`; `split: true` → `schemas/<table>.ts` + barrel | `z.object` schemas (constraints, `z.lazy` model refs) |
655
- | `data-connect-graphql` | document | `schema.gql`; `split: true` → `schema/<table>.gql` | `type … @table(name, key)`; `@col`/`@unique`/`@index`/`@default` |
656
- | `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 |
657
- | `data-connect-adapter` | document | `data-connect-adapters.ts` | convert `Any` rows ⇄ logical types |
658
- | `firestore-types` | document | `firestore-types.ts` | naive TS types with Firestore `Timestamp` (all models) |
659
- | `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 |
660
- | `api-types` | api | `api-types.ts` | endpoint request/response types |
661
- | `api-validation` | api | `api-validation.ts` | endpoint request-validation Zod |
662
- | `api-dto` | api | `<operation>.dto.ts` per api | class-validator DTO classes (NestJS `dto/` convention) |
663
- | `task-payloads` | api | `task-payloads.ts` | envelopes + `*TaskData`/`*TaskPayload` + constants |
664
- | `sql-migrations` | document | `migrations/constraints.sql` | composite FK / CHECK / index SQL — idempotent (`IF NOT EXISTS` / `duplicate_object` guard), safe to re-apply whole |
665
- | `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 |
666
- | `unions` | document | `unions.ts` | Zod discriminated unions + TS union types |
667
- | `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)) |
668
490
 
669
491
  Each generator emits nothing when its section is absent, so a small contract
670
492
  produces a small output. Select a subset with `-g`.
671
493
 
672
- **Scope** decides how a `generators:` declaration takes effect: `document`
673
- generators run once for the yml that declares them; `api` generators run only
674
- for the entries that apply them (section `defaults.generators` → entry
675
- `generators:`, entry wins).
676
-
677
494
  ### The `Any` boundary
678
495
 
679
496
  Data Connect stores JSON and embedded objects as the `Any` scalar, erasing the
@@ -701,7 +518,7 @@ const result = generate('contract.yml', {
701
518
  write: true,
702
519
  })
703
520
 
704
- // Every generator declared across the import graph:
521
+ // Every `generate:` target declared across the import graph:
705
522
  const all = generateAll('contract.yml', { write: true })
706
523
  ```
707
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"}