@metaobjectsdev/codegen-ts 0.15.19-rc.1 → 0.15.20
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/generators/api-model.js +5 -5
- package/dist/generators/api-model.js.map +1 -1
- package/dist/generators/output-prompt-file.d.ts.map +1 -1
- package/dist/generators/output-prompt-file.js +3 -2
- package/dist/generators/output-prompt-file.js.map +1 -1
- package/dist/generators/prompt-render-file.d.ts.map +1 -1
- package/dist/generators/prompt-render-file.js +3 -1
- package/dist/generators/prompt-render-file.js.map +1 -1
- package/dist/generators/render-helper-file.d.ts.map +1 -1
- package/dist/generators/render-helper-file.js +3 -2
- package/dist/generators/render-helper-file.js.map +1 -1
- package/dist/generators/template-doc-builder.d.ts.map +1 -1
- package/dist/generators/template-doc-builder.js +11 -5
- package/dist/generators/template-doc-builder.js.map +1 -1
- package/dist/generators/template-payload-tree.d.ts +1 -1
- package/dist/generators/template-payload-tree.d.ts.map +1 -1
- package/dist/generators/template-payload-tree.js +16 -9
- package/dist/generators/template-payload-tree.js.map +1 -1
- package/dist/generators/trace-helper-file.d.ts.map +1 -1
- package/dist/generators/trace-helper-file.js +3 -2
- package/dist/generators/trace-helper-file.js.map +1 -1
- package/dist/payload-codegen.d.ts +4 -3
- package/dist/payload-codegen.d.ts.map +1 -1
- package/dist/payload-codegen.js +21 -14
- package/dist/payload-codegen.js.map +1 -1
- package/dist/templates/extract-delegate-emitter.d.ts.map +1 -1
- package/dist/templates/extract-delegate-emitter.js +7 -10
- package/dist/templates/extract-delegate-emitter.js.map +1 -1
- package/dist/templates/extractor.d.ts.map +1 -1
- package/dist/templates/extractor.js +9 -11
- package/dist/templates/extractor.js.map +1 -1
- package/dist/templates/output-parser.d.ts.map +1 -1
- package/dist/templates/output-parser.js +8 -7
- package/dist/templates/output-parser.js.map +1 -1
- package/dist/templates/output-prompt.d.ts.map +1 -1
- package/dist/templates/output-prompt.js +6 -4
- package/dist/templates/output-prompt.js.map +1 -1
- package/dist/templates/render-helper.d.ts.map +1 -1
- package/dist/templates/render-helper.js +16 -8
- package/dist/templates/render-helper.js.map +1 -1
- package/package.json +6 -6
- package/src/generators/api-model.ts +5 -5
- package/src/generators/output-prompt-file.ts +3 -3
- package/src/generators/prompt-render-file.ts +3 -1
- package/src/generators/render-helper-file.ts +3 -3
- package/src/generators/template-doc-builder.ts +20 -6
- package/src/generators/template-payload-tree.ts +16 -11
- package/src/generators/trace-helper-file.ts +7 -2
- package/src/payload-codegen.ts +26 -15
- package/src/templates/extract-delegate-emitter.ts +7 -10
- package/src/templates/extractor.ts +9 -11
- package/src/templates/output-parser.ts +8 -8
- package/src/templates/output-prompt.ts +6 -5
- package/src/templates/render-helper.ts +16 -8
|
@@ -114,10 +114,12 @@ export function buildTemplateDocData(
|
|
|
114
114
|
const kind: "document" | "email" = isEmail ? TEMPLATE_KIND_EMAIL : TEMPLATE_KIND_DOCUMENT;
|
|
115
115
|
|
|
116
116
|
const payloadRefRaw = template.attr(TEMPLATE_ATTR_PAYLOAD_REF);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
// ADR-0042: keep the FULL ref for RESOLUTION (an FQN @payloadRef to another
|
|
118
|
+
// package must resolve exactly — the old bare-tail fallback that used to find
|
|
119
|
+
// it is gone); strip to the bare name only for DISPLAY labels.
|
|
120
|
+
const payloadRefFull =
|
|
121
|
+
typeof payloadRefRaw === "string" && payloadRefRaw.length > 0 ? payloadRefRaw : "unknown";
|
|
122
|
+
const payloadName = payloadRefFull !== "unknown" ? stripPackage(payloadRefFull) : "unknown";
|
|
121
123
|
|
|
122
124
|
const requiredTags = attrStringList(template.attr(TEMPLATE_ATTR_REQUIRED_TAGS));
|
|
123
125
|
const maxChars = readMaxChars(template.attr(TEMPLATE_ATTR_MAX_CHARS));
|
|
@@ -188,6 +190,7 @@ export function buildTemplateDocData(
|
|
|
188
190
|
layout,
|
|
189
191
|
template,
|
|
190
192
|
payloadName,
|
|
193
|
+
payloadRefFull,
|
|
191
194
|
// Document: the single @textRef (unlabeled). Email: one labeled part each.
|
|
192
195
|
refs:
|
|
193
196
|
parts !== undefined
|
|
@@ -221,7 +224,11 @@ interface BuildSectionArgs {
|
|
|
221
224
|
/** The `template.output` node whose page is being built — the FROM page for
|
|
222
225
|
* every relative href on this section. */
|
|
223
226
|
template: MetaData;
|
|
227
|
+
/** Bare payload name — DISPLAY only (labels, owner names). */
|
|
224
228
|
payloadName: string;
|
|
229
|
+
/** Full @payloadRef (FQN for a cross-package payload, bare for same-package) —
|
|
230
|
+
* used for RESOLUTION so a cross-package payload tree still resolves (ADR-0042). */
|
|
231
|
+
payloadRefFull: string;
|
|
225
232
|
refs: SourceRefSpec[];
|
|
226
233
|
}
|
|
227
234
|
|
|
@@ -236,8 +243,15 @@ interface BuildSectionArgs {
|
|
|
236
243
|
* resolved, so the caller omits the section entirely.
|
|
237
244
|
*/
|
|
238
245
|
function buildTemplateSourceSection(args: BuildSectionArgs): string | undefined {
|
|
239
|
-
const { provider, root, layout, template, payloadName, refs } = args;
|
|
240
|
-
|
|
246
|
+
const { provider, root, layout, template, payloadName, payloadRefFull, refs } = args;
|
|
247
|
+
// ADR-0042: resolve the payload tree from the FULL ref — an FQN cross-package
|
|
248
|
+
// @payloadRef resolves exactly; a bare same-package ref resolves in the
|
|
249
|
+
// template's package.
|
|
250
|
+
const tree: AnnotatePayloadField[] = buildEnrichedPayloadTree(
|
|
251
|
+
root,
|
|
252
|
+
payloadRefFull,
|
|
253
|
+
template.package ?? template.fileDefaultPackage ?? "",
|
|
254
|
+
);
|
|
241
255
|
const fromNode = docPageNode(template);
|
|
242
256
|
|
|
243
257
|
// Layout-aware field href: route through the SAME docPageHref the Payload
|
|
@@ -21,23 +21,21 @@
|
|
|
21
21
|
import {
|
|
22
22
|
type MetaObject,
|
|
23
23
|
type MetaRoot,
|
|
24
|
-
TYPE_OBJECT,
|
|
25
24
|
FIELD_SUBTYPE_OBJECT,
|
|
26
25
|
FIELD_ATTR_OBJECT_REF,
|
|
27
26
|
stripPackage,
|
|
28
|
-
|
|
27
|
+
resolveObjectRef,
|
|
29
28
|
} from "@metaobjectsdev/metadata";
|
|
30
29
|
import { isFieldRequired, neutralTypeStr } from "./docs-data-builder.js";
|
|
31
30
|
import type { AnnotatePayloadField } from "./template-source-annotate.js";
|
|
32
31
|
|
|
33
|
-
// ADR-0041: FQN-exact object resolution — a "::"-qualified @objectRef binds the exact
|
|
32
|
+
// ADR-0041/0042: FQN-exact object resolution — a "::"-qualified @objectRef binds the exact
|
|
34
33
|
// package (never a bare-tail fallback), so a same-named object.value in another package
|
|
35
|
-
// can't be wrongly bound (which would attach the wrong owner/type/link to a doc node)
|
|
34
|
+
// can't be wrongly bound (which would attach the wrong owner/type/link to a doc node); a
|
|
35
|
+
// bare ref binds the referrer's package FIRST, else a root-level object.
|
|
36
36
|
// Mirrors render-helper.ts's findObject + the CLI payload-field-tree resolver.
|
|
37
|
-
function findObject(root: MetaRoot, ref: string): MetaObject | undefined {
|
|
38
|
-
return root
|
|
39
|
-
| MetaObject
|
|
40
|
-
| undefined;
|
|
37
|
+
function findObject(root: MetaRoot, ref: string, referrerPkg = ""): MetaObject | undefined {
|
|
38
|
+
return resolveObjectRef(root, ref, referrerPkg).node as MetaObject | undefined;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
/**
|
|
@@ -54,12 +52,17 @@ function findObject(root: MetaRoot, ref: string): MetaObject | undefined {
|
|
|
54
52
|
export function buildEnrichedPayloadTree(
|
|
55
53
|
root: MetaRoot,
|
|
56
54
|
voName: string,
|
|
55
|
+
referrerPkg = "",
|
|
57
56
|
seen: ReadonlySet<string> = new Set(),
|
|
58
57
|
): AnnotatePayloadField[] {
|
|
59
58
|
if (seen.has(voName)) return [];
|
|
60
|
-
const vo: MetaObject | undefined = findObject(root, voName);
|
|
59
|
+
const vo: MetaObject | undefined = findObject(root, voName, referrerPkg);
|
|
61
60
|
if (vo === undefined) return [];
|
|
62
61
|
const owner = stripPackage(vo.name);
|
|
62
|
+
// ADR-0042: a nested @objectRef resolves in the FIELD's own declaring package
|
|
63
|
+
// (fallback below), which differs from this VO's when the field is inherited via
|
|
64
|
+
// extends from an abstract VO in another package (the bare ref was authored there).
|
|
65
|
+
const voPkg = vo.package ?? vo.fileDefaultPackage ?? "";
|
|
63
66
|
const nextSeen = new Set(seen).add(voName);
|
|
64
67
|
const out: AnnotatePayloadField[] = [];
|
|
65
68
|
for (const f of vo.fields()) {
|
|
@@ -74,8 +77,10 @@ export function buildEnrichedPayloadTree(
|
|
|
74
77
|
if (typeof ref === "string" && ref.length > 0) {
|
|
75
78
|
// Owner switches to the nested VO for its fields (the recursion below
|
|
76
79
|
// re-derives `owner` from the resolved VO's own name). Pass the FULL ref
|
|
77
|
-
// (not stripPackage)
|
|
78
|
-
|
|
80
|
+
// (not stripPackage), resolved package-locally against the FIELD's declaring
|
|
81
|
+
// package (ADR-0042 — the bare ref was authored there, not on the concrete VO).
|
|
82
|
+
const fieldPkg = f.parent?.package ?? f.parent?.fileDefaultPackage ?? voPkg;
|
|
83
|
+
node.fields = buildEnrichedPayloadTree(root, ref, fieldPkg, nextSeen);
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
out.push(node);
|
|
@@ -122,8 +122,13 @@ export const traceHelperFile = function traceHelperFile(opts?: TraceHelperOpts):
|
|
|
122
122
|
: "Format.JSON";
|
|
123
123
|
|
|
124
124
|
// Collect VO names for interface emission (dedupe via batch emitter).
|
|
125
|
-
// Both refs are guaranteed strings by the guards above.
|
|
126
|
-
|
|
125
|
+
// Both refs are guaranteed strings by the guards above. ADR-0042: a bare
|
|
126
|
+
// ref resolves in the prompt's package.
|
|
127
|
+
const interfaces = generatePayloadInterfacesBatch(
|
|
128
|
+
ctx.loadedRoot,
|
|
129
|
+
[payloadRef, responseRef],
|
|
130
|
+
prompt.package ?? prompt.fileDefaultPackage ?? "",
|
|
131
|
+
);
|
|
127
132
|
|
|
128
133
|
const requestType = payloadRef;
|
|
129
134
|
|
package/src/payload-codegen.ts
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
import {
|
|
14
14
|
type MetaData,
|
|
15
15
|
type MetaField,
|
|
16
|
-
TYPE_OBJECT,
|
|
17
16
|
TYPE_FIELD,
|
|
18
17
|
TYPE_TEMPLATE,
|
|
19
18
|
FIELD_SUBTYPE_OBJECT,
|
|
@@ -23,7 +22,7 @@ import {
|
|
|
23
22
|
TEMPLATE_ATTR_PAYLOAD_REF,
|
|
24
23
|
TEMPLATE_ATTR_TEXT_REF,
|
|
25
24
|
TEMPLATE_ATTR_FORMAT,
|
|
26
|
-
|
|
25
|
+
resolveObjectRef,
|
|
27
26
|
stripPackage,
|
|
28
27
|
} from "@metaobjectsdev/metadata";
|
|
29
28
|
import { enumValues } from "./enum-meta.js";
|
|
@@ -47,10 +46,9 @@ const SCALAR_TS: Record<string, string> = {
|
|
|
47
46
|
};
|
|
48
47
|
|
|
49
48
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return root.children().find((c) => c.type === TYPE_OBJECT && refMatchesObject(c, name));
|
|
49
|
+
// ADR-0042: resolveObjectRef gives package-local-before-root-level precedence for a bare ref, FQN-exact otherwise.
|
|
50
|
+
function findObject(root: MetaData, name: string, referrerPkg = ""): MetaData | undefined {
|
|
51
|
+
return resolveObjectRef(root, name, referrerPkg).node;
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
/**
|
|
@@ -106,12 +104,18 @@ function isFieldRequired(field: MetaData): boolean {
|
|
|
106
104
|
function emitInterface(
|
|
107
105
|
root: MetaData,
|
|
108
106
|
voRef: string,
|
|
107
|
+
referrerPkg: string,
|
|
109
108
|
emitted: Set<string>,
|
|
110
109
|
out: string[],
|
|
111
110
|
enumAliases: Set<string>,
|
|
112
111
|
): void {
|
|
113
|
-
const vo = findObject(root, voRef);
|
|
112
|
+
const vo = findObject(root, voRef, referrerPkg);
|
|
114
113
|
if (!vo) return;
|
|
114
|
+
// ADR-0042: a nested @objectRef resolves in the FIELD's OWN declaring package —
|
|
115
|
+
// which may differ from this resolved VO's package when the field is inherited
|
|
116
|
+
// via extends from an abstract VO in another package (the bare ref was authored
|
|
117
|
+
// there). Fall back to this VO's package when a field has no parent package.
|
|
118
|
+
const voPkg = vo.package ?? vo.fileDefaultPackage ?? "";
|
|
115
119
|
// FR-032/ADR-0041 — voRef may arrive as an FQN (a nested @objectRef); the emitted
|
|
116
120
|
// interface NAME must be the bare, TS-valid name. Dedupe on the bare name too, so a
|
|
117
121
|
// VO reached once by bare name and once by FQN still emits exactly once.
|
|
@@ -120,7 +124,7 @@ function emitInterface(
|
|
|
120
124
|
emitted.add(voName);
|
|
121
125
|
const aliasLines: string[] = [];
|
|
122
126
|
const lines: string[] = [`export interface ${voName} {`];
|
|
123
|
-
const refs: string[] = [];
|
|
127
|
+
const refs: { ref: string; pkg: string }[] = [];
|
|
124
128
|
for (const f of vo.children().filter((c) => c.type === TYPE_FIELD)) {
|
|
125
129
|
const { type, refVo, enumAlias } = fieldTsType(f, voName);
|
|
126
130
|
// Hoist the enum union alias above the interface, deduped across the whole
|
|
@@ -138,18 +142,21 @@ function emitInterface(
|
|
|
138
142
|
const tsType = isRequired ? type : `${type} | null`;
|
|
139
143
|
const optional = isRequired ? "" : "?";
|
|
140
144
|
lines.push(` ${f.name}${optional}: ${tsType};`);
|
|
141
|
-
|
|
145
|
+
// The nested ref resolves in the FIELD's declaring package (ADR-0042), not the
|
|
146
|
+
// resolved VO's — they differ when `f` is inherited from an abstract VO elsewhere.
|
|
147
|
+
if (refVo) refs.push({ ref: refVo, pkg: f.parent?.package ?? f.parent?.fileDefaultPackage ?? voPkg });
|
|
142
148
|
}
|
|
143
149
|
lines.push("}");
|
|
144
150
|
const block = aliasLines.length > 0 ? `${aliasLines.join("\n")}\n${lines.join("\n")}` : lines.join("\n");
|
|
145
151
|
out.push(block);
|
|
146
|
-
for (const r of refs) emitInterface(root, r, emitted, out, enumAliases);
|
|
152
|
+
for (const r of refs) emitInterface(root, r.ref, r.pkg, emitted, out, enumAliases);
|
|
147
153
|
}
|
|
148
154
|
|
|
149
|
-
/** Emit the payload `interface` (+ nested element interfaces) for an object.value view-object.
|
|
150
|
-
|
|
155
|
+
/** Emit the payload `interface` (+ nested element interfaces) for an object.value view-object.
|
|
156
|
+
* `referrerPkg` (ADR-0042) is the package a bare `voName` resolves in; pass an FQN and it is ignored. */
|
|
157
|
+
export function generatePayloadInterfaces(root: MetaData, voName: string, referrerPkg = ""): string {
|
|
151
158
|
const out: string[] = [];
|
|
152
|
-
emitInterface(root, voName, new Set<string>(), out, new Set<string>());
|
|
159
|
+
emitInterface(root, voName, referrerPkg, new Set<string>(), out, new Set<string>());
|
|
153
160
|
return out.join("\n\n") + "\n";
|
|
154
161
|
}
|
|
155
162
|
|
|
@@ -160,13 +167,17 @@ export function generatePayloadInterfaces(root: MetaData, voName: string): strin
|
|
|
160
167
|
*
|
|
161
168
|
* Returns the empty string when `voNames` is empty.
|
|
162
169
|
*/
|
|
163
|
-
export function generatePayloadInterfacesBatch(
|
|
170
|
+
export function generatePayloadInterfacesBatch(
|
|
171
|
+
root: MetaData,
|
|
172
|
+
voNames: readonly string[],
|
|
173
|
+
referrerPkg = "",
|
|
174
|
+
): string {
|
|
164
175
|
if (voNames.length === 0) return "";
|
|
165
176
|
const out: string[] = [];
|
|
166
177
|
const emitted = new Set<string>();
|
|
167
178
|
const enumAliases = new Set<string>();
|
|
168
179
|
for (const name of voNames) {
|
|
169
|
-
emitInterface(root, name, emitted, out, enumAliases);
|
|
180
|
+
emitInterface(root, name, referrerPkg, emitted, out, enumAliases);
|
|
170
181
|
}
|
|
171
182
|
return out.length === 0 ? "" : out.join("\n\n") + "\n";
|
|
172
183
|
}
|
|
@@ -21,30 +21,27 @@
|
|
|
21
21
|
|
|
22
22
|
import {
|
|
23
23
|
type MetaData,
|
|
24
|
-
TYPE_OBJECT,
|
|
25
24
|
TYPE_FIELD,
|
|
26
25
|
FIELD_SUBTYPE_OBJECT,
|
|
27
26
|
FIELD_SUBTYPE_ENUM,
|
|
28
27
|
FIELD_ATTR_OBJECT_REF,
|
|
29
|
-
|
|
30
|
-
refMatchesObject,
|
|
28
|
+
resolveObjectRef,
|
|
31
29
|
} from "@metaobjectsdev/metadata";
|
|
32
30
|
import { fields, isArray, scalarKind, jsonStringLiteral } from "./fr010-field-mapping.js";
|
|
33
31
|
|
|
34
32
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
// ADR-0042: resolveObjectRef gives package-local-before-root-level precedence for a bare ref, FQN-exact otherwise.
|
|
34
|
+
function findObject(root: MetaData, name: string, referrerPkg = ""): MetaData | undefined {
|
|
35
|
+
return resolveObjectRef(root, name, referrerPkg).node;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
/** The @objectRef target VO for a nested-object field, or undefined when unresolvable. */
|
|
40
39
|
function refVo(field: MetaData, root: MetaData): MetaData | undefined {
|
|
41
40
|
const ref = field.attr(FIELD_ATTR_OBJECT_REF);
|
|
42
41
|
if (typeof ref !== "string") return undefined;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (sep >= 0) return findObject(root, ref.slice(sep + PACKAGE_SEPARATOR.length));
|
|
47
|
-
return undefined;
|
|
42
|
+
// ADR-0042: resolve as authored — a bare ref binds the declaring VO's package,
|
|
43
|
+
// an FQN exactly; NO bare-tail fallback (never bind a same-named VO elsewhere).
|
|
44
|
+
return findObject(root, ref, field.parent?.package ?? field.parent?.fileDefaultPackage ?? "");
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
/** True iff the field is a nested object reference (field.object — distinct from the
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
import {
|
|
24
24
|
type MetaData,
|
|
25
25
|
type MetaField,
|
|
26
|
-
TYPE_OBJECT,
|
|
27
26
|
TYPE_TEMPLATE,
|
|
28
27
|
TEMPLATE_SUBTYPE_OUTPUT,
|
|
29
28
|
FIELD_SUBTYPE_OBJECT,
|
|
@@ -32,8 +31,7 @@ import {
|
|
|
32
31
|
FIELD_ATTR_REQUIRED,
|
|
33
32
|
TEMPLATE_ATTR_PAYLOAD_REF,
|
|
34
33
|
TEMPLATE_ATTR_FORMAT,
|
|
35
|
-
|
|
36
|
-
refMatchesObject,
|
|
34
|
+
resolveObjectRef,
|
|
37
35
|
} from "@metaobjectsdev/metadata";
|
|
38
36
|
import { fields, isArray } from "./fr010-field-mapping.js";
|
|
39
37
|
import { mirrorName } from "./extract-delegate-emitter.js";
|
|
@@ -41,8 +39,9 @@ import { enumUnionAliasName } from "./inferred-types.js";
|
|
|
41
39
|
import { enumValues } from "../enum-meta.js";
|
|
42
40
|
|
|
43
41
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
// ADR-0042: resolveObjectRef gives package-local-before-root-level precedence for a bare ref, FQN-exact otherwise.
|
|
43
|
+
function findObject(root: MetaData, name: string, referrerPkg = ""): MetaData | undefined {
|
|
44
|
+
return resolveObjectRef(root, name, referrerPkg).node;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
@@ -54,11 +53,9 @@ function findTemplate(root: MetaData, name: string): MetaData | undefined {
|
|
|
54
53
|
function refVo(field: MetaData, root: MetaData): MetaData | undefined {
|
|
55
54
|
const ref = field.attr(FIELD_ATTR_OBJECT_REF);
|
|
56
55
|
if (typeof ref !== "string") return undefined;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (sep >= 0) return findObject(root, ref.slice(sep + PACKAGE_SEPARATOR.length));
|
|
61
|
-
return undefined;
|
|
56
|
+
// ADR-0042: resolve as authored — a bare ref binds the declaring VO's package,
|
|
57
|
+
// an FQN exactly; NO bare-tail fallback (never bind a same-named VO elsewhere).
|
|
58
|
+
return findObject(root, ref, field.parent?.package ?? field.parent?.fileDefaultPackage ?? "");
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
function isObjectField(field: MetaData): boolean {
|
|
@@ -295,7 +292,8 @@ export function renderExtractor(root: MetaData, templateName: string): string {
|
|
|
295
292
|
if (typeof payloadRef !== "string") {
|
|
296
293
|
throw new Error(`template "${templateName}" missing @payloadRef`);
|
|
297
294
|
}
|
|
298
|
-
|
|
295
|
+
// ADR-0042: a bare @payloadRef resolves in the template's package.
|
|
296
|
+
const vo = findObject(root, payloadRef, tmpl.package ?? tmpl.fileDefaultPackage ?? "");
|
|
299
297
|
if (!vo) {
|
|
300
298
|
throw new Error(`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`);
|
|
301
299
|
}
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
type MetaData,
|
|
14
|
-
TYPE_OBJECT,
|
|
15
14
|
TYPE_FIELD,
|
|
16
15
|
TYPE_TEMPLATE,
|
|
17
16
|
TEMPLATE_SUBTYPE_OUTPUT,
|
|
@@ -19,7 +18,7 @@ import {
|
|
|
19
18
|
FIELD_ATTR_OBJECT_REF,
|
|
20
19
|
TEMPLATE_ATTR_PAYLOAD_REF,
|
|
21
20
|
TEMPLATE_ATTR_FORMAT,
|
|
22
|
-
|
|
21
|
+
resolveObjectRef,
|
|
23
22
|
} from "@metaobjectsdev/metadata";
|
|
24
23
|
import {
|
|
25
24
|
nestedMirrorInterfaces,
|
|
@@ -43,10 +42,9 @@ const SCALAR_ZOD: Record<string, string> = {
|
|
|
43
42
|
};
|
|
44
43
|
|
|
45
44
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return root.children().find((c) => c.type === TYPE_OBJECT && refMatchesObject(c, name));
|
|
45
|
+
// ADR-0042: resolveObjectRef gives package-local-before-root-level precedence for a bare ref, FQN-exact otherwise.
|
|
46
|
+
function findObject(root: MetaData, name: string, referrerPkg = ""): MetaData | undefined {
|
|
47
|
+
return resolveObjectRef(root, name, referrerPkg).node;
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
@@ -67,7 +65,8 @@ function fieldZod(field: MetaData, root: MetaData, seen: ReadonlySet<string>, de
|
|
|
67
65
|
// Cycle guard — emit unknown for self-references (rare; lazy schemas not in scope for v1).
|
|
68
66
|
base = "z.unknown()";
|
|
69
67
|
} else {
|
|
70
|
-
|
|
68
|
+
// ADR-0042: a bare nested @objectRef resolves in the declaring VO's package.
|
|
69
|
+
const inner = findObject(root, refName, field.parent?.package ?? field.parent?.fileDefaultPackage ?? "");
|
|
71
70
|
base = inner ? renderObjectSchema(inner, root, new Set(seen).add(refName), depth + 1) : "z.unknown()";
|
|
72
71
|
}
|
|
73
72
|
} else {
|
|
@@ -107,7 +106,8 @@ export function renderOutputParser(root: MetaData, templateName: string): string
|
|
|
107
106
|
if (typeof payloadRef !== "string") {
|
|
108
107
|
throw new Error(`template "${templateName}" missing @payloadRef`);
|
|
109
108
|
}
|
|
110
|
-
|
|
109
|
+
// ADR-0042: a bare @payloadRef resolves in the template's package.
|
|
110
|
+
const vo = findObject(root, payloadRef, tmpl.package ?? tmpl.fileDefaultPackage ?? "");
|
|
111
111
|
if (!vo) {
|
|
112
112
|
throw new Error(`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`);
|
|
113
113
|
}
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
14
|
type MetaData,
|
|
15
|
-
TYPE_OBJECT,
|
|
16
15
|
TYPE_TEMPLATE,
|
|
17
16
|
TEMPLATE_SUBTYPE_OUTPUT,
|
|
18
17
|
TEMPLATE_ATTR_PAYLOAD_REF,
|
|
19
18
|
TEMPLATE_ATTR_FORMAT,
|
|
20
|
-
|
|
19
|
+
resolveObjectRef,
|
|
21
20
|
} from "@metaobjectsdev/metadata";
|
|
22
21
|
import { specLiteral } from "./output-format-spec-emitter.js";
|
|
23
22
|
|
|
24
23
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// ADR-0042: resolveObjectRef gives package-local-before-root-level precedence for a bare ref, FQN-exact otherwise.
|
|
25
|
+
function findObject(root: MetaData, name: string, referrerPkg = ""): MetaData | undefined {
|
|
26
|
+
return resolveObjectRef(root, name, referrerPkg).node;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
@@ -59,7 +59,8 @@ export function renderOutputPrompt(root: MetaData, templateName: string): string
|
|
|
59
59
|
if (typeof payloadRef !== "string") {
|
|
60
60
|
throw new Error(`template "${templateName}" missing @payloadRef`);
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
// ADR-0042: a bare @payloadRef resolves in the template's package.
|
|
63
|
+
const vo = findObject(root, payloadRef, tmpl.package ?? tmpl.fileDefaultPackage ?? "");
|
|
63
64
|
if (!vo) {
|
|
64
65
|
throw new Error(`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`);
|
|
65
66
|
}
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
|
|
28
28
|
import {
|
|
29
29
|
type MetaData,
|
|
30
|
-
TYPE_OBJECT,
|
|
31
30
|
TYPE_FIELD,
|
|
32
31
|
TYPE_TEMPLATE,
|
|
33
32
|
FIELD_SUBTYPE_OBJECT,
|
|
@@ -43,7 +42,7 @@ import {
|
|
|
43
42
|
TEMPLATE_ATTR_SUBJECT_REF,
|
|
44
43
|
TEMPLATE_ATTR_HTML_BODY_REF,
|
|
45
44
|
TEMPLATE_ATTR_TEXT_BODY_REF,
|
|
46
|
-
|
|
45
|
+
resolveObjectRef,
|
|
47
46
|
} from "@metaobjectsdev/metadata";
|
|
48
47
|
import {
|
|
49
48
|
verify,
|
|
@@ -54,8 +53,9 @@ import {
|
|
|
54
53
|
} from "@metaobjectsdev/render";
|
|
55
54
|
|
|
56
55
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
// ADR-0042: package-local — resolveObjectRef binds a bare @objectRef in `referrerPkg` first (else root-level), an FQN exactly.
|
|
57
|
+
function findObject(root: MetaData, name: string, referrerPkg: string): MetaData | undefined {
|
|
58
|
+
return resolveObjectRef(root, name, referrerPkg).node;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// ADR-0039: resolving — root has no super (children()==ownChildren()); a top-level object/template may itself extend, so resolve rather than work-by-accident.
|
|
@@ -74,18 +74,24 @@ function findTemplate(root: MetaData, name: string): MetaData | undefined {
|
|
|
74
74
|
function derivePayloadFieldTree(
|
|
75
75
|
root: MetaData,
|
|
76
76
|
voName: string,
|
|
77
|
+
referrerPkg: string,
|
|
77
78
|
seen: ReadonlySet<string> = new Set(),
|
|
78
79
|
): PayloadField[] {
|
|
79
80
|
if (seen.has(voName)) return [];
|
|
80
|
-
const vo = findObject(root, voName);
|
|
81
|
+
const vo = findObject(root, voName, referrerPkg);
|
|
81
82
|
if (!vo) return [];
|
|
83
|
+
// ADR-0042: a nested @objectRef resolves in the FIELD's own declaring package
|
|
84
|
+
// (fallback below), which differs from this VO's when the field is inherited via
|
|
85
|
+
// extends from an abstract VO elsewhere.
|
|
86
|
+
const voPkg = vo.package ?? vo.fileDefaultPackage ?? "";
|
|
82
87
|
const nextSeen = new Set(seen).add(voName);
|
|
83
88
|
const fields: PayloadField[] = [];
|
|
84
89
|
for (const f of vo.children().filter((c) => c.type === TYPE_FIELD)) {
|
|
85
90
|
if (f.subType === FIELD_SUBTYPE_OBJECT) {
|
|
86
91
|
const ref = f.attr(FIELD_ATTR_OBJECT_REF);
|
|
87
92
|
if (typeof ref === "string") {
|
|
88
|
-
|
|
93
|
+
const fieldPkg = f.parent?.package ?? f.parent?.fileDefaultPackage ?? voPkg;
|
|
94
|
+
fields.push({ name: f.name, fields: derivePayloadFieldTree(root, ref, fieldPkg, nextSeen) });
|
|
89
95
|
continue;
|
|
90
96
|
}
|
|
91
97
|
}
|
|
@@ -157,14 +163,16 @@ export function renderRenderHelper(
|
|
|
157
163
|
if (typeof payloadRef !== "string") {
|
|
158
164
|
throw new Error(`template "${templateName}" missing @payloadRef`);
|
|
159
165
|
}
|
|
160
|
-
|
|
166
|
+
// ADR-0042: a bare @payloadRef resolves in the template's package.
|
|
167
|
+
const tmplPkg = tmpl.package ?? tmpl.fileDefaultPackage ?? "";
|
|
168
|
+
const vo = findObject(root, payloadRef, tmplPkg);
|
|
161
169
|
if (!vo) {
|
|
162
170
|
throw new Error(
|
|
163
171
|
`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`,
|
|
164
172
|
);
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
const fields = derivePayloadFieldTree(root, payloadRef);
|
|
175
|
+
const fields = derivePayloadFieldTree(root, payloadRef, tmplPkg);
|
|
168
176
|
const ft = fieldTreeLiteral(fields);
|
|
169
177
|
const fnName = `render${templateName}`;
|
|
170
178
|
|