@metaobjectsdev/codegen-ts 0.21.4 → 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.
- package/dist/api-surface.d.ts +18 -0
- package/dist/api-surface.d.ts.map +1 -0
- package/dist/api-surface.js +42 -0
- package/dist/api-surface.js.map +1 -0
- package/dist/generators/routes-file-hono.d.ts.map +1 -1
- package/dist/generators/routes-file-hono.js +35 -9
- package/dist/generators/routes-file-hono.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/instance-artifacts.d.ts +15 -9
- package/dist/instance-artifacts.d.ts.map +1 -1
- package/dist/instance-artifacts.js +37 -11
- package/dist/instance-artifacts.js.map +1 -1
- package/dist/templates/entity-meta-file.d.ts +7 -0
- package/dist/templates/entity-meta-file.d.ts.map +1 -0
- package/dist/templates/entity-meta-file.js +47 -0
- package/dist/templates/entity-meta-file.js.map +1 -0
- package/dist/templates/routes-file-hono.d.ts.map +1 -1
- package/dist/templates/routes-file-hono.js +12 -3
- package/dist/templates/routes-file-hono.js.map +1 -1
- package/package.json +8 -8
- package/src/api-surface.ts +45 -0
- package/src/generators/routes-file-hono.ts +34 -4
- package/src/index.ts +4 -0
- package/src/instance-artifacts.ts +40 -14
- package/src/templates/entity-meta-file.ts +51 -0
- package/src/templates/routes-file-hono.ts +13 -3
|
@@ -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;
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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;
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5D,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAClG,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC/F,YAAY,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGxE,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,YAAY,GACb,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAErF,YAAY,EAAE,oBAAoB,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC9P,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9G,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,YAAY,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,YAAY,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACb,YAAY,EACZ,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAEvL,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1G,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACxM,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAElG,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAGhH,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAClJ,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAOlF,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIzF,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAClH,YAAY,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,SAAS,GACV,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,kBAAkB,EAClB,eAAe,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,YAAY,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,YAAY,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AACxG,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAExG,OAAO,EAAE,yBAAyB,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAKvH,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACpB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,0BAA0B,EAC1B,eAAe,GAChB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,aAAa,EACb,eAAe,EACf,WAAW,EACX,eAAe,EACf,SAAS,EACT,aAAa,GACd,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC"}
|
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.
|
|
14
|
-
*
|
|
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:
|
|
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
|
|
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:
|
|
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":"
|
|
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
|
-
//
|
|
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.
|
|
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
|
|
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.
|
|
38
|
-
*
|
|
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
|
|
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,
|
|
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,
|
|
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":"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,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"routes-file-hono.js","sourceRoot":"","sources":["../../src/templates/routes-file-hono.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/codegen-ts",
|
|
3
|
-
"version": "0.21.
|
|
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.
|
|
115
|
-
"@metaobjectsdev/render": "0.21.
|
|
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.
|
|
127
|
-
"@metaobjectsdev/migrate-ts": "0.21.
|
|
128
|
-
"@metaobjectsdev/runtime-ts": "0.21.
|
|
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
|
|
41
|
-
|
|
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
|
-
//
|
|
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.
|
|
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
|
|
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.
|
|
42
|
-
*
|
|
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:
|
|
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
|
|
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:
|
|
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,
|