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.
- package/README.md +60 -249
- package/dist/lib/_internal/compiler/compiler.d.ts +4 -11
- package/dist/lib/_internal/compiler/compiler.d.ts.map +1 -1
- package/dist/lib/_internal/compiler/compiler.js +26 -296
- package/dist/lib/_internal/generators/api/api-dto-generator.d.ts +5 -0
- package/dist/lib/_internal/generators/api/api-dto-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/api/api-dto-generator.js +14 -29
- package/dist/lib/_internal/generators/api/api-types-generator.d.ts +5 -0
- package/dist/lib/_internal/generators/api/api-types-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/api/api-types-generator.js +22 -38
- package/dist/lib/_internal/generators/api/api-validation-generator.d.ts +4 -0
- package/dist/lib/_internal/generators/api/api-validation-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/api/api-validation-generator.js +9 -38
- package/dist/lib/_internal/generators/api/task-payload-generator.d.ts +6 -0
- package/dist/lib/_internal/generators/api/task-payload-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/api/task-payload-generator.js +19 -33
- package/dist/lib/_internal/generators/config/config-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/config/config-generator.js +1 -2
- package/dist/lib/_internal/generators/data-connect/adapter-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/data-connect/adapter-generator.js +1 -2
- package/dist/lib/_internal/generators/data-connect/graphql-generator.d.ts +7 -0
- package/dist/lib/_internal/generators/data-connect/graphql-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/data-connect/graphql-generator.js +5 -7
- package/dist/lib/_internal/generators/data-connect/operations-generator.d.ts +7 -0
- package/dist/lib/_internal/generators/data-connect/operations-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/data-connect/operations-generator.js +8 -9
- package/dist/lib/_internal/generators/firestore/firestore-projection-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/firestore/firestore-projection-generator.js +23 -9
- package/dist/lib/_internal/generators/firestore/firestore-split-generator.d.ts +1 -1
- package/dist/lib/_internal/generators/firestore/firestore-split-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/firestore/firestore-split-generator.js +48 -71
- package/dist/lib/_internal/generators/firestore/firestore-type-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/firestore/firestore-type-generator.js +1 -2
- package/dist/lib/_internal/generators/generator.d.ts +0 -38
- package/dist/lib/_internal/generators/generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/generator.js +1 -7
- package/dist/lib/_internal/generators/id/id-codec-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/id/id-codec-generator.js +1 -2
- package/dist/lib/_internal/generators/index.d.ts +5 -2
- package/dist/lib/_internal/generators/index.d.ts.map +1 -1
- package/dist/lib/_internal/generators/index.js +15 -4
- package/dist/lib/_internal/generators/sql/sql-migration-generator.d.ts +1 -2
- package/dist/lib/_internal/generators/sql/sql-migration-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/sql/sql-migration-generator.js +5 -13
- package/dist/lib/_internal/generators/support/header.d.ts.map +1 -1
- package/dist/lib/_internal/generators/support/header.js +0 -2
- package/dist/lib/_internal/generators/support/naming.d.ts +0 -1
- package/dist/lib/_internal/generators/support/naming.d.ts.map +1 -1
- package/dist/lib/_internal/generators/support/naming.js +0 -3
- package/dist/lib/_internal/generators/support/split.d.ts +1 -1
- package/dist/lib/_internal/generators/support/split.d.ts.map +1 -1
- package/dist/lib/_internal/generators/support/split.js +2 -3
- package/dist/lib/_internal/generators/typescript/typescript-generator.d.ts +1 -2
- package/dist/lib/_internal/generators/typescript/typescript-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/typescript/typescript-generator.js +79 -14
- package/dist/lib/_internal/generators/typescript/typescript-split-generator.d.ts +1 -1
- package/dist/lib/_internal/generators/typescript/typescript-split-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/typescript/typescript-split-generator.js +85 -6
- package/dist/lib/_internal/generators/union/union-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/union/union-generator.js +1 -2
- package/dist/lib/_internal/generators/zod/zod-generator.d.ts +1 -2
- package/dist/lib/_internal/generators/zod/zod-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/zod/zod-generator.js +56 -13
- package/dist/lib/_internal/generators/zod/zod-split-generator.d.ts +1 -1
- package/dist/lib/_internal/generators/zod/zod-split-generator.d.ts.map +1 -1
- package/dist/lib/_internal/generators/zod/zod-split-generator.js +57 -6
- package/dist/lib/_internal/ir/build-ir.d.ts.map +1 -1
- package/dist/lib/_internal/ir/build-ir.js +8 -95
- package/dist/lib/_internal/ir/ir.d.ts +5 -20
- package/dist/lib/_internal/ir/ir.d.ts.map +1 -1
- package/dist/lib/_internal/ir/ir.js +0 -1
- package/dist/lib/_internal/parser/parse.d.ts +3 -5
- package/dist/lib/_internal/parser/parse.d.ts.map +1 -1
- package/dist/lib/_internal/parser/parse.js +31 -297
- package/dist/lib/_internal/parser/raw-document.d.ts +9 -64
- package/dist/lib/_internal/parser/raw-document.d.ts.map +1 -1
- package/dist/lib/_internal/resolver/import-resolver.js +1 -1
- package/dist/lib/_internal/validation/rules.d.ts +0 -39
- package/dist/lib/_internal/validation/rules.d.ts.map +1 -1
- package/dist/lib/_internal/validation/rules.js +1 -133
- package/dist/lib/cli/commands/generate.d.ts.map +1 -1
- package/dist/lib/cli/commands/generate.js +5 -7
- package/dist/lib/cli/commands/index.d.ts.map +1 -1
- package/dist/lib/cli/commands/index.js +0 -2
- package/dist/lib/cli/commands/init.d.ts.map +1 -1
- package/dist/lib/cli/commands/init.js +16 -5
- package/dist/lib/cli/config.d.ts +2 -3
- package/dist/lib/cli/config.d.ts.map +1 -1
- package/dist/lib/cli/config.js +0 -3
- package/package.json +1 -1
- package/dist/lib/_internal/compiler/header-vars.d.ts +0 -41
- package/dist/lib/_internal/compiler/header-vars.d.ts.map +0 -1
- package/dist/lib/_internal/compiler/header-vars.js +0 -117
- package/dist/lib/_internal/generators/support/jsdoc.d.ts +0 -3
- package/dist/lib/_internal/generators/support/jsdoc.d.ts.map +0 -1
- package/dist/lib/_internal/generators/support/jsdoc.js +0 -9
- package/dist/lib/_internal/generators/support/split-variant.d.ts +0 -9
- package/dist/lib/_internal/generators/support/split-variant.d.ts.map +0 -1
- package/dist/lib/_internal/generators/support/split-variant.js +0 -13
- package/dist/lib/_internal/generators/support/templates.d.ts +0 -36
- package/dist/lib/_internal/generators/support/templates.d.ts.map +0 -1
- package/dist/lib/_internal/generators/support/templates.js +0 -50
- package/dist/lib/_internal/generators/typescript/render.d.ts +0 -15
- package/dist/lib/_internal/generators/typescript/render.d.ts.map +0 -1
- package/dist/lib/_internal/generators/typescript/render.js +0 -92
- package/dist/lib/_internal/generators/zod/render.d.ts +0 -12
- package/dist/lib/_internal/generators/zod/render.d.ts.map +0 -1
- package/dist/lib/_internal/generators/zod/render.js +0 -59
- package/dist/lib/cli/commands/where.d.ts +0 -3
- package/dist/lib/cli/commands/where.d.ts.map +0 -1
- 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
|
|
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
|
|
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
|
|
43
|
-
|
|
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
|
-
|
|
63
|
-
- {
|
|
64
|
-
- {
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
-
|
|
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
|
-
|
|
249
|
-
|
|
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
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
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
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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`
|
|
507
|
-
|
|
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
|
|
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
|
-
|
|
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 |
|
|
658
|
-
| ------------------------ |
|
|
659
|
-
| `typescript` |
|
|
660
|
-
| `
|
|
661
|
-
| `
|
|
662
|
-
| `
|
|
663
|
-
| `data-connect-
|
|
664
|
-
| `
|
|
665
|
-
| `
|
|
666
|
-
| `
|
|
667
|
-
| `
|
|
668
|
-
| `
|
|
669
|
-
| `
|
|
670
|
-
| `
|
|
671
|
-
| `
|
|
672
|
-
| `
|
|
673
|
-
| `
|
|
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
|
|
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
|
|
52
|
-
* imports — the one-command flow: each contract file
|
|
53
|
-
*
|
|
54
|
-
*
|
|
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,
|
|
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"}
|