@intentius/chant 0.19.1 → 0.21.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.
Files changed (164) hide show
  1. package/dist/build-params.d.ts +108 -0
  2. package/dist/build-params.d.ts.map +1 -0
  3. package/dist/build.d.ts +79 -1
  4. package/dist/build.d.ts.map +1 -1
  5. package/dist/cli/commands/build.d.ts +31 -0
  6. package/dist/cli/commands/build.d.ts.map +1 -1
  7. package/dist/cli/commands/check-lexicon-examples.d.ts +41 -0
  8. package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -0
  9. package/dist/cli/commands/check-lexicon-intrinsics.d.ts +71 -0
  10. package/dist/cli/commands/check-lexicon-intrinsics.d.ts.map +1 -0
  11. package/dist/cli/commands/check-lexicon.d.ts +1 -1
  12. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  13. package/dist/cli/commands/lint.d.ts +27 -0
  14. package/dist/cli/commands/lint.d.ts.map +1 -1
  15. package/dist/cli/handlers/build.d.ts.map +1 -1
  16. package/dist/cli/handlers/components.d.ts.map +1 -1
  17. package/dist/cli/handlers/lint.d.ts.map +1 -1
  18. package/dist/cli/handlers/run-client.d.ts +1 -1
  19. package/dist/cli/handlers/run-client.d.ts.map +1 -1
  20. package/dist/cli/handlers/run.d.ts.map +1 -1
  21. package/dist/cli/main.d.ts.map +1 -1
  22. package/dist/cli/plugins.d.ts +16 -0
  23. package/dist/cli/plugins.d.ts.map +1 -1
  24. package/dist/cli/registry.d.ts +10 -0
  25. package/dist/cli/registry.d.ts.map +1 -1
  26. package/dist/codegen/docs-sections.d.ts.map +1 -1
  27. package/dist/codegen/docs-types.d.ts +2 -0
  28. package/dist/codegen/docs-types.d.ts.map +1 -1
  29. package/dist/components/cli-support.d.ts +12 -5
  30. package/dist/components/cli-support.d.ts.map +1 -1
  31. package/dist/components/discover.d.ts +62 -7
  32. package/dist/components/discover.d.ts.map +1 -1
  33. package/dist/components/sandbox/driver.d.ts +12 -0
  34. package/dist/components/sandbox/driver.d.ts.map +1 -0
  35. package/dist/components/sandbox/run.d.ts +42 -0
  36. package/dist/components/sandbox/run.d.ts.map +1 -0
  37. package/dist/composite.d.ts +5 -0
  38. package/dist/composite.d.ts.map +1 -1
  39. package/dist/config.d.ts +71 -0
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/declarable.d.ts +16 -0
  42. package/dist/declarable.d.ts.map +1 -1
  43. package/dist/discovery/collect.d.ts.map +1 -1
  44. package/dist/discovery/entity-wire-codec.d.ts +166 -0
  45. package/dist/discovery/entity-wire-codec.d.ts.map +1 -0
  46. package/dist/discovery/entity-wire.d.ts +50 -0
  47. package/dist/discovery/entity-wire.d.ts.map +1 -0
  48. package/dist/discovery/fold-import.d.ts +239 -0
  49. package/dist/discovery/fold-import.d.ts.map +1 -0
  50. package/dist/discovery/index.d.ts +74 -1
  51. package/dist/discovery/index.d.ts.map +1 -1
  52. package/dist/discovery/sandbox/bundle.d.ts +18 -0
  53. package/dist/discovery/sandbox/bundle.d.ts.map +1 -0
  54. package/dist/discovery/sandbox/child-errors.d.ts +15 -0
  55. package/dist/discovery/sandbox/child-errors.d.ts.map +1 -0
  56. package/dist/discovery/sandbox/driver.d.ts +13 -0
  57. package/dist/discovery/sandbox/driver.d.ts.map +1 -0
  58. package/dist/discovery/sandbox/run.d.ts +69 -0
  59. package/dist/discovery/sandbox/run.d.ts.map +1 -0
  60. package/dist/errors.d.ts +9 -1
  61. package/dist/errors.d.ts.map +1 -1
  62. package/dist/fold/fold.d.ts +299 -0
  63. package/dist/fold/fold.d.ts.map +1 -0
  64. package/dist/fold/foldable-helpers.d.ts +121 -0
  65. package/dist/fold/foldable-helpers.d.ts.map +1 -0
  66. package/dist/fold/subset.d.ts +134 -0
  67. package/dist/fold/subset.d.ts.map +1 -0
  68. package/dist/index.d.ts +2 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/lexicon-output.d.ts +7 -2
  71. package/dist/lexicon-output.d.ts.map +1 -1
  72. package/dist/lexicon-schema.d.ts +4 -2
  73. package/dist/lexicon-schema.d.ts.map +1 -1
  74. package/dist/lexicon.d.ts +131 -1
  75. package/dist/lexicon.d.ts.map +1 -1
  76. package/dist/lifecycle/release-ledger.d.ts +11 -0
  77. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  78. package/dist/lint/component-checks.d.ts +7 -1
  79. package/dist/lint/component-checks.d.ts.map +1 -1
  80. package/dist/lint/rules/evl001-non-literal-expression.d.ts.map +1 -1
  81. package/dist/lint/rules/evl003-dynamic-property-access.d.ts.map +1 -1
  82. package/dist/params.d.ts +60 -0
  83. package/dist/params.d.ts.map +1 -0
  84. package/dist/provenance.d.ts +21 -0
  85. package/dist/provenance.d.ts.map +1 -1
  86. package/dist/runtime.d.ts +10 -1
  87. package/dist/runtime.d.ts.map +1 -1
  88. package/package.json +2 -1
  89. package/src/build-params.test.ts +144 -0
  90. package/src/build-params.ts +207 -0
  91. package/src/build.test.ts +38 -0
  92. package/src/build.ts +144 -7
  93. package/src/cli/commands/build.test.ts +220 -2
  94. package/src/cli/commands/build.ts +111 -3
  95. package/src/cli/commands/check-lexicon-examples.test.ts +92 -0
  96. package/src/cli/commands/check-lexicon-examples.ts +103 -0
  97. package/src/cli/commands/check-lexicon-intrinsics.test.ts +179 -0
  98. package/src/cli/commands/check-lexicon-intrinsics.ts +348 -0
  99. package/src/cli/commands/check-lexicon.test.ts +34 -0
  100. package/src/cli/commands/check-lexicon.ts +137 -1
  101. package/src/cli/commands/lint.ts +31 -3
  102. package/src/cli/commands/onboard.ts +1 -1
  103. package/src/cli/component-security-boundary.test.ts +170 -0
  104. package/src/cli/handlers/build.ts +24 -3
  105. package/src/cli/handlers/components.ts +9 -2
  106. package/src/cli/handlers/dev.ts +1 -1
  107. package/src/cli/handlers/graph.ts +7 -5
  108. package/src/cli/handlers/lifecycle.ts +2 -2
  109. package/src/cli/handlers/lint.ts +2 -0
  110. package/src/cli/handlers/misc.ts +2 -2
  111. package/src/cli/handlers/run-client.ts +1 -1
  112. package/src/cli/handlers/run.ts +20 -5
  113. package/src/cli/main.test.ts +22 -0
  114. package/src/cli/main.ts +39 -0
  115. package/src/cli/plugins.ts +20 -4
  116. package/src/cli/registry.ts +10 -0
  117. package/src/cli/security-boundary.test.ts +135 -0
  118. package/src/codegen/docs-sections.test.ts +67 -0
  119. package/src/codegen/docs-sections.ts +7 -3
  120. package/src/codegen/docs-types.ts +2 -0
  121. package/src/components/cli-support.ts +22 -10
  122. package/src/components/discover.ts +127 -25
  123. package/src/components/sandbox/driver.ts +114 -0
  124. package/src/components/sandbox/run.test.ts +185 -0
  125. package/src/components/sandbox/run.ts +177 -0
  126. package/src/composite.test.ts +21 -0
  127. package/src/composite.ts +20 -1
  128. package/src/config.ts +81 -0
  129. package/src/declarable.ts +20 -0
  130. package/src/discovery/collect.ts +17 -3
  131. package/src/discovery/entity-wire-codec.ts +487 -0
  132. package/src/discovery/entity-wire.test.ts +240 -0
  133. package/src/discovery/entity-wire.ts +67 -0
  134. package/src/discovery/fold-import.test.ts +1598 -0
  135. package/src/discovery/fold-import.ts +1998 -0
  136. package/src/discovery/index.test.ts +191 -1
  137. package/src/discovery/index.ts +242 -1
  138. package/src/discovery/sandbox/bundle.ts +218 -0
  139. package/src/discovery/sandbox/child-errors.ts +65 -0
  140. package/src/discovery/sandbox/driver.ts +147 -0
  141. package/src/discovery/sandbox/run.test.ts +179 -0
  142. package/src/discovery/sandbox/run.ts +196 -0
  143. package/src/errors.ts +9 -1
  144. package/src/fold/fold.test.ts +812 -0
  145. package/src/fold/fold.ts +805 -0
  146. package/src/fold/foldable-helpers.ts +171 -0
  147. package/src/fold/subset-doc-parity.test.ts +210 -0
  148. package/src/fold/subset.test.ts +352 -0
  149. package/src/fold/subset.ts +383 -0
  150. package/src/index.ts +2 -0
  151. package/src/lexicon-output.ts +7 -2
  152. package/src/lexicon-schema.test.ts +57 -0
  153. package/src/lexicon-schema.ts +8 -1
  154. package/src/lexicon.ts +132 -1
  155. package/src/lifecycle/git.test.ts +10 -5
  156. package/src/lifecycle/release-ledger.test.ts +28 -0
  157. package/src/lifecycle/release-ledger.ts +11 -0
  158. package/src/lint/component-checks.ts +8 -1
  159. package/src/lint/rules/evl001-non-literal-expression.ts +26 -110
  160. package/src/lint/rules/evl003-dynamic-property-access.ts +11 -2
  161. package/src/params.test.ts +22 -0
  162. package/src/params.ts +66 -0
  163. package/src/provenance.ts +22 -0
  164. package/src/runtime.ts +11 -2
@@ -0,0 +1,299 @@
1
+ import * as ts from "typescript";
2
+ import { type IntrinsicDef } from "../lexicon.js";
3
+ import { type SubsetRuleId } from "./subset.js";
4
+ /**
5
+ * fold — static AST value reducer (chant #1026/#1021/#1024, part of epic #1019)
6
+ *
7
+ * Reduces a single-file TypeScript expression AST to a value with NO
8
+ * module execution. The node-kind/operator/key subset it covers — literals,
9
+ * template interpolation, object/array literals (incl. spread), `const`
10
+ * identifier resolution, property and element access (incl. the
11
+ * cross-resource `{ __attrRef }` case, literal-key-only), unary `!`/`-`,
12
+ * the binary operators `+ - * / === !== > < >= <=`, short-circuit
13
+ * `&& || ??`, conditional expressions, `as`/`satisfies`/`!`/parenthesized
14
+ * unwrapping, a nested `new Type({...})` resource-as-value, and registered
15
+ * lexicon intrinsic tagged templates — is defined ONCE, in {@link "./subset"}
16
+ * ({@link findSubsetViolation}), and shared with EVL001/EVL003
17
+ * ({@link "../lint/rules/evl001-non-literal-expression"}), so the linted
18
+ * subset and the folded subset can never drift apart (#1024).
19
+ *
20
+ * A `CallExpression` has almost no case — a function call as a value is
21
+ * structurally unrepresentable, not merely linted against. Composite
22
+ * factory calls are out of scope here (epic Phase 5, #1023). There are
23
+ * exactly two exceptions, both closed allowlists of names declared
24
+ * somewhere a human had to write them down, and both reducing to a symbolic
25
+ * envelope that executes nothing here:
26
+ *
27
+ * - a call to a REGISTERED chant authoring helper
28
+ * ({@link "./foldable-helpers"}, chant #1082) → {@link FoldedHelperCall};
29
+ * - a call to a lexicon intrinsic whose lexicon registered it AND opted
30
+ * its call form in ({@link intrinsicCallFolds}, ../lexicon.ts, chant
31
+ * #1044) → {@link FoldedIntrinsicCall}, the same `{__intrinsic}` family
32
+ * the tagged-template form already reduces to.
33
+ *
34
+ * Everything else — a user's function, a method call, an array `.map`, a
35
+ * registered name shadowed by a local binding — still throws.
36
+ *
37
+ * Cross-file identifier resolution (chant #1020): `consts` alone is always
38
+ * this file's own top-level bindings — that part stays single-file, and
39
+ * nothing about the supported node-kind subset changes. But an identifier
40
+ * `fold()` can't find in `consts` isn't necessarily a dead end: the optional
41
+ * `externals` map (populated by ../discovery/fold-import.ts, which owns the
42
+ * module graph traversal) lets a caller pre-resolve an *imported* binding to
43
+ * its real value — a plain value for an imported `const`, or the REAL,
44
+ * already-constructed `Declarable`/`CompositeInstance` for a name bound to a
45
+ * resource/composite in the defining module — and `fold()` just returns it
46
+ * for the identifier, unchanged. This is why a bare object/array bracket
47
+ * index a few lines down (`obj[key]`) is enough to make `network.vpc.VpcId`
48
+ * fold correctly once `network` resolves via `externals` to the real,
49
+ * shared composite instance object: indexing a live class instance the same
50
+ * way as a plain object returns its real getter's real `AttrRef`, wired to
51
+ * the real shared parent — see fold-import.ts's module doc for why that
52
+ * shared identity is the entire hard part of #1020.
53
+ */
54
+ /**
55
+ * The result of folding an AST node: a plain value, a symbolic reference to
56
+ * a sibling resource's attribute, a folded intrinsic tagged template, an
57
+ * unresolved external symbol chain, or a folded resource spec.
58
+ */
59
+ export type FoldedValue = string | number | boolean | null | undefined | FoldedValue[] | {
60
+ [key: string]: FoldedValue;
61
+ } | AttrRefValue | FoldedIntrinsic | FoldedHelperCall | SymbolicValue | FoldedResource;
62
+ /**
63
+ * Symbolic reference produced when a property/element access resolves to an
64
+ * attribute of another `const`-declared resource in the same file, e.g.
65
+ * `bucket.name` (or `bucket["name"]`) where `bucket` is
66
+ * `const bucket = new S3Bucket({...})`.
67
+ *
68
+ * This is the SAME envelope `AttrRef.prototype.toJSON()` produces at
69
+ * runtime ({@link "../attrref"}) — `serializer-walker.ts`'s `walkValue`
70
+ * already recognizes a plain `{ __attrRef }` object as an AttrRef envelope
71
+ * (it doesn't require a live `AttrRef` instance), so this is not an
72
+ * invented shape: it's the existing envelope, produced without running the
73
+ * module that would otherwise construct the real `AttrRef`.
74
+ */
75
+ export interface AttrRefValue {
76
+ __attrRef: {
77
+ entity: string;
78
+ attribute: string;
79
+ };
80
+ }
81
+ /**
82
+ * The result of folding a registered lexicon intrinsic tagged template
83
+ * (e.g. `Sub\`${AWS.StackName}-x\``) to its node form: tag name, cooked
84
+ * template string parts, and folded interpolated values (in order).
85
+ * Mirrors the runtime call shape `Tag(strings, ...values)` so a later
86
+ * build path can replay it into the real intrinsic object (#1022).
87
+ */
88
+ export type FoldedIntrinsic = FoldedIntrinsicTag | FoldedIntrinsicCall;
89
+ /** The tagged-template form: `Sub\`${x}-y\`` — see {@link FoldedIntrinsic}. */
90
+ export interface FoldedIntrinsicTag {
91
+ __intrinsic: string;
92
+ strings: string[];
93
+ values: FoldedValue[];
94
+ }
95
+ /**
96
+ * The plain-call form of a registered, opted-in lexicon intrinsic
97
+ * (chant #1044) — `Ref(bucket)`, `Concat("a", b)`, `GetAtt("Fn", "Arn")`.
98
+ * Same `__intrinsic` key as the tagged-template form, so the same revival
99
+ * branch handles both and nothing downstream learns a new envelope; the
100
+ * payload differs because the call shape does — positional `args` mirroring
101
+ * `Name(...args)`, where the tag form mirrors `Name(strings, ...values)`.
102
+ *
103
+ * Symbolic, exactly like the tag form: `fold()` executes nothing, it only
104
+ * records that a registered intrinsic was called and with what. The real
105
+ * function is resolved through the folding file's own imports and invoked by
106
+ * `../discovery/fold-import.ts`'s `reviveFoldedValue`.
107
+ */
108
+ export interface FoldedIntrinsicCall {
109
+ __intrinsic: string;
110
+ args: FoldedValue[];
111
+ }
112
+ /**
113
+ * The result of folding a call to a registered chant authoring helper
114
+ * (chant #1082) — e.g. `phase("Apply", [...])`, `output(ref, "oX")`. Holds
115
+ * the helper's name and its folded arguments, in source order.
116
+ *
117
+ * Symbolic, exactly like {@link FoldedIntrinsic}: `fold()` executes nothing,
118
+ * it only records that a registered helper was called and with what. The real
119
+ * function is resolved through the folding file's own imports and invoked by
120
+ * `../discovery/fold-import.ts`'s `reviveFoldedValue`, which is also where
121
+ * the "is this name actually bound to chant's own helper" check lives. See
122
+ * {@link "./foldable-helpers"} for the allowlist and why it is closed.
123
+ */
124
+ export interface FoldedHelperCall {
125
+ __helper: string;
126
+ args: FoldedValue[];
127
+ }
128
+ /**
129
+ * A sub-expression inside a folded intrinsic that fold could not reduce to
130
+ * a value without resolving an identifier from outside this file — e.g. an
131
+ * imported pseudo-parameter namespace access like `AWS.StackName`.
132
+ * Cross-file import resolution is #1020; until then the raw source text is
133
+ * preserved verbatim (never stringified, never rejected) instead of being
134
+ * treated as an unresolved-identifier error. Only appears inside a folded
135
+ * intrinsic's `values` — see {@link foldIntrinsicValue}.
136
+ */
137
+ export interface SymbolicValue {
138
+ __symbol: string;
139
+ }
140
+ /**
141
+ * The result of folding a resource constructor: `new Type({ ...props })`.
142
+ */
143
+ export interface FoldedResource {
144
+ __resource: string;
145
+ props: {
146
+ [key: string]: FoldedValue;
147
+ };
148
+ /**
149
+ * The constructor's optional second argument — CFN-style resource-level
150
+ * attributes (`DependsOn`, `Condition`, `DeletionPolicy`,
151
+ * `UpdateReplacePolicy`, `CreationPolicy`, `Metadata`, …) some lexicons
152
+ * accept alongside `props` (see `createResource`'s `attributes` param,
153
+ * ../runtime.ts). Present only when the source actually passed one.
154
+ */
155
+ attributes?: {
156
+ [key: string]: FoldedValue;
157
+ };
158
+ /**
159
+ * chant #1082 — every constructor argument, folded, in source order. Present
160
+ * only when the argument list is NOT the classic `(props)` / `(props,
161
+ * attributes)` shape — most often because the props object isn't first
162
+ * (`new Parameter("String", {...})`, whose signature is `(type, props)`).
163
+ *
164
+ * When present this is authoritative: the entity is constructed by spreading
165
+ * it, so the constructor receives exactly what the source wrote. `props`
166
+ * alongside it is the first object-literal argument, reported for readers,
167
+ * never re-passed (which would double-count it).
168
+ */
169
+ args?: FoldedValue[];
170
+ }
171
+ /**
172
+ * One entry per exported `const` resource declaration in {@link foldModule}'s
173
+ * result. The `ok: false` case surfaces the same located, rule-id-tagged
174
+ * shape as {@link FoldError} (#1024) — `error` stays the formatted message
175
+ * string for backward-compat display, while `ruleId`/`line`/`column` let a
176
+ * caller cite the exact same rule id + position an EVL diagnostic for the
177
+ * same construct would.
178
+ */
179
+ export type FoldModuleEntry = {
180
+ ok: true;
181
+ spec: FoldedResource;
182
+ } | {
183
+ ok: false;
184
+ error: string;
185
+ ruleId: SubsetRuleId;
186
+ line: number;
187
+ column: number;
188
+ };
189
+ /**
190
+ * Error thrown when a node cannot be folded to a value without executing
191
+ * code. Carries the node's source position (1-based, matching `LintError`)
192
+ * so callers can report a located diagnostic, and the id of the EVL rule
193
+ * that flags the same construct (#1024) — "EVL001" (the general
194
+ * not-statically-evaluable umbrella) unless the rejection is specifically a
195
+ * dynamic element-access key, which is "EVL003"'s construct. A rejection
196
+ * with no EVL equivalent (unresolved identifier, unregistered intrinsic tag,
197
+ * spread of a value that turns out not to be an object/array — all
198
+ * environment/value-dependent, see {@link "./subset"}'s module doc) still
199
+ * defaults to "EVL001" since that's the closest umbrella rule, even though
200
+ * EVL can't actually detect it ahead of a real fold.
201
+ *
202
+ * chant #1020 hang fix — every `FoldError` is thrown for a routine, EXPECTED
203
+ * outcome (this node's shape isn't in the fold subset) and is ALWAYS caught
204
+ * a few frames up (`tryFoldFileCore`'s own top-level catch, ultimately),
205
+ * reduced to `.message`; `.stack` is never read anywhere on this path. V8
206
+ * still eagerly walks live JS frames to populate the (lazy) `.stack` getter's
207
+ * backing data at CONSTRUCTION time regardless of whether it's ever read —
208
+ * cheap for a shallow call stack, but expensive once the surrounding
209
+ * functions are hot enough for V8 to aggressively inline them (every corpus
210
+ * entry re-triggers the same call shapes across `foldFileMemoized` ->
211
+ * `buildExternals` -> `tryFoldFileCore` -> `resolveDeclaratorValue` ->
212
+ * `resolveLiveValue` -> `resolveCallExpression`/`fold`, chant #1020's
213
+ * cross-file resolution making that chain several layers deeper than the
214
+ * pre-#1020 single-file fold ever needed): capturing a stack from deep,
215
+ * optimized/inlined frames requires V8 to reconstruct them from deopt
216
+ * metadata, confirmed via `sample` to dominate CPU during the observed
217
+ * multi-minute stall (`Isolate::CaptureAndSetErrorStack` /
218
+ * `OptimizedJSFrame::Summarize` / `DeoptTranslationIterator`). Most files in
219
+ * the corpus (77/98 entries have at least one run-fallback file) throw one
220
+ * of these, so the cost compounds across a build. `Error.stackTraceLimit = 0`
221
+ * for the duration of `super()` makes V8 capture zero frames — free
222
+ * regardless of stack depth/optimization state — then the limit is restored
223
+ * immediately, so it doesn't suppress a real stack trace anywhere else in
224
+ * the process.
225
+ */
226
+ export declare class FoldError extends Error {
227
+ readonly line: number;
228
+ readonly column: number;
229
+ readonly ruleId: SubsetRuleId;
230
+ constructor(message: string, line: number, column: number, ruleId?: SubsetRuleId);
231
+ }
232
+ /**
233
+ * Resolve a node's 1-based line/column via its owning `SourceFile`. Exported
234
+ * (chant #1020) so fold-import.ts can build its own located `FoldError`s
235
+ * (e.g. an import-cycle diagnostic pointing at the specific `import`
236
+ * statement that closes the cycle) using the exact same position math
237
+ * `foldError` uses here, rather than a second hand-rolled implementation.
238
+ */
239
+ export declare function locate(node: ts.Node): {
240
+ line: number;
241
+ column: number;
242
+ };
243
+ /**
244
+ * Collect every top-level `const x = <initializer>` in a source file into a
245
+ * name -> initializer map. Single-file only (cross-file is #1020).
246
+ */
247
+ export declare function collectConsts(sourceFile: ts.SourceFile): Map<string, ts.Expression>;
248
+ /**
249
+ * Fold a single expression node to a value. Throws {@link FoldError} for
250
+ * anything outside the supported subset — including any `CallExpression`
251
+ * that is neither a registered chant authoring helper nor a registered,
252
+ * call-form-opted-in lexicon intrinsic (see the module doc).
253
+ *
254
+ * @param intrinsics - The active lexicons' registered intrinsics. A tagged
255
+ * template whose tag isn't in this list, or is in it without
256
+ * {@link intrinsicTagFolds}, is rejected; a plain call is rejected unless
257
+ * its callee is in this list with {@link intrinsicCallFolds} (chant
258
+ * #1044). Defaults to none — pass the target lexicon's manifest
259
+ * `intrinsics` to recognize either form.
260
+ * @param externals - chant #1020: pre-resolved imported bindings, consulted
261
+ * only when an identifier isn't in `consts`. See the module doc above.
262
+ * `undefined` (the default) preserves the exact pre-#1020 single-file
263
+ * behavior — every identifier not in `consts` is unresolved.
264
+ */
265
+ export declare function fold(node: ts.Expression, consts: Map<string, ts.Expression>, intrinsics?: readonly IntrinsicDef[], externals?: ReadonlyMap<string, unknown>): FoldedValue;
266
+ /**
267
+ * Fold a resource constructor call to its spec.
268
+ *
269
+ * The common `createResource` shape (../runtime.ts) is `new Type({ ...props
270
+ * })` or `new Type({ ...props }, { ...attributes })` — CFN-style resource
271
+ * attributes (`DependsOn`, `Condition`, `DeletionPolicy`, …) second — and
272
+ * that shape reduces to `props` (+ `attributes`) exactly as before.
273
+ *
274
+ * chant #1082 — but that is a convention, not a rule every lexicon class
275
+ * follows. AWS's deploy-time `Parameter` is `(type, props)`
276
+ * (lexicons/aws/src/parameter.ts): the props object is the SECOND argument
277
+ * and the first is a plain string. `foldResource` used to require argument 0
278
+ * to be an object literal, so no `new Parameter(...)` anywhere could ever
279
+ * fold, whatever surrounded it. The general case now folds every argument in
280
+ * source order into {@link FoldedResource.args}, which the caller constructs
281
+ * the entity from verbatim — no positional assumption at all. `props` is
282
+ * still reported (the first object-literal argument, for callers that read
283
+ * it) but is a VIEW onto `args`, not the thing constructed from.
284
+ */
285
+ export declare function foldResource(node: ts.NewExpression, consts: Map<string, ts.Expression>, intrinsics?: readonly IntrinsicDef[], externals?: ReadonlyMap<string, unknown>): FoldedResource;
286
+ /**
287
+ * Fold every exported `const X = new Type({...})` resource declaration in a
288
+ * source file to its spec, with no module execution.
289
+ *
290
+ * Non-resource `const` exports (anything whose initializer isn't a `new`
291
+ * expression) are left out of the result rather than folded or errored —
292
+ * `new`-less resource forms (composite factory calls) are epic Phase 5
293
+ * (#1023) and are not attempted here.
294
+ *
295
+ * @param intrinsics - Lexicon-registered intrinsic tags, forwarded to
296
+ * {@link fold} for every resource. See {@link fold}'s `intrinsics` param.
297
+ */
298
+ export declare function foldModule(source: string, fileName?: string, intrinsics?: readonly IntrinsicDef[]): Record<string, FoldModuleEntry>;
299
+ //# sourceMappingURL=fold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/fold/fold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * foldable-helpers — the closed, declared allowlist of chant's OWN authoring
3
+ * helpers that a call expression may fold through (chant #1082, epic #1019).
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * `fold()` has no general case for a `CallExpression`: a function call as a
8
+ * value is structurally unrepresentable there, because folding it would mean
9
+ * executing code, which is the one thing the fold path exists to avoid. That
10
+ * rule is right for user code and stays right — a user's own function, an
11
+ * arrow function, a method call (`naming.name(...)`) all keep failing exactly
12
+ * as before.
13
+ *
14
+ * But it also blocks chant's own documented authoring API. `phase("Apply",
15
+ * [...])` is how the component contract says to write a component; `output(ref,
16
+ * "oX")` is how a lexicon output is authored. An application cannot avoid them
17
+ * and still use components or outputs, so every file that uses one falls back
18
+ * to run no matter how statically evaluable the rest of it is.
19
+ *
20
+ * #1044 already settled the shape of the answer one level down, for lexicon
21
+ * intrinsics: a call-shaped thing may fold ONLY when it is registered, opt-in,
22
+ * per-helper — never because it merely looks like a call. This module is the
23
+ * same decision applied one level up, to chant's own helpers, with the
24
+ * registration written here by hand instead of coming from a lexicon manifest.
25
+ *
26
+ * ## What "registered" buys, and what still has to be true
27
+ *
28
+ * A name in this list is NOT permission to invoke whatever it happens to be
29
+ * bound to. Folding a helper call is a two-key operation:
30
+ *
31
+ * 1. **Shape + name** (here, and in `fold()`/`findSubsetViolation`): the
32
+ * callee is a bare identifier whose text is in {@link
33
+ * FOLDABLE_AUTHORING_HELPERS} and which is not shadowed by a local
34
+ * `const`. `fold()` reduces the call to a symbolic
35
+ * `{ __helper, args }` envelope — it still executes nothing.
36
+ * 2. **Provenance + invocation** (`../discovery/fold-import.ts`): the
37
+ * envelope is revived by resolving that name through the folding FILE'S
38
+ * OWN `import` bindings and checking the import actually comes from chant
39
+ * ({@link isChantOwnedSpecifier}, or a path inside chant-core's own tree
40
+ * for in-repo/absolute-specifier callers). Only then is the real function
41
+ * invoked, with the real folded arguments. A same-named helper imported
42
+ * from somewhere else, or declared in the file itself, resolves to
43
+ * nothing chant owns and the whole file falls back to run.
44
+ *
45
+ * So the function that runs is always the same function the run path would
46
+ * have called, from the same module the source itself imported — fold does not
47
+ * substitute its own reimplementation, which is why this list cannot drift
48
+ * from the helpers' real behavior.
49
+ *
50
+ * ## Admission criteria
51
+ *
52
+ * A helper belongs here only if all of these hold:
53
+ *
54
+ * - chant owns and documents it as authoring surface;
55
+ * - it is a pure function of its arguments — no I/O, no `process.env`, no
56
+ * module-level mutable state, no observable side effect;
57
+ * - calling it early (at fold time) is indistinguishable from calling it
58
+ * during a real run of the file.
59
+ *
60
+ * Deliberately NOT admitted — see this module's tests and the #1082 PR body:
61
+ *
62
+ * - `env()` (`../env.ts`) reads `process.env`. Folding it would bake one
63
+ * run's environment into a statically-derived value. It is exactly the
64
+ * kind of call fold must keep rejecting.
65
+ * - `Op()` (`../op/builders.ts`) constructs an `OpResource` — a `Declarable`.
66
+ * `fold()` already rejects a nested `new Type(...)` used as a value for a
67
+ * real, differential-caught reason (the envelope leaks into
68
+ * serialization); a factory that returns one is the same hazard wearing a
69
+ * call.
70
+ * - `propagate()`, `withDefaults()`, `resource()`, `mergeDefaults()`
71
+ * (`../composite.ts`) are composite *definition* helpers, not value-position
72
+ * helpers. `propagate()` in particular mutates its argument in place, and
73
+ * the composite spine in fold-import.ts already resolves it live.
74
+ * - `createResource()`/`createProperty()` (`../runtime.ts`) are used at a
75
+ * lexicon module's top level to build classes, never as a value inside a
76
+ * project file.
77
+ * - Lexicon intrinsics in CALL form (`Ref(...)`, `Join(...)`) are lexicon
78
+ * surface, not chant's own, and are #1044's registry (`IntrinsicDef`,
79
+ * `../lexicon.ts`) to admit — not this one. Only their tagged-template
80
+ * form folds today.
81
+ */
82
+ /**
83
+ * One registered helper. `module` and `note` carry no runtime behavior — they
84
+ * are the audit trail for why this entry passed the admission criteria above,
85
+ * kept next to the name it justifies rather than in a comment that can drift
86
+ * away from the list.
87
+ */
88
+ export interface FoldableHelperDef {
89
+ /** The exported name, matched against the callee identifier's text. */
90
+ readonly name: string;
91
+ /** Where chant defines it (a path under `packages/core/src`, for the audit trail). */
92
+ readonly module: string;
93
+ /** Why it qualifies — what it returns and why calling it at fold time is safe. */
94
+ readonly note: string;
95
+ }
96
+ /**
97
+ * The allowlist. Adding an entry is a deliberate act: it must satisfy every
98
+ * admission criterion in this module's doc, and it widens what `fold()` and
99
+ * `findSubsetViolation` accept for EVERY project, so it belongs in a PR that
100
+ * says so.
101
+ *
102
+ * Two names below are defined TWICE in chant, by different modules, with
103
+ * different return types (`phase`/`gate` by both the component contract and
104
+ * the Op builders; `stackOutput` by both the component contract and the
105
+ * cross-stack output primitive). That is fine and needs no disambiguation
106
+ * here: registration is by name, but the function actually invoked is the one
107
+ * the folding file itself imported (see step 2 in the module doc), so each
108
+ * file gets its own. Both definitions of each name independently satisfy the
109
+ * criteria, which is what makes registering the shared name safe.
110
+ */
111
+ export declare const FOLDABLE_AUTHORING_HELPERS: readonly FoldableHelperDef[];
112
+ /**
113
+ * True when `name` is a registered foldable authoring helper. Name-only — this
114
+ * is the shape-level half of the check (step 1 in the module doc). It says
115
+ * nothing about where the name is bound; `../discovery/fold-import.ts` decides
116
+ * that before anything is invoked.
117
+ */
118
+ export declare function isFoldableHelperName(name: string): boolean;
119
+ /** True for a bare specifier that names a chant-published package (or one of its subpaths). */
120
+ export declare function isChantOwnedSpecifier(specifier: string): boolean;
121
+ //# sourceMappingURL=foldable-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foldable-helpers.d.ts","sourceRoot":"","sources":["../../src/fold/foldable-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,iBAAiB,EA0BlE,CAAC;AAIF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAeD,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAIhE"}
@@ -0,0 +1,134 @@
1
+ import * as ts from "typescript";
2
+ import { type IntrinsicDef } from "../lexicon.js";
3
+ /**
4
+ * subset — the single canonical definition of chant's statically-foldable
5
+ * expression subset (chant #1024, epic #1019).
6
+ *
7
+ * `fold()` ({@link "./fold"}, the enforcement layer — a construct outside
8
+ * this subset simply has no case there) and EVL001/EVL003
9
+ * ({@link "../lint/rules/evl001-non-literal-expression"},
10
+ * {@link "../lint/rules/evl003-dynamic-property-access"} — the pre-flight
11
+ * diagnostic layer) both import this module so the two can never drift
12
+ * apart on *which node kinds, operators, and key shapes* are foldable.
13
+ * Before this module existed, `fold()` and EVL001 each hand-rolled their
14
+ * own recursive classifier; they agreed almost everywhere but had several
15
+ * real, silent gaps (see git history of #1024 for the enumerated list —
16
+ * dynamic object-literal keys, template/tagged-template interiors, and
17
+ * unrestricted binary/unary operators were all accepted by EVL001 but
18
+ * rejected by `fold()`). This module is the fix: one classifier, two
19
+ * importers.
20
+ *
21
+ * Scope — this module classifies *shape* only: the syntactic kind of an
22
+ * expression, its operator, and (for keys) its literal-ness. It
23
+ * deliberately does NOT resolve bindings or perform any evaluation, because
24
+ * three things a full fold needs are inherently environment-dependent and
25
+ * cannot be recovered from shape alone:
26
+ *
27
+ * 1. Identifier *resolution* — is a bare name actually a local `const`,
28
+ * vs. an unbound name? That needs the file's `consts` map. Both
29
+ * `fold()` and this module treat a bare identifier as shape-valid;
30
+ * `fold()` alone resolves it (and rejects if unresolved) once it has
31
+ * that map. A lint rule has no equivalent binding-resolution pass
32
+ * today, so EVL (via this module) stays permissive here — a known,
33
+ * intentional asymmetry, not a bug: it can only ever be a *false
34
+ * negative* on EVL's part (EVL passes something `fold()` might later
35
+ * reject for being unresolved), never the reverse.
36
+ * 2. Tagged-template *tag registration* — needs a lexicon's intrinsics
37
+ * manifest, which isn't available to a syntax-only lint rule. `fold()`
38
+ * alone checks it; this module treats any tag name as shape-valid and
39
+ * only classifies the interpolated values.
40
+ * 2b. Authoring-helper *provenance* (chant #1082) — a call to a registered
41
+ * chant helper (`phase(...)`, `output(...)`; ./foldable-helpers.ts)
42
+ * folds, but only when the name is genuinely bound to an import of
43
+ * chant's own. That needs the module graph, which a syntax-only lint
44
+ * rule doesn't have. This module checks the NAME only and stays
45
+ * permissive; `fold()`'s bridge does the provenance check and falls the
46
+ * file back to run when it fails. Same direction as every other item
47
+ * here — a false negative for EVL, never a false positive.
48
+ * 2c. Intrinsic *call-form* registration (chant #1044) — a plain call to a
49
+ * lexicon intrinsic the lexicon opted in (`Ref(bucket)`,
50
+ * `Concat(a, b)`; `IntrinsicDef.foldsAsCall`, ../lexicon.ts) folds.
51
+ * Whether a given name is such an intrinsic is not knowable from shape,
52
+ * so {@link findSubsetViolation} takes the registry as an OPTIONAL
53
+ * parameter instead of guessing: supply it and the answer for a call is
54
+ * exact (fold()'s own), omit it and every call is a violation, the
55
+ * pre-#1044 answer.
56
+ *
57
+ * That parameter is the whole reason the call case lives here rather
58
+ * than only in `fold()`. This module is a shared predicate, and the
59
+ * point of a shared predicate is that a consumer can ask "will this
60
+ * fold?" without running fold — a control plane deciding whether a
61
+ * repository needs a sandboxed child process at all, for instance.
62
+ * Keeping the case out of here would make the predicate answer "no" for
63
+ * idiomatic `Ref(...)` source that `fold()` reduces cleanly: not a
64
+ * permissive gap but a systematically WRONG answer in the expensive
65
+ * direction, and the one direction this module is not allowed to be
66
+ * wrong in (see the false-negative/false-positive rule in point 1, and
67
+ * the flow-sensitivity note below — the single divergence in the other
68
+ * direction, and the one this module treats as a wart). A caller with
69
+ * no registry degrades to "assume it runs", which is safe and cheap to
70
+ * reason about; EVL is exactly such a caller and its behavior on calls
71
+ * is unchanged by #1044.
72
+ * 3. Runtime *type* of a folded value — e.g. spreading `const n = 5`
73
+ * (`{...n}`) is shape-valid (`n` is a plain identifier) but `fold()`
74
+ * rejects it once it discovers `n` folds to a number, not an object.
75
+ * Only real evaluation catches this; EVL004 independently narrows
76
+ * spread sources to a stricter "traceable to a const" shape, which
77
+ * catches most real-world misuse without evaluating, but is not a
78
+ * full substitute.
79
+ *
80
+ * One more inherent gap, on the *value-flow* side rather than shape:
81
+ * `fold()` evaluates `&&`/`||`/`??` and `? :` lazily — it only folds the
82
+ * side/branch actually taken, exactly like the JS runtime — so an
83
+ * otherwise-unfoldable *untaken* branch does not reject
84
+ * (`false && sideEffect()` folds cleanly to `false`). This module (and so
85
+ * EVL) is flow-insensitive: it has no notion of "taken", so it requires
86
+ * every operand/branch to be shape-valid. This can only make EVL *stricter*
87
+ * than `fold()` (a false positive relative to fold, flagging code the
88
+ * folder would actually accept) — never the reverse. Making EVL
89
+ * flow-sensitive would mean re-implementing an evaluator inside a lint
90
+ * rule; out of scope here. See #1024.
91
+ */
92
+ /** The two EVL rule ids a shape violation can be attributed to. */
93
+ export type SubsetRuleId = "EVL001" | "EVL003";
94
+ /** A located, shape-level rejection: the offending node, the EVL rule id it maps to, and a message. */
95
+ export interface SubsetViolation {
96
+ node: ts.Node;
97
+ ruleId: SubsetRuleId;
98
+ message: string;
99
+ }
100
+ /** Binary operators `fold()` implements — see `fold()`'s operator switch in ./fold.ts. */
101
+ export declare const SUPPORTED_BINARY_OPERATORS: ReadonlySet<ts.SyntaxKind>;
102
+ /** Prefix unary operators `fold()` implements: logical-not and numeric negation. */
103
+ export declare const SUPPORTED_UNARY_OPERATORS: ReadonlySet<ts.SyntaxKind>;
104
+ /** A property name foldable without execution: identifier, string, or numeric literal (not a computed name). */
105
+ export declare function isLiteralPropertyName(node: ts.PropertyName): node is ts.Identifier | ts.StringLiteral | ts.NumericLiteral;
106
+ /** An element-access key foldable without execution: a string or numeric LITERAL only (EVL003 semantics). */
107
+ export declare function isLiteralElementKey(node: ts.Expression): node is ts.StringLiteral | ts.NumericLiteral;
108
+ export declare function computedPropertyNameMessage(node: ts.PropertyName): string;
109
+ export declare function dynamicElementAccessMessage(keyNode: ts.Expression): string;
110
+ export declare const UNSUPPORTED_OBJECT_MEMBER_MESSAGE = "unsupported object member";
111
+ export declare const UNSUPPORTED_UNARY_MESSAGE = "unsupported unary";
112
+ export declare function unsupportedBinaryMessage(opKind: ts.SyntaxKind): string;
113
+ export declare function callExpressionMessage(node: ts.CallExpression): string;
114
+ export declare function unsupportedExpressionMessage(node: ts.Node): string;
115
+ /**
116
+ * Classify one object-literal member (`{ a: 1 }`'s `a: 1`, `{ ...x }`'s
117
+ * `...x`, or a shorthand `{ a }`). Checks the key's shape before the
118
+ * value's, mirroring `propName()` in fold.ts, which runs before folding
119
+ * the value. Returns the first violation within this member, or
120
+ * `undefined` when it's fully in the subset.
121
+ */
122
+ export declare function checkObjectMember(prop: ts.ObjectLiteralElementLike, intrinsics?: readonly IntrinsicDef[]): SubsetViolation | undefined;
123
+ /**
124
+ * The canonical recursive shape classifier: is `node`'s expression *shape*
125
+ * within the subset `fold()` can reduce? Mirrors `fold()`'s own dispatch
126
+ * node-kind for node-kind (see ./fold.ts) — every branch here has a
127
+ * matching branch there, and vice versa — but performs no
128
+ * resolution/evaluation (see the module doc comment for the three
129
+ * environment-dependent exceptions). Returns the first (deepest,
130
+ * `fold()`-evaluation-order) unsupported node, or `undefined` when `node`'s
131
+ * whole shape is foldable.
132
+ */
133
+ export declare function findSubsetViolation(node: ts.Node, intrinsics?: readonly IntrinsicDef[]): SubsetViolation | undefined;
134
+ //# sourceMappingURL=subset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subset.d.ts","sourceRoot":"","sources":["../../src/fold/subset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AAEH,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/C,uGAAuG;AACvG,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,CAchE,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,CAG/D,CAAC;AAEH,gHAAgH;AAChH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,EAAE,CAAC,YAAY,GACpB,IAAI,IAAI,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,cAAc,CAE9D;AAED,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,aAAa,GAAG,EAAE,CAAC,cAAc,CAErG;AAQD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,GAAG,MAAM,CAEzE;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAE1E;AAED,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,MAAM,CAEtE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,GAAG,MAAM,CAErE;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,EAAE,CAAC,wBAAwB,EACjC,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAc7B;AAWD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,GACnC,eAAe,GAAG,SAAS,CAiK7B"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  export * from "./declarable.js";
7
7
  export * from "./composite.js";
8
8
  export * from "./provenance.js";
9
+ export * from "./build-params.js";
9
10
  export * from "./intrinsic.js";
10
11
  export * from "./types.js";
11
12
  export * from "./errors.js";
@@ -32,6 +33,7 @@ export * from "./graph-dot.js";
32
33
  export * from "./graph-layout.js";
33
34
  export * from "./graph-lens.js";
34
35
  export * from "./detectLexicon.js";
36
+ export * from "./fold/fold.js";
35
37
  export * from "./lint/parser.js";
36
38
  export * from "./lint/rule.js";
37
39
  export * from "./lint/rules/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -32,8 +32,13 @@ export declare class LexiconOutput implements Intrinsic {
32
32
  readonly outputName: string;
33
33
  /** @internal WeakRef to the source entity object for identity-based matching */
34
34
  readonly _sourceParent: WeakRef<object> | null;
35
- /** @internal Intrinsic value when constructed from an Intrinsic rather than AttrRef */
36
- private readonly _intrinsic;
35
+ /**
36
+ * @internal Intrinsic value when constructed from an Intrinsic rather than AttrRef.
37
+ * Readable outside the class (like `_sourceParent` above) so the entity-wire
38
+ * encoder can reach it without an `as unknown as` cast that would erase type
39
+ * checking on every field it reads (#1047).
40
+ */
41
+ readonly _intrinsic: Intrinsic | null;
37
42
  constructor(ref: AttrRef | Intrinsic | string, name: string);
38
43
  /**
39
44
  * Set the source entity logical name.
@@ -1 +1 @@
1
- {"version":3,"file":"lexicon-output.d.ts","sourceRoot":"","sources":["../src/lexicon-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAW5D;AAED;;;;;;;;GAQG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAG,IAAI,CAAU;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC/C,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;gBAElC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM;IA8B3D;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpC;;;;OAIG;IACH,cAAc,IAAI,OAAO;IAOzB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa;IAO5D,MAAM,IAAI;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE;CAGtC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAErF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE"}
1
+ {"version":3,"file":"lexicon-output.d.ts","sourceRoot":"","sources":["../src/lexicon-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAW5D;AAED;;;;;;;;GAQG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAG,IAAI,CAAU;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC/C;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,IAAI,CAAC;gBAE1B,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM;IA8B3D;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpC;;;;OAIG;IACH,cAAc,IAAI,OAAO;IAOzB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa;IAO5D,MAAM,IAAI;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE;CAGtC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAErF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE"}
@@ -7,7 +7,8 @@ export declare const IntrinsicDefSchema: z.ZodObject<{
7
7
  name: z.ZodString;
8
8
  description: z.ZodOptional<z.ZodString>;
9
9
  outputKey: z.ZodOptional<z.ZodString>;
10
- isTag: z.ZodOptional<z.ZodBoolean>;
10
+ isTag: z.ZodBoolean;
11
+ foldsAsCall: z.ZodOptional<z.ZodBoolean>;
11
12
  }, z.core.$strip>;
12
13
  export declare const LexiconManifestSchema: z.ZodObject<{
13
14
  name: z.ZodString;
@@ -18,7 +19,8 @@ export declare const LexiconManifestSchema: z.ZodObject<{
18
19
  name: z.ZodString;
19
20
  description: z.ZodOptional<z.ZodString>;
20
21
  outputKey: z.ZodOptional<z.ZodString>;
21
- isTag: z.ZodOptional<z.ZodBoolean>;
22
+ isTag: z.ZodBoolean;
23
+ foldsAsCall: z.ZodOptional<z.ZodBoolean>;
22
24
  }, z.core.$strip>>>;
23
25
  pseudoParameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
24
26
  }, z.core.$strip>;