@intentius/chant 0.18.16 → 0.18.17
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/components/verbs/cloud-executor.d.ts.map +1 -1
- package/dist/components/verbs/wait-verify.d.ts +2 -0
- package/dist/components/verbs/wait-verify.d.ts.map +1 -1
- package/dist/stack-output.d.ts +6 -3
- package/dist/stack-output.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/verbs/cloud-executor.ts +6 -1
- package/src/components/verbs/wait-verify.ts +11 -2
- package/src/stack-output.ts +27 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-executor.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/cloud-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cloud-executor.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/cloud-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAK1C,eAAO,MAAM,aAAa,2BAAkB,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,uDAAuD;IACvD,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,4FAA4F;IAC5F,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yEAAyE;IACzE,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,uFAAuF;IACvF,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAID,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/E;AAID,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAcD,eAAO,MAAM,UAAU,EAAE,YAmCxB,CAAC;AA6BF,wHAAwH;AACxH,wBAAgB,iBAAiB,IAAI,aAAa,CAEjD;AAKD,+FAA+F;AAC/F,wBAAgB,oBAAoB,IAAI,aAAa,CAGpD;AAED,sFAAsF;AACtF,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
|
|
@@ -68,6 +68,8 @@ export declare const waitEndpointCapability: Capability<WaitEndpointInput, WaitE
|
|
|
68
68
|
export interface HealthGateInput {
|
|
69
69
|
/** Health check path or full URL. */
|
|
70
70
|
path: string;
|
|
71
|
+
/** Optional base URL (scheme + host) composed with `path` via `new URL(path, host)`. May be a cross-stack Wiring value; a bare host gets `http://` prepended. */
|
|
72
|
+
host?: string;
|
|
71
73
|
/** Number of consecutive successes required. Default: 1. */
|
|
72
74
|
consecutiveSuccesses?: number;
|
|
73
75
|
/** Poll interval in ms. Default: 5000. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-verify.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/wait-verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnF,yGAAyG;AACzG,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAKzE,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,GAAE,aAAsC,GAC/C,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CAAC,CAoB/D;AAED,qFAAqF;AACrF,eAAO,MAAM,4BAA4B,EAAE,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CACjE,CAAC;AAIvC,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0FAA0F;AAC1F,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAsBjI;AAED,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAkC,CAAC;AAIxH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"wait-verify.d.ts","sourceRoot":"","sources":["../../../src/components/verbs/wait-verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnF,yGAAyG;AACzG,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAKzE,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,GAAE,aAAsC,GAC/C,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CAAC,CAoB/D;AAED,qFAAqF;AACrF,eAAO,MAAM,4BAA4B,EAAE,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CACjE,CAAC;AAIvC,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0FAA0F;AAC1F,wBAAgB,4BAA4B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAsBjI;AAED,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAkC,CAAC;AAIxH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,iKAAiK;IACjK,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB;AASD,iHAAiH;AACjH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,OAAwB,GAAG,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAyB3H;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,EAAE,UAAU,CAAC,eAAe,EAAE,gBAAgB,CAAgC,CAAC"}
|
package/dist/stack-output.d.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* it via `nestedStack().outputs.name`.
|
|
7
7
|
*/
|
|
8
8
|
import { DECLARABLE_MARKER, type Declarable } from "./declarable.js";
|
|
9
|
-
import
|
|
9
|
+
import { AttrRef } from "./attrref.js";
|
|
10
|
+
import { type Intrinsic } from "./intrinsic.js";
|
|
10
11
|
/**
|
|
11
12
|
* Marker symbol for stack output identification.
|
|
12
13
|
*/
|
|
@@ -21,7 +22,9 @@ export interface StackOutput extends Declarable {
|
|
|
21
22
|
readonly lexicon: string;
|
|
22
23
|
readonly entityType: string;
|
|
23
24
|
readonly kind: "output";
|
|
24
|
-
|
|
25
|
+
/** The exported value: a bare attribute reference, or an intrinsic wrapping
|
|
26
|
+
* one (e.g. `Join(",", zone.NameServers)`). */
|
|
27
|
+
readonly sourceRef: AttrRef | Intrinsic;
|
|
25
28
|
readonly description?: string;
|
|
26
29
|
}
|
|
27
30
|
/**
|
|
@@ -46,7 +49,7 @@ export declare function isStackOutput(value: unknown): value is StackOutput;
|
|
|
46
49
|
* });
|
|
47
50
|
* ```
|
|
48
51
|
*/
|
|
49
|
-
export declare function stackOutput(ref: AttrRef, options?: {
|
|
52
|
+
export declare function stackOutput(ref: AttrRef | Intrinsic, options?: {
|
|
50
53
|
description?: string;
|
|
51
54
|
}): StackOutput;
|
|
52
55
|
//# sourceMappingURL=stack-output.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack-output.d.ts","sourceRoot":"","sources":["../src/stack-output.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"stack-output.d.ts","sourceRoot":"","sources":["../src/stack-output.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAAkC,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAAC;IACrC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB;mDAC+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAgBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAOlE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,GAAG,SAAS,EACxB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,WAAW,CAuBb"}
|
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { exec } from "node:child_process";
|
|
20
20
|
import { createConnection } from "node:net";
|
|
21
21
|
import { promisify } from "node:util";
|
|
22
|
+
import { isAbsolute, join } from "node:path";
|
|
22
23
|
|
|
23
24
|
export const execFileAsync = promisify(exec);
|
|
24
25
|
|
|
@@ -104,7 +105,11 @@ function q(value: string): string {
|
|
|
104
105
|
export const realDocker: DockerClient = {
|
|
105
106
|
async build(args) {
|
|
106
107
|
const parts = [`docker build`, `-t ${q(args.tag)}`];
|
|
107
|
-
if (args.dockerfile)
|
|
108
|
+
if (args.dockerfile) {
|
|
109
|
+
// dockerfile is relative to `context` (its documented contract); docker's `-f` resolves a relative path against cwd, not the context dir, so join them here (chant#936).
|
|
110
|
+
const dockerfilePath = isAbsolute(args.dockerfile) ? args.dockerfile : join(args.context, args.dockerfile);
|
|
111
|
+
parts.push(`-f ${q(dockerfilePath)}`);
|
|
112
|
+
}
|
|
108
113
|
if (args.target) parts.push(`--target ${q(args.target)}`);
|
|
109
114
|
for (const [k, v] of Object.entries(args.buildArgs ?? {})) parts.push(`--build-arg ${q(`${k}=${v}`)}`);
|
|
110
115
|
parts.push(q(args.context));
|
|
@@ -128,6 +128,8 @@ export const waitEndpointCapability: Capability<WaitEndpointInput, WaitEndpointO
|
|
|
128
128
|
export interface HealthGateInput {
|
|
129
129
|
/** Health check path or full URL. */
|
|
130
130
|
path: string;
|
|
131
|
+
/** Optional base URL (scheme + host) composed with `path` via `new URL(path, host)`. May be a cross-stack Wiring value; a bare host gets `http://` prepended. */
|
|
132
|
+
host?: string;
|
|
131
133
|
/** Number of consecutive successes required. Default: 1. */
|
|
132
134
|
consecutiveSuccesses?: number;
|
|
133
135
|
/** Poll interval in ms. Default: 5000. */
|
|
@@ -139,6 +141,13 @@ export interface HealthGateOutput {
|
|
|
139
141
|
healthy: boolean;
|
|
140
142
|
}
|
|
141
143
|
|
|
144
|
+
/** Compose the fetchable URL: `host` set → resolve `path` against it (bare host → `http://` prepended); else `path` as-is. */
|
|
145
|
+
function healthGateUrl(input: HealthGateInput): string {
|
|
146
|
+
if (!input.host) return input.path;
|
|
147
|
+
const base = /^https?:\/\//.test(input.host) ? input.host : `http://${input.host}`;
|
|
148
|
+
return new URL(input.path, base).toString();
|
|
149
|
+
}
|
|
150
|
+
|
|
142
151
|
/** Block progression until a health check passes — the generic post-deploy verification gate. Cloud-agnostic. */
|
|
143
152
|
export function createHealthGateCapability(fetcher: Fetcher = defaultFetcher): Capability<HealthGateInput, HealthGateOutput> {
|
|
144
153
|
return {
|
|
@@ -152,14 +161,14 @@ export function createHealthGateCapability(fetcher: Fetcher = defaultFetcher): C
|
|
|
152
161
|
for (;;) {
|
|
153
162
|
let ok = false;
|
|
154
163
|
try {
|
|
155
|
-
ok = (await fetcher(input
|
|
164
|
+
ok = (await fetcher(healthGateUrl(input))).ok;
|
|
156
165
|
} catch {
|
|
157
166
|
ok = false;
|
|
158
167
|
}
|
|
159
168
|
streak = ok ? streak + 1 : 0;
|
|
160
169
|
if (streak >= need) return { healthy: true };
|
|
161
170
|
if (Date.now() >= deadline) {
|
|
162
|
-
throw new Error(`health-gate: ${input
|
|
171
|
+
throw new Error(`health-gate: ${healthGateUrl(input)} did not reach ${need} consecutive healthy check(s) within 300000ms`);
|
|
163
172
|
}
|
|
164
173
|
await sleep(intervalMs);
|
|
165
174
|
}
|
package/src/stack-output.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { DECLARABLE_MARKER, type Declarable } from "./declarable";
|
|
10
|
-
import
|
|
10
|
+
import { AttrRef } from "./attrref";
|
|
11
|
+
import { isIntrinsic, type Intrinsic } from "./intrinsic";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Marker symbol for stack output identification.
|
|
@@ -24,10 +25,26 @@ export interface StackOutput extends Declarable {
|
|
|
24
25
|
readonly lexicon: string;
|
|
25
26
|
readonly entityType: string;
|
|
26
27
|
readonly kind: "output";
|
|
27
|
-
|
|
28
|
+
/** The exported value: a bare attribute reference, or an intrinsic wrapping
|
|
29
|
+
* one (e.g. `Join(",", zone.NameServers)`). */
|
|
30
|
+
readonly sourceRef: AttrRef | Intrinsic;
|
|
28
31
|
readonly description?: string;
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
/** Find the first AttrRef anywhere inside a value (walking intrinsics/objects/
|
|
35
|
+
* arrays), so a wrapping intrinsic can still borrow its parent's lexicon. */
|
|
36
|
+
function firstAttrRef(value: unknown, seen = new Set<unknown>()): AttrRef | undefined {
|
|
37
|
+
if (value === null || typeof value !== "object" || seen.has(value)) return undefined;
|
|
38
|
+
if (value instanceof AttrRef) return value;
|
|
39
|
+
seen.add(value);
|
|
40
|
+
const children = Array.isArray(value) ? value : Object.values(value as Record<string, unknown>);
|
|
41
|
+
for (const child of children) {
|
|
42
|
+
const found = firstAttrRef(child, seen);
|
|
43
|
+
if (found) return found;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
/**
|
|
32
49
|
* Type guard for StackOutput.
|
|
33
50
|
*/
|
|
@@ -59,11 +76,16 @@ export function isStackOutput(value: unknown): value is StackOutput {
|
|
|
59
76
|
* ```
|
|
60
77
|
*/
|
|
61
78
|
export function stackOutput(
|
|
62
|
-
ref: AttrRef,
|
|
79
|
+
ref: AttrRef | Intrinsic,
|
|
63
80
|
options?: { description?: string },
|
|
64
81
|
): StackOutput {
|
|
65
|
-
|
|
66
|
-
|
|
82
|
+
if (!(ref instanceof AttrRef) && !isIntrinsic(ref)) {
|
|
83
|
+
throw new Error("stackOutput(ref): ref must be an attribute reference or an intrinsic wrapping one");
|
|
84
|
+
}
|
|
85
|
+
// Derive lexicon from the referenced entity — for a bare AttrRef, its parent;
|
|
86
|
+
// for an intrinsic (Join etc.), the first AttrRef nested inside it.
|
|
87
|
+
const anchor = ref instanceof AttrRef ? ref : firstAttrRef(ref);
|
|
88
|
+
const parent = anchor?.parent.deref();
|
|
67
89
|
const lexicon = parent && typeof (parent as Record<string, unknown>).lexicon === "string"
|
|
68
90
|
? (parent as Record<string, unknown>).lexicon as string
|
|
69
91
|
: "unknown";
|