@metaobjectsdev/codegen-ts 1.0.0-rc.4 → 1.0.0-rc.6
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/column-mapper.d.ts +12 -0
- package/dist/column-mapper.d.ts.map +1 -1
- package/dist/column-mapper.js +16 -0
- package/dist/column-mapper.js.map +1 -1
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -1
- package/dist/generator-registry.d.ts.map +1 -1
- package/dist/generator-registry.js +1 -0
- package/dist/generator-registry.js.map +1 -1
- package/dist/generator.d.ts +15 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js.map +1 -1
- package/dist/generators/agent-docs-file.d.ts.map +1 -1
- package/dist/generators/agent-docs-file.js +12 -3
- package/dist/generators/agent-docs-file.js.map +1 -1
- package/dist/generators/agent-schema-input.d.ts +11 -0
- package/dist/generators/agent-schema-input.d.ts.map +1 -1
- package/dist/generators/agent-schema-page.d.ts.map +1 -1
- package/dist/generators/agent-schema-page.js +13 -1
- package/dist/generators/agent-schema-page.js.map +1 -1
- package/dist/generators/agent-ui-page.d.ts.map +1 -1
- package/dist/generators/agent-ui-page.js +11 -9
- package/dist/generators/agent-ui-page.js.map +1 -1
- package/dist/generators/api-model.d.ts +2 -1
- package/dist/generators/api-model.d.ts.map +1 -1
- package/dist/generators/api-model.js +12 -6
- package/dist/generators/api-model.js.map +1 -1
- package/dist/generators/barrel.d.ts.map +1 -1
- package/dist/generators/barrel.js +2 -1
- package/dist/generators/barrel.js.map +1 -1
- package/dist/generators/callable-file.d.ts.map +1 -1
- package/dist/generators/callable-file.js +2 -1
- package/dist/generators/callable-file.js.map +1 -1
- package/dist/generators/docs-data-builder.d.ts.map +1 -1
- package/dist/generators/docs-data-builder.js +6 -5
- package/dist/generators/docs-data-builder.js.map +1 -1
- package/dist/generators/entity-file.d.ts.map +1 -1
- package/dist/generators/entity-file.js +2 -1
- package/dist/generators/entity-file.js.map +1 -1
- package/dist/generators/names-file.d.ts +22 -1
- package/dist/generators/names-file.d.ts.map +1 -1
- package/dist/generators/names-file.js +13 -18
- package/dist/generators/names-file.js.map +1 -1
- package/dist/generators/queries-file.d.ts.map +1 -1
- package/dist/generators/queries-file.js +2 -1
- package/dist/generators/queries-file.js.map +1 -1
- package/dist/generators/render-helper-file.js +1 -1
- package/dist/generators/render-helper-file.js.map +1 -1
- package/dist/generators/requirements-markdown.d.ts.map +1 -1
- package/dist/generators/requirements-markdown.js +26 -1
- package/dist/generators/requirements-markdown.js.map +1 -1
- package/dist/generators/routes-file-hono.d.ts.map +1 -1
- package/dist/generators/routes-file-hono.js +2 -1
- package/dist/generators/routes-file-hono.js.map +1 -1
- package/dist/generators/routes-file.d.ts.map +1 -1
- package/dist/generators/routes-file.js +2 -1
- package/dist/generators/routes-file.js.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/metaobjects-config.d.ts +10 -0
- package/dist/metaobjects-config.d.ts.map +1 -1
- package/dist/metaobjects-config.js +14 -1
- package/dist/metaobjects-config.js.map +1 -1
- package/dist/names.d.ts.map +1 -1
- package/dist/names.js +5 -4
- package/dist/names.js.map +1 -1
- package/dist/overwrite-policy.d.ts +23 -9
- package/dist/overwrite-policy.d.ts.map +1 -1
- package/dist/overwrite-policy.js +48 -0
- package/dist/overwrite-policy.js.map +1 -1
- package/dist/runner.d.ts +24 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +143 -13
- package/dist/runner.js.map +1 -1
- package/dist/templates/callable-file.d.ts.map +1 -1
- package/dist/templates/callable-file.js +2 -1
- package/dist/templates/callable-file.js.map +1 -1
- package/dist/templates/drizzle-schema.d.ts.map +1 -1
- package/dist/templates/drizzle-schema.js +39 -14
- package/dist/templates/drizzle-schema.js.map +1 -1
- package/dist/templates/entity-file.d.ts.map +1 -1
- package/dist/templates/entity-file.js +4 -2
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/filter-allowlist.d.ts.map +1 -1
- package/dist/templates/filter-allowlist.js +10 -6
- package/dist/templates/filter-allowlist.js.map +1 -1
- package/dist/templates/filter-shared.d.ts +42 -1
- package/dist/templates/filter-shared.d.ts.map +1 -1
- package/dist/templates/filter-shared.js +68 -5
- package/dist/templates/filter-shared.js.map +1 -1
- package/dist/templates/inferred-types.d.ts.map +1 -1
- package/dist/templates/inferred-types.js +9 -6
- package/dist/templates/inferred-types.js.map +1 -1
- package/dist/templates/projection-decl.d.ts.map +1 -1
- package/dist/templates/projection-decl.js +4 -2
- package/dist/templates/projection-decl.js.map +1 -1
- package/dist/templates/queries-file.d.ts.map +1 -1
- package/dist/templates/queries-file.js +6 -5
- package/dist/templates/queries-file.js.map +1 -1
- package/dist/templates/relations-block.d.ts.map +1 -1
- package/dist/templates/relations-block.js +2 -1
- package/dist/templates/relations-block.js.map +1 -1
- package/dist/templates/render-helper.d.ts +12 -1
- package/dist/templates/render-helper.d.ts.map +1 -1
- package/dist/templates/render-helper.js +30 -7
- package/dist/templates/render-helper.js.map +1 -1
- package/dist/templates/routes-file-hono.d.ts.map +1 -1
- package/dist/templates/routes-file-hono.js +2 -1
- package/dist/templates/routes-file-hono.js.map +1 -1
- package/dist/templates/routes-file.d.ts.map +1 -1
- package/dist/templates/routes-file.js +18 -10
- package/dist/templates/routes-file.js.map +1 -1
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +7 -4
- package/dist/templates/zod-validators.js.map +1 -1
- package/dist/ui-tier-gate.d.ts +44 -0
- package/dist/ui-tier-gate.d.ts.map +1 -0
- package/dist/ui-tier-gate.js +68 -0
- package/dist/ui-tier-gate.js.map +1 -0
- package/package.json +6 -6
- package/src/column-mapper.ts +17 -0
- package/src/constants.ts +11 -0
- package/src/generator-registry.ts +1 -0
- package/src/generator.ts +15 -0
- package/src/generators/agent-docs-file.ts +11 -2
- package/src/generators/agent-schema-input.ts +11 -0
- package/src/generators/agent-schema-page.ts +14 -1
- package/src/generators/agent-ui-page.ts +10 -10
- package/src/generators/api-model.ts +14 -7
- package/src/generators/barrel.ts +2 -1
- package/src/generators/callable-file.ts +2 -1
- package/src/generators/docs-data-builder.ts +6 -5
- package/src/generators/entity-file.ts +2 -1
- package/src/generators/names-file.ts +34 -4
- package/src/generators/queries-file.ts +2 -1
- package/src/generators/render-helper-file.ts +1 -1
- package/src/generators/requirements-markdown.ts +28 -1
- package/src/generators/routes-file-hono.ts +2 -1
- package/src/generators/routes-file.ts +2 -1
- package/src/index.ts +23 -7
- package/src/metaobjects-config.ts +20 -1
- package/src/names.ts +5 -4
- package/src/overwrite-policy.ts +62 -11
- package/src/reference/barrel.ts +2 -1
- package/src/reference/entity.ts +2 -2
- package/src/reference/names.ts +30 -4
- package/src/reference/queries.ts +3 -3
- package/src/reference/routes-hono.ts +2 -1
- package/src/reference/routes.ts +2 -1
- package/src/runner.ts +162 -12
- package/src/templates/callable-file.ts +2 -1
- package/src/templates/drizzle-schema.ts +43 -13
- package/src/templates/entity-file.ts +4 -2
- package/src/templates/filter-allowlist.ts +9 -6
- package/src/templates/filter-shared.ts +91 -6
- package/src/templates/inferred-types.ts +9 -6
- package/src/templates/projection-decl.ts +4 -2
- package/src/templates/queries-file.ts +6 -5
- package/src/templates/relations-block.ts +2 -1
- package/src/templates/render-helper.ts +31 -6
- package/src/templates/routes-file-hono.ts +2 -1
- package/src/templates/routes-file.ts +18 -10
- package/src/templates/zod-validators.ts +7 -4
- package/src/ui-tier-gate.ts +79 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { Generator, GenContext, EmittedFile } from "../generator.js";
|
|
2
2
|
import { entityOutputPath, crossEntitySpecifier } from "../import-path.js";
|
|
3
|
+
import { NAMES_FILE_SUFFIX } from "../constants.js";
|
|
3
4
|
import { renderNamesDecl } from "../templates/names-decl.js";
|
|
4
5
|
import { namesArtifactSuperOf, resolveObjectNames } from "../names.js";
|
|
5
6
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
7
|
+
import { effectivePackage } from "../docs-paths.js";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* §A1/§A2/§A6 — `<Entity>Names`: the physical database names for one object, as constants a
|
|
@@ -18,8 +20,29 @@ import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
|
18
20
|
* artifact is a MINOR under docs/compatibility-policy.md and adds zero bytes to existing
|
|
19
21
|
* files, where a flag would move every $table-carrying golden for the same functionality.
|
|
20
22
|
*/
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
+
export interface NamesFileOpts {
|
|
24
|
+
/**
|
|
25
|
+
* Narrow which objects get a names artifact. ANDed with the generator's own
|
|
26
|
+
* gates, so it can only narrow.
|
|
27
|
+
*
|
|
28
|
+
* A multi-package model is the reason this exists: one metadata tree can drive
|
|
29
|
+
* several consumers (a TypeScript data layer, a wire protocol, a JVM rail), and
|
|
30
|
+
* only some of those objects belong to the tier being generated. Without a
|
|
31
|
+
* filter, wiring this generator emitted an artifact for every persistable object
|
|
32
|
+
* in the tree — including the ones another rail owns — while every sibling
|
|
33
|
+
* generator carried `filter` and narrowed correctly.
|
|
34
|
+
*
|
|
35
|
+
* Note the abstract bases a MATCHED object extends are still emitted, filter or
|
|
36
|
+
* not: the matched object's own artifact `extends` them, so excluding them would
|
|
37
|
+
* emit an artifact whose import does not resolve.
|
|
38
|
+
*/
|
|
39
|
+
filter?: (entity: MetaObject) => boolean;
|
|
40
|
+
/** Named output target, as on every other generator. */
|
|
41
|
+
target?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function namesFile(opts?: NamesFileOpts): Generator {
|
|
45
|
+
const generator: Generator = {
|
|
23
46
|
name: "names",
|
|
24
47
|
// §A6 — the marker the runner aggregates into ResolvedGenConfig.includeNames, so the
|
|
25
48
|
// entity generator can tell whether this artifact will exist. Exactly the mechanism
|
|
@@ -39,13 +62,13 @@ export function namesFile(): Generator {
|
|
|
39
62
|
// its entity sits at <pkg>/<Entity>.ts — an unresolvable import, and a hard
|
|
40
63
|
// conflicting-duplicate-path failure as soon as two packages declare a
|
|
41
64
|
// same-bare-named entity.
|
|
42
|
-
entityOutputPath(layout, obj
|
|
65
|
+
entityOutputPath(layout, effectivePackage(obj), `${obj.name}${NAMES_FILE_SUFFIX}`);
|
|
43
66
|
|
|
44
67
|
const superSpecifierFor = (obj: MetaObject): string | undefined => {
|
|
45
68
|
const sup = namesArtifactSuperOf(obj);
|
|
46
69
|
return sup === undefined
|
|
47
70
|
? undefined
|
|
48
|
-
: crossEntitySpecifier(layout, obj
|
|
71
|
+
: crossEntitySpecifier(layout, effectivePackage(obj), effectivePackage(sup), `${sup.name}.names`, extStyle);
|
|
49
72
|
};
|
|
50
73
|
|
|
51
74
|
const out: EmittedFile[] = [];
|
|
@@ -95,4 +118,11 @@ export function namesFile(): Generator {
|
|
|
95
118
|
return out;
|
|
96
119
|
},
|
|
97
120
|
};
|
|
121
|
+
if (opts?.filter) {
|
|
122
|
+
generator.filter = opts.filter;
|
|
123
|
+
}
|
|
124
|
+
if (opts?.target) {
|
|
125
|
+
generator.target = opts.target;
|
|
126
|
+
}
|
|
127
|
+
return generator;
|
|
98
128
|
}
|
|
@@ -5,6 +5,7 @@ import { isTphSubtype } from "../templates/zod-validators.js";
|
|
|
5
5
|
import { hasAnyRdbSource } from "../source-detect.js";
|
|
6
6
|
import { formatTs } from "../format.js";
|
|
7
7
|
import { entityOutputPath } from "../import-path.js";
|
|
8
|
+
import { effectivePackage } from "../docs-paths.js";
|
|
8
9
|
|
|
9
10
|
export interface QueriesFileOpts {
|
|
10
11
|
filter?: (entity: MetaObject) => boolean;
|
|
@@ -40,7 +41,7 @@ export const queriesFile = function queriesFile(opts?: QueriesFileOpts): Generat
|
|
|
40
41
|
throw new Error("queries-file: renderContext is required (provided by runGen)");
|
|
41
42
|
}
|
|
42
43
|
return {
|
|
43
|
-
path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity
|
|
44
|
+
path: entityOutputPath(ctx.config.outputLayout ?? "flat", effectivePackage(entity), `${entity.name}.queries.ts`),
|
|
44
45
|
content: await formatTs(renderQueriesFile(entity, ctx.renderContext)),
|
|
45
46
|
};
|
|
46
47
|
}),
|
|
@@ -64,7 +64,7 @@ export const renderHelper = function renderHelper(opts?: RenderHelperOpts): Gene
|
|
|
64
64
|
// renderRenderHelper THROWS (fails codegen) on a mustache↔VO drift —
|
|
65
65
|
// intentionally NOT caught: a drifted template is a build error.
|
|
66
66
|
path: `${dirPrefix}${t.name}.render.ts`,
|
|
67
|
-
content: renderRenderHelper(root, t.name, provider),
|
|
67
|
+
content: renderRenderHelper(root, t.name, provider, ctx.config.extStyle ?? "js"),
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
70
|
return files;
|
|
@@ -47,10 +47,37 @@ function heading(depth: number): string {
|
|
|
47
47
|
*/
|
|
48
48
|
function headingLine(r: RequirementRow): string {
|
|
49
49
|
const title = r.title?.replace(/\s+/g, " ").trim();
|
|
50
|
-
const label =
|
|
50
|
+
const label =
|
|
51
|
+
title === undefined || title === "" || titleRestatesLeaf(r.path, title)
|
|
52
|
+
? ""
|
|
53
|
+
: ` — ${title}`;
|
|
51
54
|
return `${heading(r.depth)} ${r.path}${label}`;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
/**
|
|
58
|
+
* True when the title says nothing the path's LEAF SEGMENT does not already say.
|
|
59
|
+
*
|
|
60
|
+
* Measured on a hand-curated 262-entry ledger: **64 headings (24%)** read
|
|
61
|
+
* `## security — Security`, `### security.integrity — Integrity`. That is not bad
|
|
62
|
+
* authoring — `title` is chartered as "a short display label", and for a node called
|
|
63
|
+
* `integrity` the honest label IS "Integrity". The redundancy is in the RENDER, so
|
|
64
|
+
* the render is what changes.
|
|
65
|
+
*
|
|
66
|
+
* Only the LEAF is compared, never the whole path: a node `security.integrity`
|
|
67
|
+
* titled "Data Integrity" keeps its title, and one titled "Integrity" loses it. And
|
|
68
|
+
* the path always survives — dropping the path instead would break the two
|
|
69
|
+
* properties the heading is built on (it is unique by construction, so anchors
|
|
70
|
+
* cannot collide, and every sibling surface names a requirement by it).
|
|
71
|
+
*
|
|
72
|
+
* Comparison is case- and separator-insensitive so `data-integrity` / "Data
|
|
73
|
+
* Integrity" / "data integrity" all count as the same word.
|
|
74
|
+
*/
|
|
75
|
+
function titleRestatesLeaf(path: string, title: string): boolean {
|
|
76
|
+
const normalize = (s: string): string => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
77
|
+
const leaf = path.slice(path.lastIndexOf(".") + 1);
|
|
78
|
+
return normalize(leaf) === normalize(title);
|
|
79
|
+
}
|
|
80
|
+
|
|
54
81
|
/** The one-line fact bar: the attrs that are scannable rather than readable. */
|
|
55
82
|
function facts(r: RequirementRow): string {
|
|
56
83
|
const parts: string[] = [`\`${r.subType}\``];
|
|
@@ -6,6 +6,7 @@ import { formatTs } from "../format.js";
|
|
|
6
6
|
import { entityOutputPath } from "../import-path.js";
|
|
7
7
|
import { isTphSubtype } from "../templates/zod-validators.js";
|
|
8
8
|
import { resolveExpose, type ExposeOption } from "../routes-expose.js";
|
|
9
|
+
import { effectivePackage } from "../docs-paths.js";
|
|
9
10
|
|
|
10
11
|
export interface RoutesFileHonoOpts {
|
|
11
12
|
filter?: (entity: MetaObject) => boolean;
|
|
@@ -87,7 +88,7 @@ export const routesFileHono = function routesFileHono(opts?: RoutesFileHonoOpts)
|
|
|
87
88
|
return {
|
|
88
89
|
path: entityOutputPath(
|
|
89
90
|
ctx.config.outputLayout ?? "flat",
|
|
90
|
-
entity
|
|
91
|
+
effectivePackage(entity),
|
|
91
92
|
`${entity.name}.routes.hono.ts`,
|
|
92
93
|
),
|
|
93
94
|
content: await formatTs(renderRoutesFileHono(entity, ctx.renderContext, resolveExpose(entity, opts?.expose))),
|
|
@@ -6,6 +6,7 @@ import { hasAnyRdbSource } from "../source-detect.js";
|
|
|
6
6
|
import { formatTs } from "../format.js";
|
|
7
7
|
import { entityOutputPath } from "../import-path.js";
|
|
8
8
|
import { resolveExpose, type ExposeOption } from "../routes-expose.js";
|
|
9
|
+
import { effectivePackage } from "../docs-paths.js";
|
|
9
10
|
|
|
10
11
|
export interface RoutesFileOpts {
|
|
11
12
|
filter?: (entity: MetaObject) => boolean;
|
|
@@ -49,7 +50,7 @@ export const routesFile = function routesFile(opts?: RoutesFileOpts): Generator
|
|
|
49
50
|
throw new Error("routes-file: renderContext is required (provided by runGen)");
|
|
50
51
|
}
|
|
51
52
|
return {
|
|
52
|
-
path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity
|
|
53
|
+
path: entityOutputPath(ctx.config.outputLayout ?? "flat", effectivePackage(entity), `${entity.name}.routes.ts`),
|
|
53
54
|
content: await formatTs(renderRoutesFile(entity, ctx.renderContext, resolveExpose(entity, opts?.expose))),
|
|
54
55
|
};
|
|
55
56
|
}),
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,10 @@ export type { RunGenOpts, RunGenResult } from "./runner.js";
|
|
|
8
8
|
|
|
9
9
|
export type { Generator, GenContext, EmittedFile, GeneratorFactory } from "./generator.js";
|
|
10
10
|
export { perEntity, perPackage, perModel, oncePerRun } from "./generator.js";
|
|
11
|
+
// The one aggregation of the UI-tier markers. Exported because `meta docs` is the
|
|
12
|
+
// SECOND door onto `agent/ui.md` and must answer "does this run emit a UI tier?"
|
|
13
|
+
// with the same function the gen runner uses, not a second derivation of it.
|
|
14
|
+
export { runEmitsUiTier, runEmitsHonoRoutes, UI_TIER_GENERATOR_NAMES } from "./ui-tier-gate.js";
|
|
11
15
|
|
|
12
16
|
// SP-1 declarative Mustache template-codegen — scope walks, neutral data dict,
|
|
13
17
|
// output-pattern, and the JSON template-spec the CLI ports reuse.
|
|
@@ -42,7 +46,7 @@ export { defineConfig, normalizeConfig, resolveGenerators, resolveDocsConfig } f
|
|
|
42
46
|
// The dialect every generator falls back to when a config declares none. Exported because
|
|
43
47
|
// `meta docs` must apply the SAME default `normalizeConfig` does — a command that resolved
|
|
44
48
|
// the dialect differently would document a schema the toolchain does not produce.
|
|
45
|
-
export { DEFAULT_DIALECT } from "./metaobjects-config.js";
|
|
49
|
+
export { DEFAULT_DIALECT, DEFAULT_DOCS_DIR } from "./metaobjects-config.js";
|
|
46
50
|
// The runner's own "does this model need a dialect?" guard. `meta docs` must ask it rather
|
|
47
51
|
// than defaulting, because DEFAULT_DIALECT is inert and a DB project with no dialect is one
|
|
48
52
|
// `meta gen` REFUSES — documenting it as sqlite states an answer the toolchain never gave.
|
|
@@ -50,7 +54,7 @@ export { dbEmittingObjects, missingDialectMessage } from "./db-emitting.js";
|
|
|
50
54
|
export { apiLabel } from "./generators/api-label.js";
|
|
51
55
|
|
|
52
56
|
export type { ColumnSpec, DefaultExpr } from "./column-mapper.js";
|
|
53
|
-
export { mapColumnType } from "./column-mapper.js";
|
|
57
|
+
export { mapColumnType, PG_IDENTITY_CAPABLE_FNS } from "./column-mapper.js";
|
|
54
58
|
|
|
55
59
|
export type { PkInfo } from "./pk-resolver.js";
|
|
56
60
|
export { buildPkMap } from "./pk-resolver.js";
|
|
@@ -68,7 +72,7 @@ export type {
|
|
|
68
72
|
BaselineMode,
|
|
69
73
|
DecideAndWriteOpts,
|
|
70
74
|
} from "./overwrite-policy.js";
|
|
71
|
-
export { decideAndWrite, GitMissingError } from "./overwrite-policy.js";
|
|
75
|
+
export { decideAndWrite, GitMissingError, WRITE_STATUSES } from "./overwrite-policy.js";
|
|
72
76
|
// The committed half of `.gen-state`. Exported for `verify --codegen`, which needs
|
|
73
77
|
// the same "is this still exactly what the generator wrote?" evidence the write path
|
|
74
78
|
// uses — without it the gate cannot tell a preserved hand edit from stale output.
|
|
@@ -78,12 +82,17 @@ export { decideAndWrite, GitMissingError } from "./overwrite-policy.js";
|
|
|
78
82
|
export { contentHash, readGeneratedHash, listGeneratedPaths } from "./overwrite-policy.js";
|
|
79
83
|
|
|
80
84
|
export { CodegenError } from "./errors.js";
|
|
81
|
-
export { GENERATED_HEADER, DEFAULT_OUT_DIR, RETIRED_CODEGEN_ATTRS, type RetiredCodegenAttr } from "./constants.js";
|
|
85
|
+
export { GENERATED_HEADER, NAMES_FILE_SUFFIX, DEFAULT_OUT_DIR, RETIRED_CODEGEN_ATTRS, type RetiredCodegenAttr } from "./constants.js";
|
|
82
86
|
export { warnRetiredCodegenAttrs } from "./retired-codegen-attrs.js";
|
|
83
87
|
|
|
84
88
|
export { formatTs } from "./format.js";
|
|
85
89
|
|
|
86
|
-
export { pluralize, columnNameFromField, tableNameFromEntity, viewNameFromProjection } from "./naming.js";
|
|
90
|
+
export { pluralize, columnNameFromField, tableNameFromEntity, viewNameFromProjection, routesHandlerName } from "./naming.js";
|
|
91
|
+
// routesHandlerName is public for the same reason the routes-expose members below are: the
|
|
92
|
+
// routes reference template tells an adopter retargeting to another HTTP framework to copy
|
|
93
|
+
// `renderRoutesFile`'s body out of the package source, and that body names this. See the
|
|
94
|
+
// owned-composition-imports gate in test/ — it derives the required set from that body rather
|
|
95
|
+
// than trusting this list to stay complete.
|
|
87
96
|
|
|
88
97
|
export { packageToPath, entityOutputPath, crossEntitySpecifier, barrelEntrySpecifier, relativeModuleSpecifier, entityModuleSpecifier, siblingSpecifier, barrelModuleSpecifier } from "./import-path.js";
|
|
89
98
|
export type { OutputLayout, ResolvedTarget } from "./import-path.js";
|
|
@@ -122,7 +131,14 @@ export { isTphSubtype, tphDiscriminatorBase, tphDiscriminatorPin } from "./templ
|
|
|
122
131
|
// emitter, say) marks a column sortable by ASKING the server's rule rather than
|
|
123
132
|
// reimplementing its three branches out of tree. A hand-copied predicate is how the
|
|
124
133
|
// grid came to offer headers the allowlist rejects (#352/#354).
|
|
125
|
-
export {
|
|
134
|
+
export {
|
|
135
|
+
isSortableField,
|
|
136
|
+
sortableFields,
|
|
137
|
+
declaredSortDefaultOrder,
|
|
138
|
+
sortDefaultOrder,
|
|
139
|
+
resolveGridDefaultSort,
|
|
140
|
+
} from "./templates/filter-shared.js";
|
|
141
|
+
export type { SortOrder, GridDefaultSort } from "./templates/filter-shared.js";
|
|
126
142
|
|
|
127
143
|
// ADR-0034 reference-template composition helpers. Promoted to the public engine
|
|
128
144
|
// surface so a COPIED reference generator (src/reference/*.ts → consumer's
|
|
@@ -194,7 +210,7 @@ export { renderEntityConstants, resourcePath } from "./templates/entity-constant
|
|
|
194
210
|
export { renderQueriesFile } from "./templates/queries-file.js";
|
|
195
211
|
// #348 — which CRUD verbs a generated routes file mounts. Public because an OWNED
|
|
196
212
|
// routes generator (ADR-0034) composes the same render call and needs the same option.
|
|
197
|
-
export { CRUD_VERBS, resolveExpose, intersectExpose, exposeLine } from "./routes-expose.js";
|
|
213
|
+
export { CRUD_VERBS, TPH_POLYMORPHIC_VERBS, resolveExpose, intersectExpose, exposeLine } from "./routes-expose.js";
|
|
198
214
|
export type { CrudVerb, ExposeOption } from "./routes-expose.js";
|
|
199
215
|
export { renderRoutesFile } from "./templates/routes-file.js";
|
|
200
216
|
export { renderRoutesFileHono } from "./templates/routes-file-hono.js";
|
|
@@ -63,6 +63,11 @@ export interface ResolvedGenConfig {
|
|
|
63
63
|
* Undefined ⇒ false. Templates read the same fact off `RenderContext.includeNames`,
|
|
64
64
|
* which the runner sets from this same aggregation. */
|
|
65
65
|
includeNames?: boolean;
|
|
66
|
+
/** Whether any CLIENT UI generator (form, hook, grid, columns) is active in the
|
|
67
|
+
* run — aggregated by the runner from the suite's `emitsUiTier` markers.
|
|
68
|
+
* `agent/ui.md` reads this to decide whether a UI tier exists to describe;
|
|
69
|
+
* a metadata predicate can only say a UI *could* be generated. Undefined ⇒ false. */
|
|
70
|
+
includeUiTier?: boolean;
|
|
66
71
|
/**
|
|
67
72
|
* FR-019 / ADR-0026: the module specifier from which an externally-PROVIDED
|
|
68
73
|
* shared enum (`@provided: true` on an abstract package-level `field.enum`) is
|
|
@@ -289,13 +294,27 @@ export interface ResolvedDocsConfig {
|
|
|
289
294
|
/** Merge the config `docs:` block with CLI overrides over documented defaults.
|
|
290
295
|
* `fallbackLayout` is the project's `outputLayout` so docs default to the same
|
|
291
296
|
* page placement as codegen when `docs.layout` is unset. */
|
|
297
|
+
/**
|
|
298
|
+
* Where `meta docs` writes when nothing says otherwise. A SUB-directory on purpose: the
|
|
299
|
+
* generated pages are MetaObjects' to own and overwrite, and `docs/` as a whole is not.
|
|
300
|
+
*/
|
|
301
|
+
export const DEFAULT_DOCS_DIR = "./docs/generated";
|
|
302
|
+
|
|
292
303
|
export function resolveDocsConfig(
|
|
293
304
|
block: DocsConfig | undefined,
|
|
294
305
|
cli: Partial<ResolvedDocsConfig>,
|
|
295
306
|
fallbackLayout: OutputLayout,
|
|
296
307
|
): ResolvedDocsConfig {
|
|
297
308
|
return {
|
|
298
|
-
|
|
309
|
+
// F57 — NOT "./docs". `docs/` is the human documentation folder in most repos: one
|
|
310
|
+
// estate's held a business-strategy .docx, product screenshots, email drafts and an
|
|
311
|
+
// analytics roadmap, and a bare `meta docs` scattered 29 generated pages through it
|
|
312
|
+
// and wanted to own `docs/README.md`. The gate's own design language is right —
|
|
313
|
+
// "docs.outDir is a directory, not a namespace MetaObjects owns" — and that is
|
|
314
|
+
// precisely the argument for not defaulting into the most-owned directory name in
|
|
315
|
+
// the ecosystem. `meta init` scaffolds this key explicitly so a new project's choice
|
|
316
|
+
// is visible rather than implied.
|
|
317
|
+
outDir: cli.outDir ?? block?.outDir ?? DEFAULT_DOCS_DIR,
|
|
299
318
|
layout: cli.layout ?? block?.layout ?? fallbackLayout,
|
|
300
319
|
baseUrl: cli.baseUrl ?? block?.baseUrl ?? "",
|
|
301
320
|
// `requirements` defaults ON. Safe ONLY because requirementsFile() emits ZERO
|
package/src/names.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { code, imp, type Code } from "ts-poet";
|
|
27
27
|
import { crossEntitySpecifier } from "./import-path.js";
|
|
28
28
|
import type { RenderContext } from "./render-context.js";
|
|
29
|
+
import { effectivePackage } from "./docs-paths.js";
|
|
29
30
|
|
|
30
31
|
export interface FieldNames { readonly name: string; readonly column: string; }
|
|
31
32
|
|
|
@@ -335,7 +336,7 @@ export function resolveObjectNames(
|
|
|
335
336
|
const superObj = namesArtifactSuperOf(obj);
|
|
336
337
|
const superNames: SuperNames | undefined = superObj === undefined
|
|
337
338
|
? undefined
|
|
338
|
-
: { name: superObj.name, package: superObj
|
|
339
|
+
: { name: superObj.name, package: effectivePackage(superObj) };
|
|
339
340
|
// Identity of the resolved source NODE, not equality of the resolved strings: a
|
|
340
341
|
// divergence guard is exactly what this codebase forbids here, and the question being
|
|
341
342
|
// asked is structural — did this object declare a source, or is it using its parent's?
|
|
@@ -438,7 +439,7 @@ export function resolveSuperFragmentNames(
|
|
|
438
439
|
ownIndexes: keysOf(obj.ownLookupIndexes()),
|
|
439
440
|
superNames: superObj === undefined
|
|
440
441
|
? undefined
|
|
441
|
-
: { name: superObj.name, package: superObj
|
|
442
|
+
: { name: superObj.name, package: effectivePackage(superObj) },
|
|
442
443
|
inheritsSource: false,
|
|
443
444
|
};
|
|
444
445
|
}
|
|
@@ -466,7 +467,7 @@ export function resolveSuperFragmentNames(
|
|
|
466
467
|
export function namesRef(
|
|
467
468
|
obj: MetaObject,
|
|
468
469
|
ctx: RenderContext,
|
|
469
|
-
fromPackage: string | undefined = obj
|
|
470
|
+
fromPackage: string | undefined = effectivePackage(obj),
|
|
470
471
|
): { readonly resolved: ObjectNames; readonly symbol: Code } | undefined {
|
|
471
472
|
if (!ctx.includeNames) return undefined;
|
|
472
473
|
const resolved = resolveObjectNames(obj, ctx.columnNamingStrategy);
|
|
@@ -475,7 +476,7 @@ export function namesRef(
|
|
|
475
476
|
`${obj.name}Names@${crossEntitySpecifier(
|
|
476
477
|
ctx.selfTarget.outputLayout,
|
|
477
478
|
fromPackage,
|
|
478
|
-
obj
|
|
479
|
+
effectivePackage(obj),
|
|
479
480
|
`${obj.name}.names`,
|
|
480
481
|
ctx.extStyle,
|
|
481
482
|
)}`,
|
package/src/overwrite-policy.ts
CHANGED
|
@@ -45,20 +45,36 @@ import { spawnSync } from "node:child_process";
|
|
|
45
45
|
import { tmpdir } from "node:os";
|
|
46
46
|
import { createHash, randomBytes } from "node:crypto";
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Every outcome a write decision can have. An `as const` array rather than a bare
|
|
50
|
+
* union so a consumer that MAPS these — the CLI's reporting layer does — can be
|
|
51
|
+
* gated against the full set instead of against a second list of its own. The CLI
|
|
52
|
+
* silently folded "overwrite" into "new" for exactly as long as no test could
|
|
53
|
+
* enumerate what it was folding.
|
|
54
|
+
*/
|
|
55
|
+
export const WRITE_STATUSES = [
|
|
56
|
+
"new",
|
|
57
|
+
"unchanged",
|
|
58
|
+
"overwrite",
|
|
59
|
+
"merged",
|
|
60
|
+
"conflict",
|
|
61
|
+
"refused",
|
|
62
|
+
"skipped",
|
|
63
|
+
/** `--baseline=adopt` — the file WOULD have been refused, and instead its current
|
|
64
|
+
* content was recorded as the merge base. Nothing was written. Its own status
|
|
65
|
+
* rather than "unchanged" or "skipped" because the run's whole product is the
|
|
66
|
+
* manifest it just created: a summary that reported these as unchanged would
|
|
67
|
+
* hide the one thing the adopter has to commit. */
|
|
68
|
+
"adopted",
|
|
56
69
|
/** FR-038 §8 — deleted because it was generated by a previous run, is no longer
|
|
57
70
|
* generated, and was never edited by hand. Reported as a file outcome rather
|
|
58
71
|
* than a warning because a deletion is exactly as consequential as a write,
|
|
59
72
|
* and a run summary that lists writes but hides deletions is how a silent
|
|
60
73
|
* deletion happens. */
|
|
61
|
-
|
|
74
|
+
"removed",
|
|
75
|
+
] as const;
|
|
76
|
+
|
|
77
|
+
export type WriteStatus = (typeof WRITE_STATUSES)[number];
|
|
62
78
|
|
|
63
79
|
/**
|
|
64
80
|
* "overwrite" — default; three-way merge if .gen-state exists, else write-if-
|
|
@@ -71,8 +87,20 @@ export type MergeStrategy = "overwrite" | "skip-existing";
|
|
|
71
87
|
/** "default" — the standard three-way merge flow described in the file header.
|
|
72
88
|
* "fresh" — opt-in via `meta gen --baseline=fresh`. When .gen-state is absent
|
|
73
89
|
* but the file exists, OVERWRITE with fresh content and seed .gen-state from
|
|
74
|
-
* the fresh content (caveat 3 escape hatch).
|
|
75
|
-
|
|
90
|
+
* the fresh content (caveat 3 escape hatch).
|
|
91
|
+
* "adopt" — opt-in via `meta gen --baseline=adopt`. Same population, opposite
|
|
92
|
+
* half: where the run would REFUSE, record the file's CURRENT content as the
|
|
93
|
+
* merge base and write nothing. It exists because the refusal's leading remedy
|
|
94
|
+
* ("commit .hashes.json") could not be performed by the population it named —
|
|
95
|
+
* nothing writes a manifest until a gen succeeds, and gen refuses until one
|
|
96
|
+
* exists. `adopt` is the run that produces the file to commit.
|
|
97
|
+
*
|
|
98
|
+
* What it is NOT: protection for an edit already inside one of those files. The
|
|
99
|
+
* base becomes the edited text, so base == ours and the next regen's three-way
|
|
100
|
+
* merge takes fresh output wholesale. It protects edits made FROM THEN ON, and
|
|
101
|
+
* it guarantees that establishing the baseline writes nothing — which is what
|
|
102
|
+
* lets the content change land as its own reviewable diff afterwards. */
|
|
103
|
+
export type BaselineMode = "default" | "fresh" | "adopt";
|
|
76
104
|
|
|
77
105
|
export interface DecideAndWriteOpts {
|
|
78
106
|
strategy?: MergeStrategy;
|
|
@@ -458,6 +486,7 @@ type WriteCase =
|
|
|
458
486
|
| { kind: "no-snapshot-unchanged" }
|
|
459
487
|
| { kind: "no-snapshot-pristine-overwrite" }
|
|
460
488
|
| { kind: "no-snapshot-refused"; hasRecord: boolean }
|
|
489
|
+
| { kind: "no-snapshot-adopt"; currentText: string }
|
|
461
490
|
| { kind: "snapshot-unchanged" }
|
|
462
491
|
| { kind: "snapshot-merge-required"; snapshotText: string };
|
|
463
492
|
|
|
@@ -511,6 +540,18 @@ function classifyWrite(
|
|
|
511
540
|
|
|
512
541
|
// Either somebody edited it (hash mismatch) or we have no record of writing
|
|
513
542
|
// it at all (no hash). Both are unprovable, so fail closed.
|
|
543
|
+
//
|
|
544
|
+
// …unless the caller has explicitly adopted what is on disk. `adopt` is placed
|
|
545
|
+
// HERE, at the refusal, rather than at the top of the no-snapshot branch, and
|
|
546
|
+
// that placement is the design: it means adopting can only ever convert a
|
|
547
|
+
// refusal into a recorded baseline. Everything else — unchanged, and the
|
|
548
|
+
// pristine-file overwrite a fresh clone depends on — keeps behaving exactly as
|
|
549
|
+
// it does without the flag, so a project cannot accidentally freeze its
|
|
550
|
+
// regeneration by passing it.
|
|
551
|
+
if ((opts.baseline ?? "default") === "adopt") {
|
|
552
|
+
return { kind: "no-snapshot-adopt", currentText: current };
|
|
553
|
+
}
|
|
554
|
+
|
|
514
555
|
return {
|
|
515
556
|
kind: "no-snapshot-refused",
|
|
516
557
|
hasRecord: readGeneratedHash(genStateDir, relPath) !== undefined,
|
|
@@ -560,6 +601,8 @@ export function previewWriteStatus(
|
|
|
560
601
|
return "overwrite";
|
|
561
602
|
case "no-snapshot-refused":
|
|
562
603
|
return "refused";
|
|
604
|
+
case "no-snapshot-adopt":
|
|
605
|
+
return "adopted";
|
|
563
606
|
case "snapshot-merge-required":
|
|
564
607
|
return "overwrite";
|
|
565
608
|
}
|
|
@@ -631,6 +674,14 @@ export function decideAndWrite(
|
|
|
631
674
|
"--baseline=fresh to overwrite it and adopt fresh output as the baseline.",
|
|
632
675
|
};
|
|
633
676
|
|
|
677
|
+
case "no-snapshot-adopt":
|
|
678
|
+
// Record what is ON DISK — deliberately `kase.currentText`, never `content`.
|
|
679
|
+
// Recording fresh output would claim we wrote a file we did not, and the next
|
|
680
|
+
// run would then read the adopter's file as edited-since-generated and refuse
|
|
681
|
+
// all over again, which is the loop this mode exists to end.
|
|
682
|
+
advanceSnapshot(genStateDir, relPath, kase.currentText);
|
|
683
|
+
return { path, status: "adopted" };
|
|
684
|
+
|
|
634
685
|
case "snapshot-unchanged":
|
|
635
686
|
return { path, status: "unchanged" };
|
|
636
687
|
|
package/src/reference/barrel.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
barrelModuleSpecifier,
|
|
27
27
|
formatTs,
|
|
28
28
|
GENERATED_HEADER,
|
|
29
|
+
effectivePackage,
|
|
29
30
|
} from "@metaobjectsdev/codegen-ts";
|
|
30
31
|
|
|
31
32
|
interface BarrelEntry {
|
|
@@ -63,7 +64,7 @@ export const barrel = function barrel(opts?: BarrelOpts): Generator {
|
|
|
63
64
|
path: "index.ts",
|
|
64
65
|
content: await formatTs(
|
|
65
66
|
renderBarrel(
|
|
66
|
-
entities.map((e) => ({ name: rc.valueObjectEmittedName(e), package: e
|
|
67
|
+
entities.map((e) => ({ name: rc.valueObjectEmittedName(e), package: effectivePackage(e) })),
|
|
67
68
|
rc.extStyle,
|
|
68
69
|
rc.selfTarget,
|
|
69
70
|
rc.entityModuleTarget,
|
package/src/reference/entity.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
// primitives below, or (with a globally-installed / linked CLI, where the project and
|
|
33
33
|
// the CLI resolve ts-poet to different physical copies) every section renders
|
|
34
34
|
// standalone with its own duplicate import header.
|
|
35
|
-
import { joinCode, type Code } from "@metaobjectsdev/codegen-ts";
|
|
35
|
+
import { joinCode, type Code, effectivePackage } from "@metaobjectsdev/codegen-ts";
|
|
36
36
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
37
37
|
import {
|
|
38
38
|
perEntity,
|
|
@@ -164,7 +164,7 @@ export const entityFile = function entityFile(opts?: EntityFileOpts): Generator
|
|
|
164
164
|
return [];
|
|
165
165
|
}
|
|
166
166
|
return {
|
|
167
|
-
path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity
|
|
167
|
+
path: entityOutputPath(ctx.config.outputLayout ?? "flat", effectivePackage(entity), `${entity.name}.ts`),
|
|
168
168
|
content: await formatTs(renderEntity(entity, ctx.renderContext, { allowlists })),
|
|
169
169
|
};
|
|
170
170
|
});
|
package/src/reference/names.ts
CHANGED
|
@@ -36,14 +36,30 @@ import {
|
|
|
36
36
|
namesArtifactSuperOf,
|
|
37
37
|
renderNamesDecl,
|
|
38
38
|
resolveObjectNames,
|
|
39
|
+
NAMES_FILE_SUFFIX,
|
|
39
40
|
type EmittedFile,
|
|
40
41
|
type GenContext,
|
|
41
42
|
type Generator,
|
|
43
|
+
effectivePackage,
|
|
42
44
|
} from "@metaobjectsdev/codegen-ts";
|
|
43
45
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
44
46
|
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
+
export interface NamesFileOpts {
|
|
48
|
+
/**
|
|
49
|
+
* Narrow which objects get a names artifact. ANDed with the generator's own
|
|
50
|
+
* gates, so it can only narrow — the abstract bases a MATCHED object extends
|
|
51
|
+
* are still emitted, because the matched object's artifact `extends` them.
|
|
52
|
+
*
|
|
53
|
+
* A multi-package model is why this exists: one metadata tree can drive several
|
|
54
|
+
* consumers, and only some of its objects belong to the tier being generated.
|
|
55
|
+
*/
|
|
56
|
+
filter?: (entity: MetaObject) => boolean;
|
|
57
|
+
/** Named output target, as on every other generator. */
|
|
58
|
+
target?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function namesFile(opts?: NamesFileOpts): Generator {
|
|
62
|
+
const generator: Generator = {
|
|
47
63
|
name: "names",
|
|
48
64
|
// §A6 — the marker the runner aggregates into ResolvedGenConfig.includeNames, so the
|
|
49
65
|
// entity generator can tell whether this artifact will exist. Exactly the mechanism
|
|
@@ -63,13 +79,16 @@ export function namesFile(): Generator {
|
|
|
63
79
|
// its entity sits at <pkg>/<Entity>.ts — an unresolvable import, and a hard
|
|
64
80
|
// conflicting-duplicate-path failure as soon as two packages declare a
|
|
65
81
|
// same-bare-named entity.
|
|
66
|
-
|
|
82
|
+
// NAMES_FILE_SUFFIX, not a literal: `meta verify --codegen` treats this artifact as
|
|
83
|
+
// fail-closed (a hand edit in it IS drift, unlike every other generated file) and
|
|
84
|
+
// recognises it BY THIS SUFFIX. Rename it and you opt out of that protection.
|
|
85
|
+
entityOutputPath(layout, effectivePackage(obj), `${obj.name}${NAMES_FILE_SUFFIX}`);
|
|
67
86
|
|
|
68
87
|
const superSpecifierFor = (obj: MetaObject): string | undefined => {
|
|
69
88
|
const sup = namesArtifactSuperOf(obj);
|
|
70
89
|
return sup === undefined
|
|
71
90
|
? undefined
|
|
72
|
-
: crossEntitySpecifier(layout, obj
|
|
91
|
+
: crossEntitySpecifier(layout, effectivePackage(obj), effectivePackage(sup), `${sup.name}.names`, extStyle);
|
|
73
92
|
};
|
|
74
93
|
|
|
75
94
|
const out: EmittedFile[] = [];
|
|
@@ -122,4 +141,11 @@ export function namesFile(): Generator {
|
|
|
122
141
|
return out;
|
|
123
142
|
},
|
|
124
143
|
};
|
|
144
|
+
if (opts?.filter) {
|
|
145
|
+
generator.filter = opts.filter;
|
|
146
|
+
}
|
|
147
|
+
if (opts?.target) {
|
|
148
|
+
generator.target = opts.target;
|
|
149
|
+
}
|
|
150
|
+
return generator;
|
|
125
151
|
}
|
package/src/reference/queries.ts
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// primitives below, or (with a globally-installed / linked CLI, where the project and
|
|
31
31
|
// the CLI resolve ts-poet to different physical copies) every section renders
|
|
32
32
|
// standalone with its own duplicate import header.
|
|
33
|
-
import { code, joinCode, type Code } from "@metaobjectsdev/codegen-ts";
|
|
33
|
+
import { code, joinCode, type Code, effectivePackage } from "@metaobjectsdev/codegen-ts";
|
|
34
34
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
35
35
|
import {
|
|
36
36
|
perEntity,
|
|
@@ -71,7 +71,7 @@ function renderQueries(obj: MetaObject, ctx: RenderContext): string {
|
|
|
71
71
|
const entityFileName = entityModuleSpecifier(
|
|
72
72
|
ctx.selfTarget,
|
|
73
73
|
ctx.entityModuleTarget,
|
|
74
|
-
obj
|
|
74
|
+
effectivePackage(obj),
|
|
75
75
|
entityName,
|
|
76
76
|
ctx.extStyle,
|
|
77
77
|
);
|
|
@@ -162,7 +162,7 @@ export const queriesFile = function queriesFile(opts?: QueriesFileOpts): Generat
|
|
|
162
162
|
throw new Error("queries-file: renderContext is required (provided by runGen)");
|
|
163
163
|
}
|
|
164
164
|
return {
|
|
165
|
-
path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity
|
|
165
|
+
path: entityOutputPath(ctx.config.outputLayout ?? "flat", effectivePackage(entity), `${entity.name}.queries.ts`),
|
|
166
166
|
content: await formatTs(renderQueries(entity, ctx.renderContext)),
|
|
167
167
|
};
|
|
168
168
|
}),
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
hasAnyRdbSource,
|
|
39
39
|
formatTs,
|
|
40
40
|
entityOutputPath,
|
|
41
|
+
effectivePackage,
|
|
41
42
|
} from "@metaobjectsdev/codegen-ts";
|
|
42
43
|
|
|
43
44
|
export interface RoutesFileHonoOpts {
|
|
@@ -100,7 +101,7 @@ export const routesFileHono = function routesFileHono(opts?: RoutesFileHonoOpts)
|
|
|
100
101
|
return {
|
|
101
102
|
path: entityOutputPath(
|
|
102
103
|
ctx.config.outputLayout ?? "flat",
|
|
103
|
-
entity
|
|
104
|
+
effectivePackage(entity),
|
|
104
105
|
`${entity.name}.routes.hono.ts`,
|
|
105
106
|
),
|
|
106
107
|
content: await formatTs(renderRoutesFileHono(entity, ctx.renderContext, resolveExpose(entity, opts?.expose))),
|
package/src/reference/routes.ts
CHANGED
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
hasAnyRdbSource,
|
|
47
47
|
formatTs,
|
|
48
48
|
entityOutputPath,
|
|
49
|
+
effectivePackage,
|
|
49
50
|
} from "@metaobjectsdev/codegen-ts";
|
|
50
51
|
|
|
51
52
|
export interface RoutesFileOpts {
|
|
@@ -79,7 +80,7 @@ export const routesFile = function routesFile(opts?: RoutesFileOpts): Generator
|
|
|
79
80
|
throw new Error("routes-file: renderContext is required (provided by runGen)");
|
|
80
81
|
}
|
|
81
82
|
return {
|
|
82
|
-
path: entityOutputPath(ctx.config.outputLayout ?? "flat", entity
|
|
83
|
+
path: entityOutputPath(ctx.config.outputLayout ?? "flat", effectivePackage(entity), `${entity.name}.routes.ts`),
|
|
83
84
|
content: await formatTs(renderRoutesFile(entity, ctx.renderContext, resolveExpose(entity, opts?.expose))),
|
|
84
85
|
};
|
|
85
86
|
}),
|