@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.
- package/dist/build-params.d.ts +108 -0
- package/dist/build-params.d.ts.map +1 -0
- package/dist/build.d.ts +79 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts +31 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts +41 -0
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -0
- package/dist/cli/commands/check-lexicon-intrinsics.d.ts +71 -0
- package/dist/cli/commands/check-lexicon-intrinsics.d.ts.map +1 -0
- package/dist/cli/commands/check-lexicon.d.ts +1 -1
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts +27 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/lint.d.ts.map +1 -1
- package/dist/cli/handlers/run-client.d.ts +1 -1
- package/dist/cli/handlers/run-client.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/plugins.d.ts +16 -0
- package/dist/cli/plugins.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +10 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/docs-sections.d.ts.map +1 -1
- package/dist/codegen/docs-types.d.ts +2 -0
- package/dist/codegen/docs-types.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +12 -5
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/discover.d.ts +62 -7
- package/dist/components/discover.d.ts.map +1 -1
- package/dist/components/sandbox/driver.d.ts +12 -0
- package/dist/components/sandbox/driver.d.ts.map +1 -0
- package/dist/components/sandbox/run.d.ts +42 -0
- package/dist/components/sandbox/run.d.ts.map +1 -0
- package/dist/composite.d.ts +5 -0
- package/dist/composite.d.ts.map +1 -1
- package/dist/config.d.ts +71 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/declarable.d.ts +16 -0
- package/dist/declarable.d.ts.map +1 -1
- package/dist/discovery/collect.d.ts.map +1 -1
- package/dist/discovery/entity-wire-codec.d.ts +166 -0
- package/dist/discovery/entity-wire-codec.d.ts.map +1 -0
- package/dist/discovery/entity-wire.d.ts +50 -0
- package/dist/discovery/entity-wire.d.ts.map +1 -0
- package/dist/discovery/fold-import.d.ts +239 -0
- package/dist/discovery/fold-import.d.ts.map +1 -0
- package/dist/discovery/index.d.ts +74 -1
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.d.ts +18 -0
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -0
- package/dist/discovery/sandbox/child-errors.d.ts +15 -0
- package/dist/discovery/sandbox/child-errors.d.ts.map +1 -0
- package/dist/discovery/sandbox/driver.d.ts +13 -0
- package/dist/discovery/sandbox/driver.d.ts.map +1 -0
- package/dist/discovery/sandbox/run.d.ts +69 -0
- package/dist/discovery/sandbox/run.d.ts.map +1 -0
- package/dist/errors.d.ts +9 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/fold/fold.d.ts +299 -0
- package/dist/fold/fold.d.ts.map +1 -0
- package/dist/fold/foldable-helpers.d.ts +121 -0
- package/dist/fold/foldable-helpers.d.ts.map +1 -0
- package/dist/fold/subset.d.ts +134 -0
- package/dist/fold/subset.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon-output.d.ts +7 -2
- package/dist/lexicon-output.d.ts.map +1 -1
- package/dist/lexicon-schema.d.ts +4 -2
- package/dist/lexicon-schema.d.ts.map +1 -1
- package/dist/lexicon.d.ts +131 -1
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts +11 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lint/component-checks.d.ts +7 -1
- package/dist/lint/component-checks.d.ts.map +1 -1
- package/dist/lint/rules/evl001-non-literal-expression.d.ts.map +1 -1
- package/dist/lint/rules/evl003-dynamic-property-access.d.ts.map +1 -1
- package/dist/params.d.ts +60 -0
- package/dist/params.d.ts.map +1 -0
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/runtime.d.ts +10 -1
- package/dist/runtime.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/build-params.test.ts +144 -0
- package/src/build-params.ts +207 -0
- package/src/build.test.ts +38 -0
- package/src/build.ts +144 -7
- package/src/cli/commands/build.test.ts +220 -2
- package/src/cli/commands/build.ts +111 -3
- package/src/cli/commands/check-lexicon-examples.test.ts +92 -0
- package/src/cli/commands/check-lexicon-examples.ts +103 -0
- package/src/cli/commands/check-lexicon-intrinsics.test.ts +179 -0
- package/src/cli/commands/check-lexicon-intrinsics.ts +348 -0
- package/src/cli/commands/check-lexicon.test.ts +34 -0
- package/src/cli/commands/check-lexicon.ts +137 -1
- package/src/cli/commands/lint.ts +31 -3
- package/src/cli/commands/onboard.ts +1 -1
- package/src/cli/component-security-boundary.test.ts +170 -0
- package/src/cli/handlers/build.ts +24 -3
- package/src/cli/handlers/components.ts +9 -2
- package/src/cli/handlers/dev.ts +1 -1
- package/src/cli/handlers/graph.ts +7 -5
- package/src/cli/handlers/lifecycle.ts +2 -2
- package/src/cli/handlers/lint.ts +2 -0
- package/src/cli/handlers/misc.ts +2 -2
- package/src/cli/handlers/run-client.ts +1 -1
- package/src/cli/handlers/run.ts +20 -5
- package/src/cli/main.test.ts +22 -0
- package/src/cli/main.ts +39 -0
- package/src/cli/plugins.ts +20 -4
- package/src/cli/registry.ts +10 -0
- package/src/cli/security-boundary.test.ts +135 -0
- package/src/codegen/docs-sections.test.ts +67 -0
- package/src/codegen/docs-sections.ts +7 -3
- package/src/codegen/docs-types.ts +2 -0
- package/src/components/cli-support.ts +22 -10
- package/src/components/discover.ts +127 -25
- package/src/components/sandbox/driver.ts +114 -0
- package/src/components/sandbox/run.test.ts +185 -0
- package/src/components/sandbox/run.ts +177 -0
- package/src/composite.test.ts +21 -0
- package/src/composite.ts +20 -1
- package/src/config.ts +81 -0
- package/src/declarable.ts +20 -0
- package/src/discovery/collect.ts +17 -3
- package/src/discovery/entity-wire-codec.ts +487 -0
- package/src/discovery/entity-wire.test.ts +240 -0
- package/src/discovery/entity-wire.ts +67 -0
- package/src/discovery/fold-import.test.ts +1598 -0
- package/src/discovery/fold-import.ts +1998 -0
- package/src/discovery/index.test.ts +191 -1
- package/src/discovery/index.ts +242 -1
- package/src/discovery/sandbox/bundle.ts +218 -0
- package/src/discovery/sandbox/child-errors.ts +65 -0
- package/src/discovery/sandbox/driver.ts +147 -0
- package/src/discovery/sandbox/run.test.ts +179 -0
- package/src/discovery/sandbox/run.ts +196 -0
- package/src/errors.ts +9 -1
- package/src/fold/fold.test.ts +812 -0
- package/src/fold/fold.ts +805 -0
- package/src/fold/foldable-helpers.ts +171 -0
- package/src/fold/subset-doc-parity.test.ts +210 -0
- package/src/fold/subset.test.ts +352 -0
- package/src/fold/subset.ts +383 -0
- package/src/index.ts +2 -0
- package/src/lexicon-output.ts +7 -2
- package/src/lexicon-schema.test.ts +57 -0
- package/src/lexicon-schema.ts +8 -1
- package/src/lexicon.ts +132 -1
- package/src/lifecycle/git.test.ts +10 -5
- package/src/lifecycle/release-ledger.test.ts +28 -0
- package/src/lifecycle/release-ledger.ts +11 -0
- package/src/lint/component-checks.ts +8 -1
- package/src/lint/rules/evl001-non-literal-expression.ts +26 -110
- package/src/lint/rules/evl003-dynamic-property-access.ts +11 -2
- package/src/params.test.ts +22 -0
- package/src/params.ts +66 -0
- package/src/provenance.ts +22 -0
- package/src/runtime.ts +11 -2
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chant #1045 (Phase 1) — the JSON wire format for a discovered, named,
|
|
3
|
+
* ref-resolved entity set, plus (below) the standalone `discover()` +
|
|
4
|
+
* encode entry point.
|
|
5
|
+
*
|
|
6
|
+
* The codec itself — {@link WireValue}, {@link EntitySetWire},
|
|
7
|
+
* {@link encodeEntitySet}, {@link decodeEntitySet}, and friends — lives in
|
|
8
|
+
* `./entity-wire-codec.ts` (chant #1045 Phase 2 split this out) and is
|
|
9
|
+
* re-exported here unchanged. That file has NO dependency on `discover()` (or
|
|
10
|
+
* anything that pulls in the `typescript` compiler package), which matters
|
|
11
|
+
* because chant #1045 Phase 2's sandboxed child bundles JUST the codec —
|
|
12
|
+
* bundling this file, `discoverEntitySetJson` and all, would drag `discover`
|
|
13
|
+
* → `fold-import` → `typescript` (a multi-megabyte CJS package that doesn't
|
|
14
|
+
* survive ESM bundling on its own) into a driver that only ever needs to
|
|
15
|
+
* encode, never to discover. See `./sandbox/driver.ts`.
|
|
16
|
+
*/
|
|
17
|
+
export type { WireValue, WireDeclarableEntity, WireLexiconOutputEntity, WireEntity, EntitySetWire, } from "./entity-wire-codec.js";
|
|
18
|
+
export { encodeEntitySet, decodeEntitySet } from "./entity-wire-codec.js";
|
|
19
|
+
import type { FoldDecision } from "./index.js";
|
|
20
|
+
import { type DiscoveryOptions } from "./index.js";
|
|
21
|
+
import { type EntitySetWire } from "./entity-wire-codec.js";
|
|
22
|
+
/** A discovery run's full result as pure JSON — {@link encodeEntitySet} plus the already-JSON-safe rest of {@link DiscoveryResult} (`./index.ts`). */
|
|
23
|
+
export interface DiscoveredEntitiesJson {
|
|
24
|
+
entitySet: EntitySetWire;
|
|
25
|
+
sourceFiles: string[];
|
|
26
|
+
/** `DiscoveryError.toJSON()` output — see `../errors.ts`. */
|
|
27
|
+
errors: Array<{
|
|
28
|
+
name: string;
|
|
29
|
+
file: string;
|
|
30
|
+
message: string;
|
|
31
|
+
type: string;
|
|
32
|
+
}>;
|
|
33
|
+
foldDecisions: FoldDecision[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Run discovery over `path` — scanning files, importing/folding modules,
|
|
37
|
+
* naming entities, and resolving `AttrRef`s (all unchanged, reusing
|
|
38
|
+
* `discover()` as-is) — and return the result as pure JSON via
|
|
39
|
+
* {@link encodeEntitySet}. This is the boundary chant#1045 Phase 2 moved into
|
|
40
|
+
* a sandboxed child process for the run-fallback subset — see
|
|
41
|
+
* `./sandbox/run.ts` — Phase 1 only proved the data can cross it losslessly
|
|
42
|
+
* (see the fold-vs-JSON differential in `examples/`).
|
|
43
|
+
*
|
|
44
|
+
* Reuses `discover()` unchanged, so the fold/run-fallback split and the
|
|
45
|
+
* `planFoldTaint` identity-taint invariant (`./fold-import.ts`) are exactly
|
|
46
|
+
* what they are today — this function only serializes whatever `discover()`
|
|
47
|
+
* already decided to produce.
|
|
48
|
+
*/
|
|
49
|
+
export declare function discoverEntitySetJson(path: string, options?: DiscoveryOptions): Promise<DiscoveredEntitiesJson>;
|
|
50
|
+
//# sourceMappingURL=entity-wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-wire.d.ts","sourceRoot":"","sources":["../../src/discovery/entity-wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,YAAY,EACV,SAAS,EACT,oBAAoB,EACpB,uBAAuB,EACvB,UAAU,EACV,aAAa,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAY,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAO1E,sJAAsJ;AACtJ,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,aAAa,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6DAA6D;IAC7D,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAQrH"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { type Declarable } from "../declarable.js";
|
|
2
|
+
import { type CompositeInstance } from "../composite.js";
|
|
3
|
+
import type { IntrinsicDef } from "../lexicon.js";
|
|
4
|
+
import type { BuildParamValue } from "../build-params.js";
|
|
5
|
+
/**
|
|
6
|
+
* Bridges the static folder ({@link ../fold/fold}, #1026) into discovery
|
|
7
|
+
* (#1022/#1023, epic #1019): attempts to fold one source file into real
|
|
8
|
+
* `Declarable`/`CompositeInstance` instances with zero execution of the
|
|
9
|
+
* file's own top-level code, so `discover()` can skip `importModule` for it
|
|
10
|
+
* entirely.
|
|
11
|
+
*
|
|
12
|
+
* The folder only reduces expressions to plain values — it has no notion of
|
|
13
|
+
* lexicon resource classes or composites. This module supplies that missing
|
|
14
|
+
* piece: it reads the file's `import` declarations to learn which module
|
|
15
|
+
* each `new Type(...)` constructor or bare composite-factory call names,
|
|
16
|
+
* resolves and imports *that* module (a trusted lexicon/vendor module, not
|
|
17
|
+
* the file under fold), and constructs the real resource/composite instance
|
|
18
|
+
* from the folded props. Importing the lexicon module is not a regression on
|
|
19
|
+
* "no module execution" — the run path already imports it to get the same
|
|
20
|
+
* class/function; the only thing skipped here is executing the file's *own*
|
|
21
|
+
* statements.
|
|
22
|
+
*
|
|
23
|
+
* chant #1023 (epic #1019 Phase 5) extends this from leaf resources
|
|
24
|
+
* (`new Type(...)`) to composite factory calls — `SomeComposite({...})`,
|
|
25
|
+
* `propagate(SomeComposite({...}), {...})`, member access on the result
|
|
26
|
+
* (`web.deployment`), and destructuring (`const { a, b } = SomeComposite(...)`
|
|
27
|
+
* or `export const { a, b } = SomeComposite(...)`). A composite factory is a
|
|
28
|
+
* pure function of its props (EVL009/EVL010 guarantee its body only
|
|
29
|
+
* references props, sibling members, and imports), so — exactly like a
|
|
30
|
+
* resource constructor — it's safe to resolve through the file's imports and
|
|
31
|
+
* actually invoke with statically-folded props: no need to pre-verify "is
|
|
32
|
+
* this specifically a registered composite" via a shared registry (which
|
|
33
|
+
* would be unreliable across separately-loaded module instances of
|
|
34
|
+
* `@intentius/chant` anyway) — {@link resolveCallExpression} just resolves,
|
|
35
|
+
* invokes, and lets the RESULT speak. If it satisfies
|
|
36
|
+
* {@link isCompositeInstance} (or, for a plain resource-returning helper,
|
|
37
|
+
* {@link isDeclarable}), it's used. Nested composites and `propagate()`'d
|
|
38
|
+
* shared props need no special-casing: a nested composite is just another
|
|
39
|
+
* member the real factory call already produced (real JS execution inside a
|
|
40
|
+
* trusted module), and `propagate` is just another resolvable imported
|
|
41
|
+
* function that receives a live `CompositeInstance` plus folded shared props
|
|
42
|
+
* and returns it — `expandComposite()` (invoked downstream by
|
|
43
|
+
* `collectEntities`, unchanged) does the recursive expansion and the shared-
|
|
44
|
+
* prop merge exactly as it does for the run path.
|
|
45
|
+
*/
|
|
46
|
+
/** One exported `const` name folded to a real, constructed `Declarable` or `CompositeInstance`. */
|
|
47
|
+
export type FoldedEntity = [name: string, entity: Declarable | CompositeInstance];
|
|
48
|
+
export type FoldFileResult = {
|
|
49
|
+
ok: true;
|
|
50
|
+
entities: FoldedEntity[];
|
|
51
|
+
/**
|
|
52
|
+
* chant #1020 — EVERY exported name's fully-resolved value, not just
|
|
53
|
+
* the `Declarable`/`CompositeInstance` ones already in `entities`: a
|
|
54
|
+
* plain value folds too (a string, a number, a plain object), it just
|
|
55
|
+
* contributes nothing to `entities` (see {@link applyResolvedValue}).
|
|
56
|
+
* This is the table another file's cross-file reference resolves
|
|
57
|
+
* against — see `buildExternals` below and the module doc on
|
|
58
|
+
* `planFoldTaint` for why a resource/composite value here MUST be the
|
|
59
|
+
* exact same object every referencing file sees.
|
|
60
|
+
*/
|
|
61
|
+
exportedValues: Map<string, unknown>;
|
|
62
|
+
/**
|
|
63
|
+
* chant #1044 — the OTHER project files whose exported OBJECTS this
|
|
64
|
+
* fold consumed (a cross-file `Declarable`, composite instance, or any
|
|
65
|
+
* other non-primitive reached through `buildExternals`/a re-export).
|
|
66
|
+
*
|
|
67
|
+
* Object identity is the thing that cannot survive one side of the
|
|
68
|
+
* build folding while the other runs, so `planFoldTaint` needs to know
|
|
69
|
+
* who consumed whose objects: if a file here is forced back to run, the
|
|
70
|
+
* instance THIS file already captured is not the instance discovery
|
|
71
|
+
* will collect, and serialization fails on an entity with no logical
|
|
72
|
+
* name. A primitive (string, number, boolean, null) is never recorded —
|
|
73
|
+
* it has no identity to disagree about.
|
|
74
|
+
*/
|
|
75
|
+
liveSources: ReadonlySet<string>;
|
|
76
|
+
} | {
|
|
77
|
+
ok: false;
|
|
78
|
+
reason: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* A per-build memo (chant #1020) so a project file imported by several
|
|
82
|
+
* others is folded exactly ONCE — every referrer resolves against the SAME
|
|
83
|
+
* `FoldFileResult`, and therefore the SAME constructed
|
|
84
|
+
* `Declarable`/`CompositeInstance` objects, no matter how many files
|
|
85
|
+
* cross-file-reference it or in what order discovery visits them. Also
|
|
86
|
+
* tracks the current resolution call chain (`stack`) so a genuine reference
|
|
87
|
+
* cycle (fileA needs fileB needs fileA) is DETECTED — rather than an
|
|
88
|
+
* infinite recursion / a promise awaiting itself forever — and reported as a
|
|
89
|
+
* located `FoldError` naming the cycle path.
|
|
90
|
+
*
|
|
91
|
+
* `discover()` creates exactly one session per `{ fold: true }` build and
|
|
92
|
+
* passes it to every top-level `tryFoldFile` call, so its own per-file loop
|
|
93
|
+
* and any cross-file reference reaching into the same file share the
|
|
94
|
+
* identical cache. Callers that don't care about cross-file sharing (unit
|
|
95
|
+
* tests exercising a single file in isolation) can omit it — {@link tryFoldFile}
|
|
96
|
+
* creates a private, single-call session on their behalf.
|
|
97
|
+
*/
|
|
98
|
+
export interface FoldSession {
|
|
99
|
+
readonly intrinsics: readonly IntrinsicDef[];
|
|
100
|
+
readonly cache: Map<string, Promise<FoldFileResult>>;
|
|
101
|
+
readonly stack: string[];
|
|
102
|
+
/**
|
|
103
|
+
* Per-build memo (chant #1020 hang fix) for {@link importModule} itself —
|
|
104
|
+
* keyed by resolved absolute module path, shared session-wide exactly like
|
|
105
|
+
* {@link cache} above. Cross-file resolution means MANY files in one
|
|
106
|
+
* directory can each independently resolve the SAME constructor/composite-
|
|
107
|
+
* factory import (e.g. every file that constructs an AWS resource imports
|
|
108
|
+
* the same lexicon barrel) — before this, every one of those calls issued
|
|
109
|
+
* its own `await import(path)`, relying entirely on the runtime's own
|
|
110
|
+
* module cache to make the repeats cheap. That assumption holds for a
|
|
111
|
+
* plain `node`/`tsx` process, but NOT for a real dynamic import running
|
|
112
|
+
* inside a vitest worker: `vite-node`'s own SSR module graph can take a
|
|
113
|
+
* real, non-trivial amount of wall-clock time to re-resolve/re-register an
|
|
114
|
+
* already-loaded module on EVERY call, not just the first — harmless at
|
|
115
|
+
* single-digit call counts, but #1020's cross-file resolution can issue
|
|
116
|
+
* several times as many `importModule` calls for the same handful of large
|
|
117
|
+
* lexicon barrels within one `discover()` pass as the pre-#1020 single-file
|
|
118
|
+
* fold did. Memoizing the import itself (not just the path resolution)
|
|
119
|
+
* caps it at exactly one real `import()` per unique path per session,
|
|
120
|
+
* regardless of how many files reference it — this is what actually keeps
|
|
121
|
+
* a session-local retry (e.g. `sandbox-differential.test.ts`'s
|
|
122
|
+
* `vi.resetModules()` + rebuild path, which reruns fold from a cold
|
|
123
|
+
* module cache) from compounding into a multi-minute stall. Purely a cache
|
|
124
|
+
* over an idempotent operation (the same resolved path always yields the
|
|
125
|
+
* same module namespace object) — doesn't change what folds.
|
|
126
|
+
*/
|
|
127
|
+
readonly importCache: Map<string, Promise<Record<string, unknown>>>;
|
|
128
|
+
/**
|
|
129
|
+
* Per-build memo (chant #1020 hang fix) for {@link resolveModulePath}'s
|
|
130
|
+
* RELATIVE/absolute-specifier branch only — keyed by
|
|
131
|
+
* `${dirname(fromFile)}\0${specifier}`. See {@link resolveModulePathMemoized}'s
|
|
132
|
+
* doc for the full story, including why bare (package) specifiers are
|
|
133
|
+
* memoized in a separate, process-wide cache instead of this session-
|
|
134
|
+
* scoped one: a relative specifier resolves against PROJECT source, which
|
|
135
|
+
* `chant build --watch` can legitimately change between rebuilds (a new
|
|
136
|
+
* sibling file appearing mid-session), so this cache is intentionally
|
|
137
|
+
* thrown away with the rest of the session at the end of every
|
|
138
|
+
* `discover()` call, unlike the bare-specifier one.
|
|
139
|
+
*/
|
|
140
|
+
readonly resolvePathCache: Map<string, string>;
|
|
141
|
+
/**
|
|
142
|
+
* chant #1064 — this build's resolved build-time parameter values (see
|
|
143
|
+
* ../build-params.ts), consulted only by {@link buildExternals}'s one
|
|
144
|
+
* recognized bare-specifier case: a named `params` import resolving to
|
|
145
|
+
* ../params.ts. `undefined` when the build supplied none (no `chant.config.ts`
|
|
146
|
+
* `buildParams` declared, or the caller didn't pass any) — a project that
|
|
147
|
+
* doesn't use build-time parameters pays nothing extra here.
|
|
148
|
+
*/
|
|
149
|
+
readonly buildParams?: Readonly<Record<string, BuildParamValue>>;
|
|
150
|
+
}
|
|
151
|
+
/** Create a fresh, empty {@link FoldSession}. */
|
|
152
|
+
export declare function createFoldSession(intrinsics?: readonly IntrinsicDef[], buildParams?: Readonly<Record<string, BuildParamValue>>): FoldSession;
|
|
153
|
+
/**
|
|
154
|
+
* Attempt to fold one source file with zero execution of its own top-level
|
|
155
|
+
* code. Returns the folded, instantiated entities on success, or a reason
|
|
156
|
+
* to fall back to the run path (`importModule`) on the first construct
|
|
157
|
+
* outside the fold subset.
|
|
158
|
+
*
|
|
159
|
+
* @param intrinsics - Lexicon-registered intrinsic tags (chant #1039), e.g.
|
|
160
|
+
* AWS's `Sub`. Threaded down to {@link fold}/{@link foldResource} so a
|
|
161
|
+
* registered tagged template folds instead of unconditionally throwing
|
|
162
|
+
* "unregistered tagged template intrinsic". Defaults to none — the caller
|
|
163
|
+
* (`discover()`, ultimately `chant build --fold`) is expected to pass the
|
|
164
|
+
* target lexicons' combined `intrinsics()`. Ignored when `session` is
|
|
165
|
+
* given (its own `intrinsics`, fixed at creation, apply instead).
|
|
166
|
+
* @param session - chant #1020: share ONE {@link FoldSession} across every
|
|
167
|
+
* file in a build (as `discover()` does) so a project file imported by
|
|
168
|
+
* several others folds exactly once and every referrer shares the same
|
|
169
|
+
* constructed entities — see {@link FoldSession}'s doc. Omit for a
|
|
170
|
+
* standalone, single-file fold attempt (creates a private session scoped
|
|
171
|
+
* to just this call — a cross-file reference reachable from `file` still
|
|
172
|
+
* resolves, just without sharing its cache with any other top-level call).
|
|
173
|
+
*/
|
|
174
|
+
export declare function tryFoldFile(file: string, intrinsics?: readonly IntrinsicDef[], session?: FoldSession): Promise<FoldFileResult>;
|
|
175
|
+
/**
|
|
176
|
+
* A file that folds successfully in isolation must still be forced back to
|
|
177
|
+
* run if some OTHER discovered file — one that itself falls back to run —
|
|
178
|
+
* imports it (directly, or transitively through another sibling file it
|
|
179
|
+
* imports). Composite folding is what makes this reachable: `network.ts`
|
|
180
|
+
* exporting `export const network = VpcDefault({})` folds cleanly on its
|
|
181
|
+
* own (no cross-file reference needed), landing its Declarables (`vpc`, its
|
|
182
|
+
* subnets, …) in `entities` as ONE set of real objects, built by literally
|
|
183
|
+
* invoking `VpcDefault` from inside `tryFoldFile` — bypassing `network.ts`
|
|
184
|
+
* as a module entirely (that's the whole point of folding it).
|
|
185
|
+
*
|
|
186
|
+
* Before chant #1020, a sibling file like `alb.ts` that did
|
|
187
|
+
* `import { network } from "./network"; ... vpcId: network.vpc.VpcId`
|
|
188
|
+
* could never fold that cross-file reference and fell back to run — but
|
|
189
|
+
* running `alb.ts` for real re-executes `import "./network"` for real too,
|
|
190
|
+
* which (via Node's module cache) produces the SAME `network.ts` module
|
|
191
|
+
* instance for every OTHER run-fallback file that imports it, but a
|
|
192
|
+
* DIFFERENT one than the object `tryFoldFile("network.ts")` already built.
|
|
193
|
+
* `alb.ts`'s AttrRef for `network.vpc.VpcId` then points at an object
|
|
194
|
+
* that's never in the `entities` map (only the folded one is), so it can
|
|
195
|
+
* never be assigned a logical name and serialization fails outright — not
|
|
196
|
+
* drift, a crash.
|
|
197
|
+
*
|
|
198
|
+
* The fix: fold and run must never disagree about which object identity a
|
|
199
|
+
* given file's exports have. Since `network.ts` itself doesn't need
|
|
200
|
+
* anything cross-file to fold (only a file's own successful fold could ever
|
|
201
|
+
* reach this taint — an unresolvable cross-file reference already fails
|
|
202
|
+
* that file's OWN fold attempt), the safe rule is to force `network.ts`
|
|
203
|
+
* back to run too, so both `alb.ts`'s real import and `network.ts`'s own
|
|
204
|
+
* discovery entry resolve through the exact same `importModule` call and
|
|
205
|
+
* share the exact same singleton module instance. This has to propagate
|
|
206
|
+
* transitively (if `alb.ts` itself is only reachable by importing a file
|
|
207
|
+
* that imports `network.ts`), so this is a forward-reachability walk over
|
|
208
|
+
* the discovered files' relative-import graph, seeded from every file that
|
|
209
|
+
* doesn't fold on its own.
|
|
210
|
+
*
|
|
211
|
+
* chant #1044 adds the OTHER half of the same hazard, in the opposite
|
|
212
|
+
* direction along the same edges. Forward taint covers "a run file imports a
|
|
213
|
+
* folded file"; it does not cover "a FOLDED file consumed the objects of a
|
|
214
|
+
* file that later got forced to run". Once a plain-call intrinsic can fold,
|
|
215
|
+
* that second case is easy to reach: in `lexicons/aws/examples/lambda-api`,
|
|
216
|
+
* `health-api.ts` folds and captures `params.ts`'s real `Parameter` instance
|
|
217
|
+
* through `Ref(environment)`, while `params.ts` itself is forced to run
|
|
218
|
+
* because a DIFFERENT sibling (`data-bucket.ts`) imports it and falls back.
|
|
219
|
+
* Discovery then collects the run instance and serializes the folded one —
|
|
220
|
+
* the same "Logical name not set" crash described above, arriving from the
|
|
221
|
+
* other side. So `liveSources` (see {@link FoldFileResult}) contributes
|
|
222
|
+
* reverse edges here: a tainted file taints every folded file that captured
|
|
223
|
+
* one of its objects. Only object identity propagates — a file that imported
|
|
224
|
+
* a plain string from a tainted file has nothing to disagree about.
|
|
225
|
+
*
|
|
226
|
+
* chant #1020 changes the calculus but not this function: `alb.ts` can now
|
|
227
|
+
* often fold `network.vpc.VpcId` too (see `buildExternals`/`foldFileMemoized`
|
|
228
|
+
* above), by reusing THE EXACT SAME `tryFoldFile("network.ts")` call (memoized
|
|
229
|
+
* per `FoldSession`) that `discover()`'s own per-file loop also uses — so
|
|
230
|
+
* `alb.ts` and `network.ts` share one real `vpc` object without ever
|
|
231
|
+
* disagreeing. This invariant is still needed for whatever STILL falls back
|
|
232
|
+
* after #1020 (a call-as-a-value construct, #1044; a shape #1020 doesn't
|
|
233
|
+
* cover): the edge collection below is unconditional — it doesn't care
|
|
234
|
+
* whether an edge happens to ALSO be used for cross-file value resolution —
|
|
235
|
+
* so the exact same forced-taint safety net still applies to that remaining
|
|
236
|
+
* boundary, unchanged.
|
|
237
|
+
*/
|
|
238
|
+
export declare function planFoldTaint(files: readonly string[], wouldFold: ReadonlyMap<string, boolean>, liveSources?: ReadonlyMap<string, ReadonlySet<string>>): Promise<Set<string>>;
|
|
239
|
+
//# sourceMappingURL=fold-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fold-import.d.ts","sourceRoot":"","sources":["../../src/discovery/fold-import.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAgB3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,mGAAmG;AACnG,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,iBAAiB,CAAC,CAAC;AAElF,MAAM,MAAM,cAAc,GACtB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;;;;;OASG;IACH,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;;;;;;;;;;OAYG;IACH,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAClE;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAC/B,UAAU,GAAE,SAAS,YAAY,EAAO,EACxC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,GACtD,WAAW,CAEb;AAsmDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,SAAS,YAAY,EAAO,EACxC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,CAEzB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GACrD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA8EtB"}
|
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
import type { Declarable } from "../declarable.js";
|
|
2
2
|
import type { DiscoveryError } from "../errors.js";
|
|
3
|
+
import type { IntrinsicDef } from "../lexicon.js";
|
|
4
|
+
import type { BuildParamProvenance } from "../provenance.js";
|
|
5
|
+
/**
|
|
6
|
+
* Per-file fold-vs-run outcome (chant #1022, epic #1019), populated only
|
|
7
|
+
* when {@link DiscoveryOptions.fold} was requested. Lets a caller (`chant
|
|
8
|
+
* build --fold`) report which files skipped module execution and which
|
|
9
|
+
* fell back to the run path, and why.
|
|
10
|
+
*/
|
|
11
|
+
export interface FoldDecision {
|
|
12
|
+
/** Absolute path of the source file this decision covers. */
|
|
13
|
+
file: string;
|
|
14
|
+
/** "fold" — folded statically, zero execution. "run" — imported/executed as before. */
|
|
15
|
+
mode: "fold" | "run";
|
|
16
|
+
/** Why the file fell back to run. Present only when `mode === "run"` and fold was requested. */
|
|
17
|
+
reason?: string;
|
|
18
|
+
/** Number of entities the fold produced. Present only when `mode === "fold"`. */
|
|
19
|
+
resourceCount?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Optional inputs to {@link discover}.
|
|
23
|
+
*/
|
|
24
|
+
export interface DiscoveryOptions {
|
|
25
|
+
/**
|
|
26
|
+
* chant #1022/#1023 (epic #1019) — opt-in: for each source file, try to
|
|
27
|
+
* fold it to `Declarable`/`CompositeInstance` entities statically (no
|
|
28
|
+
* module execution) before falling back to importing/running it. Anything
|
|
29
|
+
* the folder can't represent (a non-`new`, non-composite-call export, a
|
|
30
|
+
* cross-file-only reference, …) falls back per-file — see
|
|
31
|
+
* {@link planFoldTaint} for the one case where a file that WOULD fold in
|
|
32
|
+
* isolation is still forced back to run, to keep fold and run from ever
|
|
33
|
+
* disagreeing about a shared entity's identity. Default `false` — behavior
|
|
34
|
+
* is unchanged unless requested.
|
|
35
|
+
*/
|
|
36
|
+
fold?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* chant #1039 — lexicon-registered intrinsic tags (e.g. AWS's `Sub`) to
|
|
39
|
+
* recognize while folding. Threaded down to `tryFoldFile`/the static
|
|
40
|
+
* folder so a registered tagged template folds instead of falling back to
|
|
41
|
+
* run. Only meaningful when {@link fold} is set; ignored otherwise.
|
|
42
|
+
* Default: none (an intrinsic-using file still folds up to that point,
|
|
43
|
+
* then falls back to run at the unregistered tag).
|
|
44
|
+
*/
|
|
45
|
+
intrinsics?: IntrinsicDef[];
|
|
46
|
+
/**
|
|
47
|
+
* chant #1045 Phase 2 — opt-in: whatever would otherwise reach the
|
|
48
|
+
* in-process `importModule` step (every file, when {@link fold} isn't set;
|
|
49
|
+
* only the per-file run-fallback remainder, when it is) instead runs
|
|
50
|
+
* together, isolated, in one sandboxed child process — see
|
|
51
|
+
* `./sandbox/run.ts`. Folded files are unaffected: fold already executes
|
|
52
|
+
* zero of a file's own top-level code, so it stays in this process exactly
|
|
53
|
+
* as it does today. Default `false` — behavior, including performance
|
|
54
|
+
* (no bundling, no child process, no IPC), is unchanged unless requested.
|
|
55
|
+
*/
|
|
56
|
+
sandbox?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* chant #1064 — this build's resolved build-time parameter values (see
|
|
59
|
+
* ../build-params.ts's `resolveBuildParams`, driven by the CLI's
|
|
60
|
+
* `--param`/`--params-file`/declared `env` mapping/`chant.config.ts`
|
|
61
|
+
* defaults). Populated into `../params.ts`'s shared `params` object
|
|
62
|
+
* (`setBuildParams`, below) before any project file is imported or folded,
|
|
63
|
+
* and threaded into the fold session so a `params.<name>` reference
|
|
64
|
+
* resolves to a literal instead of an unresolved identifier. Default: none
|
|
65
|
+
* — `params` stays empty, matching a project that declares no
|
|
66
|
+
* `buildParams` at all.
|
|
67
|
+
*/
|
|
68
|
+
buildParams?: BuildParamProvenance[];
|
|
69
|
+
}
|
|
3
70
|
/**
|
|
4
71
|
* Result of the discovery process
|
|
5
72
|
*/
|
|
@@ -12,6 +79,11 @@ export interface DiscoveryResult {
|
|
|
12
79
|
sourceFiles: string[];
|
|
13
80
|
/** Array of errors encountered during discovery */
|
|
14
81
|
errors: DiscoveryError[];
|
|
82
|
+
/**
|
|
83
|
+
* Per-file fold-vs-run decisions (#1022). Empty unless
|
|
84
|
+
* {@link DiscoveryOptions.fold} was set.
|
|
85
|
+
*/
|
|
86
|
+
foldDecisions: FoldDecision[];
|
|
15
87
|
}
|
|
16
88
|
/**
|
|
17
89
|
* Discovers all declarable entities in a directory by scanning files,
|
|
@@ -19,7 +91,8 @@ export interface DiscoveryResult {
|
|
|
19
91
|
* a dependency graph.
|
|
20
92
|
*
|
|
21
93
|
* @param path - The directory path to discover entities in
|
|
94
|
+
* @param options - Optional discovery behavior, e.g. {@link DiscoveryOptions.fold}
|
|
22
95
|
* @returns DiscoveryResult with entities, dependencies, sourceFiles, and errors
|
|
23
96
|
*/
|
|
24
|
-
export declare function discover(path: string): Promise<DiscoveryResult>;
|
|
97
|
+
export declare function discover(path: string, options?: DiscoveryOptions): Promise<DiscoveryResult>;
|
|
25
98
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;IAE5B;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,8DAA8D;IAC9D,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,qDAAqD;IACrD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mDAAmD;IACnD,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB;;;OAGG;IACH,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoQjG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface BundleResult {
|
|
2
|
+
/** Absolute, REALPATH'd path to the bundled entry file — this and {@link bundleDir} are what the caller grants `--allow-fs-read` to. macOS's `/tmp` is a symlink to `/private/tmp`; an un-canonicalized path here would silently fail to match Node's own (already-canonicalized) permission check. */
|
|
3
|
+
bundlePath: string;
|
|
4
|
+
/** Absolute, REALPATH'd directory containing {@link bundlePath} — remove with `rmSync(bundleDir, { recursive: true, force: true })` once done. */
|
|
5
|
+
bundleDir: string;
|
|
6
|
+
/** Directories the child ALSO needs `--allow-fs-read` for — the resolved locations of {@link EXTERNAL_PACKAGES}, which are deliberately left unbundled (see {@link externalTrustedPackagesPlugin}'s doc). Empty when none of those packages were actually imported. */
|
|
7
|
+
externalReadPaths: string[];
|
|
8
|
+
/** Wall-clock bundling time — chant#1045 asks this be measured and reported, not silently accepted. */
|
|
9
|
+
durationMs: number;
|
|
10
|
+
/** Bundle size in bytes. */
|
|
11
|
+
bytes: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Bundle `driverSource` (see {@link import("./driver.js").generateDriverSource})
|
|
15
|
+
* into a single self-contained ESM file.
|
|
16
|
+
*/
|
|
17
|
+
export declare function bundleDriver(driverSource: string): Promise<BundleResult>;
|
|
18
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../src/discovery/sandbox/bundle.ts"],"names":[],"mappings":"AA4KA,MAAM,WAAW,YAAY;IAC3B,uSAAuS;IACvS,UAAU,EAAE,MAAM,CAAC;IACnB,kJAAkJ;IAClJ,SAAS,EAAE,MAAM,CAAC;IAClB,uQAAuQ;IACvQ,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,uGAAuG;IACvG,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA4B9E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DiscoveryError, type DiscoveryErrorType } from "../../errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Classify one error raised while executing run-fallback project source (or
|
|
4
|
+
* chant's own collect/resolve/encode step) inside the sandboxed child.
|
|
5
|
+
*
|
|
6
|
+
* @param file - The project source file being executed when `err` was
|
|
7
|
+
* thrown, or `""` for an error not attributable to one specific file (e.g.
|
|
8
|
+
* `collectEntities`/`resolveAttrRefs` over the whole batch).
|
|
9
|
+
* @param fallbackType - The {@link DiscoveryErrorType} to use when `err`
|
|
10
|
+
* isn't a permission denial — mirrors how `discover()` itself types a
|
|
11
|
+
* plain import failure `"import"` vs. a collection/resolution failure
|
|
12
|
+
* `"resolution"`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function classifyChildError(file: string, err: unknown, fallbackType?: DiscoveryErrorType): DiscoveryError;
|
|
15
|
+
//# sourceMappingURL=child-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-errors.d.ts","sourceRoot":"","sources":["../../../src/discovery/sandbox/child-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAkCvE;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,EACZ,YAAY,GAAE,kBAA6B,GAC1C,cAAc,CAchB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface GenerateDriverOptions {
|
|
2
|
+
/** Absolute paths to the run-fallback files this build decided NOT to fold — see `discover()`'s fold/taint loop in `../index.ts`. */
|
|
3
|
+
files: readonly string[];
|
|
4
|
+
/** The build root — threaded to `collectEntities` exactly as `discover()` threads its own `path` argument, so cross-directory stack-prefix disambiguation (chant #932) is computed the same way for this subset. */
|
|
5
|
+
buildRoot: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Generate the driver module's full TypeScript source. Written to a tmp file
|
|
9
|
+
* and bundled (see `./bundle.ts`) before being handed to a sandboxed child —
|
|
10
|
+
* never executed directly by the parent process.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateDriverSource(options: GenerateDriverOptions): string;
|
|
13
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../src/discovery/sandbox/driver.ts"],"names":[],"mappings":"AA4CA,MAAM,WAAW,qBAAqB;IACpC,qIAAqI;IACrI,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,oNAAoN;IACpN,SAAS,EAAE,MAAM,CAAC;CACnB;AAOD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAqF3E"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Declarable } from "../../declarable.js";
|
|
2
|
+
import { DiscoveryError } from "../../errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* chant #1045 Phase 2 — runs every run-fallback file for a build TOGETHER, as
|
|
5
|
+
* one bundled module graph, inside one sandboxed child process, and returns
|
|
6
|
+
* the same shape `discover()`'s own in-process run path would have produced:
|
|
7
|
+
* a named, ref-resolved entities map plus any errors.
|
|
8
|
+
*
|
|
9
|
+
* Isolation mechanics (verified on Node v24.13.1 — see the chant#1045 PR
|
|
10
|
+
* description for the full write-up):
|
|
11
|
+
* - `--permission --allow-fs-read=<bundle dir>,<project dir>[,<trusted
|
|
12
|
+
* external package dirs>]` — no filesystem write, no child-process, no
|
|
13
|
+
* worker-thread access. Bundling with esbuild first (not a packaging
|
|
14
|
+
* change — see `./bundle.ts`) means the child needs NO TypeScript loader
|
|
15
|
+
* (no `tsx`, so no `--allow-worker` and no writable temp dir either),
|
|
16
|
+
* unlike the plain `tsx`-based run path. The "trusted external package
|
|
17
|
+
* dirs" allowance is narrow and specific: `./bundle.ts` deliberately
|
|
18
|
+
* leaves a couple of chant/lexicon-internal dependencies (`typescript`)
|
|
19
|
+
* unbundled and resolves them to their real, fixed location instead —
|
|
20
|
+
* project source never controls what's installed there.
|
|
21
|
+
* - The env is a spawn-time scrub (`env: {}` below, plus `PATH` — see the
|
|
22
|
+
* option below), not `--permission`: Node's Permission Model does not gate
|
|
23
|
+
* `process.env` at all (confirmed: every key stays readable even under
|
|
24
|
+
* `--permission`).
|
|
25
|
+
* - Network egress is NOT addressed here — Node has no flag for it. See the
|
|
26
|
+
* chant#1045 PR description / docs for the residual-risk statement and
|
|
27
|
+
* deployment guidance (a container with no egress, a network namespace).
|
|
28
|
+
* This function does not claim to close that gap.
|
|
29
|
+
*
|
|
30
|
+
* What does NOT run inside the child: fold (`tryFoldFile`, `../fold-import`)
|
|
31
|
+
* stays exactly where it is today, in the parent, unsandboxed — fold already
|
|
32
|
+
* executes zero of the file's own top-level code (chant #1022/#1023), so
|
|
33
|
+
* isolating it buys nothing and would only cost a bundle+spawn per build.
|
|
34
|
+
* Only genuine run-fallback files are handed to this function.
|
|
35
|
+
*/
|
|
36
|
+
export interface SandboxRunResult {
|
|
37
|
+
/** Named, ref-resolved entities from the run-fallback set — decoded from the child's `EntitySetWire` response, functionally indistinguishable from what `importModule` + `collectEntities` + `resolveAttrRefs` would have produced in-process for this same file set (see `../entity-wire.ts`'s `decodeEntitySet` doc). */
|
|
38
|
+
entities: Map<string, Declarable>;
|
|
39
|
+
/** Import/collection/resolution/permission errors, already chant-shaped (see `./child-errors.ts` — a permission denial names the file and the operation, never a raw `ERR_ACCESS_DENIED`). */
|
|
40
|
+
errors: DiscoveryError[];
|
|
41
|
+
/** esbuild bundling wall-clock time — chant#1045 asks this be measured, not silently accepted. */
|
|
42
|
+
bundleMs: number;
|
|
43
|
+
/** Bundle size in bytes. */
|
|
44
|
+
bundleBytes: number;
|
|
45
|
+
/**
|
|
46
|
+
* Entity name → declaring file, for every entity in {@link entities} whose
|
|
47
|
+
* provenance (`../../provenance.ts`) named one. The wire format itself
|
|
48
|
+
* doesn't carry this (`encodeEntitySet` intentionally drops build metadata,
|
|
49
|
+
* not declared configuration) — it rides back as a small side channel so a
|
|
50
|
+
* parent-side merge collision against the fold-only set (a bare name
|
|
51
|
+
* genuinely exported by both a folded and a run-fallback file in the same
|
|
52
|
+
* directory) can name the real file, not the entity name. See `../index.ts`.
|
|
53
|
+
*/
|
|
54
|
+
provenanceByName: Record<string, string>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Run `files` (already decided "run" by `discover()`'s fold/taint pass)
|
|
58
|
+
* together, isolated, in one sandboxed child process. Returns the same
|
|
59
|
+
* `{ entities, errors }` shape the parent's own `collectEntities` +
|
|
60
|
+
* `resolveAttrRefs` would have — see `../index.ts`'s `discover()`, which
|
|
61
|
+
* merges this result into the entities it collected from folded files.
|
|
62
|
+
*
|
|
63
|
+
* @param files - Absolute paths to run-fallback files.
|
|
64
|
+
* @param buildRoot - The directory `discover()` was pointed at — threaded to
|
|
65
|
+
* `collectEntities` inside the child (stack-prefix disambiguation, #932)
|
|
66
|
+
* and used to compute the project-directory read allowance.
|
|
67
|
+
*/
|
|
68
|
+
export declare function runFallbackFilesSandboxed(files: readonly string[], buildRoot: string): Promise<SandboxRunResult>;
|
|
69
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/discovery/sandbox/run.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAA2B,MAAM,cAAc,CAAC;AAMvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,2TAA2T;IAC3T,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,8LAA8L;IAC9L,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAsC3B"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Error types for chant discovery, build, and lint failures
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* `"permission"` (chant #1045 Phase 2) — a run-fallback file executing inside
|
|
6
|
+
* the sandboxed child (`./discovery/sandbox/`) hit Node's Permission Model
|
|
7
|
+
* (`ERR_ACCESS_DENIED`) — filesystem, child-process, or worker-thread access
|
|
8
|
+
* outside the sandbox's allowlist. Distinct from `"import"` (a module simply
|
|
9
|
+
* failed to load/execute for an ordinary reason) so a permission denial is
|
|
10
|
+
* recognizable as a sandbox boundary hit, not a generic import failure.
|
|
11
|
+
*/
|
|
12
|
+
export type DiscoveryErrorType = "import" | "resolution" | "circular" | "permission";
|
|
5
13
|
/**
|
|
6
14
|
* Error during file discovery or module import
|
|
7
15
|
*/
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,CAAC;AAErF;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;gBAEtB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB;IAOnE,MAAM;;;;;;CAQP;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAM/C,MAAM;;;;;CAOP;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM;IAUjB,MAAM;;;;;;;;CAUP"}
|