@metaobjectsdev/codegen-ts 0.21.4-rc.1 → 0.21.5

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.
@@ -0,0 +1,18 @@
1
+ import type { MetaObject } from "@metaobjectsdev/metadata";
2
+ /**
3
+ * True when the object is served by a generated READ endpoint — so a hook has
4
+ * something to fetch and a grid has something to render.
5
+ *
6
+ * Abstract types are excluded (no instance to address). Today the endpoint test is
7
+ * "declares or inherits a `source.rdb`", which is precisely the predicate
8
+ * `routesFile` / `routesFileHono` gate on, so hooks exist exactly where routes do.
9
+ */
10
+ export declare function servesReadApi(entity: MetaObject): boolean;
11
+ /**
12
+ * True when the object is served by generated WRITE endpoints — so a form has
13
+ * somewhere to submit. Requires a WRITABLE source: the same predicate the entity-file
14
+ * generator uses to decide whether `Insert`/`Update` schemas exist at all, so a form
15
+ * can never be emitted against schemas that were never generated.
16
+ */
17
+ export declare function servesWriteApi(entity: MetaObject): boolean;
18
+ //# sourceMappingURL=api-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-surface.d.ts","sourceRoot":"","sources":["../src/api-surface.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAE1D"}
@@ -0,0 +1,42 @@
1
+ // Does this object have a generated HTTP API surface?
2
+ //
3
+ // THIS is the question the UI tier should ask. A hook, a grid and a form are all
4
+ // clients of a REST endpoint: hooks fetch one, a grid renders what a hook returned,
5
+ // a form submits to one. None of them knows or cares where the data is stored — that
6
+ // is the whole point of the architecture, and `@metaobjectsdev/runtime-web` is
7
+ // deliberately browser-only with no database dependency at all.
8
+ //
9
+ // The UI generators used to ask `hasAnyRdbSource` directly, which produced the RIGHT
10
+ // answer for the WRONG reason: routes are currently derived from sources (FR-008/009
11
+ // derived CRUD), so "has a relational source" and "has an endpoint" happen to
12
+ // coincide today. They are not the same question, and the coincidence is temporary —
13
+ // FR-024 declared `api.*` surfaces and #211 non-RDB projection materialization both
14
+ // break it, at which point a UI tier reaching through to storage starts refusing to
15
+ // generate hooks for entities that genuinely do have endpoints.
16
+ //
17
+ // So the reach-through lives in exactly one place now, named for what it means. When
18
+ // route derivation grows a second source of truth, this function changes and every
19
+ // UI generator follows for free.
20
+ import { isAbstract } from "./instance-artifacts.js";
21
+ import { hasAnyRdbSource, hasWritableRdbSource } from "./source-detect.js";
22
+ /**
23
+ * True when the object is served by a generated READ endpoint — so a hook has
24
+ * something to fetch and a grid has something to render.
25
+ *
26
+ * Abstract types are excluded (no instance to address). Today the endpoint test is
27
+ * "declares or inherits a `source.rdb`", which is precisely the predicate
28
+ * `routesFile` / `routesFileHono` gate on, so hooks exist exactly where routes do.
29
+ */
30
+ export function servesReadApi(entity) {
31
+ return !isAbstract(entity) && hasAnyRdbSource(entity);
32
+ }
33
+ /**
34
+ * True when the object is served by generated WRITE endpoints — so a form has
35
+ * somewhere to submit. Requires a WRITABLE source: the same predicate the entity-file
36
+ * generator uses to decide whether `Insert`/`Update` schemas exist at all, so a form
37
+ * can never be emitted against schemas that were never generated.
38
+ */
39
+ export function servesWriteApi(entity) {
40
+ return !isAbstract(entity) && hasWritableRdbSource(entity);
41
+ }
42
+ //# sourceMappingURL=api-surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-surface.js","sourceRoot":"","sources":["../src/api-surface.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,iFAAiF;AACjF,oFAAoF;AACpF,qFAAqF;AACrF,+EAA+E;AAC/E,gEAAgE;AAChE,EAAE;AACF,qFAAqF;AACrF,qFAAqF;AACrF,8EAA8E;AAC9E,qFAAqF;AACrF,oFAAoF;AACpF,oFAAoF;AACpF,gEAAgE;AAChE,EAAE;AACF,qFAAqF;AACrF,mFAAmF;AACnF,iCAAiC;AAGjC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,MAAkB;IAC9C,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes-file-hono.d.ts","sourceRoot":"","sources":["../../src/generators/routes-file-hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAOnF,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,EA4BtB,gBAAgB,CAAC,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"routes-file-hono.d.ts","sourceRoot":"","sources":["../../src/generators/routes-file-hono.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQnF,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,EAyDtB,gBAAgB,CAAC,kBAAkB,CAAC,CAAC"}
@@ -4,6 +4,7 @@ import { hasAnyRdbSource } from "../source-detect.js";
4
4
  import { formatTs } from "../format.js";
5
5
  import { entityOutputPath } from "../import-path.js";
6
6
  import { CODEGEN_ATTR_EMIT_ROUTES } from "../constants.js";
7
+ import { isTphSubtype } from "../templates/zod-validators.js";
7
8
  /**
8
9
  * Hono variant of routesFile() — emits `<Entity>.routes.hono.ts` mounting
9
10
  * the same five CRUD verbs (GET list / GET :id / POST / PATCH+PUT / DELETE)
@@ -29,17 +30,42 @@ export const routesFileHono = function routesFileHono(opts) {
29
30
  // `ctx.config.includeHonoRoutes` and api-docs auto-documents the Hono surface.
30
31
  emitsHonoRoutes: true,
31
32
  // ADR-0039: resolving — a concrete entity may inherit @emitRoutes via extends.
32
- filter: (e) => e.attr(CODEGEN_ATTR_EMIT_ROUTES) !== false && hasAnyRdbSource(e) && userFilter(e),
33
- generate: perEntity(async (entity, ctx) => {
34
- if (!ctx.renderContext) {
35
- throw new Error("routes-file-hono: renderContext is required (provided by runGen)");
33
+ //
34
+ // TPH subtypes are EXCLUDED, matching the Fastify generator. A TPH subtype shares
35
+ // its base's table, so mounting vanilla CRUD for it produced routes with no
36
+ // discriminator scoping at all: the list returned EVERY subtype's rows, and
37
+ // get/patch/delete by id happily operated on rows belonging to a different
38
+ // subtype. Silently wrong data, which is worse than no route. Fastify dispatches
39
+ // these to a discriminator-aware renderer; the Hono runtime has no discriminator
40
+ // support yet, so this fails CLOSED and the run says so (see the warning below)
41
+ // rather than shipping an artifact that returns the wrong rows.
42
+ filter: (e) => e.attr(CODEGEN_ATTR_EMIT_ROUTES) !== false
43
+ && hasAnyRdbSource(e)
44
+ && !isTphSubtype(e)
45
+ && userFilter(e),
46
+ generate: async (ctx) => {
47
+ // One note per run naming every TPH subtype held back, so the gap is visible at
48
+ // `meta gen` time rather than discovered as missing endpoints in production.
49
+ const skipped = ctx.entities.filter((e) => e.attr(CODEGEN_ATTR_EMIT_ROUTES) !== false
50
+ && hasAnyRdbSource(e) && isTphSubtype(e) && userFilter(e));
51
+ if (skipped.length > 0) {
52
+ ctx.warn(`no Hono routes emitted for the TPH subtype(s) ${skipped.map((e) => e.name).join(", ")} — ` +
53
+ "the Hono adapter has no discriminator scoping yet, so per-subtype CRUD would " +
54
+ "return and mutate OTHER subtypes' rows. Use routesFile() (Fastify), which " +
55
+ "dispatches TPH correctly, or hand-write the scoped routes.");
36
56
  }
37
- return {
38
- path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity.package, `${entity.name}.routes.hono.ts`),
39
- content: await formatTs(renderRoutesFileHono(entity, ctx.renderContext)),
40
- };
41
- }),
57
+ return emit(ctx);
58
+ },
42
59
  };
60
+ const emit = perEntity(async (entity, ctx) => {
61
+ if (!ctx.renderContext) {
62
+ throw new Error("routes-file-hono: renderContext is required (provided by runGen)");
63
+ }
64
+ return {
65
+ path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity.package, `${entity.name}.routes.hono.ts`),
66
+ content: await formatTs(renderRoutesFileHono(entity, ctx.renderContext)),
67
+ };
68
+ });
43
69
  if (opts?.target) {
44
70
  generator.target = opts.target;
45
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"routes-file-hono.js","sourceRoot":"","sources":["../../src/generators/routes-file-hono.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAO3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,cAAc,CAAC,IAAyB;IAC7E,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,kBAAkB;QACxB,sEAAsE;QACtE,+EAA+E;QAC/E,eAAe,EAAE,IAAI;QACrB,+EAA+E;QAC/E,MAAM,EAAE,CAAC,CAAa,EAAE,EAAE,CACxB,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,KAAK,KAAK,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC;QACnF,QAAQ,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;YACxC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;YACtF,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,gBAAgB,CACpB,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,EACjC,MAAM,CAAC,OAAO,EACd,GAAG,MAAM,CAAC,IAAI,iBAAiB,CAChC;gBACD,OAAO,EAAE,MAAM,QAAQ,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;aACzE,CAAC;QACJ,CAAC,CAAC;KACH,CAAC;IACF,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAyC,CAAC"}
1
+ {"version":3,"file":"routes-file-hono.js","sourceRoot":"","sources":["../../src/generators/routes-file-hono.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAO9D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,cAAc,CAAC,IAAyB;IAC7E,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,kBAAkB;QACxB,sEAAsE;QACtE,+EAA+E;QAC/E,eAAe,EAAE,IAAI;QACrB,+EAA+E;QAC/E,EAAE;QACF,kFAAkF;QAClF,4EAA4E;QAC5E,4EAA4E;QAC5E,2EAA2E;QAC3E,iFAAiF;QACjF,iFAAiF;QACjF,gFAAgF;QAChF,gEAAgE;QAChE,MAAM,EAAE,CAAC,CAAa,EAAE,EAAE,CACxB,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,KAAK,KAAK;eACvC,eAAe,CAAC,CAAC,CAAC;eAClB,CAAC,YAAY,CAAC,CAAC,CAAC;eAChB,UAAU,CAAC,CAAC,CAAC;QAClB,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACtB,gFAAgF;YAChF,6EAA6E;YAC7E,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,KAAK,KAAK;mBAC5C,eAAe,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAC5D,CAAC;YACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,GAAG,CAAC,IAAI,CACN,iDAAiD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;oBAC3F,+EAA+E;oBAC/E,4EAA4E;oBAC5E,4DAA4D,CAC7D,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;KACF,CAAC;IACF,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QACzC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QACD,OAAO;YACL,IAAI,EAAE,gBAAgB,CACpB,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,EACjC,MAAM,CAAC,OAAO,EACd,GAAG,MAAM,CAAC,IAAI,iBAAiB,CAChC;YACD,OAAO,EAAE,MAAM,QAAQ,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;SACzE,CAAC;IACN,CAAC,CAAC,CAAC;IACH,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAyC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ export { docPageOutputPath, docPageHref, docPageNode, effectivePackage, assertNo
33
33
  export type { DocPageNode, DocPagePlacement } from "./docs-paths.js";
34
34
  export { isProjection, isWriteThrough } from "./projection/projection-detector.js";
35
35
  export { isAbstract, emitsInstanceArtifacts, emitsWriteArtifacts } from "./instance-artifacts.js";
36
+ export { servesReadApi, servesWriteApi } from "./api-surface.js";
37
+ export { renderEntityMetaFile, entityMetaFileName, entityMetaSpecifier } from "./templates/entity-meta-file.js";
36
38
  export { isTphDiscriminatorBase, tphConcreteSubtypes, collectTphSubtypeFields, tphPlan, tphRouteSegment } from "./templates/tph-discriminator.js";
37
39
  export type { TphPlan, TphSubtypePlan } from "./templates/tph-discriminator.js";
38
40
  export { isTphSubtype, tphDiscriminatorPin } from "./templates/zod-validators.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -26,6 +26,10 @@ export { packageToPath, entityOutputPath, crossEntitySpecifier, barrelEntrySpeci
26
26
  export { docPageOutputPath, docPageHref, docPageNode, effectivePackage, assertNoDuplicateDocPaths, } from "./docs-paths.js";
27
27
  export { isProjection, isWriteThrough } from "./projection/projection-detector.js";
28
28
  export { isAbstract, emitsInstanceArtifacts, emitsWriteArtifacts } from "./instance-artifacts.js";
29
+ // The UI tier asks THESE — "is there an endpoint?" — never the storage predicates.
30
+ export { servesReadApi, servesWriteApi } from "./api-surface.js";
31
+ // The DB-free descriptor module the UI tier imports from (see entity-meta-file.ts).
32
+ export { renderEntityMetaFile, entityMetaFileName, entityMetaSpecifier } from "./templates/entity-meta-file.js";
29
33
  // FR-017 TPH helpers — used by the per-framework codegen packages (tanstack,
30
34
  // react) to dispatch polymorphic/per-subtype emission and skip subtype files.
31
35
  export { isTphDiscriminatorBase, tphConcreteSubtypes, collectTphSubtypeFields, tphPlan, tphRouteSegment } from "./templates/tph-discriminator.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { MetaData } from "@metaobjectsdev/metadata";
1
+ import type { MetaData, MetaObject } from "@metaobjectsdev/metadata";
2
2
  /**
3
3
  * True when `entity` is abstract (`@isAbstract: true`).
4
4
  *
@@ -10,20 +10,26 @@ import type { MetaData } from "@metaobjectsdev/metadata";
10
10
  export declare function isAbstract(entity: MetaData): boolean;
11
11
  /**
12
12
  * True when `entity` should produce INSTANCE artifacts of ANY kind (read OR
13
- * write): CRUD/read hooks, grid columns, grid hooks. Abstract types are
14
- * excluded they have no instantiable representation.
13
+ * write): CRUD/read hooks, grid columns, grid hooks. Excludes abstract types
14
+ * (no instantiable representation) and sourceless objects (no route for the
15
+ * artifact to talk to — see the header note, and #248 for the doctrine).
15
16
  *
16
17
  * Read-capable generators (tanstack hooks/grids) compose this so they skip
17
- * abstract bases while still serving projections via their own
18
- * `isProjection` read-only branch.
18
+ * abstract bases while still serving VIEW-BACKED projections via their own
19
+ * `isProjection` read-only branch — a projection over a `@kind: view` source
20
+ * has a source, so it passes here and keeps its read-only hooks.
19
21
  */
20
- export declare function emitsInstanceArtifacts(entity: MetaData): boolean;
22
+ export declare function emitsInstanceArtifacts(entity: MetaObject): boolean;
21
23
  /**
22
24
  * True when `entity` should produce WRITE artifacts (write forms, mutation
23
- * surfaces). Excludes both abstract types (no instance at all) and projections
24
- * (read-only views — instantiable for read, never for write).
25
+ * surfaces). Excludes abstract types (no instance at all), projections
26
+ * (read-only views — instantiable for read, never for write), and objects with
27
+ * no WRITABLE source (nothing to submit to; this is the same predicate the
28
+ * entity-file generator uses to decide whether an `Insert`/`Update` surface
29
+ * exists at all, so a form can no longer be emitted against schemas that were
30
+ * never generated).
25
31
  *
26
32
  * WRITE-only generators (e.g. the React form generator) compose this.
27
33
  */
28
- export declare function emitsWriteArtifacts(entity: MetaData): boolean;
34
+ export declare function emitsWriteArtifacts(entity: MetaObject): boolean;
29
35
  //# sourceMappingURL=instance-artifacts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instance-artifacts.d.ts","sourceRoot":"","sources":["../src/instance-artifacts.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAEpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAE7D"}
1
+ {"version":3,"file":"instance-artifacts.d.ts","sourceRoot":"","sources":["../src/instance-artifacts.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAIrE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAEpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAElE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAE/D"}
@@ -1,7 +1,7 @@
1
1
  // Framework-level guard shared by every generator that emits INSTANCE / WRITE
2
2
  // artifacts (write forms, CRUD hooks, grid columns, grid hooks, …).
3
3
  //
4
- // Two MetaData concepts make an entity *not* a source of instance artifacts:
4
+ // THREE things make an object *not* a source of instance artifacts:
5
5
  //
6
6
  // 1. Abstract (`@isAbstract: true`) — a fundamental MetaData concept: an
7
7
  // abstract type contributes shape via inheritance ONLY. It never has an
@@ -11,7 +11,25 @@
11
11
  // consumers can reference its shape), but nothing that points at an
12
12
  // `<E>Insert` schema / `$table` / mutation hook it does not have.
13
13
  //
14
- // 2. Projection (read-only view; see `isProjection`) instantiable for READ
14
+ // 2. SOURCELESS no declared/inherited `source.*` at all. #248 settled that DB
15
+ // participation derives from a declared source, never from the object subtype,
16
+ // and the routes/queries tier already gates on exactly this. An instance
17
+ // artifact is a client for a route: hooks fetch one, a grid renders what hooks
18
+ // return, a form submits to one. A sourceless object has no route, so there is
19
+ // nothing for any of them to talk to. This subsumes `object.value` — a value is
20
+ // sourceless by loader-enforced purity (ADR-0028) — WITHOUT reintroducing a
21
+ // subtype check, which is the family #248 spent two releases eradicating. It
22
+ // also covers sourceless entities and the sourceless `object.projection` that
23
+ // #210 made the recommended payload re-host: that shape's generated surface is
24
+ // the payload VO + render helper + output parser, never TanStack CRUD.
25
+ //
26
+ // This is a BUG FIX, not a policy change. Before it, a value object got a
27
+ // `<V>.hooks.ts` importing `<V>Filter` / `<V>Insert` / `<V>Update` and the
28
+ // `<V>` const — none of which the entity module emits for a value — so the
29
+ // generated file could not typecheck (TS2305 ×3, TS2693) and could not even
30
+ // link under native ESM. There was never working output here to lose.
31
+ //
32
+ // 3. Projection (read-only view; see `isProjection`) — instantiable for READ
15
33
  // but never for WRITE. It legitimately gets read models + read-only hooks
16
34
  // + grids, but NOT a write form. WRITE-only generators (forms) reuse
17
35
  // `emitsWriteArtifacts` to skip these; read-capable generators (tanstack
@@ -19,8 +37,10 @@
19
37
  //
20
38
  // Centralizing these as `emitsInstanceArtifacts` / `emitsWriteArtifacts` keeps
21
39
  // the rule in one place: a generator composes the matching guard into its
22
- // `filter` rather than re-deriving "is this abstract / read-only" ad hoc.
40
+ // `filter` rather than re-deriving "is this abstract / read-only / persisted" ad
41
+ // hoc — and a third-party generator composing the guard inherits the fix.
23
42
  import { isProjection } from "./projection/projection-detector.js";
43
+ import { hasAnyRdbSource, hasWritableRdbSource } from "./source-detect.js";
24
44
  /**
25
45
  * True when `entity` is abstract (`@isAbstract: true`).
26
46
  *
@@ -34,24 +54,30 @@ export function isAbstract(entity) {
34
54
  }
35
55
  /**
36
56
  * True when `entity` should produce INSTANCE artifacts of ANY kind (read OR
37
- * write): CRUD/read hooks, grid columns, grid hooks. Abstract types are
38
- * excluded they have no instantiable representation.
57
+ * write): CRUD/read hooks, grid columns, grid hooks. Excludes abstract types
58
+ * (no instantiable representation) and sourceless objects (no route for the
59
+ * artifact to talk to — see the header note, and #248 for the doctrine).
39
60
  *
40
61
  * Read-capable generators (tanstack hooks/grids) compose this so they skip
41
- * abstract bases while still serving projections via their own
42
- * `isProjection` read-only branch.
62
+ * abstract bases while still serving VIEW-BACKED projections via their own
63
+ * `isProjection` read-only branch — a projection over a `@kind: view` source
64
+ * has a source, so it passes here and keeps its read-only hooks.
43
65
  */
44
66
  export function emitsInstanceArtifacts(entity) {
45
- return !isAbstract(entity);
67
+ return !isAbstract(entity) && hasAnyRdbSource(entity);
46
68
  }
47
69
  /**
48
70
  * True when `entity` should produce WRITE artifacts (write forms, mutation
49
- * surfaces). Excludes both abstract types (no instance at all) and projections
50
- * (read-only views — instantiable for read, never for write).
71
+ * surfaces). Excludes abstract types (no instance at all), projections
72
+ * (read-only views — instantiable for read, never for write), and objects with
73
+ * no WRITABLE source (nothing to submit to; this is the same predicate the
74
+ * entity-file generator uses to decide whether an `Insert`/`Update` surface
75
+ * exists at all, so a form can no longer be emitted against schemas that were
76
+ * never generated).
51
77
  *
52
78
  * WRITE-only generators (e.g. the React form generator) compose this.
53
79
  */
54
80
  export function emitsWriteArtifacts(entity) {
55
- return !isAbstract(entity) && !isProjection(entity);
81
+ return !isAbstract(entity) && !isProjection(entity) && hasWritableRdbSource(entity);
56
82
  }
57
83
  //# sourceMappingURL=instance-artifacts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instance-artifacts.js","sourceRoot":"","sources":["../src/instance-artifacts.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oEAAoE;AACpE,EAAE;AACF,6EAA6E;AAC7E,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,uEAAuE;AACvE,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,0EAA0E;AAC1E,8EAA8E;AAC9E,iEAAiE;AACjE,EAAE;AACF,+EAA+E;AAC/E,0EAA0E;AAC1E,0EAA0E;AAG1E,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAEnE;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,MAAgB;IACzC,OAAO,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC;AACpC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAgB;IACrD,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAgB;IAClD,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"instance-artifacts.js","sourceRoot":"","sources":["../src/instance-artifacts.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oEAAoE;AACpE,EAAE;AACF,oEAAoE;AACpE,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,uEAAuE;AACvE,EAAE;AACF,kFAAkF;AAClF,oFAAoF;AACpF,8EAA8E;AAC9E,oFAAoF;AACpF,oFAAoF;AACpF,qFAAqF;AACrF,iFAAiF;AACjF,kFAAkF;AAClF,mFAAmF;AACnF,oFAAoF;AACpF,4EAA4E;AAC5E,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,gFAAgF;AAChF,iFAAiF;AACjF,2EAA2E;AAC3E,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,0EAA0E;AAC1E,8EAA8E;AAC9E,iEAAiE;AACjE,EAAE;AACF,+EAA+E;AAC/E,0EAA0E;AAC1E,iFAAiF;AACjF,0EAA0E;AAG1E,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,MAAgB;IACzC,OAAO,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC;AACpC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAkB;IACvD,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAkB;IACpD,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACtF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { MetaObject } from "@metaobjectsdev/metadata";
2
+ /** File name (no directory) of an entity's DB-free descriptor module. */
3
+ export declare function entityMetaFileName(entityName: string): string;
4
+ /** Module specifier the UI files use to reach it — a same-directory sibling. */
5
+ export declare function entityMetaSpecifier(entityName: string, extStyle: string | undefined): string;
6
+ export declare function renderEntityMetaFile(entity: MetaObject, apiPrefix?: string): string;
7
+ //# sourceMappingURL=entity-meta-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-meta-file.d.ts","sourceRoot":"","sources":["../../src/templates/entity-meta-file.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE5F;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,SAAK,GAAG,MAAM,CAa/E"}
@@ -0,0 +1,47 @@
1
+ // `<Entity>.meta.ts` — the entity descriptor, with no database in the module graph.
2
+ //
3
+ // The generated UI files (hooks, grid hooks, forms) value-import exactly ONE thing
4
+ // from the entity module: the `<Entity>` descriptor const. Everything else they take
5
+ // is `import type`, which the compiler erases. But `<Entity>.ts` also constructs the
6
+ // Drizzle table at module scope, so that single value import dragged the entire ORM
7
+ // into every browser bundle — measured at 716 KB for one generated hook, containing
8
+ // `SQLiteTable` and the whole driver.
9
+ //
10
+ // Nothing in the UI path READS the table. The descriptor is plain data — `$table` is
11
+ // a string, not a table object — so this was never a semantic dependency on the
12
+ // database, only a physical one created by sharing a module. A `/* @__PURE__ */`
13
+ // annotation on the table construction does NOT help (measured: still 716 KB), so
14
+ // separating the module is the fix.
15
+ //
16
+ // Deliberately ADDITIVE. `<Entity>.ts` is untouched and still exports the descriptor,
17
+ // so every existing import keeps working and this stays a PATCH. The UI generators
18
+ // simply take the descriptor from here instead, and each emits this file itself —
19
+ // byte-identical between them, which #266 collapses — rather than depending on the
20
+ // consumer having wired an extra generator, since the entity generator is
21
+ // scaffold-and-own (ADR-0034) and cannot be changed from the package.
22
+ import { code } from "ts-poet";
23
+ import { GENERATED_HEADER } from "../constants.js";
24
+ import { renderEntityConstants } from "./entity-constants.js";
25
+ /** File name (no directory) of an entity's DB-free descriptor module. */
26
+ export function entityMetaFileName(entityName) {
27
+ return `${entityName}.meta.ts`;
28
+ }
29
+ /** Module specifier the UI files use to reach it — a same-directory sibling. */
30
+ export function entityMetaSpecifier(entityName, extStyle) {
31
+ return `./${entityName}.meta${extStyle === "js" ? ".js" : ""}`;
32
+ }
33
+ export function renderEntityMetaFile(entity, apiPrefix = "") {
34
+ const body = code `
35
+ // ${GENERATED_HEADER} — DO NOT EDIT.
36
+ // Source metadata: ${entity.name}
37
+ //
38
+ // Browser-safe: this module contains ONLY the entity descriptor — plain data, no
39
+ // Drizzle table and no database import of any kind. The generated UI files import it
40
+ // from here so a client bundle never pulls the ORM in. \`${entity.name}.ts\` also
41
+ // exports this descriptor, for server-side and pre-existing consumers.
42
+
43
+ ${renderEntityConstants(entity, apiPrefix)}
44
+ `;
45
+ return body.toString();
46
+ }
47
+ //# sourceMappingURL=entity-meta-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-meta-file.js","sourceRoot":"","sources":["../../src/templates/entity-meta-file.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,EAAE;AACF,mFAAmF;AACnF,qFAAqF;AACrF,qFAAqF;AACrF,oFAAoF;AACpF,oFAAoF;AACpF,sCAAsC;AACtC,EAAE;AACF,qFAAqF;AACrF,gFAAgF;AAChF,iFAAiF;AACjF,kFAAkF;AAClF,oCAAoC;AACpC,EAAE;AACF,sFAAsF;AACtF,mFAAmF;AACnF,kFAAkF;AAClF,mFAAmF;AACnF,0EAA0E;AAC1E,sEAAsE;AAEtE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,yEAAyE;AACzE,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,OAAO,GAAG,UAAU,UAAU,CAAC;AACjC,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,mBAAmB,CAAC,UAAkB,EAAE,QAA4B;IAClF,OAAO,KAAK,UAAU,QAAQ,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAkB,EAAE,SAAS,GAAG,EAAE;IACrE,MAAM,IAAI,GAAG,IAAI,CAAA;KACd,gBAAgB;sBACC,MAAM,CAAC,IAAI;;;;4DAI2B,MAAM,CAAC,IAAI;;;EAGrE,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC;CACzC,CAAC;IACA,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;AACzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes-file-hono.d.ts","sourceRoot":"","sources":["../../src/templates/routes-file-hono.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK1D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CA2GnF"}
1
+ {"version":3,"file":"routes-file-hono.d.ts","sourceRoot":"","sources":["../../src/templates/routes-file-hono.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK1D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAqHnF"}
@@ -27,7 +27,7 @@ import { code, imp } from "ts-poet";
27
27
  import {} from "../render-context.js";
28
28
  import { entityModuleSpecifier } from "../import-path.js";
29
29
  import { GENERATED_HEADER } from "../constants.js";
30
- import { isProjection } from "../projection/projection-detector.js";
30
+ import { isProjection, isWriteThrough } from "../projection/projection-detector.js";
31
31
  export function renderRoutesFileHono(entity, ctx) {
32
32
  const entityName = entity.name;
33
33
  const handlerName = `register${entityName}Routes`;
@@ -77,6 +77,15 @@ export function ${handlerName}(app: ${HonoSym}<any, any, any>, deps: { db: unkno
77
77
  }
78
78
  // --- Vanilla / write-through entity path: full CRUD routes ---
79
79
  const tableVar = ctx.collectionName(entityName);
80
+ // #214: a write-through entity reads through its replica view so derived origin.*
81
+ // columns are present. Without this the Hono adapter returned rows missing every
82
+ // derived field the generated type and Zod schema promise, and a filter or sort on
83
+ // one — both ALLOWED by the generated allowlists — hit a column the table does not
84
+ // have, producing a 500. Fastify has done this since #214; Hono was simply never
85
+ // wired, exactly as it was never wired for #286's `.all()`/`.get()` fix.
86
+ const writeThrough = isWriteThrough(entity);
87
+ const camelName = entityName.charAt(0).toLowerCase() + entityName.slice(1);
88
+ const readViewLine = writeThrough ? `\n readView: ${camelName}View,` : "";
80
89
  const HonoSym = imp("t:Hono@hono");
81
90
  const mountCrudRoutesSym = imp("mountCrudRoutes@@metaobjectsdev/runtime-ts/hono");
82
91
  const literalImports = code `
@@ -86,7 +95,7 @@ import {
86
95
  ${entityName}InsertSchema,
87
96
  ${entityName}UpdateSchema,
88
97
  ${entityName}FilterAllowlist,
89
- ${entityName}SortAllowlist,
98
+ ${entityName}SortAllowlist,${writeThrough ? `\n ${camelName}View,` : ""}
90
99
  } from ${JSON.stringify(entityFileSpec)};
91
100
  `;
92
101
  const body = code `
@@ -104,7 +113,7 @@ export function ${handlerName}(app: ${HonoSym}<any, any, any>, deps: { db: unkno
104
113
  app,
105
114
  path: ${pathExpr},
106
115
  db: deps.db,
107
- table: ${tableVar},
116
+ table: ${tableVar},${readViewLine}
108
117
  insertSchema: ${entityName}InsertSchema,
109
118
  updateSchema: ${entityName}UpdateSchema,
110
119
  filterAllowlist: ${entityName}FilterAllowlist,
@@ -1 +1 @@
1
- {"version":3,"file":"routes-file-hono.js","sourceRoot":"","sources":["../../src/templates/routes-file-hono.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routes-file-hono.js","sourceRoot":"","sources":["../../src/templates/routes-file-hono.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,8DAA8D;AAC9D,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,SAAS;AACT,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,qEAAqE;AACrE,iEAAiE;AACjE,uEAAuE;AACvE,kEAAkE;AAClE,qEAAqE;AACrE,6DAA6D;AAC7D,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,wEAAwE;AACxE,uCAAuC;AACvC,EAAE;AACF,kCAAkC;AAClC,qFAAqF;AACrF,2EAA2E;AAE3E,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAsB,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEpF,MAAM,UAAU,oBAAoB,CAAC,MAAkB,EAAE,GAAkB;IACzE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;IAC/B,MAAM,WAAW,GAAG,WAAW,UAAU,QAAQ,CAAC;IAElD,MAAM,cAAc,GAAG,qBAAqB,CAC1C,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,kBAAkB,EACtB,MAAM,CAAC,OAAO,EACd,UAAU,EACV,GAAG,CAAC,QAAQ,CACb,CAAC;IAEF,MAAM,MAAM,GACV,MAAM,gBAAgB,mBAAmB;QACzC,uBAAuB,UAAU,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK;QACvD,oBAAoB,UAAU,kEAAkE,CAAC;IAEnG,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS;QAC5B,CAAC,CAAC,KAAK,GAAG,CAAC,SAAS,MAAM,UAAU,WAAW;QAC/C,CAAC,CAAC,GAAG,UAAU,QAAQ,CAAC;IAE1B,iEAAiE;IACjE,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;QACnC,MAAM,0BAA0B,GAAG,GAAG,CACpC,yDAAyD,CAC1D,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,CAAA;;IAE3B,UAAU;IACV,SAAS;IACT,UAAU;IACV,UAAU;SACL,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;CACtC,CAAC;QAEE,MAAM,IAAI,GAAG,IAAI,CAAA;;wCAEmB,UAAU;;;;;;;kBAOhC,WAAW,SAAS,OAAO;IACzC,0BAA0B;;YAElB,QAAQ;;YAER,SAAS;uBACE,UAAU;qBACZ,UAAU;eAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;;;CAGzC,CAAC;QAEE,OAAO,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9D,CAAC;IAED,gEAAgE;IAChE,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAEhD,kFAAkF;IAClF,iFAAiF;IACjF,mFAAmF;IACnF,mFAAmF;IACnF,iFAAiF;IACjF,yEAAyE;IACzE,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,mBAAmB,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7E,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;IACnC,MAAM,kBAAkB,GAAG,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAElF,MAAM,cAAc,GAAG,IAAI,CAAA;;IAEzB,UAAU;IACV,QAAQ;IACR,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU,iBAAiB,YAAY,CAAC,CAAC,CAAC,OAAO,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE;SACjE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;CACtC,CAAC;IAEA,MAAM,IAAI,GAAG,IAAI,CAAA;;6CAE0B,UAAU;;;;;;;;kBAQrC,WAAW,SAAS,OAAO;IACzC,kBAAkB;;YAEV,QAAQ;;aAEP,QAAQ,IAAI,YAAY;oBACjB,UAAU;oBACV,UAAU;uBACP,UAAU;qBACZ,UAAU;eAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;;;CAGzC,CAAC;IAEA,OAAO,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC9D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaobjectsdev/codegen-ts",
3
- "version": "0.21.4-rc.1",
3
+ "version": "0.21.5",
4
4
  "description": "TypeScript codegen engine for MetaObjects — emits Drizzle, Zod, and Fastify artifacts.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -111,21 +111,21 @@
111
111
  "access": "public"
112
112
  },
113
113
  "dependencies": {
114
- "@metaobjectsdev/metadata": "0.21.4-rc.1",
115
- "@metaobjectsdev/render": "0.21.4-rc.1",
114
+ "@metaobjectsdev/metadata": "0.21.5",
115
+ "@metaobjectsdev/render": "0.21.5",
116
116
  "@biomejs/js-api": "^0.7.0",
117
117
  "@biomejs/wasm-nodejs": "^1.9.4",
118
118
  "ts-poet": "^6.10.0"
119
119
  },
120
120
  "peerDependencies": {
121
- "drizzle-orm": ">=0.36.0",
122
- "zod": ">=3.23.0"
121
+ "drizzle-orm": ">=0.36.0 <1.0.0",
122
+ "zod": ">=3.23.0 <5.0.0"
123
123
  },
124
124
  "devDependencies": {
125
125
  "@biomejs/biome": "^1.9.0",
126
- "@metaobjectsdev/codegen-ts-react": "0.21.4-rc.1",
127
- "@metaobjectsdev/migrate-ts": "0.21.4-rc.1",
128
- "@metaobjectsdev/runtime-ts": "0.21.4-rc.1",
126
+ "@metaobjectsdev/codegen-ts-react": "0.21.5",
127
+ "@metaobjectsdev/migrate-ts": "0.21.5",
128
+ "@metaobjectsdev/runtime-ts": "0.21.5",
129
129
  "bun-types": "latest",
130
130
  "drizzle-orm": "^0.36.0",
131
131
  "hono": "^4.6.0",
@@ -0,0 +1,45 @@
1
+ // Does this object have a generated HTTP API surface?
2
+ //
3
+ // THIS is the question the UI tier should ask. A hook, a grid and a form are all
4
+ // clients of a REST endpoint: hooks fetch one, a grid renders what a hook returned,
5
+ // a form submits to one. None of them knows or cares where the data is stored — that
6
+ // is the whole point of the architecture, and `@metaobjectsdev/runtime-web` is
7
+ // deliberately browser-only with no database dependency at all.
8
+ //
9
+ // The UI generators used to ask `hasAnyRdbSource` directly, which produced the RIGHT
10
+ // answer for the WRONG reason: routes are currently derived from sources (FR-008/009
11
+ // derived CRUD), so "has a relational source" and "has an endpoint" happen to
12
+ // coincide today. They are not the same question, and the coincidence is temporary —
13
+ // FR-024 declared `api.*` surfaces and #211 non-RDB projection materialization both
14
+ // break it, at which point a UI tier reaching through to storage starts refusing to
15
+ // generate hooks for entities that genuinely do have endpoints.
16
+ //
17
+ // So the reach-through lives in exactly one place now, named for what it means. When
18
+ // route derivation grows a second source of truth, this function changes and every
19
+ // UI generator follows for free.
20
+
21
+ import type { MetaObject } from "@metaobjectsdev/metadata";
22
+ import { isAbstract } from "./instance-artifacts.js";
23
+ import { hasAnyRdbSource, hasWritableRdbSource } from "./source-detect.js";
24
+
25
+ /**
26
+ * True when the object is served by a generated READ endpoint — so a hook has
27
+ * something to fetch and a grid has something to render.
28
+ *
29
+ * Abstract types are excluded (no instance to address). Today the endpoint test is
30
+ * "declares or inherits a `source.rdb`", which is precisely the predicate
31
+ * `routesFile` / `routesFileHono` gate on, so hooks exist exactly where routes do.
32
+ */
33
+ export function servesReadApi(entity: MetaObject): boolean {
34
+ return !isAbstract(entity) && hasAnyRdbSource(entity);
35
+ }
36
+
37
+ /**
38
+ * True when the object is served by generated WRITE endpoints — so a form has
39
+ * somewhere to submit. Requires a WRITABLE source: the same predicate the entity-file
40
+ * generator uses to decide whether `Insert`/`Update` schemas exist at all, so a form
41
+ * can never be emitted against schemas that were never generated.
42
+ */
43
+ export function servesWriteApi(entity: MetaObject): boolean {
44
+ return !isAbstract(entity) && hasWritableRdbSource(entity);
45
+ }
@@ -5,6 +5,7 @@ import { hasAnyRdbSource } from "../source-detect.js";
5
5
  import { formatTs } from "../format.js";
6
6
  import { entityOutputPath } from "../import-path.js";
7
7
  import { CODEGEN_ATTR_EMIT_ROUTES } from "../constants.js";
8
+ import { isTphSubtype } from "../templates/zod-validators.js";
8
9
 
9
10
  export interface RoutesFileHonoOpts {
10
11
  filter?: (entity: MetaObject) => boolean;
@@ -36,9 +37,39 @@ export const routesFileHono = function routesFileHono(opts?: RoutesFileHonoOpts)
36
37
  // `ctx.config.includeHonoRoutes` and api-docs auto-documents the Hono surface.
37
38
  emitsHonoRoutes: true,
38
39
  // ADR-0039: resolving — a concrete entity may inherit @emitRoutes via extends.
40
+ //
41
+ // TPH subtypes are EXCLUDED, matching the Fastify generator. A TPH subtype shares
42
+ // its base's table, so mounting vanilla CRUD for it produced routes with no
43
+ // discriminator scoping at all: the list returned EVERY subtype's rows, and
44
+ // get/patch/delete by id happily operated on rows belonging to a different
45
+ // subtype. Silently wrong data, which is worse than no route. Fastify dispatches
46
+ // these to a discriminator-aware renderer; the Hono runtime has no discriminator
47
+ // support yet, so this fails CLOSED and the run says so (see the warning below)
48
+ // rather than shipping an artifact that returns the wrong rows.
39
49
  filter: (e: MetaObject) =>
40
- e.attr(CODEGEN_ATTR_EMIT_ROUTES) !== false && hasAnyRdbSource(e) && userFilter(e),
41
- generate: perEntity(async (entity, ctx) => {
50
+ e.attr(CODEGEN_ATTR_EMIT_ROUTES) !== false
51
+ && hasAnyRdbSource(e)
52
+ && !isTphSubtype(e)
53
+ && userFilter(e),
54
+ generate: async (ctx) => {
55
+ // One note per run naming every TPH subtype held back, so the gap is visible at
56
+ // `meta gen` time rather than discovered as missing endpoints in production.
57
+ const skipped = ctx.entities.filter(
58
+ (e) => e.attr(CODEGEN_ATTR_EMIT_ROUTES) !== false
59
+ && hasAnyRdbSource(e) && isTphSubtype(e) && userFilter(e),
60
+ );
61
+ if (skipped.length > 0) {
62
+ ctx.warn(
63
+ `no Hono routes emitted for the TPH subtype(s) ${skipped.map((e) => e.name).join(", ")} — ` +
64
+ "the Hono adapter has no discriminator scoping yet, so per-subtype CRUD would " +
65
+ "return and mutate OTHER subtypes' rows. Use routesFile() (Fastify), which " +
66
+ "dispatches TPH correctly, or hand-write the scoped routes.",
67
+ );
68
+ }
69
+ return emit(ctx);
70
+ },
71
+ };
72
+ const emit = perEntity(async (entity, ctx) => {
42
73
  if (!ctx.renderContext) {
43
74
  throw new Error("routes-file-hono: renderContext is required (provided by runGen)");
44
75
  }
@@ -50,8 +81,7 @@ export const routesFileHono = function routesFileHono(opts?: RoutesFileHonoOpts)
50
81
  ),
51
82
  content: await formatTs(renderRoutesFileHono(entity, ctx.renderContext)),
52
83
  };
53
- }),
54
- };
84
+ });
55
85
  if (opts?.target) {
56
86
  generator.target = opts.target;
57
87
  }
package/src/index.ts CHANGED
@@ -82,6 +82,10 @@ export type { DocPageNode, DocPagePlacement } from "./docs-paths.js";
82
82
 
83
83
  export { isProjection, isWriteThrough } from "./projection/projection-detector.js";
84
84
  export { isAbstract, emitsInstanceArtifacts, emitsWriteArtifacts } from "./instance-artifacts.js";
85
+ // The UI tier asks THESE — "is there an endpoint?" — never the storage predicates.
86
+ export { servesReadApi, servesWriteApi } from "./api-surface.js";
87
+ // The DB-free descriptor module the UI tier imports from (see entity-meta-file.ts).
88
+ export { renderEntityMetaFile, entityMetaFileName, entityMetaSpecifier } from "./templates/entity-meta-file.js";
85
89
  // FR-017 TPH helpers — used by the per-framework codegen packages (tanstack,
86
90
  // react) to dispatch polymorphic/per-subtype emission and skip subtype files.
87
91
  export { isTphDiscriminatorBase, tphConcreteSubtypes, collectTphSubtypeFields, tphPlan, tphRouteSegment } from "./templates/tph-discriminator.js";
@@ -1,7 +1,7 @@
1
1
  // Framework-level guard shared by every generator that emits INSTANCE / WRITE
2
2
  // artifacts (write forms, CRUD hooks, grid columns, grid hooks, …).
3
3
  //
4
- // Two MetaData concepts make an entity *not* a source of instance artifacts:
4
+ // THREE things make an object *not* a source of instance artifacts:
5
5
  //
6
6
  // 1. Abstract (`@isAbstract: true`) — a fundamental MetaData concept: an
7
7
  // abstract type contributes shape via inheritance ONLY. It never has an
@@ -11,7 +11,25 @@
11
11
  // consumers can reference its shape), but nothing that points at an
12
12
  // `<E>Insert` schema / `$table` / mutation hook it does not have.
13
13
  //
14
- // 2. Projection (read-only view; see `isProjection`) instantiable for READ
14
+ // 2. SOURCELESS no declared/inherited `source.*` at all. #248 settled that DB
15
+ // participation derives from a declared source, never from the object subtype,
16
+ // and the routes/queries tier already gates on exactly this. An instance
17
+ // artifact is a client for a route: hooks fetch one, a grid renders what hooks
18
+ // return, a form submits to one. A sourceless object has no route, so there is
19
+ // nothing for any of them to talk to. This subsumes `object.value` — a value is
20
+ // sourceless by loader-enforced purity (ADR-0028) — WITHOUT reintroducing a
21
+ // subtype check, which is the family #248 spent two releases eradicating. It
22
+ // also covers sourceless entities and the sourceless `object.projection` that
23
+ // #210 made the recommended payload re-host: that shape's generated surface is
24
+ // the payload VO + render helper + output parser, never TanStack CRUD.
25
+ //
26
+ // This is a BUG FIX, not a policy change. Before it, a value object got a
27
+ // `<V>.hooks.ts` importing `<V>Filter` / `<V>Insert` / `<V>Update` and the
28
+ // `<V>` const — none of which the entity module emits for a value — so the
29
+ // generated file could not typecheck (TS2305 ×3, TS2693) and could not even
30
+ // link under native ESM. There was never working output here to lose.
31
+ //
32
+ // 3. Projection (read-only view; see `isProjection`) — instantiable for READ
15
33
  // but never for WRITE. It legitimately gets read models + read-only hooks
16
34
  // + grids, but NOT a write form. WRITE-only generators (forms) reuse
17
35
  // `emitsWriteArtifacts` to skip these; read-capable generators (tanstack
@@ -19,10 +37,12 @@
19
37
  //
20
38
  // Centralizing these as `emitsInstanceArtifacts` / `emitsWriteArtifacts` keeps
21
39
  // the rule in one place: a generator composes the matching guard into its
22
- // `filter` rather than re-deriving "is this abstract / read-only" ad hoc.
40
+ // `filter` rather than re-deriving "is this abstract / read-only / persisted" ad
41
+ // hoc — and a third-party generator composing the guard inherits the fix.
23
42
 
24
- import type { MetaData } from "@metaobjectsdev/metadata";
43
+ import type { MetaData, MetaObject } from "@metaobjectsdev/metadata";
25
44
  import { isProjection } from "./projection/projection-detector.js";
45
+ import { hasAnyRdbSource, hasWritableRdbSource } from "./source-detect.js";
26
46
 
27
47
  /**
28
48
  * True when `entity` is abstract (`@isAbstract: true`).
@@ -38,24 +58,30 @@ export function isAbstract(entity: MetaData): boolean {
38
58
 
39
59
  /**
40
60
  * True when `entity` should produce INSTANCE artifacts of ANY kind (read OR
41
- * write): CRUD/read hooks, grid columns, grid hooks. Abstract types are
42
- * excluded they have no instantiable representation.
61
+ * write): CRUD/read hooks, grid columns, grid hooks. Excludes abstract types
62
+ * (no instantiable representation) and sourceless objects (no route for the
63
+ * artifact to talk to — see the header note, and #248 for the doctrine).
43
64
  *
44
65
  * Read-capable generators (tanstack hooks/grids) compose this so they skip
45
- * abstract bases while still serving projections via their own
46
- * `isProjection` read-only branch.
66
+ * abstract bases while still serving VIEW-BACKED projections via their own
67
+ * `isProjection` read-only branch — a projection over a `@kind: view` source
68
+ * has a source, so it passes here and keeps its read-only hooks.
47
69
  */
48
- export function emitsInstanceArtifacts(entity: MetaData): boolean {
49
- return !isAbstract(entity);
70
+ export function emitsInstanceArtifacts(entity: MetaObject): boolean {
71
+ return !isAbstract(entity) && hasAnyRdbSource(entity);
50
72
  }
51
73
 
52
74
  /**
53
75
  * True when `entity` should produce WRITE artifacts (write forms, mutation
54
- * surfaces). Excludes both abstract types (no instance at all) and projections
55
- * (read-only views — instantiable for read, never for write).
76
+ * surfaces). Excludes abstract types (no instance at all), projections
77
+ * (read-only views — instantiable for read, never for write), and objects with
78
+ * no WRITABLE source (nothing to submit to; this is the same predicate the
79
+ * entity-file generator uses to decide whether an `Insert`/`Update` surface
80
+ * exists at all, so a form can no longer be emitted against schemas that were
81
+ * never generated).
56
82
  *
57
83
  * WRITE-only generators (e.g. the React form generator) compose this.
58
84
  */
59
- export function emitsWriteArtifacts(entity: MetaData): boolean {
60
- return !isAbstract(entity) && !isProjection(entity);
85
+ export function emitsWriteArtifacts(entity: MetaObject): boolean {
86
+ return !isAbstract(entity) && !isProjection(entity) && hasWritableRdbSource(entity);
61
87
  }
@@ -0,0 +1,51 @@
1
+ // `<Entity>.meta.ts` — the entity descriptor, with no database in the module graph.
2
+ //
3
+ // The generated UI files (hooks, grid hooks, forms) value-import exactly ONE thing
4
+ // from the entity module: the `<Entity>` descriptor const. Everything else they take
5
+ // is `import type`, which the compiler erases. But `<Entity>.ts` also constructs the
6
+ // Drizzle table at module scope, so that single value import dragged the entire ORM
7
+ // into every browser bundle — measured at 716 KB for one generated hook, containing
8
+ // `SQLiteTable` and the whole driver.
9
+ //
10
+ // Nothing in the UI path READS the table. The descriptor is plain data — `$table` is
11
+ // a string, not a table object — so this was never a semantic dependency on the
12
+ // database, only a physical one created by sharing a module. A `/* @__PURE__ */`
13
+ // annotation on the table construction does NOT help (measured: still 716 KB), so
14
+ // separating the module is the fix.
15
+ //
16
+ // Deliberately ADDITIVE. `<Entity>.ts` is untouched and still exports the descriptor,
17
+ // so every existing import keeps working and this stays a PATCH. The UI generators
18
+ // simply take the descriptor from here instead, and each emits this file itself —
19
+ // byte-identical between them, which #266 collapses — rather than depending on the
20
+ // consumer having wired an extra generator, since the entity generator is
21
+ // scaffold-and-own (ADR-0034) and cannot be changed from the package.
22
+
23
+ import { code } from "ts-poet";
24
+ import type { MetaObject } from "@metaobjectsdev/metadata";
25
+ import { GENERATED_HEADER } from "../constants.js";
26
+ import { renderEntityConstants } from "./entity-constants.js";
27
+
28
+ /** File name (no directory) of an entity's DB-free descriptor module. */
29
+ export function entityMetaFileName(entityName: string): string {
30
+ return `${entityName}.meta.ts`;
31
+ }
32
+
33
+ /** Module specifier the UI files use to reach it — a same-directory sibling. */
34
+ export function entityMetaSpecifier(entityName: string, extStyle: string | undefined): string {
35
+ return `./${entityName}.meta${extStyle === "js" ? ".js" : ""}`;
36
+ }
37
+
38
+ export function renderEntityMetaFile(entity: MetaObject, apiPrefix = ""): string {
39
+ const body = code`
40
+ // ${GENERATED_HEADER} — DO NOT EDIT.
41
+ // Source metadata: ${entity.name}
42
+ //
43
+ // Browser-safe: this module contains ONLY the entity descriptor — plain data, no
44
+ // Drizzle table and no database import of any kind. The generated UI files import it
45
+ // from here so a client bundle never pulls the ORM in. \`${entity.name}.ts\` also
46
+ // exports this descriptor, for server-side and pre-existing consumers.
47
+
48
+ ${renderEntityConstants(entity, apiPrefix)}
49
+ `;
50
+ return body.toString();
51
+ }
@@ -29,7 +29,7 @@ import type { MetaObject } from "@metaobjectsdev/metadata";
29
29
  import { type RenderContext } from "../render-context.js";
30
30
  import { entityModuleSpecifier } from "../import-path.js";
31
31
  import { GENERATED_HEADER } from "../constants.js";
32
- import { isProjection } from "../projection/projection-detector.js";
32
+ import { isProjection, isWriteThrough } from "../projection/projection-detector.js";
33
33
 
34
34
  export function renderRoutesFileHono(entity: MetaObject, ctx: RenderContext): string {
35
35
  const entityName = entity.name;
@@ -98,6 +98,16 @@ export function ${handlerName}(app: ${HonoSym}<any, any, any>, deps: { db: unkno
98
98
  // --- Vanilla / write-through entity path: full CRUD routes ---
99
99
  const tableVar = ctx.collectionName(entityName);
100
100
 
101
+ // #214: a write-through entity reads through its replica view so derived origin.*
102
+ // columns are present. Without this the Hono adapter returned rows missing every
103
+ // derived field the generated type and Zod schema promise, and a filter or sort on
104
+ // one — both ALLOWED by the generated allowlists — hit a column the table does not
105
+ // have, producing a 500. Fastify has done this since #214; Hono was simply never
106
+ // wired, exactly as it was never wired for #286's `.all()`/`.get()` fix.
107
+ const writeThrough = isWriteThrough(entity);
108
+ const camelName = entityName.charAt(0).toLowerCase() + entityName.slice(1);
109
+ const readViewLine = writeThrough ? `\n readView: ${camelName}View,` : "";
110
+
101
111
  const HonoSym = imp("t:Hono@hono");
102
112
  const mountCrudRoutesSym = imp("mountCrudRoutes@@metaobjectsdev/runtime-ts/hono");
103
113
 
@@ -108,7 +118,7 @@ import {
108
118
  ${entityName}InsertSchema,
109
119
  ${entityName}UpdateSchema,
110
120
  ${entityName}FilterAllowlist,
111
- ${entityName}SortAllowlist,
121
+ ${entityName}SortAllowlist,${writeThrough ? `\n ${camelName}View,` : ""}
112
122
  } from ${JSON.stringify(entityFileSpec)};
113
123
  `;
114
124
 
@@ -127,7 +137,7 @@ export function ${handlerName}(app: ${HonoSym}<any, any, any>, deps: { db: unkno
127
137
  app,
128
138
  path: ${pathExpr},
129
139
  db: deps.db,
130
- table: ${tableVar},
140
+ table: ${tableVar},${readViewLine}
131
141
  insertSchema: ${entityName}InsertSchema,
132
142
  updateSchema: ${entityName}UpdateSchema,
133
143
  filterAllowlist: ${entityName}FilterAllowlist,