@intentius/chant 0.44.5 → 0.44.7
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/cli/commands/carve-bridge.d.ts.map +1 -1
- package/dist/cli/commands/carve-emit.d.ts +3 -1
- package/dist/cli/commands/carve-emit.d.ts.map +1 -1
- package/dist/cli/commands/carve.d.ts +64 -2
- package/dist/cli/commands/carve.d.ts.map +1 -1
- package/dist/terraform/adopt-state.d.ts +18 -1
- package/dist/terraform/adopt-state.d.ts.map +1 -1
- package/dist/terraform/aws-resources.d.ts +29 -0
- package/dist/terraform/aws-resources.d.ts.map +1 -1
- package/dist/terraform/bridge.d.ts +8 -0
- package/dist/terraform/bridge.d.ts.map +1 -1
- package/dist/terraform/carve.d.ts +8 -3
- package/dist/terraform/carve.d.ts.map +1 -1
- package/dist/terraform/graph.d.ts +10 -4
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/parse.d.ts.map +1 -1
- package/dist/terraform/score.d.ts +11 -0
- package/dist/terraform/score.d.ts.map +1 -1
- package/dist/terraform/types.d.ts +11 -0
- package/dist/terraform/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/carve-bridge.test.ts +32 -0
- package/src/cli/commands/carve-bridge.ts +3 -0
- package/src/cli/commands/carve-emit-state.test.ts +107 -0
- package/src/cli/commands/carve-emit.ts +37 -5
- package/src/cli/commands/carve.test.ts +82 -3
- package/src/cli/commands/carve.ts +81 -6
- package/src/terraform/__fixtures__/advise.test.ts +114 -1
- package/src/terraform/adopt-state.test.ts +64 -0
- package/src/terraform/adopt-state.ts +52 -2
- package/src/terraform/aws-resources.test.ts +102 -1
- package/src/terraform/aws-resources.ts +144 -2
- package/src/terraform/bridge.test.ts +30 -0
- package/src/terraform/bridge.ts +19 -1
- package/src/terraform/carve.test.ts +34 -0
- package/src/terraform/carve.ts +0 -0
- package/src/terraform/graph.test.ts +45 -0
- package/src/terraform/graph.ts +35 -16
- package/src/terraform/parse.ts +4 -1
- package/src/terraform/score.test.ts +25 -0
- package/src/terraform/score.ts +27 -4
- package/src/terraform/types.ts +11 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carve-bridge.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/carve-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAAkB,KAAK,UAAU,EAAuB,MAAM,wBAAwB,CAAC;AAK9F,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,mDAAmD;IACnD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AASD,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+GtF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"carve-bridge.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/carve-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAAkB,KAAK,UAAU,EAAuB,MAAM,wBAAwB,CAAC;AAK9F,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,mDAAmD;IACnD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AASD,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+GtF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAqCnE"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* resource at the observe position: emitted, reversible, nothing mutated.
|
|
13
13
|
*/
|
|
14
14
|
import { type CarveReport } from "../../terraform/carve.js";
|
|
15
|
-
import { type DeferredParam } from "../../terraform/adopt-state.js";
|
|
15
|
+
import { type DeferredParam, type FoldedContribution } from "../../terraform/adopt-state.js";
|
|
16
16
|
import type { LexiconPlugin, ResourceSelector } from "../../lexicon.js";
|
|
17
17
|
import type { ImportResult, LiveImportOptions } from "./import.js";
|
|
18
18
|
export interface CarveEmitOptions {
|
|
@@ -56,6 +56,8 @@ export interface CarveEmitResult {
|
|
|
56
56
|
scaffolded?: string[];
|
|
57
57
|
/** Deferred outbound inputs declared as build parameters in the emitted project (#998). */
|
|
58
58
|
params?: DeferredParam[];
|
|
59
|
+
/** Folded sub-resources and the props each joined into the emitted parent (#1637). */
|
|
60
|
+
folded?: FoldedContribution[];
|
|
59
61
|
/** The persisted carve state manifest bridge/apply compose with. */
|
|
60
62
|
manifestPath?: string;
|
|
61
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carve-emit.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/carve-emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAI5F,OAAO,
|
|
1
|
+
{"version":3,"file":"carve-emit.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/carve-emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAI5F,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEhE,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7F;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,oCAAoC;IACpC,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC5B,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB,sFAAsF;IACtF,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC9B,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAyGrG;AAiJD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAwD/D"}
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* emit/boundary/apply phases stay in #197, gated on demand.
|
|
8
8
|
*/
|
|
9
9
|
import { type Peelability } from "../../terraform/score.js";
|
|
10
|
+
import { type BoundaryEdge } from "../../terraform/carve.js";
|
|
11
|
+
import type { TfGraph } from "../../terraform/types.js";
|
|
10
12
|
export interface CarveAdviseOptions {
|
|
11
13
|
/** Terraform estate directory (from `--from`). */
|
|
12
14
|
from?: string;
|
|
@@ -20,10 +22,70 @@ export interface CarveAdviseResult {
|
|
|
20
22
|
error?: string;
|
|
21
23
|
from?: string;
|
|
22
24
|
results?: Peelability[];
|
|
25
|
+
/**
|
|
26
|
+
* The parsed dependency graph the scores came from. Kept so the JSON report
|
|
27
|
+
* can carry the boundary edge lists (#1636) rather than only their counts.
|
|
28
|
+
* Not part of the JSON payload — `carveJson` derives from it.
|
|
29
|
+
*/
|
|
30
|
+
graph?: TfGraph;
|
|
23
31
|
}
|
|
24
32
|
export declare function carveAdvise(opts: CarveAdviseOptions): Promise<CarveAdviseResult>;
|
|
25
|
-
/**
|
|
26
|
-
|
|
33
|
+
/**
|
|
34
|
+
* The schema version of the `--json` / `--report` payload (#1636).
|
|
35
|
+
*
|
|
36
|
+
* The report is a cross-tool contract — behold renders it as a graph — so it
|
|
37
|
+
* says which shape it is. The promise attached to this number:
|
|
38
|
+
*
|
|
39
|
+
* - **Additive within a version.** New top-level fields, new per-resource
|
|
40
|
+
* fields, new kinds of entry in an existing list, and new values in an
|
|
41
|
+
* open-ended enum (a `bridge` kind, say) may appear in any release. A
|
|
42
|
+
* reader must ignore keys and values it does not know.
|
|
43
|
+
* - **A removal, a rename, or a changed meaning bumps it.** So does narrowing
|
|
44
|
+
* a field's type (an optional becoming required is additive; the reverse is
|
|
45
|
+
* not).
|
|
46
|
+
* - A reader that does not know the version it is handed should refuse the
|
|
47
|
+
* report rather than half-read it.
|
|
48
|
+
*/
|
|
49
|
+
export declare const CARVE_REPORT_VERSION = 1;
|
|
50
|
+
/** One ranked resource in the JSON report: its score, plus the boundary its carve would cut. */
|
|
51
|
+
export interface CarveJsonResource extends Peelability {
|
|
52
|
+
/**
|
|
53
|
+
* Every dependency edge carving this resource would cut (#1636), in chant's
|
|
54
|
+
* own `BoundaryEdge` shape — the same classification the emit/bridge path
|
|
55
|
+
* runs on. `inbound` edges need a Terraform `data`-source patch the moment
|
|
56
|
+
* the carve lands; `outbound` edges become deploy-time inputs, deferred
|
|
57
|
+
* until apply.
|
|
58
|
+
*
|
|
59
|
+
* The lists are the *carve set's* boundary, so a folded sub-resource never
|
|
60
|
+
* appears as an endpoint: it carves with its parent, and the parent's edges
|
|
61
|
+
* stand in for it. Edges internal to the carve set are not boundary work and
|
|
62
|
+
* are not listed.
|
|
63
|
+
*
|
|
64
|
+
* An inbound edge's survivor can be an `output.<name>` pseudo-address
|
|
65
|
+
* (#1638), carrying `bridge: "tf-output-rewrite"` and `via: ["value"]`. It
|
|
66
|
+
* is counted in `breakdown.outputs`, not `breakdown.inbound`.
|
|
67
|
+
*
|
|
68
|
+
* Present (possibly with two empty lists) whenever the graph was available;
|
|
69
|
+
* absent means this chant did not compute it — "none" and "not reported" are
|
|
70
|
+
* different claims. `breakdown.inbound`/`outbound` keep the counts.
|
|
71
|
+
*/
|
|
72
|
+
boundary?: {
|
|
73
|
+
inbound: BoundaryEdge[];
|
|
74
|
+
outbound: BoundaryEdge[];
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** The `chant carve advise --json` / `--report` payload. Versioned; see {@link CARVE_REPORT_VERSION}. */
|
|
78
|
+
export interface CarveJsonReport {
|
|
79
|
+
version: number;
|
|
80
|
+
from?: string;
|
|
81
|
+
advisory: string;
|
|
82
|
+
count: number;
|
|
83
|
+
/** Band name -> how many resources landed in it. */
|
|
84
|
+
bands: Record<string, number>;
|
|
85
|
+
resources: CarveJsonResource[];
|
|
86
|
+
}
|
|
87
|
+
/** Build the `--json` / `--report` payload. */
|
|
88
|
+
export declare function carveJson(result: CarveAdviseResult): CarveJsonReport;
|
|
27
89
|
/** Human-readable banded, ranked summary. */
|
|
28
90
|
export declare function formatCarveReport(result: CarveAdviseResult): string;
|
|
29
91
|
//# sourceMappingURL=carve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carve.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/carve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAe,KAAK,WAAW,EAAwB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"carve.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/carve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAe,KAAK,WAAW,EAAwB,MAAM,uBAAuB,CAAC;AAC5F,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAID,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2BtF;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,gGAAgG;AAChG,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,YAAY,EAAE,CAAC;QAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;CAClE;AAED,yGAAyG;AACzG,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC;AAED,+CAA+C;AAC/C,wBAAgB,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAapE;AAUD,6CAA6C;AAC7C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAyBnE"}
|
|
@@ -38,6 +38,13 @@ export interface DeferredParam {
|
|
|
38
38
|
/** The state-resolved value — the parameter's declared default. */
|
|
39
39
|
default?: string | number | boolean;
|
|
40
40
|
}
|
|
41
|
+
/** What one folded sub-resource contributed to the parent's emitted props (#1637). */
|
|
42
|
+
export interface FoldedContribution {
|
|
43
|
+
/** The sub-resource's Terraform address, e.g. `aws_s3_bucket_versioning.assets`. */
|
|
44
|
+
address: string;
|
|
45
|
+
/** CFN properties it added to the parent, e.g. `["VersioningConfiguration"]`. */
|
|
46
|
+
props: string[];
|
|
47
|
+
}
|
|
41
48
|
export interface AdoptedSource {
|
|
42
49
|
fileName: string;
|
|
43
50
|
content: string;
|
|
@@ -46,6 +53,8 @@ export interface AdoptedSource {
|
|
|
46
53
|
nativeType: string;
|
|
47
54
|
/** Deferred params actually substituted into the emitted props (#998). */
|
|
48
55
|
parameterized: string[];
|
|
56
|
+
/** Folded sub-resources and the props each one joined into the parent (#1637). */
|
|
57
|
+
folded: FoldedContribution[];
|
|
49
58
|
}
|
|
50
59
|
/** Is this Terraform type adoptable from state (has a native constructor)? */
|
|
51
60
|
export declare function canAdoptFromState(tfType: string): boolean;
|
|
@@ -59,6 +68,14 @@ export declare function supportedStateAdoptionTypes(): string[];
|
|
|
59
68
|
* A mapped attribute named by a `DeferredParam` renders as a `params.<name>`
|
|
60
69
|
* reference (a real chant build parameter) instead of the state literal —
|
|
61
70
|
* the value came from a survivor, so it stays overridable per build.
|
|
71
|
+
*
|
|
72
|
+
* `folded` carries the carve set's sub-resources (`aws_s3_bucket_versioning`
|
|
73
|
+
* and friends), read from the same state file. Their mappable attributes join
|
|
74
|
+
* the parent's props (#1637) — a fold that only announced itself and left the
|
|
75
|
+
* emitted resource without the versioning or public-access block the Terraform
|
|
76
|
+
* declared was a silent loss of configuration. A sub-resource's setting wins
|
|
77
|
+
* over the parent's own legacy in-state block: it is the one the config
|
|
78
|
+
* actually declares.
|
|
62
79
|
*/
|
|
63
|
-
export declare function adoptFromState(resource: StateResource, params?: DeferredParam[]): AdoptedSource | null;
|
|
80
|
+
export declare function adoptFromState(resource: StateResource, params?: DeferredParam[], folded?: StateResource[]): AdoptedSource | null;
|
|
64
81
|
//# sourceMappingURL=adopt-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-state.d.ts","sourceRoot":"","sources":["../../src/terraform/adopt-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"adopt-state.d.ts","sourceRoot":"","sources":["../../src/terraform/adopt-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,uEAAuE;AACvE,eAAO,MAAM,aAAa,4BAA4B,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CACrC;AAED,sFAAsF;AACtF,MAAM,WAAW,kBAAkB;IACjC,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kFAAkF;IAClF,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,uFAAuF;AACvF,wBAAgB,2BAA2B,IAAI,MAAM,EAAE,CAEtD;AAUD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,aAAa,EACvB,MAAM,GAAE,aAAa,EAAO,EAC5B,MAAM,GAAE,aAAa,EAAO,GAC3B,aAAa,GAAG,IAAI,CAoEtB"}
|
|
@@ -36,6 +36,35 @@ export interface AwsCarveType {
|
|
|
36
36
|
export declare const AWS_LEXICON_IMPORT = "@intentius/chant-lexicon-aws";
|
|
37
37
|
export declare const AWS_CARVE_TYPES: AwsCarveType[];
|
|
38
38
|
export declare function awsCarveType(tfType: string): AwsCarveType | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* How a folded sub-resource (see `FOLDS_INTO`) joins its parent's emitted
|
|
41
|
+
* properties (#1637). Terraform splits configuration the CloudFormation shape
|
|
42
|
+
* keeps inside the parent resource, so the fold is not just a carve-set
|
|
43
|
+
* membership claim: the sub-resource's attributes have to land in the parent's
|
|
44
|
+
* props, or the emitted resource silently loses what the Terraform declared.
|
|
45
|
+
*/
|
|
46
|
+
export interface AwsFoldMapper {
|
|
47
|
+
/** Sub-resource attributes this mapper reads. Anything else stays unmapped. */
|
|
48
|
+
consumes: string[];
|
|
49
|
+
/** The parent CFN properties this sub-resource contributes. */
|
|
50
|
+
map: (attrs: Record<string, unknown>) => Record<string, unknown>;
|
|
51
|
+
}
|
|
52
|
+
export declare const AWS_FOLD_MAPPERS: Record<string, AwsFoldMapper>;
|
|
53
|
+
/**
|
|
54
|
+
* Apply a folded sub-resource's state attributes to its parent's properties.
|
|
55
|
+
*
|
|
56
|
+
* Returns the props it contributes plus the attributes that stay genuinely
|
|
57
|
+
* unmappable (which the emitted source preserves in its reference comment). A
|
|
58
|
+
* mapper that produced nothing consumes nothing — the caller reports the whole
|
|
59
|
+
* sub-resource rather than claiming a fold that did not happen. `null` means
|
|
60
|
+
* this sub-resource type has no fold mapping at all.
|
|
61
|
+
*/
|
|
62
|
+
export declare function applyAwsFold(tfType: string, attrs: Record<string, unknown>): {
|
|
63
|
+
props: Record<string, unknown>;
|
|
64
|
+
unmapped: Record<string, unknown>;
|
|
65
|
+
} | null;
|
|
66
|
+
/** A folded sub-resource's attributes minus what was consumed and its parent link. */
|
|
67
|
+
export declare function unmappedFoldAttrs(attrs: Record<string, unknown>, consumed?: ReadonlySet<string>): Record<string, unknown>;
|
|
39
68
|
/**
|
|
40
69
|
* Apply an entry's field mappings to a resource's Terraform attributes, yielding
|
|
41
70
|
* CloudFormation properties and the set of attribute keys that were consumed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aws-resources.d.ts","sourceRoot":"","sources":["../../src/terraform/aws-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,+DAA+D;AAC/D,KAAK,SAAS,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,kEAAkE;IAClE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"aws-resources.d.ts","sourceRoot":"","sources":["../../src/terraform/aws-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,+DAA+D;AAC/D,KAAK,SAAS,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,kEAAkE;IAClE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AA6DjE,eAAO,MAAM,eAAe,EAAE,YAAY,EA2NzC,CAAC;AAIF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAErE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,+DAA+D;IAC/D,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClE;AAKD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAiC1D,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAM9E;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAa,GACxC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB;AASD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAuB1D"}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* Bridge: add a `data` source for the (now chant-managed) resource and
|
|
9
9
|
* rewrite the survivor's `type.name.attr` references to `data.type.name.attr`.
|
|
10
10
|
* Required immediately, or `terraform plan` errors on the dangling ref.
|
|
11
|
+
* An `output` block reading the carved resource is such a survivor (#1638):
|
|
12
|
+
* same data source, same textual rewrite, applied to the output's value.
|
|
11
13
|
*
|
|
12
14
|
* - outbound edge → the carved resource read a value from a survivor. That
|
|
13
15
|
* value must enter chant from outside synthesis, as a deploy-time input.
|
|
@@ -55,6 +57,12 @@ export interface BridgePlan {
|
|
|
55
57
|
deferredInputs: DeferredInput[];
|
|
56
58
|
/** Every carved address whose own block the rewrites remove, across files. */
|
|
57
59
|
excised: string[];
|
|
60
|
+
/**
|
|
61
|
+
* `output` blocks whose value the rewrites repoint at a data source (#1638),
|
|
62
|
+
* as `output.<name>`. They are inbound edges like any other — listed
|
|
63
|
+
* separately only because the patch is a one-line expression edit.
|
|
64
|
+
*/
|
|
65
|
+
outputRewrites: string[];
|
|
58
66
|
runbook: string;
|
|
59
67
|
}
|
|
60
68
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/terraform/bridge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/terraform/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAG9D,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,qFAAqF;IACrF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;OAIG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAiBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC/C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACtC,UAAU,CA8DZ"}
|
|
@@ -27,10 +27,15 @@ export type BoundaryDirection = "inbound" | "outbound";
|
|
|
27
27
|
* - outbound → the carve set depends on a survivor. Bridge: the value enters
|
|
28
28
|
* chant as a deploy-time input. Deferred until apply; only provenance is
|
|
29
29
|
* recorded at the observe position.
|
|
30
|
+
*
|
|
31
|
+
* An inbound edge whose survivor is an `output` block (#1638) is the same
|
|
32
|
+
* urgency and the same patch — the output's expression is rewritten onto the
|
|
33
|
+
* data source — but it is called out as `tf-output-rewrite` so a reader can
|
|
34
|
+
* tell a one-line output edit from a resource's rewiring.
|
|
30
35
|
*/
|
|
31
36
|
export interface BoundaryEdge {
|
|
32
37
|
direction: BoundaryDirection;
|
|
33
|
-
/** The survivor side of the edge. */
|
|
38
|
+
/** The survivor side of the edge. `output.<name>` for an output block. */
|
|
34
39
|
survivor: string;
|
|
35
40
|
/** The carve-set side of the edge. */
|
|
36
41
|
carved: string;
|
|
@@ -39,10 +44,10 @@ export interface BoundaryEdge {
|
|
|
39
44
|
* The referring block's own top-level attribute(s) the reference sits in
|
|
40
45
|
* (#998). For an outbound edge this names the carved resource's attribute
|
|
41
46
|
* that reads the survivor — what the deferred input's build parameter is
|
|
42
|
-
* named after on emit.
|
|
47
|
+
* named after on emit. For an output edge it is `["value"]`.
|
|
43
48
|
*/
|
|
44
49
|
via: string[];
|
|
45
|
-
bridge: "tf-data-source" | "deferred-input";
|
|
50
|
+
bridge: "tf-data-source" | "tf-output-rewrite" | "deferred-input";
|
|
46
51
|
required: "immediately" | "at-apply";
|
|
47
52
|
}
|
|
48
53
|
export interface CarveReport {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carve.d.ts","sourceRoot":"","sources":["../../src/terraform/carve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvD
|
|
1
|
+
{"version":3,"file":"carve.d.ts","sourceRoot":"","sources":["../../src/terraform/carve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;OAKG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,MAAM,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;IAClE,QAAQ,EAAE,aAAa,GAAG,UAAU,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,iFAAiF;IACjF,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CAgB7E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAkDjF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
|
@@ -31,9 +31,9 @@ interface RawRef {
|
|
|
31
31
|
*/
|
|
32
32
|
export declare function refFromAccessor(accessor: string): RawRef | null;
|
|
33
33
|
/**
|
|
34
|
-
* Every string value carrying an interpolation across the tree's resource
|
|
35
|
-
* module blocks — exactly the expressions `parse.ts` must resolve
|
|
36
|
-
* AST before `buildGraph` can classify them.
|
|
34
|
+
* Every string value carrying an interpolation across the tree's resource,
|
|
35
|
+
* module and output blocks — exactly the expressions `parse.ts` must resolve
|
|
36
|
+
* through the AST before `buildGraph` can classify them.
|
|
37
37
|
*/
|
|
38
38
|
export declare function collectExpressions(tree: Hcl2JsonTree): string[];
|
|
39
39
|
/**
|
|
@@ -44,9 +44,15 @@ export declare function collectExpressions(tree: Hcl2JsonTree): string[];
|
|
|
44
44
|
* marks the referring node dynamic. An edge is recorded only when its target
|
|
45
45
|
* resolves to a known resource/module node — references to `var`/`local`/data
|
|
46
46
|
* are dropped.
|
|
47
|
+
*
|
|
48
|
+
* `output` blocks are not nodes either — nothing carves an output — but they
|
|
49
|
+
* do reference, and a reference to a carved resource breaks the surviving plan
|
|
50
|
+
* exactly like a resource's does. So an output contributes an edge tagged
|
|
51
|
+
* `fromKind: "output"` from the pseudo-address `output.<name>` (#1638),
|
|
52
|
+
* which the scorer weights lower and `carve bridge` patches.
|
|
47
53
|
*/
|
|
48
54
|
export declare function buildGraph(tree: Hcl2JsonTree, exprRefs: ExpressionRefs): TfGraph;
|
|
49
|
-
/** Edges where
|
|
55
|
+
/** Edges where something in the surviving Terraform depends on `address`. */
|
|
50
56
|
export declare function inboundEdges(graph: TfGraph, address: string): TfEdge[];
|
|
51
57
|
/** Edges where `address` depends on other nodes (each → a deferred deploy-time input). */
|
|
52
58
|
export declare function outboundEdges(graph: TfGraph, address: string): TfEdge[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/terraform/graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAU,MAAM,SAAS,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;AAKpE,UAAU,MAAM;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA4BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe/D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/terraform/graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAU,MAAM,SAAS,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;AAKpE,UAAU,MAAM;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA4BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe/D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,EAAE,CAe/D;AA4DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAoFhF;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtE;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/terraform/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAErD,wDAAwD;AACxD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAChE,yFAAyF;IACzF,yBAAyB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CACxG;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,KAAK,EAAE,OAAO;CAQ3B;AAED;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAMtD;
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/terraform/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAErD,wDAAwD;AACxD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAChE,yFAAyF;IACzF,yBAAyB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CACxG;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,KAAK,EAAE,OAAO;CAQ3B;AAED;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAMtD;AAkDD,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,CAWvG"}
|
|
@@ -6,11 +6,18 @@
|
|
|
6
6
|
* score = 100
|
|
7
7
|
* - 12 * inbound # survivors that depend on this → each a TF data-source patch
|
|
8
8
|
* - 4 * outbound # this depends on survivors → a deferred deploy-time input
|
|
9
|
+
* - 4 * outputs # an output block reads this → a one-line rewrite (#1638)
|
|
9
10
|
* - 15 * (tier - 1) # native-spec map: tier1=0, tier2=-15, tier3=-30
|
|
10
11
|
* - 10 * has_dynamic # count / for_each / data present
|
|
11
12
|
* - 3 * (instances - 1) # state-expanded instance count
|
|
12
13
|
* clamp 0..100 (unsupported provider/type → 0)
|
|
13
14
|
*
|
|
15
|
+
* An `output` block referencing the target is a real inbound dependency — the
|
|
16
|
+
* surviving plan errors on the dangling reference — so it cannot score as
|
|
17
|
+
* free. It is not a data-source patch either: bridging it rewrites one
|
|
18
|
+
* expression in a block that manages no infrastructure, the same order of work
|
|
19
|
+
* as recording an outbound deferred input. Hence 4, not 12.
|
|
20
|
+
*
|
|
14
21
|
* Sub-resources that inline into a parent (see `FOLDS_INTO`) are folded into the
|
|
15
22
|
* parent's carve set: they are removed from the ranking and their edge to the
|
|
16
23
|
* parent is not counted as inbound — inlining them is free, not boundary work.
|
|
@@ -18,8 +25,11 @@
|
|
|
18
25
|
import type { TfGraph } from "./types.js";
|
|
19
26
|
export type PeelabilityBand = "clean leaf" | "carvable w/ edits" | "leave in Terraform";
|
|
20
27
|
export interface PeelabilityBreakdown {
|
|
28
|
+
/** Inbound edges from resource/module blocks — a data-source patch each. */
|
|
21
29
|
inbound: number;
|
|
22
30
|
outbound: number;
|
|
31
|
+
/** Inbound edges from `output` blocks — a one-line rewrite each (#1638). */
|
|
32
|
+
outputs: number;
|
|
23
33
|
tier: 1 | 2 | 3 | null;
|
|
24
34
|
hasDynamic: boolean;
|
|
25
35
|
instances: number;
|
|
@@ -27,6 +37,7 @@ export interface PeelabilityBreakdown {
|
|
|
27
37
|
penalties: {
|
|
28
38
|
inbound: number;
|
|
29
39
|
outbound: number;
|
|
40
|
+
outputs: number;
|
|
30
41
|
tier: number;
|
|
31
42
|
dynamic: number;
|
|
32
43
|
instances: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/terraform/score.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"score.d.ts","sourceRoot":"","sources":["../../src/terraform/score.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAU,MAAM,SAAS,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,mBAAmB,GAAG,oBAAoB,CAAC;AAExF,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAID,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAItD;AA6FD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CAMzD"}
|
|
@@ -44,6 +44,15 @@ export interface TfNode {
|
|
|
44
44
|
export interface TfEdge {
|
|
45
45
|
from: string;
|
|
46
46
|
to: string;
|
|
47
|
+
/**
|
|
48
|
+
* The kind of block the reference came from, when it is not one of the
|
|
49
|
+
* graph's own nodes. `"output"` marks a root-module `output` block (#1638):
|
|
50
|
+
* a real dependency — `terraform plan` errors on the dangling reference the
|
|
51
|
+
* moment the carve lands — but a cheaper one to bridge than a resource's,
|
|
52
|
+
* since the patch is a single expression edit in a block that manages
|
|
53
|
+
* nothing. Absent means the reference came from a resource or module node.
|
|
54
|
+
*/
|
|
55
|
+
fromKind?: "output";
|
|
47
56
|
/** The attribute path(s) referenced, e.g. `["id", "arn"]`. */
|
|
48
57
|
attrs: string[];
|
|
49
58
|
/**
|
|
@@ -68,6 +77,8 @@ export interface Hcl2JsonTree {
|
|
|
68
77
|
resource?: Record<string, Record<string, unknown[]>>;
|
|
69
78
|
module?: Record<string, unknown[]>;
|
|
70
79
|
data?: Record<string, Record<string, unknown[]>>;
|
|
80
|
+
/** Root-module `output` blocks. Not nodes — they reference, they are not carvable (#1638). */
|
|
81
|
+
output?: Record<string, unknown[]>;
|
|
71
82
|
[k: string]: unknown;
|
|
72
83
|
}
|
|
73
84
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/terraform/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,MAAM;IACrB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC5B,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,UAAU,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;OAKG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/terraform/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,MAAM;IACrB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC5B,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,UAAU,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;OAKG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACjD,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB"}
|
package/package.json
CHANGED
|
@@ -162,6 +162,38 @@ describe("carveBridge", () => {
|
|
|
162
162
|
});
|
|
163
163
|
});
|
|
164
164
|
|
|
165
|
+
test("an output-only dependency is patched, not left dangling (#1638)", async () => {
|
|
166
|
+
if (!parserAvailable) return;
|
|
167
|
+
const dir = mkdtempSync(join(tmpdir(), "chant-bridge-outputs-"));
|
|
168
|
+
try {
|
|
169
|
+
// Nothing but an output reads the bucket. Before outputs entered the
|
|
170
|
+
// graph this produced no data source and no rewrite at all, so the
|
|
171
|
+
// surviving plan broke on the dangling reference at handoff.
|
|
172
|
+
writeFileSync(join(dir, "bucket.tf"), BUCKET_TF);
|
|
173
|
+
writeFileSync(
|
|
174
|
+
join(dir, "outputs.tf"),
|
|
175
|
+
`output "assets_bucket" {\n value = aws_s3_bucket.assets.bucket\n}\n`,
|
|
176
|
+
);
|
|
177
|
+
const out = join(dir, "carveout");
|
|
178
|
+
const res = await carveBridge({ from: dir, select: "aws_s3_bucket.assets", output: out });
|
|
179
|
+
expect(res.ok).toBe(true);
|
|
180
|
+
expect(res.plan!.outputRewrites).toEqual(["output.assets_bucket"]);
|
|
181
|
+
|
|
182
|
+
expect(readFileSync(join(out, "aws_s3_bucket-assets-datasources.tf"), "utf-8")).toContain(
|
|
183
|
+
'data "aws_s3_bucket" "assets"',
|
|
184
|
+
);
|
|
185
|
+
expect(readFileSync(join(out, "outputs.tf"), "utf-8")).toContain("value = data.aws_s3_bucket.assets.bucket");
|
|
186
|
+
|
|
187
|
+
const patch = readFileSync(res.patchPath!, "utf-8");
|
|
188
|
+
expect(patch).toContain("diff --git a/outputs.tf b/outputs.tf");
|
|
189
|
+
expect(patch).toContain("- value = aws_s3_bucket.assets.bucket");
|
|
190
|
+
expect(patch).toContain("+ value = data.aws_s3_bucket.assets.bucket");
|
|
191
|
+
expect(formatCarveBridge(res)).toContain("1 output block(s) repointed at the data source: output.assets_bucket");
|
|
192
|
+
} finally {
|
|
193
|
+
rmSync(dir, { recursive: true, force: true });
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
|
|
165
197
|
test("formatCarveBridge summarizes data sources, rewires, and safety", async () => {
|
|
166
198
|
if (!parserAvailable) return;
|
|
167
199
|
await withEstate(async (dir) => {
|
|
@@ -183,6 +183,9 @@ export function formatCarveBridge(result: CarveBridgeResult): string {
|
|
|
183
183
|
if (changed.length) {
|
|
184
184
|
L.push(` ${changed.length} survivor file(s) rewired: ${changed.map((r) => basename(r.path)).join(", ")}`);
|
|
185
185
|
}
|
|
186
|
+
if (p.outputRewrites.length) {
|
|
187
|
+
L.push(` ${p.outputRewrites.length} output block(s) repointed at the data source: ${p.outputRewrites.join(", ")}`);
|
|
188
|
+
}
|
|
186
189
|
if (p.deferredInputs.length) {
|
|
187
190
|
L.push(` ${p.deferredInputs.length} deferred deploy-time input(s) (wired at apply):`);
|
|
188
191
|
for (const d of p.deferredInputs) L.push(` - ${d.note}`);
|
|
@@ -3,6 +3,7 @@ import { mkdtempSync, writeFileSync, rmSync, readFileSync } from "fs";
|
|
|
3
3
|
import { tmpdir } from "os";
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import { carveEmit, formatCarveEmit } from "./carve-emit";
|
|
6
|
+
import { lintCommand } from "./lint";
|
|
6
7
|
import { loadHcl2json } from "../../terraform/parse";
|
|
7
8
|
import { readCarveManifest } from "../../terraform/manifest";
|
|
8
9
|
import type { ImportResult, LiveImportOptions } from "./import";
|
|
@@ -212,6 +213,112 @@ resource "aws_subnet" "a" {
|
|
|
212
213
|
}
|
|
213
214
|
});
|
|
214
215
|
|
|
216
|
+
test("folded sub-resources land in the emitted bucket's properties (#1637)", async () => {
|
|
217
|
+
if (!parserAvailable) return;
|
|
218
|
+
const dir = mkdtempSync(join(tmpdir(), "chant-emit-fold-"));
|
|
219
|
+
try {
|
|
220
|
+
writeFileSync(
|
|
221
|
+
join(dir, "main.tf"),
|
|
222
|
+
`
|
|
223
|
+
resource "aws_s3_bucket" "assets" { bucket = "myapp-assets-prod" }
|
|
224
|
+
resource "aws_s3_bucket_versioning" "assets" {
|
|
225
|
+
bucket = aws_s3_bucket.assets.id
|
|
226
|
+
versioning_configuration { status = "Enabled" }
|
|
227
|
+
}
|
|
228
|
+
resource "aws_s3_bucket_public_access_block" "assets" {
|
|
229
|
+
bucket = aws_s3_bucket.assets.id
|
|
230
|
+
block_public_acls = true
|
|
231
|
+
block_public_policy = true
|
|
232
|
+
ignore_public_acls = true
|
|
233
|
+
restrict_public_buckets = true
|
|
234
|
+
}
|
|
235
|
+
`,
|
|
236
|
+
);
|
|
237
|
+
const attrs = (extra: Record<string, unknown>) => ({ id: "myapp-assets-prod", bucket: "myapp-assets-prod", ...extra });
|
|
238
|
+
writeFileSync(
|
|
239
|
+
join(dir, "terraform.tfstate"),
|
|
240
|
+
JSON.stringify({
|
|
241
|
+
version: 4,
|
|
242
|
+
resources: [
|
|
243
|
+
{
|
|
244
|
+
mode: "managed",
|
|
245
|
+
type: "aws_s3_bucket",
|
|
246
|
+
name: "assets",
|
|
247
|
+
instances: [
|
|
248
|
+
{
|
|
249
|
+
attributes: attrs({
|
|
250
|
+
arn: "arn:aws:s3:::myapp-assets-prod",
|
|
251
|
+
versioning: [{ enabled: true, mfa_delete: false }],
|
|
252
|
+
server_side_encryption_configuration: [
|
|
253
|
+
{
|
|
254
|
+
rule: [
|
|
255
|
+
{
|
|
256
|
+
apply_server_side_encryption_by_default: [{ sse_algorithm: "AES256", kms_master_key_id: "" }],
|
|
257
|
+
bucket_key_enabled: false,
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
}),
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
mode: "managed",
|
|
268
|
+
type: "aws_s3_bucket_versioning",
|
|
269
|
+
name: "assets",
|
|
270
|
+
instances: [{ attributes: attrs({ versioning_configuration: [{ status: "Enabled", mfa_delete: "" }] }) }],
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
mode: "managed",
|
|
274
|
+
type: "aws_s3_bucket_public_access_block",
|
|
275
|
+
name: "assets",
|
|
276
|
+
instances: [
|
|
277
|
+
{
|
|
278
|
+
attributes: attrs({
|
|
279
|
+
block_public_acls: true,
|
|
280
|
+
block_public_policy: true,
|
|
281
|
+
ignore_public_acls: true,
|
|
282
|
+
restrict_public_buckets: true,
|
|
283
|
+
}),
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
}),
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
const out = join(dir, "carveout");
|
|
292
|
+
const res = await carveEmit(
|
|
293
|
+
{ from: dir, select: "aws_s3_bucket.assets", statePath: join(dir, "terraform.tfstate"), output: out },
|
|
294
|
+
{ plugins: [], liveImport },
|
|
295
|
+
);
|
|
296
|
+
expect(res.ok).toBe(true);
|
|
297
|
+
|
|
298
|
+
// The fold is applied, not merely announced: the emitted Bucket carries
|
|
299
|
+
// the versioning and public-access block the Terraform declared.
|
|
300
|
+
const emitted = readFileSync(join(out, "src", "assets.ts"), "utf-8");
|
|
301
|
+
expect(emitted).toContain('VersioningConfiguration: {"Status":"Enabled"}');
|
|
302
|
+
expect(emitted).toContain('"BlockPublicAcls":true');
|
|
303
|
+
expect(emitted).toContain('"RestrictPublicBuckets":true');
|
|
304
|
+
expect(emitted).toContain('BucketEncryption: {"ServerSideEncryptionConfiguration"');
|
|
305
|
+
|
|
306
|
+
expect(res.folded).toEqual([
|
|
307
|
+
{ address: "aws_s3_bucket_public_access_block.assets", props: ["PublicAccessBlockConfiguration"] },
|
|
308
|
+
{ address: "aws_s3_bucket_versioning.assets", props: ["VersioningConfiguration"] },
|
|
309
|
+
]);
|
|
310
|
+
const text = formatCarveEmit(res);
|
|
311
|
+
expect(text).toContain("aws_s3_bucket_versioning.assets (VersioningConfiguration)");
|
|
312
|
+
expect(text).toContain("aws_s3_bucket_public_access_block.assets (PublicAccessBlockConfiguration)");
|
|
313
|
+
|
|
314
|
+
// And the emitted project still lints clean (no errors).
|
|
315
|
+
const lint = await lintCommand({ path: out, format: "stylish" });
|
|
316
|
+
expect(lint.diagnostics.filter((d) => d.severity === "error")).toEqual([]);
|
|
317
|
+
} finally {
|
|
318
|
+
rmSync(dir, { recursive: true, force: true });
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
215
322
|
test("without --state or --env it explains both adoption sources", async () => {
|
|
216
323
|
if (!parserAvailable) return;
|
|
217
324
|
await withEstate(async (dir) => {
|