@metaobjectsdev/codegen-ts 1.0.2 → 1.0.4-rc.1
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/dist/catalog-gates.d.ts +52 -0
- package/dist/catalog-gates.d.ts.map +1 -0
- package/dist/catalog-gates.js +183 -0
- package/dist/catalog-gates.js.map +1 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +26 -0
- package/dist/constants.js.map +1 -1
- package/dist/enum-shared.d.ts +9 -2
- package/dist/enum-shared.d.ts.map +1 -1
- package/dist/enum-shared.js +12 -3
- package/dist/enum-shared.js.map +1 -1
- package/dist/generator-registry.d.ts +73 -0
- package/dist/generator-registry.d.ts.map +1 -1
- package/dist/generator-registry.js +182 -38
- package/dist/generator-registry.js.map +1 -1
- package/dist/generator.d.ts +48 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js.map +1 -1
- package/dist/generators/entity-file.d.ts.map +1 -1
- package/dist/generators/entity-file.js +4 -1
- package/dist/generators/entity-file.js.map +1 -1
- package/dist/generators/index.d.ts +1 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +5 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/shared-model-file.d.ts +23 -0
- package/dist/generators/shared-model-file.d.ts.map +1 -0
- package/dist/generators/shared-model-file.js +235 -0
- package/dist/generators/shared-model-file.js.map +1 -0
- package/dist/generators/trace-helper-file.d.ts.map +1 -1
- package/dist/generators/trace-helper-file.js +54 -11
- package/dist/generators/trace-helper-file.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/metaobjects-config.d.ts +0 -15
- package/dist/metaobjects-config.d.ts.map +1 -1
- package/dist/metaobjects-config.js.map +1 -1
- package/dist/projection/extract-view-spec.d.ts.map +1 -1
- package/dist/projection/extract-view-spec.js +111 -4
- package/dist/projection/extract-view-spec.js.map +1 -1
- package/dist/relation-resolver.d.ts.map +1 -1
- package/dist/relation-resolver.js +11 -9
- package/dist/relation-resolver.js.map +1 -1
- package/dist/routes-expose.d.ts +30 -0
- package/dist/routes-expose.d.ts.map +1 -1
- package/dist/routes-expose.js +46 -0
- package/dist/routes-expose.js.map +1 -1
- package/dist/runner.d.ts +29 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +38 -1
- package/dist/runner.js.map +1 -1
- package/dist/templates/entity-file.js +2 -2
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/enums-file.d.ts +11 -1
- package/dist/templates/enums-file.d.ts.map +1 -1
- package/dist/templates/enums-file.js +10 -2
- package/dist/templates/enums-file.js.map +1 -1
- package/dist/templates/queries-file.js +5 -5
- package/dist/templates/queries-file.js.map +1 -1
- package/dist/templates/routes-file-hono.d.ts.map +1 -1
- package/dist/templates/routes-file-hono.js +10 -3
- package/dist/templates/routes-file-hono.js.map +1 -1
- package/dist/templates/routes-file.d.ts.map +1 -1
- package/dist/templates/routes-file.js +21 -4
- package/dist/templates/routes-file.js.map +1 -1
- package/dist/templates/value-object-file.js +2 -2
- package/dist/templates/value-object-file.js.map +1 -1
- package/package.json +6 -6
- package/src/catalog-gates.ts +222 -0
- package/src/constants.ts +27 -0
- package/src/enum-shared.ts +17 -3
- package/src/generator-registry.ts +253 -41
- package/src/generator.ts +48 -1
- package/src/generators/entity-file.ts +7 -1
- package/src/generators/index.ts +11 -0
- package/src/generators/shared-model-file.ts +292 -0
- package/src/generators/trace-helper-file.ts +55 -12
- package/src/index.ts +17 -3
- package/src/metaobjects-config.ts +0 -15
- package/src/projection/extract-view-spec.ts +126 -5
- package/src/reference/entity.ts +12 -3
- package/src/reference/queries.ts +2 -2
- package/src/relation-resolver.ts +14 -8
- package/src/routes-expose.ts +57 -0
- package/src/runner.ts +77 -1
- package/src/templates/entity-file.ts +2 -2
- package/src/templates/enums-file.ts +13 -2
- package/src/templates/queries-file.ts +5 -5
- package/src/templates/routes-file-hono.ts +10 -3
- package/src/templates/routes-file.ts +21 -4
- package/src/templates/value-object-file.ts +2 -2
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
// factory-array config keeps working unchanged — the registry powers `--list`
|
|
11
11
|
// and a stable identity, it does not replace the config path.
|
|
12
12
|
//
|
|
13
|
+
// **This is a SLICE, not the whole catalog.** `codegen-ts` cannot import
|
|
14
|
+
// `codegen-ts-react` / `codegen-ts-tanstack` (dependency direction), so those two
|
|
15
|
+
// packages export their own slices and the CLI unions all three
|
|
16
|
+
// (`cli/src/lib/catalog.ts`). Set equality against the cross-port manifest is a
|
|
17
|
+
// property of the COMPOSED catalog and is asserted there; this package's own
|
|
18
|
+
// conformance test can only check one direction — no rogue names.
|
|
19
|
+
//
|
|
13
20
|
// Tiering (ADR-0020 / ADR-0021 D1):
|
|
14
21
|
// - "native" — the recommended Tier-1 `meta gen` suite (idiomatic emission).
|
|
15
22
|
// - "neutral" — Tier-2 artifacts owned by the neutral docs engine. `docs` and
|
|
@@ -18,6 +25,8 @@
|
|
|
18
25
|
// door for documentation is `meta docs` (D1).
|
|
19
26
|
|
|
20
27
|
import type { Generator } from "./generator.js";
|
|
28
|
+
import type { MetaobjectsGenConfig } from "./metaobjects-config.js";
|
|
29
|
+
import { REFERENCE_GENERATOR_NAMES } from "./reference-templates.js";
|
|
21
30
|
// The four ADR-0034 ownable generators are no longer exported from ./generators/index.js
|
|
22
31
|
// (1.0 removed them — see that file's header). They remain the engine's internal composers
|
|
23
32
|
// and the stable-name registry still constructs them, so import them from their own modules.
|
|
@@ -39,13 +48,56 @@ import {
|
|
|
39
48
|
docsFile,
|
|
40
49
|
templateGenerator,
|
|
41
50
|
traceHelperFile,
|
|
51
|
+
sharedModelFile,
|
|
52
|
+
requirementTests,
|
|
42
53
|
} from "./generators/index.js";
|
|
43
54
|
|
|
44
55
|
export type GeneratorTier = "native" | "neutral";
|
|
45
56
|
|
|
57
|
+
/**
|
|
58
|
+
* The six layers a generator can belong to — the axis an adopter SELECTS BY.
|
|
59
|
+
*
|
|
60
|
+
* Cross-port: `layer` is gated by every port's registry-conformance test against
|
|
61
|
+
* `fixtures/generator-registry-conformance/registry.json`, exactly as `tier` is, so a
|
|
62
|
+
* polyglot agent groups the catalog by the same words everywhere.
|
|
63
|
+
*
|
|
64
|
+
* Six, not ten. The first four are app-shape decisions a builder makes; `docs` is on by
|
|
65
|
+
* default (`meta docs`); `capability` holds the ones the MODEL has already made — nobody
|
|
66
|
+
* picks `prompt-render` by browsing a taxonomy, they pick it because they declared a
|
|
67
|
+
* `template.prompt`, which `meta gen --list --probe` reports with a real file count. A
|
|
68
|
+
* layer with one member does no grouping work, so do not split `capability` to tidy it.
|
|
69
|
+
*/
|
|
70
|
+
export const GENERATOR_LAYERS = [
|
|
71
|
+
"model",
|
|
72
|
+
"persistence",
|
|
73
|
+
"api",
|
|
74
|
+
"client",
|
|
75
|
+
"docs",
|
|
76
|
+
"capability",
|
|
77
|
+
] as const;
|
|
78
|
+
export type Layer = (typeof GENERATOR_LAYERS)[number];
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The framework a generator's OUTPUT targets. Absent = framework-neutral.
|
|
82
|
+
*
|
|
83
|
+
* Exclusivity is an ADVISORY and only on the `api` layer (spec §8a): `routes` and
|
|
84
|
+
* `routes-hono` emit to different paths, so wiring both is legal and silently produces
|
|
85
|
+
* two HTTP surfaces — worth a warning, never an error, because migrating between them is
|
|
86
|
+
* legitimate. There is NO general per-layer rule: `@metaobjectsdev/tanstack` peers on
|
|
87
|
+
* `react`, so `form` (react) + `hooks`/`grid` (tanstack) is the intended composition.
|
|
88
|
+
*/
|
|
89
|
+
export type GeneratorFramework = "fastify" | "hono" | "react" | "tanstack";
|
|
90
|
+
|
|
46
91
|
export interface GeneratorRegistryEntry {
|
|
47
92
|
/** Stable, cross-port-consistent id. Equals the registry map key. */
|
|
48
93
|
name: string;
|
|
94
|
+
/**
|
|
95
|
+
* Catalog discriminator. Today every entry is a generator; FR-043 adds
|
|
96
|
+
* `kind: "library"` rows to the same table rather than building a parallel one.
|
|
97
|
+
*/
|
|
98
|
+
kind: "generator";
|
|
99
|
+
/** The selection axis — see {@link GENERATOR_LAYERS}. Gated cross-port. */
|
|
100
|
+
layer: Layer;
|
|
49
101
|
/** One-line (no newline) human description for `--list`. */
|
|
50
102
|
description: string;
|
|
51
103
|
/** "native" = recommended `meta gen` suite; "neutral" = `meta docs`-owned. */
|
|
@@ -54,10 +106,55 @@ export interface GeneratorRegistryEntry {
|
|
|
54
106
|
factory: () => Generator;
|
|
55
107
|
/** Optional one-line options summary for `--list`. */
|
|
56
108
|
options?: string;
|
|
109
|
+
/** The framework this generator's OUTPUT targets. Absent = framework-neutral. */
|
|
110
|
+
framework?: GeneratorFramework;
|
|
111
|
+
/**
|
|
112
|
+
* Stable names whose emitted output THIS generator's output imports.
|
|
113
|
+
*
|
|
114
|
+
* Resolved, not trusted: a gate dry-runs every generator, resolves each emitted
|
|
115
|
+
* RELATIVE import back to whichever generator emits that path, and asserts the result
|
|
116
|
+
* is a subset of this list — so a generator that quietly starts depending on `entity`
|
|
117
|
+
* cannot ship claiming it depends on nothing.
|
|
118
|
+
*/
|
|
119
|
+
requires?: readonly string[];
|
|
120
|
+
/**
|
|
121
|
+
* The `@metaobjectsdev` runtime packages the EMITTED code imports.
|
|
122
|
+
*
|
|
123
|
+
* PLURAL, against the design's first sketch, because the emitted code is: an
|
|
124
|
+
* `output-parser` module imports `@metaobjectsdev/metadata`, `/render` AND
|
|
125
|
+
* `/runtime-ts`, and a `hooks` module imports `/runtime-web` and `/tanstack`. A
|
|
126
|
+
* singular field would have forced two of the three to go undeclared, which is the
|
|
127
|
+
* exact under-declaration the gate exists to catch. Resolved, not trusted — the
|
|
128
|
+
* emitted files are read back and every `@metaobjectsdev` import must appear here.
|
|
129
|
+
*/
|
|
130
|
+
runtimePackages?: readonly string[];
|
|
131
|
+
/**
|
|
132
|
+
* Third-party packages the EMITTED code imports.
|
|
133
|
+
*
|
|
134
|
+
* Per generator rather than derived from {@link runtimePackages}, because
|
|
135
|
+
* `@metaobjectsdev/runtime-ts`'s peers are a union (drizzle-orm, fastify, hono, kysely,
|
|
136
|
+
* zod) — deriving per package would tell someone ejecting `entity` to install both
|
|
137
|
+
* Fastify and Hono. Version RANGES are read from the runtime package's own
|
|
138
|
+
* `peerDependencies`, never written here. Gated the same way `requires` is.
|
|
139
|
+
*/
|
|
140
|
+
runtimePeers?: readonly string[];
|
|
141
|
+
/**
|
|
142
|
+
* Config keys this generator reads. Typed against the real config so a renamed key
|
|
143
|
+
* breaks the build instead of going quietly stale — the same "resolved, not trusted"
|
|
144
|
+
* doctrine as `requires`, obtained here for free from the type system.
|
|
145
|
+
*/
|
|
146
|
+
configKeys?: readonly (keyof MetaobjectsGenConfig)[];
|
|
147
|
+
/** True iff this package ships a `src/reference/<name>.ts` for `meta eject`. */
|
|
148
|
+
ejectable: boolean;
|
|
57
149
|
/** Optional note — used to point neutral entries at their canonical door. */
|
|
58
150
|
note?: string;
|
|
59
151
|
}
|
|
60
152
|
|
|
153
|
+
/** True iff this package ships a copyable reference template for `name`. */
|
|
154
|
+
function ejectable(name: string): boolean {
|
|
155
|
+
return (REFERENCE_GENERATOR_NAMES as readonly string[]).includes(name);
|
|
156
|
+
}
|
|
157
|
+
|
|
61
158
|
// The `template` generator is a PRIMITIVE: callers supply { name, walk,
|
|
62
159
|
// template }. For registry identity + `--list` we expose a no-op default so the
|
|
63
160
|
// factory constructs a valid Generator without throwing; real use passes opts
|
|
@@ -72,129 +169,244 @@ function templatePrimitive(): Generator {
|
|
|
72
169
|
}
|
|
73
170
|
|
|
74
171
|
export const generatorRegistry: Record<string, GeneratorRegistryEntry> = {
|
|
75
|
-
// -----
|
|
172
|
+
// ----- model ------------------------------------------------------------
|
|
76
173
|
entity: {
|
|
77
174
|
name: "entity",
|
|
175
|
+
kind: "generator",
|
|
176
|
+
layer: "model",
|
|
78
177
|
description: "Per-entity Drizzle table + typed model module (the entity module).",
|
|
79
178
|
tier: "native",
|
|
80
179
|
factory: () => entityFile(),
|
|
81
180
|
options: "filter?, target?",
|
|
181
|
+
requires: [],
|
|
182
|
+
runtimePackages: ["@metaobjectsdev/runtime-ts"],
|
|
183
|
+
runtimePeers: ["drizzle-orm", "zod"],
|
|
184
|
+
configKeys: ["dialect", "extStyle", "outputLayout", "columnNamingStrategy",
|
|
185
|
+
"pluralizeCollections", "collectionNameOverrides", "providedEnumModule", "apiPrefix"],
|
|
186
|
+
ejectable: ejectable("entity"),
|
|
187
|
+
},
|
|
188
|
+
names: {
|
|
189
|
+
name: "names",
|
|
190
|
+
kind: "generator",
|
|
191
|
+
layer: "model",
|
|
192
|
+
description: "Per-entity physical database name constants (table/view, schema, columns).",
|
|
193
|
+
tier: "native",
|
|
194
|
+
factory: () => namesFile(),
|
|
195
|
+
options: "filter?, target?",
|
|
196
|
+
configKeys: ["columnNamingStrategy"],
|
|
197
|
+
ejectable: ejectable("names"),
|
|
82
198
|
},
|
|
199
|
+
barrel: {
|
|
200
|
+
name: "barrel",
|
|
201
|
+
kind: "generator",
|
|
202
|
+
layer: "model",
|
|
203
|
+
description: "Single index.ts re-exporting every generated entity module.",
|
|
204
|
+
tier: "native",
|
|
205
|
+
factory: () => barrel(),
|
|
206
|
+
options: "target?",
|
|
207
|
+
requires: ["entity"],
|
|
208
|
+
configKeys: ["extStyle"],
|
|
209
|
+
ejectable: ejectable("barrel"),
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
// ----- persistence ------------------------------------------------------
|
|
83
213
|
queries: {
|
|
84
214
|
name: "queries",
|
|
215
|
+
kind: "generator",
|
|
216
|
+
layer: "persistence",
|
|
85
217
|
description: "Per-entity typed query helpers (findById/create/...).",
|
|
86
218
|
tier: "native",
|
|
87
219
|
factory: () => queriesFile(),
|
|
88
220
|
options: "filter?, target?",
|
|
221
|
+
requires: ["entity"],
|
|
222
|
+
runtimePeers: ["drizzle-orm"],
|
|
223
|
+
configKeys: ["dialect", "extStyle", "pluralizeCollections", "collectionNameOverrides"],
|
|
224
|
+
ejectable: ejectable("queries"),
|
|
89
225
|
},
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
description: "Per-entity callable/service surface wrapping the query helpers.",
|
|
93
|
-
tier: "native",
|
|
94
|
-
factory: () => callableFile(),
|
|
95
|
-
options: "filter?, target?",
|
|
96
|
-
},
|
|
226
|
+
|
|
227
|
+
// ----- api --------------------------------------------------------------
|
|
97
228
|
routes: {
|
|
98
229
|
name: "routes",
|
|
230
|
+
kind: "generator",
|
|
231
|
+
layer: "api",
|
|
99
232
|
description: "Per-entity Fastify CRUD routes (drizzle-fastify mountCrudRoutes).",
|
|
100
233
|
tier: "native",
|
|
101
234
|
factory: () => routesFile(),
|
|
102
235
|
options: "filter?, target?",
|
|
236
|
+
framework: "fastify",
|
|
237
|
+
requires: ["entity"],
|
|
238
|
+
runtimePackages: ["@metaobjectsdev/runtime-ts"],
|
|
239
|
+
runtimePeers: ["fastify"],
|
|
240
|
+
configKeys: ["dbImport", "apiPrefix", "dialect", "extStyle", "outputLayout", "columnNamingStrategy"],
|
|
241
|
+
ejectable: ejectable("routes"),
|
|
103
242
|
},
|
|
104
243
|
"routes-hono": {
|
|
105
244
|
name: "routes-hono",
|
|
245
|
+
kind: "generator",
|
|
246
|
+
layer: "api",
|
|
106
247
|
description: "Per-entity Hono CRUD routes (runtime-ts/hono mountCrudRoutes).",
|
|
107
248
|
tier: "native",
|
|
108
249
|
factory: () => routesFileHono(),
|
|
109
250
|
options: "filter?, target?",
|
|
251
|
+
framework: "hono",
|
|
252
|
+
requires: ["entity"],
|
|
253
|
+
runtimePackages: ["@metaobjectsdev/runtime-ts"],
|
|
254
|
+
runtimePeers: ["hono"],
|
|
255
|
+
configKeys: ["dbImport", "apiPrefix", "dialect", "extStyle"],
|
|
256
|
+
ejectable: ejectable("routes-hono"),
|
|
110
257
|
},
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
258
|
+
|
|
259
|
+
// ----- docs -------------------------------------------------------------
|
|
260
|
+
"api-docs": {
|
|
261
|
+
name: "api-docs",
|
|
262
|
+
kind: "generator",
|
|
263
|
+
layer: "docs",
|
|
264
|
+
description:
|
|
265
|
+
"Per-entity/template SDK API reference (the generated code's API, human + agent forms).",
|
|
114
266
|
tier: "native",
|
|
115
|
-
factory: () =>
|
|
116
|
-
options: "target?",
|
|
267
|
+
factory: () => apiDocsFile(),
|
|
268
|
+
options: "filter?, target?",
|
|
269
|
+
ejectable: ejectable("api-docs"),
|
|
117
270
|
},
|
|
118
|
-
|
|
119
|
-
name: "
|
|
120
|
-
|
|
271
|
+
docs: {
|
|
272
|
+
name: "docs",
|
|
273
|
+
kind: "generator",
|
|
274
|
+
layer: "docs",
|
|
275
|
+
description: "Neutral per-entity / per-template Markdown documentation pages.",
|
|
276
|
+
tier: "neutral",
|
|
277
|
+
factory: () => docsFile(),
|
|
278
|
+
ejectable: ejectable("docs"),
|
|
279
|
+
note: "neutral artifact — use `meta docs` (the single docs door, ADR-0021 D1); not part of the recommended `meta gen` native suite.",
|
|
280
|
+
},
|
|
281
|
+
"mermaid-er": {
|
|
282
|
+
name: "mermaid-er",
|
|
283
|
+
kind: "generator",
|
|
284
|
+
layer: "docs",
|
|
285
|
+
description: "Mermaid ER diagram of the entity/relationship model.",
|
|
286
|
+
tier: "neutral",
|
|
287
|
+
factory: () => mermaidErDiagram(),
|
|
288
|
+
ejectable: ejectable("mermaid-er"),
|
|
289
|
+
note: "neutral artifact owned by the docs engine (ADR-0020); surfaced via `meta docs`, not the recommended `meta gen` native suite.",
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
// ----- capability -------------------------------------------------------
|
|
293
|
+
// Not chosen by browsing this list — chosen because the MODEL already asks for
|
|
294
|
+
// them. `meta gen --list --probe` reports a real file count per entry.
|
|
295
|
+
callable: {
|
|
296
|
+
name: "callable",
|
|
297
|
+
kind: "generator",
|
|
298
|
+
layer: "capability",
|
|
299
|
+
description: "Per-entity callable/service surface wrapping the query helpers.",
|
|
121
300
|
tier: "native",
|
|
122
|
-
factory: () =>
|
|
301
|
+
factory: () => callableFile(),
|
|
123
302
|
options: "filter?, target?",
|
|
303
|
+
requires: ["entity"],
|
|
304
|
+
runtimePeers: ["drizzle-orm"],
|
|
305
|
+
configKeys: ["columnNamingStrategy"],
|
|
306
|
+
ejectable: ejectable("callable"),
|
|
124
307
|
},
|
|
125
308
|
"prompt-render": {
|
|
126
309
|
name: "prompt-render",
|
|
310
|
+
kind: "generator",
|
|
311
|
+
layer: "capability",
|
|
127
312
|
description: "Per-template prompt-render helper over the render engine.",
|
|
128
313
|
tier: "native",
|
|
129
314
|
factory: () => promptRender(),
|
|
130
315
|
options: "filter?, target?",
|
|
316
|
+
runtimePackages: ["@metaobjectsdev/render"],
|
|
317
|
+
ejectable: ejectable("prompt-render"),
|
|
131
318
|
},
|
|
132
319
|
"output-parser": {
|
|
133
320
|
name: "output-parser",
|
|
321
|
+
kind: "generator",
|
|
322
|
+
layer: "capability",
|
|
134
323
|
description: "Per-template tolerant output parser (recover-on-receipt).",
|
|
135
324
|
tier: "native",
|
|
136
325
|
factory: () => outputParser(),
|
|
137
326
|
options: "filter?, target?",
|
|
327
|
+
runtimePackages: ["@metaobjectsdev/metadata", "@metaobjectsdev/render", "@metaobjectsdev/runtime-ts"],
|
|
328
|
+
runtimePeers: ["zod"],
|
|
329
|
+
ejectable: ejectable("output-parser"),
|
|
138
330
|
},
|
|
139
331
|
extractor: {
|
|
140
332
|
name: "extractor",
|
|
333
|
+
kind: "generator",
|
|
334
|
+
layer: "capability",
|
|
141
335
|
description: "Per-template typed extract<Name> helper (strict payload extraction).",
|
|
142
336
|
tier: "native",
|
|
143
337
|
factory: () => extractor(),
|
|
144
338
|
options: "filter?, target?",
|
|
339
|
+
requires: ["entity", "output-parser"],
|
|
340
|
+
runtimePackages: ["@metaobjectsdev/metadata", "@metaobjectsdev/render"],
|
|
341
|
+
ejectable: ejectable("extractor"),
|
|
145
342
|
},
|
|
146
343
|
"output-prompt": {
|
|
147
344
|
name: "output-prompt",
|
|
345
|
+
kind: "generator",
|
|
346
|
+
layer: "capability",
|
|
148
347
|
description: "Per-template output-format prompt fragment generator.",
|
|
149
348
|
tier: "native",
|
|
150
349
|
factory: () => outputPrompt(),
|
|
151
350
|
options: "filter?, target?",
|
|
351
|
+
runtimePackages: ["@metaobjectsdev/render"],
|
|
352
|
+
ejectable: ejectable("output-prompt"),
|
|
152
353
|
},
|
|
153
354
|
"render-helper": {
|
|
154
355
|
name: "render-helper",
|
|
356
|
+
kind: "generator",
|
|
357
|
+
layer: "capability",
|
|
155
358
|
description: "Per-template.output render helper (document/email typed wrappers).",
|
|
156
359
|
tier: "native",
|
|
157
360
|
factory: () => renderHelper(),
|
|
158
361
|
options: "filter?, target?",
|
|
362
|
+
runtimePackages: ["@metaobjectsdev/render"],
|
|
363
|
+
configKeys: ["extStyle"],
|
|
364
|
+
ejectable: ejectable("render-helper"),
|
|
159
365
|
},
|
|
160
366
|
template: {
|
|
161
367
|
name: "template",
|
|
368
|
+
kind: "generator",
|
|
369
|
+
layer: "capability",
|
|
162
370
|
description: "Generic Mustache template primitive (walk + template → files).",
|
|
163
371
|
tier: "native",
|
|
164
372
|
factory: () => templatePrimitive(),
|
|
165
373
|
options: "name, walk, template, format?, filter?, provider?, target?",
|
|
374
|
+
ejectable: ejectable("template"),
|
|
166
375
|
},
|
|
167
|
-
"api-docs": {
|
|
168
|
-
name: "api-docs",
|
|
169
|
-
description:
|
|
170
|
-
"Per-entity/template SDK API reference (the generated code's API, human + agent forms).",
|
|
171
|
-
tier: "native",
|
|
172
|
-
factory: () => apiDocsFile(),
|
|
173
|
-
options: "filter?, target?",
|
|
174
|
-
},
|
|
175
|
-
|
|
176
376
|
"trace-helper": {
|
|
177
377
|
name: "trace-helper",
|
|
178
|
-
|
|
378
|
+
kind: "generator",
|
|
379
|
+
layer: "capability",
|
|
380
|
+
description:
|
|
381
|
+
"Per-entity typed record<Entity>/call<Entity> trace helpers (extract + buildLlmCallRow + persist; LlmCallBase-derived entities only).",
|
|
179
382
|
tier: "native",
|
|
180
383
|
factory: () => traceHelperFile(),
|
|
181
384
|
options: "outDir?, target?",
|
|
385
|
+
ejectable: ejectable("trace-helper"),
|
|
182
386
|
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
description: "
|
|
188
|
-
tier: "
|
|
189
|
-
factory: () =>
|
|
190
|
-
|
|
387
|
+
"requirement-tests": {
|
|
388
|
+
name: "requirement-tests",
|
|
389
|
+
kind: "generator",
|
|
390
|
+
layer: "capability",
|
|
391
|
+
description: "Per-requirement test stub, one per requirement.functional claim in the ledger.",
|
|
392
|
+
tier: "native",
|
|
393
|
+
factory: () => requirementTests(),
|
|
394
|
+
options: "filter?, target?",
|
|
395
|
+
ejectable: ejectable("requirement-tests"),
|
|
191
396
|
},
|
|
192
|
-
"
|
|
193
|
-
name: "
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
397
|
+
"shared-model": {
|
|
398
|
+
name: "shared-model",
|
|
399
|
+
kind: "generator",
|
|
400
|
+
layer: "capability",
|
|
401
|
+
description:
|
|
402
|
+
"FR-023: a publisher's flattened shared-model artifact + manifest for a consumer's `meta deps sync`.",
|
|
403
|
+
tier: "native",
|
|
404
|
+
// `name`/`include` are required at run time (an empty include matches
|
|
405
|
+
// everything, so a placeholder here constructs without throwing — real use
|
|
406
|
+
// always supplies both, same as `template`'s templatePrimitive() above).
|
|
407
|
+
factory: () => sharedModelFile({ name: "shared-model", include: [] }),
|
|
408
|
+
options: "name, include, exclude?, files?, version?, target?",
|
|
409
|
+
ejectable: ejectable("shared-model"),
|
|
198
410
|
},
|
|
199
411
|
};
|
|
200
412
|
|
package/src/generator.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { MetaObject, MetaRoot } from "@metaobjectsdev/metadata";
|
|
1
|
+
import type { MetaObject, MetaRoot, TypeRegistry } from "@metaobjectsdev/metadata";
|
|
2
|
+
import type { LibraryManifest } from "@metaobjectsdev/metadata/library";
|
|
2
3
|
import type { RenderContext } from "./render-context.js";
|
|
3
4
|
import type { ResolvedGenConfig } from "./metaobjects-config.js";
|
|
4
5
|
import type { OrphanPolicy } from "./reconcile-orphans.js";
|
|
@@ -20,6 +21,16 @@ export interface GenContext {
|
|
|
20
21
|
* filter is set). Always call this from helpers; do not call generator.filter
|
|
21
22
|
* directly. */
|
|
22
23
|
matches: (entity: MetaObject) => boolean;
|
|
24
|
+
/** FR-023 §11.1 item 2 — the model-wide output-scope predicate over a node's
|
|
25
|
+
* `resolutionKey()` (the runner's own `RunGenOpts.scope`, verbatim). A
|
|
26
|
+
* DIFFERENT knob from `matches`: `matches` is the per-generator `filter`
|
|
27
|
+
* (ANDed into what THIS generator emits), while `select` is the whole-model
|
|
28
|
+
* scope every generator shares — for a template that renders once over
|
|
29
|
+
* `ctx.loadedRoot` rather than per-entity (the shared-enums module is the
|
|
30
|
+
* first such template), `matches` never runs at all, so that template must
|
|
31
|
+
* read `select` directly to honour the same exclusion. Undefined ⇒ every
|
|
32
|
+
* node is in scope, byte-identical to a project with no `scope` declared. */
|
|
33
|
+
select?: (fqn: string) => boolean;
|
|
23
34
|
config: ResolvedGenConfig;
|
|
24
35
|
/** Pre-built by the runner for built-in generators that wrap existing
|
|
25
36
|
* templates. Third-party generators typically don't need this. Always
|
|
@@ -35,6 +46,42 @@ export interface GenContext {
|
|
|
35
46
|
* in a sub-directory. Undefined only when the runner was driven
|
|
36
47
|
* programmatically without an explicit projectRoot. */
|
|
37
48
|
projectRoot?: string;
|
|
49
|
+
/**
|
|
50
|
+
* FR-023 §4.3 — the run's composed registry (core providers plus whatever this
|
|
51
|
+
* project's `metaobjects.config.ts` `providers` adds), filled by the runner. The
|
|
52
|
+
* SAME vocabulary `opts.metadata` was loaded with. `sharedModelFile()`'s
|
|
53
|
+
* standalone re-loads of a `files` subset use this so a publisher project's own
|
|
54
|
+
* consumer-supplied vocabulary is honoured identically to the main load. Optional
|
|
55
|
+
* on the type so tests and custom callers don't need a placeholder; always
|
|
56
|
+
* present at run time when invoked via `runGen()`.
|
|
57
|
+
*/
|
|
58
|
+
registry?: TypeRegistry;
|
|
59
|
+
/**
|
|
60
|
+
* FR-023 §4.3 — the collection's own source files (never a dependency's
|
|
61
|
+
* artifact), filled by the runner from `RunGenOpts.sourceFiles`. Distinct from
|
|
62
|
+
* `loadedRoot`, which is already fully loaded and merged: `sharedModelFile()`
|
|
63
|
+
* needs the raw file LIST so it can re-load a `files:`-narrowed subset of it
|
|
64
|
+
* standalone. Undefined when the caller never supplied `RunGenOpts.sourceFiles`
|
|
65
|
+
* (a generator relying on it should default sensibly, as `sharedModelFile()`'s
|
|
66
|
+
* own `files` option does).
|
|
67
|
+
*/
|
|
68
|
+
sourceFiles?: readonly string[];
|
|
69
|
+
/**
|
|
70
|
+
* FR-043 §6 — the manifests of the libraries this project opted into, filled by the
|
|
71
|
+
* runner from `RunGenOpts.libraries`.
|
|
72
|
+
*
|
|
73
|
+
* What a generator reads it FOR is the `anchor`: the library node it keys on. That
|
|
74
|
+
* retires the hard-coded entity name a library-aware generator would otherwise carry
|
|
75
|
+
* (`trace-helper` compared `.name === "LlmCallBase"`, so ANY adopter entity of that
|
|
76
|
+
* name in ANY package triggered it) in favour of resolving the manifest's anchor to a
|
|
77
|
+
* node and comparing by node identity.
|
|
78
|
+
*
|
|
79
|
+
* Undefined means the caller never said — a programmatic `runGen()` rather than
|
|
80
|
+
* `meta gen`. A generator reading it should fall back to every SHIPPED manifest's
|
|
81
|
+
* anchors, which is still FQN-anchored and still not a bare name. An empty array is
|
|
82
|
+
* the opposite and is meaningful: the caller looked, and this project opted into none.
|
|
83
|
+
*/
|
|
84
|
+
libraries?: readonly LibraryManifest[];
|
|
38
85
|
warn: (msg: string) => void;
|
|
39
86
|
}
|
|
40
87
|
|
|
@@ -59,7 +59,13 @@ export const entityFile = function entityFile(opts?: EntityFileOpts): Generator
|
|
|
59
59
|
// FR-019: emit the shared-enums module ONCE per run, into the entity-module
|
|
60
60
|
// target root. Returns null (no file) when the model uses no materialized
|
|
61
61
|
// shared enums — keeping the inline-enum default byte-identical (no new file).
|
|
62
|
-
|
|
62
|
+
// FR-023 §11.1 item 2: `select` (never `ctx.matches` — this renders from the
|
|
63
|
+
// WHOLE root, not this generator's filtered subset) excludes an enum used
|
|
64
|
+
// only by an imported, out-of-scope entity.
|
|
65
|
+
const sharedEnums = renderSharedEnumsFile(
|
|
66
|
+
ctx.loadedRoot,
|
|
67
|
+
ctx.select !== undefined ? { select: ctx.select } : undefined,
|
|
68
|
+
);
|
|
63
69
|
if (sharedEnums !== null) {
|
|
64
70
|
files.push({
|
|
65
71
|
path: `${SHARED_ENUMS_BASENAME}.ts`,
|
package/src/generators/index.ts
CHANGED
|
@@ -35,6 +35,17 @@ export {
|
|
|
35
35
|
type TemplateFormat,
|
|
36
36
|
} from "./template-generator.js";
|
|
37
37
|
export { traceHelperFile, type TraceHelperOpts } from "./trace-helper-file.js";
|
|
38
|
+
// FR-023 §4.3 — the publisher's flattened shared-model artifact + manifest generator.
|
|
39
|
+
// The three tool-file constants are re-exported alongside it purely so a `cli`
|
|
40
|
+
// test can assert they stay byte-equal to sdk's canonical copies (see that
|
|
41
|
+
// module's own comment for why codegen-ts can't just import sdk directly).
|
|
42
|
+
export {
|
|
43
|
+
sharedModelFile,
|
|
44
|
+
type SharedModelFileOpts,
|
|
45
|
+
MANIFEST_FILE as SHARED_MODEL_MANIFEST_FILE,
|
|
46
|
+
ARTIFACT_SUFFIX as SHARED_MODEL_ARTIFACT_SUFFIX,
|
|
47
|
+
INTEGRITY_PREFIX as SHARED_MODEL_INTEGRITY_PREFIX,
|
|
48
|
+
} from "./shared-model-file.js";
|
|
38
49
|
export type {
|
|
39
50
|
EntityDocData,
|
|
40
51
|
StorageFieldDoc,
|