@telorun/analyzer 0.72.0 → 0.74.0
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/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +76 -20
- package/dist/artifact-axes.d.ts +14 -0
- package/dist/artifact-axes.d.ts.map +1 -0
- package/dist/artifact-axes.js +12 -0
- package/dist/artifact-layer-index.d.ts +2 -2
- package/dist/artifact-layer-index.d.ts.map +1 -1
- package/dist/artifact-layer-index.js +9 -4
- package/dist/artifact-selector.d.ts +47 -21
- package/dist/artifact-selector.d.ts.map +1 -1
- package/dist/artifact-selector.js +85 -16
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +144 -113
- package/dist/call-graph.d.ts +12 -1
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +22 -0
- package/dist/catch-scope.js +1 -1
- package/dist/cel-scope-query.d.ts.map +1 -1
- package/dist/cel-scope-query.js +32 -11
- package/dist/cel-scope.d.ts.map +1 -1
- package/dist/cel-scope.js +1 -0
- package/dist/eval-paths.d.ts +36 -5
- package/dist/eval-paths.d.ts.map +1 -1
- package/dist/eval-paths.js +47 -6
- package/dist/extends-resolution.d.ts +12 -0
- package/dist/extends-resolution.d.ts.map +1 -1
- package/dist/extends-resolution.js +23 -0
- package/dist/forwarded-declaration.d.ts +26 -0
- package/dist/forwarded-declaration.d.ts.map +1 -0
- package/dist/forwarded-declaration.js +31 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/kernel-globals.d.ts.map +1 -1
- package/dist/kernel-globals.js +21 -5
- package/dist/module-alias-scope.d.ts +11 -0
- package/dist/module-alias-scope.d.ts.map +1 -1
- package/dist/module-alias-scope.js +10 -0
- package/dist/module-file-claims.d.ts +17 -1
- package/dist/module-file-claims.d.ts.map +1 -1
- package/dist/module-file-claims.js +38 -3
- package/dist/module-named-files.d.ts +72 -0
- package/dist/module-named-files.d.ts.map +1 -0
- package/dist/module-named-files.js +115 -0
- package/dist/native-entries.d.ts +83 -0
- package/dist/native-entries.d.ts.map +1 -0
- package/dist/native-entries.js +169 -0
- package/dist/nearest-name.d.ts +22 -0
- package/dist/nearest-name.d.ts.map +1 -0
- package/dist/nearest-name.js +43 -0
- package/dist/normalize-inline-resources.d.ts +41 -13
- package/dist/normalize-inline-resources.d.ts.map +1 -1
- package/dist/normalize-inline-resources.js +236 -54
- package/dist/reference-field-map.d.ts +59 -1
- package/dist/reference-field-map.d.ts.map +1 -1
- package/dist/reference-field-map.js +200 -34
- package/dist/release/destinations.d.ts +59 -0
- package/dist/release/destinations.d.ts.map +1 -0
- package/dist/release/destinations.js +75 -0
- package/dist/release/index.d.ts +6 -2
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +3 -1
- package/dist/release/ledger.d.ts +20 -11
- package/dist/release/ledger.d.ts.map +1 -1
- package/dist/release/ledger.js +43 -14
- package/dist/release/payload-digest.d.ts +2 -1
- package/dist/release/payload-digest.d.ts.map +1 -1
- package/dist/release/payload-digest.js +2 -1
- package/dist/release/release-plan.d.ts +3 -2
- package/dist/release/release-plan.d.ts.map +1 -1
- package/dist/release/release-plan.js +12 -19
- package/dist/release/workspace-config.d.ts +114 -34
- package/dist/release/workspace-config.d.ts.map +1 -1
- package/dist/release/workspace-config.js +322 -38
- package/dist/release/workspace-schema.d.ts +41 -0
- package/dist/release/workspace-schema.d.ts.map +1 -0
- package/dist/release/workspace-schema.js +77 -0
- package/dist/resolve-ref-sentinels.d.ts.map +1 -1
- package/dist/resolve-ref-sentinels.js +8 -5
- package/dist/resolve-throws-union.d.ts +25 -4
- package/dist/resolve-throws-union.d.ts.map +1 -1
- package/dist/resolve-throws-union.js +62 -32
- package/dist/resolve-zone-requirements.d.ts.map +1 -1
- package/dist/resolve-zone-requirements.js +2 -1
- package/dist/rewrite-synthetic-origins.d.ts +6 -1
- package/dist/rewrite-synthetic-origins.d.ts.map +1 -1
- package/dist/rewrite-synthetic-origins.js +107 -13
- package/dist/schema-compat.d.ts.map +1 -1
- package/dist/schema-compat.js +18 -5
- package/dist/schema-error-report.d.ts +7 -0
- package/dist/schema-error-report.d.ts.map +1 -1
- package/dist/schema-error-report.js +9 -4
- package/dist/schema-walk.d.ts +47 -13
- package/dist/schema-walk.d.ts.map +1 -1
- package/dist/schema-walk.js +150 -30
- package/dist/scope-declarations.d.ts +59 -0
- package/dist/scope-declarations.d.ts.map +1 -0
- package/dist/scope-declarations.js +45 -0
- package/dist/source-entries.d.ts +119 -0
- package/dist/source-entries.d.ts.map +1 -0
- package/dist/source-entries.js +349 -0
- package/dist/step-bodies.d.ts +24 -0
- package/dist/step-bodies.d.ts.map +1 -0
- package/dist/step-bodies.js +28 -0
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/template-body.d.ts +10 -0
- package/dist/template-body.d.ts.map +1 -1
- package/dist/template-body.js +25 -0
- package/dist/validate-cel-context.d.ts +23 -8
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +51 -18
- package/dist/validate-exports.d.ts +28 -0
- package/dist/validate-exports.d.ts.map +1 -0
- package/dist/validate-exports.js +146 -0
- package/dist/validate-extends.d.ts.map +1 -1
- package/dist/validate-extends.js +37 -1
- package/dist/validate-module-artifact.d.ts +4 -2
- package/dist/validate-module-artifact.d.ts.map +1 -1
- package/dist/validate-module-artifact.js +43 -4
- package/dist/validate-native-entries.d.ts +15 -0
- package/dist/validate-native-entries.d.ts.map +1 -0
- package/dist/validate-native-entries.js +103 -0
- package/dist/validate-observed-state.d.ts +7 -1
- package/dist/validate-observed-state.d.ts.map +1 -1
- package/dist/validate-observed-state.js +24 -6
- package/dist/validate-provider-coherence.d.ts +4 -8
- package/dist/validate-provider-coherence.d.ts.map +1 -1
- package/dist/validate-provider-coherence.js +12 -123
- package/dist/validate-reference-forms.d.ts.map +1 -1
- package/dist/validate-reference-forms.js +2 -2
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +152 -65
- package/dist/validate-scope-reach.d.ts +31 -0
- package/dist/validate-scope-reach.d.ts.map +1 -0
- package/dist/validate-scope-reach.js +180 -0
- package/dist/validate-source-entries.d.ts +16 -0
- package/dist/validate-source-entries.d.ts.map +1 -0
- package/dist/validate-source-entries.js +90 -0
- package/dist/validate-template-body.d.ts +36 -0
- package/dist/validate-template-body.d.ts.map +1 -0
- package/dist/validate-template-body.js +246 -0
- package/dist/validate-throws-coverage.d.ts.map +1 -1
- package/dist/validate-throws-coverage.js +21 -39
- package/dist/value-type-keyword.d.ts +22 -5
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +16 -7
- package/package.json +4 -3
- package/src/analyzer.ts +97 -20
- package/src/artifact-axes.ts +24 -0
- package/src/artifact-layer-index.ts +9 -6
- package/src/artifact-selector.ts +110 -35
- package/src/builtins.ts +160 -113
- package/src/call-graph.ts +30 -0
- package/src/catch-scope.ts +1 -1
- package/src/cel-scope-query.ts +28 -9
- package/src/cel-scope.ts +1 -0
- package/src/eval-paths.ts +53 -6
- package/src/extends-resolution.ts +24 -0
- package/src/forwarded-declaration.ts +32 -0
- package/src/index.ts +37 -1
- package/src/kernel-globals.ts +28 -5
- package/src/migrations/CLAUDE.md +35 -0
- package/src/module-alias-scope.ts +17 -0
- package/src/module-file-claims.ts +63 -4
- package/src/module-named-files.ts +162 -0
- package/src/native-entries.ts +227 -0
- package/src/nearest-name.ts +47 -0
- package/src/normalize-inline-resources.ts +326 -70
- package/src/reference-field-map.ts +257 -52
- package/src/release/CLAUDE.md +32 -0
- package/src/release/destinations.ts +105 -0
- package/src/release/index.ts +33 -2
- package/src/release/ledger.ts +51 -21
- package/src/release/payload-digest.ts +2 -1
- package/src/release/release-plan.ts +16 -26
- package/src/release/workspace-config.ts +483 -47
- package/src/release/workspace-schema.ts +99 -0
- package/src/resolve-ref-sentinels.ts +7 -6
- package/src/resolve-throws-union.ts +87 -32
- package/src/resolve-zone-requirements.ts +2 -1
- package/src/rewrite-synthetic-origins.ts +107 -16
- package/src/schema-compat.ts +18 -4
- package/src/schema-error-report.ts +16 -4
- package/src/schema-walk.ts +162 -34
- package/src/scope-declarations.ts +98 -0
- package/src/source-entries.ts +502 -0
- package/src/step-bodies.ts +55 -0
- package/src/telo-version.ts +1 -1
- package/src/template-body.ts +25 -0
- package/src/validate-cel-context.ts +60 -18
- package/src/validate-exports.ts +185 -0
- package/src/validate-extends.ts +43 -0
- package/src/validate-module-artifact.ts +46 -3
- package/src/validate-native-entries.ts +147 -0
- package/src/validate-observed-state.ts +36 -7
- package/src/validate-provider-coherence.ts +17 -127
- package/src/validate-reference-forms.ts +2 -3
- package/src/validate-references.ts +151 -66
- package/src/validate-scope-reach.ts +213 -0
- package/src/validate-source-entries.ts +120 -0
- package/src/validate-template-body.ts +274 -0
- package/src/validate-throws-coverage.ts +24 -31
- package/src/value-type-keyword.ts +35 -9
- package/dist/validate-template-dispatch.d.ts +0 -27
- package/dist/validate-template-dispatch.d.ts.map +0 -1
- package/dist/validate-template-dispatch.js +0 -95
- package/src/validate-template-dispatch.ts +0 -99
|
@@ -1,7 +1,26 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import type { DefinitionRegistry } from "./definition-registry.js";
|
|
1
|
+
import { inlineStepTargetName, type ResourceDefinition, type ResourceManifest } from "@telorun/sdk";
|
|
2
|
+
import { isTaggedSentinel } from "@telorun/templating";
|
|
4
3
|
import type { AliasResolver } from "./alias-resolver.js";
|
|
4
|
+
import type { DefinitionRegistry } from "./definition-registry.js";
|
|
5
|
+
import {
|
|
6
|
+
controllerBearingAncestor,
|
|
7
|
+
hasOwnControllerOrTemplate,
|
|
8
|
+
type DefResolver,
|
|
9
|
+
} from "./extends-resolution.js";
|
|
10
|
+
import { isForwardedDeclaration } from "./forwarded-declaration.js";
|
|
11
|
+
import { definitionInScope } from "./module-alias-scope.js";
|
|
12
|
+
import { isInlineResource, isRefEntry } from "./reference-field-map.js";
|
|
13
|
+
import { gatherPropertySchemas } from "./schema-walk.js";
|
|
14
|
+
import {
|
|
15
|
+
declaredScopes,
|
|
16
|
+
outsideScopesOf,
|
|
17
|
+
scopeEncloses,
|
|
18
|
+
scopeMembers,
|
|
19
|
+
type DeclaredScope,
|
|
20
|
+
type OutsideScope,
|
|
21
|
+
} from "./scope-declarations.js";
|
|
22
|
+
import { forEachStep, stepBodiesOf } from "./step-bodies.js";
|
|
23
|
+
import { readStepSlot } from "./step-slot.js";
|
|
5
24
|
|
|
6
25
|
const SYSTEM_KINDS = new Set([
|
|
7
26
|
"Telo.Definition",
|
|
@@ -46,23 +65,88 @@ function cloneForMutation(value: unknown): unknown {
|
|
|
46
65
|
return out;
|
|
47
66
|
}
|
|
48
67
|
|
|
68
|
+
type NamedManifest = ResourceManifest & { metadata: { name: string } };
|
|
69
|
+
|
|
70
|
+
/** What an extraction inherits from the declaration it was written in: the
|
|
71
|
+
* module its kinds are written in, whether it is a dependency's code, and the
|
|
72
|
+
* declaring module's config contract its CEL is typed against. */
|
|
73
|
+
interface Provenance {
|
|
74
|
+
module: string | undefined;
|
|
75
|
+
forwarded: boolean;
|
|
76
|
+
moduleGlobals: unknown;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** A declaration waiting to have its inline slots extracted. */
|
|
80
|
+
interface Declaration extends Provenance {
|
|
81
|
+
manifest: NamedManifest;
|
|
82
|
+
/** The set it is declared in — the module's top level (undefined), or the
|
|
83
|
+
* `x-telo-scope` array holding it. What it declares inline joins the same set
|
|
84
|
+
* unless the slot lies in a region of a scope it declares itself. */
|
|
85
|
+
home: unknown[] | undefined;
|
|
86
|
+
/** Scopes it is lexically inside and not created in — see {@link OutsideScope}.
|
|
87
|
+
* Whatever it declares inline is created where it is, so inherits them. */
|
|
88
|
+
outside: OutsideScope[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** What `metadata.xTeloOrigin` records: where an extracted declaration was
|
|
92
|
+
* written, so a diagnostic about it anchors in its author's document. */
|
|
93
|
+
interface Origin {
|
|
94
|
+
parentKind: string;
|
|
95
|
+
parentName: string;
|
|
96
|
+
/** Concrete dotted path with `[N]` indices, matching `buildPositionIndex` keys
|
|
97
|
+
* (e.g. `routes[0].handler`). */
|
|
98
|
+
pathFromParent: string;
|
|
99
|
+
/** Set on a step's dispatch target, whose identity is its path-derived name
|
|
100
|
+
* alone — see `inlineStepTargetName`. */
|
|
101
|
+
stepTarget?: true;
|
|
102
|
+
outsideScopes?: OutsideScope[];
|
|
103
|
+
}
|
|
104
|
+
|
|
49
105
|
/**
|
|
50
106
|
* Phase 2 — Inline resource normalization.
|
|
51
107
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
108
|
+
* Every inline declaration (a `{kind, …config}` with no `name`) is extracted as a
|
|
109
|
+
* first-class manifest under a deterministic name and replaced in place with
|
|
110
|
+
* `{kind, name}`. Two kinds of slot carry one:
|
|
111
|
+
*
|
|
112
|
+
* - a REFERENCE slot, found through the kind's field map, named
|
|
113
|
+
* `{parentName}_{pathSegment}[_{itemName|index}]_{fieldName}`
|
|
114
|
+
* (`TestBasicAddition_steps_AddTwoNumbers_invoke`);
|
|
115
|
+
* - a STEP's dispatch target, at any nesting depth of a step body, named by
|
|
116
|
+
* `inlineStepTargetName` — the name the step engine has always registered it
|
|
117
|
+
* under, which is durable identity and so must not move with the extraction.
|
|
118
|
+
*
|
|
119
|
+
* Step slots are found through the kind's step-body annotation and walked with
|
|
120
|
+
* `walkStepArray`, never through the field map: that map is the kernel's Phase-5
|
|
121
|
+
* injection surface, and a step's target resolves at dispatch.
|
|
122
|
+
*
|
|
123
|
+
* Every extracted manifest is queued in turn, so an inline declaration nested in
|
|
124
|
+
* another's slots — a handler inside an inline step target — is extracted too.
|
|
125
|
+
* So is every member of an `x-telo-scope` array, which is a declaration of its
|
|
126
|
+
* own.
|
|
127
|
+
*
|
|
128
|
+
* WHERE an extraction is created:
|
|
129
|
+
*
|
|
130
|
+
* - a reference slot lying in a region of a scope its owner declares (a
|
|
131
|
+
* sequence's `targets:`) resolves against that scope, so its declaration
|
|
132
|
+
* joins the scope's array and is created per scope run;
|
|
133
|
+
* - a step target is created where its owner is — the module's top level, or
|
|
134
|
+
* the scope array holding a scope member — and never in a scope the owner
|
|
135
|
+
* declares, because that would make every step target of a sequence with a
|
|
136
|
+
* `with:` block a scoped resource and move its durable identity;
|
|
137
|
+
* - any other extraction is created where its owner is.
|
|
57
138
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
139
|
+
* A declaration written inside a scope's region and created outside it records
|
|
140
|
+
* the scope (`xTeloOrigin.outsideScopes`), and `validateScopedNameReach` reports
|
|
141
|
+
* a reference from it to a name that scope declares.
|
|
142
|
+
*
|
|
143
|
+
* An extraction out of a dependency's forwarded manifest is that dependency's
|
|
144
|
+
* code: it is stamped `forwardedInternal` (see `isForwardedDeclaration`) and
|
|
145
|
+
* carries the declaring module's `moduleGlobals`, as its parent does.
|
|
62
146
|
*
|
|
63
147
|
* Returns a new array of deep-cloned manifests (the rewrites land on the clones)
|
|
64
|
-
* plus
|
|
65
|
-
* never mutated; this is the analyzer's immutability boundary.
|
|
148
|
+
* plus every top-level extraction. The caller's manifests — array and elements —
|
|
149
|
+
* are never mutated; this is the analyzer's immutability boundary.
|
|
66
150
|
*/
|
|
67
151
|
export function normalizeInlineResources(
|
|
68
152
|
resources: ResourceManifest[],
|
|
@@ -71,97 +155,258 @@ export function normalizeInlineResources(
|
|
|
71
155
|
aliasesByModule?: Map<string, AliasResolver>,
|
|
72
156
|
): ResourceManifest[] {
|
|
73
157
|
// Deep-clone the input so this pass — and `resolveRefSentinels`, which runs on
|
|
74
|
-
// this output — never mutate caller-owned manifests.
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
// reference form). The clone is the analyzer's immutability boundary.
|
|
158
|
+
// this output — never mutate caller-owned manifests. The extractions rewrite
|
|
159
|
+
// slots in place, so without cloning we'd corrupt shared state such as the
|
|
160
|
+
// editor's `LoadedFile.manifests` parse cache (a reused sentinel would be
|
|
161
|
+
// rewritten to `{kind, name}`, later misread as an authored reference form).
|
|
79
162
|
const result = resources.map(cloneForMutation) as ResourceManifest[];
|
|
80
163
|
|
|
81
|
-
// Queue: all non-system resources with a name. Extracted resources are appended.
|
|
82
|
-
// Filter the CLONES (not the originals) so traversal mutates copies.
|
|
83
164
|
// System kinds join the queue too: their inline-accepting slots are filtered
|
|
84
165
|
// per entry below, so a system document is walked but only its opted-in slots
|
|
85
166
|
// are extracted from.
|
|
86
|
-
const queue = result
|
|
87
|
-
(r): r is
|
|
88
|
-
|
|
89
|
-
|
|
167
|
+
const queue: Declaration[] = result
|
|
168
|
+
.filter((r): r is NamedManifest => typeof r.metadata?.name === "string" && !!r.kind)
|
|
169
|
+
.map((manifest) => ({
|
|
170
|
+
manifest,
|
|
171
|
+
home: undefined,
|
|
172
|
+
outside: outsideScopesOf(manifest),
|
|
173
|
+
...provenanceOf(manifest, undefined),
|
|
174
|
+
}));
|
|
90
175
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
176
|
+
const place = (manifest: ResourceManifest, into: unknown[] | undefined, module?: string) => {
|
|
177
|
+
if (into) into.push(manifest);
|
|
178
|
+
else result.push(manifest);
|
|
179
|
+
queue.push({
|
|
180
|
+
manifest: manifest as NamedManifest,
|
|
181
|
+
home: into,
|
|
182
|
+
outside: outsideScopesOf(manifest),
|
|
183
|
+
...provenanceOf(manifest, module),
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
for (let i = 0; i < queue.length; i++) {
|
|
188
|
+
const current = queue[i];
|
|
189
|
+
const { manifest: resource, home, outside } = current;
|
|
190
|
+
// The registry reads a kind's alias table off `metadata.module`; a scope
|
|
191
|
+
// member is looked up through a view carrying its owner's.
|
|
192
|
+
const view =
|
|
193
|
+
current.module !== undefined && moduleOf(resource) === undefined
|
|
194
|
+
? ({ ...resource, metadata: { ...resource.metadata, module: current.module } } as NamedManifest)
|
|
195
|
+
: resource;
|
|
94
196
|
// When aliasesByModule is available, use the expanded map so inline refs
|
|
95
197
|
// hidden behind an x-telo-schema-from indirection (e.g. an encoder inside
|
|
96
198
|
// an HttpDispatch.Outcomes/$defs/Returns sub-schema) reach extraction.
|
|
97
199
|
const fieldMap =
|
|
98
200
|
aliases && aliasesByModule
|
|
99
|
-
? registry.expandedFieldMapForResource(
|
|
201
|
+
? registry.expandedFieldMapForResource(view, aliases, aliasesByModule)
|
|
100
202
|
: registry.getFieldMapForKind(resource.kind, aliases);
|
|
101
203
|
if (!fieldMap) continue;
|
|
102
204
|
|
|
103
|
-
const parentName = resource.metadata.name
|
|
104
|
-
const parentModule =
|
|
205
|
+
const parentName = resource.metadata.name;
|
|
206
|
+
const parentModule = moduleOf(view);
|
|
207
|
+
const inherit: Provenance = {
|
|
208
|
+
module: parentModule,
|
|
209
|
+
forwarded: current.forwarded,
|
|
210
|
+
moduleGlobals: current.moduleGlobals,
|
|
211
|
+
};
|
|
105
212
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
for (const
|
|
112
|
-
|
|
213
|
+
const scopes = declaredScopes(resource, fieldMap);
|
|
214
|
+
// Queued BEFORE anything is extracted into these arrays: an extraction
|
|
215
|
+
// queues itself, and must not be walked twice. A member is created inside
|
|
216
|
+
// this resource's scope, which is itself created where this resource is.
|
|
217
|
+
for (const scope of scopes) {
|
|
218
|
+
for (const member of scopeMembers(scope)) {
|
|
219
|
+
queue.push({ manifest: member, home: scope.declarations, outside, ...inherit });
|
|
113
220
|
}
|
|
114
221
|
}
|
|
222
|
+
const outsideAt = (slotPath: string, createdIn?: DeclaredScope): OutsideScope[] => [
|
|
223
|
+
...outside,
|
|
224
|
+
...scopes
|
|
225
|
+
.filter((scope) => scope !== createdIn && scopeEncloses(scope, slotPath))
|
|
226
|
+
.map((scope) => ({
|
|
227
|
+
ownerKind: resource.kind,
|
|
228
|
+
ownerName: parentName,
|
|
229
|
+
field: scope.path,
|
|
230
|
+
names: scopeMembers(scope).map((member) => member.metadata.name),
|
|
231
|
+
}))
|
|
232
|
+
.filter((scope) => scope.names.length > 0),
|
|
233
|
+
];
|
|
115
234
|
|
|
116
235
|
for (const [fieldPath, entry] of fieldMap) {
|
|
117
236
|
if (!isRefEntry(entry)) continue;
|
|
118
237
|
if (!acceptsInline(resource.kind, entry)) continue;
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
(prefix) =>
|
|
122
|
-
fieldPath === prefix ||
|
|
123
|
-
fieldPath.startsWith(prefix + ".") ||
|
|
124
|
-
fieldPath.startsWith(prefix + "["),
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const invocationContext = isRefEntry(entry) ? entry.context : undefined;
|
|
128
|
-
const extracted = extractInlinesAtPath(
|
|
238
|
+
const scope = scopes.find((s) => scopeEncloses(s, fieldPath));
|
|
239
|
+
for (const manifest of extractInlinesAtPath(
|
|
129
240
|
resource,
|
|
130
241
|
fieldPath,
|
|
131
242
|
parentName,
|
|
132
243
|
resource.kind,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
queue.push(manifest as ResourceManifest & { metadata: { name: string } });
|
|
139
|
-
// TODO Phase 5: when inScope, add to parent's scope array instead of outer set
|
|
140
|
-
void inScope;
|
|
244
|
+
inherit,
|
|
245
|
+
outsideAt(fieldPath, scope),
|
|
246
|
+
entry.context,
|
|
247
|
+
)) {
|
|
248
|
+
place(manifest, scope?.declarations ?? home, parentModule);
|
|
141
249
|
}
|
|
142
250
|
}
|
|
251
|
+
|
|
252
|
+
if (SYSTEM_KINDS.has(resource.kind)) continue;
|
|
253
|
+
extractStepTargets(resource, view, registry, aliases, aliasesByModule, inherit, outsideAt, (m) =>
|
|
254
|
+
place(m, home, parentModule),
|
|
255
|
+
);
|
|
143
256
|
}
|
|
144
257
|
|
|
145
258
|
return result;
|
|
146
259
|
}
|
|
147
260
|
|
|
261
|
+
const moduleOf = (manifest: ResourceManifest): string | undefined => {
|
|
262
|
+
const module = (manifest.metadata as { module?: unknown } | undefined)?.module;
|
|
263
|
+
return typeof module === "string" ? module : undefined;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
function provenanceOf(manifest: ResourceManifest, module: string | undefined): Provenance {
|
|
267
|
+
return {
|
|
268
|
+
module: moduleOf(manifest) ?? module,
|
|
269
|
+
forwarded: isForwardedDeclaration(manifest),
|
|
270
|
+
moduleGlobals: (manifest.metadata as { moduleGlobals?: unknown } | undefined)?.moduleGlobals,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Extract every inline dispatch target of every step in `resource`'s step
|
|
276
|
+
* bodies, at any nesting depth, into a named manifest.
|
|
277
|
+
*
|
|
278
|
+
* The name is the step engine's, so it names what the RUNTIME owner passes it:
|
|
279
|
+
*
|
|
280
|
+
* - the owner kind is the kind whose CONTROLLER runs the body — the kind
|
|
281
|
+
* itself, or for an `extends` child that inherits its controller, the
|
|
282
|
+
* ancestor that supplies it;
|
|
283
|
+
* - the path's first segment is the field the controller reads its body from.
|
|
284
|
+
* For a `base:`-form child that is the PARENT's field the body is mapped onto,
|
|
285
|
+
* which is taken from a pure `self.<field>` mapping; a body `base:` reshapes any
|
|
286
|
+
* other way is left inline, for the runtime to name exactly as it always has;
|
|
287
|
+
* - an inline declaration stating its own `metadata.name` keeps it, as
|
|
288
|
+
* `ensureKindRef` always has.
|
|
289
|
+
*/
|
|
290
|
+
function extractStepTargets(
|
|
291
|
+
resource: NamedManifest,
|
|
292
|
+
view: NamedManifest,
|
|
293
|
+
registry: DefinitionRegistry,
|
|
294
|
+
aliases: AliasResolver | undefined,
|
|
295
|
+
aliasesByModule: Map<string, AliasResolver> | undefined,
|
|
296
|
+
inherit: Provenance,
|
|
297
|
+
outsideAt: (slotPath: string) => OutsideScope[],
|
|
298
|
+
emit: (manifest: ResourceManifest) => void,
|
|
299
|
+
): void {
|
|
300
|
+
const definition = definitionInScope<ResourceDefinition>(
|
|
301
|
+
registry,
|
|
302
|
+
view.kind,
|
|
303
|
+
view.metadata,
|
|
304
|
+
aliases,
|
|
305
|
+
aliasesByModule,
|
|
306
|
+
);
|
|
307
|
+
if (!definition) return;
|
|
308
|
+
const schema = registry.effectiveSchemaOf(definition) as Record<string, any> | undefined;
|
|
309
|
+
if (!schema) return;
|
|
310
|
+
const resolveDef: DefResolver = (kind, from) =>
|
|
311
|
+
definitionInScope<ResourceDefinition>(registry, kind, from?.metadata, aliases, aliasesByModule);
|
|
312
|
+
const runner = hasOwnControllerOrTemplate(definition)
|
|
313
|
+
? definition
|
|
314
|
+
: (controllerBearingAncestor(definition, resolveDef) ?? definition);
|
|
315
|
+
const owner = { kind: runner.metadata.name, resourceName: resource.metadata.name };
|
|
316
|
+
const base = runner !== definition ? (definition as { base?: unknown }).base : undefined;
|
|
317
|
+
|
|
318
|
+
for (const body of stepBodiesOf(resource, schema)) {
|
|
319
|
+
const root = base === undefined ? body.field : mappedStepField(base, body.field, runner, registry);
|
|
320
|
+
if (root === undefined) continue;
|
|
321
|
+
const outsideScopes = outsideAt(body.field);
|
|
322
|
+
|
|
323
|
+
forEachStep(body, schema, (step, stepPath) => {
|
|
324
|
+
const target = step[body.invokeField];
|
|
325
|
+
if (!target || typeof target !== "object" || Array.isArray(target)) return;
|
|
326
|
+
if (!isInlineResource(target as Record<string, unknown>)) return;
|
|
327
|
+
// The step grammar requires a name, and a target is named after it; a step
|
|
328
|
+
// without one is reported by schema validation and left as written.
|
|
329
|
+
if (typeof step.name !== "string") return;
|
|
330
|
+
const inline = target as Record<string, unknown>;
|
|
331
|
+
const declared = (inline.metadata as { name?: unknown } | undefined)?.name;
|
|
332
|
+
const name =
|
|
333
|
+
typeof declared === "string"
|
|
334
|
+
? declared
|
|
335
|
+
: inlineStepTargetName(owner, [root, ...stepPathSegments(stepPath).slice(1)], step.name);
|
|
336
|
+
step[body.invokeField] = { kind: inline.kind, name };
|
|
337
|
+
emit(
|
|
338
|
+
buildManifest(
|
|
339
|
+
inline,
|
|
340
|
+
name,
|
|
341
|
+
{
|
|
342
|
+
parentKind: resource.kind,
|
|
343
|
+
parentName: resource.metadata.name,
|
|
344
|
+
pathFromParent: `${stepPath}.${body.invokeField}`,
|
|
345
|
+
stepTarget: true,
|
|
346
|
+
...(outsideScopes.length > 0 ? { outsideScopes } : {}),
|
|
347
|
+
},
|
|
348
|
+
inherit,
|
|
349
|
+
),
|
|
350
|
+
);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** The runner's step field a `base:` mapping forwards `field` into, when it does
|
|
356
|
+
* so verbatim (`steps: !cel "self.<field>"`); undefined otherwise. */
|
|
357
|
+
function mappedStepField(
|
|
358
|
+
base: unknown,
|
|
359
|
+
field: string,
|
|
360
|
+
runner: ResourceDefinition,
|
|
361
|
+
registry: DefinitionRegistry,
|
|
362
|
+
): string | undefined {
|
|
363
|
+
if (!base || typeof base !== "object" || Array.isArray(base)) return undefined;
|
|
364
|
+
const runnerSchema = registry.effectiveSchemaOf(runner) as Record<string, any> | undefined;
|
|
365
|
+
if (!runnerSchema) return undefined;
|
|
366
|
+
const runnerSteps = new Set(
|
|
367
|
+
gatherPropertySchemas(runnerSchema)
|
|
368
|
+
.filter(([, schema]) => readStepSlot(schema) !== undefined)
|
|
369
|
+
.map(([key]) => key),
|
|
370
|
+
);
|
|
371
|
+
for (const [target, value] of Object.entries(base as Record<string, unknown>)) {
|
|
372
|
+
if (runnerSteps.has(target) && pureSelfField(value) === field) return target;
|
|
373
|
+
}
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** `f` for a CEL value that is exactly `self.f`, in any spelling it arrives in. */
|
|
378
|
+
function pureSelfField(value: unknown): string | undefined {
|
|
379
|
+
let source: string | undefined;
|
|
380
|
+
if (isTaggedSentinel(value)) {
|
|
381
|
+
if (value.engine === "cel") source = value.source;
|
|
382
|
+
} else if (value && typeof value === "object" && (value as { __compiled?: unknown }).__compiled) {
|
|
383
|
+
const compiled = (value as { source?: unknown }).source;
|
|
384
|
+
if (typeof compiled === "string") source = compiled;
|
|
385
|
+
} else if (typeof value === "string") {
|
|
386
|
+
source = /^\s*\$\{\{([\s\S]*)\}\}\s*$/.exec(value)?.[1];
|
|
387
|
+
}
|
|
388
|
+
return source === undefined ? undefined : /^self\.([A-Za-z_$][\w$]*)$/.exec(source.trim())?.[1];
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/** `steps[1].cases.a[0]` → `["steps", "1", "cases", "a", "0"]`. Exact even for a
|
|
392
|
+
* case key holding punctuation: the name keeps only alphanumeric runs, so
|
|
393
|
+
* splitting inside a key cannot change it. */
|
|
394
|
+
function stepPathSegments(path: string): string[] {
|
|
395
|
+
return path.split(/[.[\]]/).filter((segment) => segment.length > 0);
|
|
396
|
+
}
|
|
397
|
+
|
|
148
398
|
/**
|
|
149
399
|
* Walks `resource` following `fieldPath` (dot notation, `[]` = array traversal).
|
|
150
400
|
* Mutates the resource in-place: replaces each inline value with `{kind, name}`.
|
|
151
401
|
* Returns the extracted manifests.
|
|
152
|
-
*
|
|
153
|
-
* Each extracted manifest carries `metadata.xTeloOrigin` so downstream
|
|
154
|
-
* diagnostics can be rerouted back to the parent doc's YAML position:
|
|
155
|
-
* - `parentKind` / `parentName` — the resource that owned the inline slot
|
|
156
|
-
* - `pathFromParent` — concrete dotted path with `[N]` indices, matching
|
|
157
|
-
* `buildPositionIndex` keys (e.g. `routes[0].handler`)
|
|
158
402
|
*/
|
|
159
403
|
function extractInlinesAtPath(
|
|
160
404
|
resource: ResourceManifest,
|
|
161
405
|
fieldPath: string,
|
|
162
406
|
parentName: string,
|
|
163
407
|
parentKind: string,
|
|
164
|
-
|
|
408
|
+
inherit: Provenance,
|
|
409
|
+
outsideScopes: OutsideScope[],
|
|
165
410
|
invocationContext?: Record<string, any>,
|
|
166
411
|
): ResourceManifest[] {
|
|
167
412
|
const extracted: ResourceManifest[] = [];
|
|
@@ -174,7 +419,18 @@ function extractInlinesAtPath(
|
|
|
174
419
|
): string {
|
|
175
420
|
const name = sanitizeName([parentName, ...nameSegments].join("_"));
|
|
176
421
|
extracted.push(
|
|
177
|
-
buildManifest(
|
|
422
|
+
buildManifest(
|
|
423
|
+
inline,
|
|
424
|
+
name,
|
|
425
|
+
{
|
|
426
|
+
parentKind,
|
|
427
|
+
parentName,
|
|
428
|
+
pathFromParent: concretePath,
|
|
429
|
+
...(outsideScopes.length > 0 ? { outsideScopes } : {}),
|
|
430
|
+
},
|
|
431
|
+
inherit,
|
|
432
|
+
invocationContext,
|
|
433
|
+
),
|
|
178
434
|
);
|
|
179
435
|
return name;
|
|
180
436
|
}
|
|
@@ -259,10 +515,8 @@ function extractInlinesAtPath(
|
|
|
259
515
|
function buildManifest(
|
|
260
516
|
inline: Record<string, unknown>,
|
|
261
517
|
name: string,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
pathFromParent: string,
|
|
265
|
-
parentModule: string | undefined,
|
|
518
|
+
origin: Origin,
|
|
519
|
+
inherit: Provenance,
|
|
266
520
|
invocationContext?: Record<string, any>,
|
|
267
521
|
): ResourceManifest {
|
|
268
522
|
const existingMeta =
|
|
@@ -275,9 +529,11 @@ function buildManifest(
|
|
|
275
529
|
...existingMeta,
|
|
276
530
|
name,
|
|
277
531
|
// Inherit parent module only if the inline doesn't already declare one
|
|
278
|
-
...(
|
|
532
|
+
...(inherit.module && !existingMeta.module ? { module: inherit.module } : {}),
|
|
533
|
+
...(inherit.forwarded ? { forwardedInternal: true } : {}),
|
|
534
|
+
...(inherit.moduleGlobals !== undefined ? { moduleGlobals: inherit.moduleGlobals } : {}),
|
|
279
535
|
...(invocationContext ? { xTeloInvocationContext: invocationContext } : {}),
|
|
280
|
-
xTeloOrigin:
|
|
536
|
+
xTeloOrigin: origin,
|
|
281
537
|
},
|
|
282
538
|
} as unknown as ResourceManifest;
|
|
283
539
|
}
|