@intentius/chant 0.124.18 → 0.124.19
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/import.d.ts +2 -0
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +6 -2
- package/dist/cli/handlers/graph.js +24 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +2 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +4 -0
- package/dist/cli/registry.d.ts +2 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +9 -3
- package/dist/graph-dot.d.ts.map +1 -1
- package/dist/graph-dot.js +36 -2
- package/dist/graph-ir.d.ts +98 -3
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +71 -0
- package/dist/graph-lens.js +12 -1
- package/dist/graph-mermaid.d.ts +5 -1
- package/dist/graph-mermaid.d.ts.map +1 -1
- package/dist/graph-mermaid.js +46 -2
- package/dist/lexicon.d.ts +22 -1
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/wave-runtime.mjs +169 -169
- package/package.json +1 -1
- package/src/cli/commands/import-live.test.ts +24 -0
- package/src/cli/commands/import.ts +8 -2
- package/src/cli/handlers/graph.test.ts +23 -0
- package/src/cli/handlers/graph.ts +22 -1
- package/src/cli/handlers/misc.ts +2 -1
- package/src/cli/main.test.ts +5 -0
- package/src/cli/parse-args.ts +3 -0
- package/src/cli/registry.ts +2 -0
- package/src/codegen/publish-order.test.ts +118 -4
- package/src/graph-ci-edges.test.ts +97 -0
- package/src/graph-detail.ts +9 -3
- package/src/graph-dot.ts +34 -2
- package/src/graph-ir.ts +156 -3
- package/src/graph-lens.ts +10 -1
- package/src/graph-mermaid.ts +44 -2
- package/src/lexicon.ts +23 -1
package/src/graph-ir.ts
CHANGED
|
@@ -79,16 +79,90 @@ export interface IRNode {
|
|
|
79
79
|
runtimeOwner?: string;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* What an edge means (#3910). `ref` is a typed cross-resource reference (an
|
|
84
|
+
* `AttrRef`, a `Ref` intrinsic, a whole node held in props, or an
|
|
85
|
+
* {@link EntityReference}). The rest are the dependency strings a CI lexicon
|
|
86
|
+
* writes, reported through a plugin's `graphEdges` hook:
|
|
87
|
+
*
|
|
88
|
+
* - `needs` — job waits for job (GitHub/GitLab `needs:`, GitLab stage order)
|
|
89
|
+
* - `calls` — job runs a reusable workflow or a local composite action (`uses:`)
|
|
90
|
+
* - `triggers` — a pipeline starts another one: GitLab `trigger:` (from starts to),
|
|
91
|
+
* GitHub `on.workflow_run` (to finishing starts from)
|
|
92
|
+
* - `includes` — a pipeline pulls in another file's config (GitLab `include:`)
|
|
93
|
+
* - `extends` — a job inherits another job's keys (GitLab `extends:`)
|
|
94
|
+
*
|
|
95
|
+
* Every edge points from the entity that holds the reference to the entity it
|
|
96
|
+
* names. The set grows additively ({@link GRAPH_IR_VERSION}): a reader ignores
|
|
97
|
+
* a kind it does not know.
|
|
98
|
+
*/
|
|
99
|
+
export type IREdgeKind = "ref" | "needs" | "calls" | "triggers" | "includes" | "extends";
|
|
100
|
+
|
|
101
|
+
/** A directed dependency: `from` references `to` (an attribute of it, for `ref`). */
|
|
83
102
|
export interface IREdge {
|
|
84
103
|
from: string;
|
|
85
104
|
to: string;
|
|
86
|
-
/** "ref" for an AttrRef-derived edge. */
|
|
87
|
-
kind:
|
|
105
|
+
/** "ref" for an AttrRef-derived edge; a CI kind otherwise (see {@link IREdgeKind}). */
|
|
106
|
+
kind: IREdgeKind;
|
|
88
107
|
/** The consumer-side property the reference flows through, when derivable. */
|
|
89
108
|
viaAttr?: string;
|
|
90
109
|
/** The producer-side attribute referenced (e.g. "id"). Added at detail T3. */
|
|
91
110
|
toAttr?: string;
|
|
111
|
+
/**
|
|
112
|
+
* True when the edge leaves the pipeline `from` belongs to (#3910): a
|
|
113
|
+
* reusable-workflow call, a `workflow_run` trigger, a GitLab child or
|
|
114
|
+
* multi-project trigger, an include, a cross-project `needs`. A renderer
|
|
115
|
+
* that draws each pipeline as a group ({@link IRGroups.byPipeline}) reads
|
|
116
|
+
* this to route the edge between groups. Absent on every in-pipeline edge.
|
|
117
|
+
*/
|
|
118
|
+
crossPipeline?: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* A reference whose target is not a node of this graph (#3910): a job
|
|
123
|
+
* `needs` a job no workflow declares, a `uses:` names another repository's
|
|
124
|
+
* workflow, a GitLab `include:` names a file chant did not generate. Kept on
|
|
125
|
+
* the IR rather than dropped or matched to a near name, so a reader can tell
|
|
126
|
+
* "no dependency" from "a dependency on something outside this project".
|
|
127
|
+
* Field names follow the live resolver's `DanglingRef` (./graph-refs.ts).
|
|
128
|
+
*/
|
|
129
|
+
export interface IRDanglingRef {
|
|
130
|
+
/** The node holding the reference. */
|
|
131
|
+
from: string;
|
|
132
|
+
/** The edge kind the reference would have been. */
|
|
133
|
+
kind: IREdgeKind;
|
|
134
|
+
/** Where on `from` it was written, e.g. `needs`, `uses`, `trigger.include`. */
|
|
135
|
+
path: string;
|
|
136
|
+
/** The reference exactly as written. */
|
|
137
|
+
value: string;
|
|
138
|
+
/** Same meaning as {@link IREdge.crossPipeline}. */
|
|
139
|
+
crossPipeline?: boolean;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* One reference a lexicon reports through its `graphEdges` hook (#3910),
|
|
144
|
+
* resolved by the lexicon from strings core cannot read: job names, workflow
|
|
145
|
+
* file paths, pipeline names. `from` and `to` are entity keys. A reference
|
|
146
|
+
* the lexicon could not resolve sets `dangling` and carries the string as
|
|
147
|
+
* written in `to`; core turns it into an {@link IRDanglingRef}.
|
|
148
|
+
*/
|
|
149
|
+
export interface LexiconGraphReference {
|
|
150
|
+
from: string;
|
|
151
|
+
to: string;
|
|
152
|
+
kind: IREdgeKind;
|
|
153
|
+
viaAttr?: string;
|
|
154
|
+
crossPipeline?: boolean;
|
|
155
|
+
dangling?: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** What a lexicon's `graphEdges` hook returns (#3910). */
|
|
159
|
+
export interface LexiconGraphEdges {
|
|
160
|
+
references: LexiconGraphReference[];
|
|
161
|
+
/**
|
|
162
|
+
* Pipeline membership, `pipeline name -> entity keys`: a workflow and its
|
|
163
|
+
* jobs, a GitLab pipeline and its jobs. Lands on {@link IRGroups.byPipeline}.
|
|
164
|
+
*/
|
|
165
|
+
pipelines?: Record<string, string[]>;
|
|
92
166
|
}
|
|
93
167
|
|
|
94
168
|
/**
|
|
@@ -210,6 +284,11 @@ export interface IRGroups {
|
|
|
210
284
|
* wave-laned renderer reads this the way `byStack` drives boundary boxes.
|
|
211
285
|
* Present only for the component-DAG projection; absent for entity IR. */
|
|
212
286
|
byWave?: Record<string, string[]>;
|
|
287
|
+
/** CI pipeline membership (#3910): a workflow or pipeline name -> the node
|
|
288
|
+
* ids it runs (the workflow node and its jobs). Reported by a CI lexicon's
|
|
289
|
+
* `graphEdges` hook; absent when no lexicon reports one. Edges marked
|
|
290
|
+
* `crossPipeline` run between these groups. */
|
|
291
|
+
byPipeline?: Record<string, string[]>;
|
|
213
292
|
}
|
|
214
293
|
|
|
215
294
|
/** A cross-stack export this stack publishes (a `stackOutput`/`output`): its
|
|
@@ -335,6 +414,11 @@ export interface GraphIR {
|
|
|
335
414
|
imports?: IRImport[];
|
|
336
415
|
/** The CI/pipeline projection alongside the component graph (#989) — see {@link IRPipeline}. */
|
|
337
416
|
pipeline?: IRPipeline;
|
|
417
|
+
/**
|
|
418
|
+
* References that name nothing in this graph (#3910) — see
|
|
419
|
+
* {@link IRDanglingRef}. Absent when there are none.
|
|
420
|
+
*/
|
|
421
|
+
dangling?: IRDanglingRef[];
|
|
338
422
|
/**
|
|
339
423
|
* Attributes chant computed rather than read back from the provider, keyed by the kind
|
|
340
424
|
* they were folded onto. An enrichment pass records what it derived here so callers can
|
|
@@ -685,6 +769,75 @@ export function buildGraphIr(
|
|
|
685
769
|
return ir;
|
|
686
770
|
}
|
|
687
771
|
|
|
772
|
+
/**
|
|
773
|
+
* Add what the lexicons' `graphEdges` hooks reported (#3910) to a built IR.
|
|
774
|
+
*
|
|
775
|
+
* A resolved reference between two nodes becomes an edge. When it lands on
|
|
776
|
+
* the same `from`/`to`/`viaAttr` as an edge the AttrRef walk already found
|
|
777
|
+
* (a GitLab `needs:` holding the Job object itself, say), the lexicon's edge
|
|
778
|
+
* replaces it, since the lexicon knows the reference is a `needs` and the walk
|
|
779
|
+
* only knows it is a reference. A reference marked `dangling`, or whose
|
|
780
|
+
* target is not a node, goes on `ir.dangling` as written. One whose `from` is
|
|
781
|
+
* not a node is dropped: there is nothing to hang it on.
|
|
782
|
+
*
|
|
783
|
+
* Pure. Returns `ir` itself when no report added anything, so a project with
|
|
784
|
+
* no CI lexicon prints exactly what it did before.
|
|
785
|
+
*/
|
|
786
|
+
export function applyLexiconGraphEdges(ir: GraphIR, reports: readonly LexiconGraphEdges[]): GraphIR {
|
|
787
|
+
const nodeIds = new Set(ir.nodes.map((n) => n.id));
|
|
788
|
+
const edgeMap = new Map<string, IREdge>(ir.edges.map((e) => [edgeKey(e), e]));
|
|
789
|
+
const danglingMap = new Map<string, IRDanglingRef>((ir.dangling ?? []).map((d) => [danglingKey(d), d]));
|
|
790
|
+
const byPipeline: Record<string, string[]> = { ...(ir.groups.byPipeline ?? {}) };
|
|
791
|
+
let changed = false;
|
|
792
|
+
|
|
793
|
+
for (const report of reports) {
|
|
794
|
+
for (const ref of report.references) {
|
|
795
|
+
if (!nodeIds.has(ref.from)) continue;
|
|
796
|
+
if (ref.dangling || !nodeIds.has(ref.to)) {
|
|
797
|
+
const d: IRDanglingRef = {
|
|
798
|
+
from: ref.from,
|
|
799
|
+
kind: ref.kind,
|
|
800
|
+
path: ref.viaAttr ?? ref.kind,
|
|
801
|
+
value: ref.to,
|
|
802
|
+
...(ref.crossPipeline ? { crossPipeline: true } : {}),
|
|
803
|
+
};
|
|
804
|
+
danglingMap.set(danglingKey(d), d);
|
|
805
|
+
changed = true;
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
if (ref.to === ref.from) continue;
|
|
809
|
+
const e: IREdge = {
|
|
810
|
+
from: ref.from,
|
|
811
|
+
to: ref.to,
|
|
812
|
+
kind: ref.kind,
|
|
813
|
+
...(ref.viaAttr ? { viaAttr: ref.viaAttr } : {}),
|
|
814
|
+
...(ref.crossPipeline ? { crossPipeline: true } : {}),
|
|
815
|
+
};
|
|
816
|
+
edgeMap.set(edgeKey(e), e);
|
|
817
|
+
changed = true;
|
|
818
|
+
}
|
|
819
|
+
for (const [name, members] of Object.entries(report.pipelines ?? {})) {
|
|
820
|
+
const present = members.filter((m) => nodeIds.has(m));
|
|
821
|
+
if (present.length === 0) continue;
|
|
822
|
+
byPipeline[name] = [...new Set([...(byPipeline[name] ?? []), ...present])].sort();
|
|
823
|
+
changed = true;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
if (!changed) return ir;
|
|
827
|
+
|
|
828
|
+
const edges = [...edgeMap.values()].sort((a, b) => edgeKey(a).localeCompare(edgeKey(b)));
|
|
829
|
+
const dangling = [...danglingMap.values()].sort((a, b) => danglingKey(a).localeCompare(danglingKey(b)));
|
|
830
|
+
const groups: IRGroups = { ...ir.groups };
|
|
831
|
+
if (Object.keys(byPipeline).length) groups.byPipeline = sortKeys(byPipeline);
|
|
832
|
+
const out: GraphIR = { ...ir, edges, groups };
|
|
833
|
+
if (dangling.length) out.dangling = dangling;
|
|
834
|
+
return out;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function danglingKey(d: IRDanglingRef): string {
|
|
838
|
+
return `${d.from}\0${d.path}\0${d.value}`;
|
|
839
|
+
}
|
|
840
|
+
|
|
688
841
|
function sortKeys(rec: Record<string, string[]>): Record<string, string[]> {
|
|
689
842
|
const out: Record<string, string[]> = {};
|
|
690
843
|
for (const k of Object.keys(rec).sort()) out[k] = rec[k];
|
package/src/graph-lens.ts
CHANGED
|
@@ -116,8 +116,17 @@ function subgraph(ir: GraphIR, keep: Set<string>): GraphIR {
|
|
|
116
116
|
const groups: GraphIR["groups"] = {};
|
|
117
117
|
if (Object.keys(byLexicon).length) groups.byLexicon = sortGroups(byLexicon);
|
|
118
118
|
if (Object.keys(byComposite).length) groups.byComposite = sortGroups(byComposite);
|
|
119
|
+
if (ir.groups.byPipeline) {
|
|
120
|
+
const byPipeline: Record<string, string[]> = {};
|
|
121
|
+
for (const [name, members] of Object.entries(ir.groups.byPipeline)) {
|
|
122
|
+
const kept = members.filter((m) => keep.has(m));
|
|
123
|
+
if (kept.length) byPipeline[name] = kept;
|
|
124
|
+
}
|
|
125
|
+
if (Object.keys(byPipeline).length) groups.byPipeline = sortGroups(byPipeline);
|
|
126
|
+
}
|
|
127
|
+
const dangling = ir.dangling?.filter((d) => keep.has(d.from));
|
|
119
128
|
|
|
120
|
-
return { nodes, edges, groups };
|
|
129
|
+
return { nodes, edges, groups, ...(dangling && dangling.length ? { dangling } : {}) };
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
function sortGroups(rec: Record<string, string[]>): Record<string, string[]> {
|
package/src/graph-mermaid.ts
CHANGED
|
@@ -25,16 +25,35 @@ export function toMermaid(ir: GraphIR): string {
|
|
|
25
25
|
// sorted, so output is deterministic.
|
|
26
26
|
const clusters = ir.groups.byWave ?? ir.groups.byLexicon;
|
|
27
27
|
const clusterPrefix = ir.groups.byWave ? "wave" : "lex";
|
|
28
|
+
// CI pipelines (#3910) nest inside their lexicon's cluster, one subgraph per
|
|
29
|
+
// workflow or pipeline, so a cross-pipeline edge visibly leaves its box.
|
|
30
|
+
const pipelineOf = new Map<string, string>();
|
|
31
|
+
for (const [name, members] of Object.entries(ir.groups.byPipeline ?? {})) {
|
|
32
|
+
for (const id of members) if (!pipelineOf.has(id)) pipelineOf.set(id, name);
|
|
33
|
+
}
|
|
28
34
|
const grouped = new Set<string>();
|
|
29
35
|
if (clusters) {
|
|
30
36
|
for (const [name, members] of Object.entries(clusters)) {
|
|
31
37
|
lines.push(` subgraph ${safeId(`${clusterPrefix}_${name}`, ids)}[${quote(name)}]`);
|
|
38
|
+
const nested = new Map<string, IRNode[]>();
|
|
32
39
|
for (const id of members) {
|
|
33
40
|
const node = ir.nodes.find((n) => n.id === id);
|
|
34
41
|
if (!node) continue;
|
|
35
42
|
grouped.add(id);
|
|
43
|
+
const pipeline = pipelineOf.get(id);
|
|
44
|
+
if (pipeline !== undefined) {
|
|
45
|
+
const arr = nested.get(pipeline) ?? [];
|
|
46
|
+
arr.push(node);
|
|
47
|
+
nested.set(pipeline, arr);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
36
50
|
lines.push(` ${nodeLine(node, ids)}`);
|
|
37
51
|
}
|
|
52
|
+
for (const [pipeline, nodes] of [...nested].sort(([a], [b]) => a.localeCompare(b))) {
|
|
53
|
+
lines.push(` subgraph ${safeId(`pipe_${name}_${pipeline}`, ids)}[${quote(pipeline)}]`);
|
|
54
|
+
for (const node of nodes) lines.push(` ${nodeLine(node, ids)}`);
|
|
55
|
+
lines.push(" end");
|
|
56
|
+
}
|
|
38
57
|
lines.push(" end");
|
|
39
58
|
}
|
|
40
59
|
}
|
|
@@ -47,6 +66,19 @@ export function toMermaid(ir: GraphIR): string {
|
|
|
47
66
|
lines.push(` ${edgeLine(e, ids)}`);
|
|
48
67
|
}
|
|
49
68
|
|
|
69
|
+
// A reference to nothing in the graph (#3910) is drawn, not dropped: a
|
|
70
|
+
// dashed edge to a rounded stub named by the string as written.
|
|
71
|
+
const stubs = new Map<string, string>();
|
|
72
|
+
for (const d of ir.dangling ?? []) {
|
|
73
|
+
let stub = stubs.get(d.value);
|
|
74
|
+
if (!stub) {
|
|
75
|
+
stub = safeId(`dangling_${d.value}`, ids);
|
|
76
|
+
stubs.set(d.value, stub);
|
|
77
|
+
lines.push(` ${stub}([${quote(`${d.value}\n(not declared)`)}])`);
|
|
78
|
+
}
|
|
79
|
+
lines.push(` ${safeId(d.from, ids)} -.->|${quote(d.kind)}| ${stub}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
50
82
|
return lines.join("\n") + "\n";
|
|
51
83
|
}
|
|
52
84
|
|
|
@@ -60,8 +92,18 @@ function nodeLine(node: IRNode, ids: Map<string, string>): string {
|
|
|
60
92
|
function edgeLine(e: IREdge, ids: Map<string, string>): string {
|
|
61
93
|
const from = safeId(e.from, ids);
|
|
62
94
|
const to = safeId(e.to, ids);
|
|
63
|
-
const label =
|
|
64
|
-
|
|
95
|
+
const label = edgeLabel(e);
|
|
96
|
+
// A cross-pipeline edge is dashed, so it reads as leaving its workflow.
|
|
97
|
+
const arrow = e.crossPipeline ? "-.->" : "-->";
|
|
98
|
+
return label ? `${from} ${arrow}|${quote(label)}| ${to}` : `${from} ${arrow} ${to}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** A typed reference is labelled by the attribute it flows through; a CI edge
|
|
102
|
+
* (#3910) by its kind, plus the attribute when that says something more
|
|
103
|
+
* (`needs (stage)` for GitLab's stage order). */
|
|
104
|
+
export function edgeLabel(e: IREdge): string {
|
|
105
|
+
if (e.kind === "ref" || !e.kind) return [e.viaAttr, e.toAttr].filter(Boolean).join(" → ");
|
|
106
|
+
return e.viaAttr && e.viaAttr !== e.kind ? `${e.kind} (${e.viaAttr})` : e.kind;
|
|
65
107
|
}
|
|
66
108
|
|
|
67
109
|
/** Map an arbitrary logical name to a stable, unique Mermaid-safe node id. */
|
package/src/lexicon.ts
CHANGED
|
@@ -23,7 +23,7 @@ import type { OwnershipChannel, OwnershipMarker } from "./ownership";
|
|
|
23
23
|
import type { LexiconConfigSchema } from "./lexicon-config";
|
|
24
24
|
import type { RuleMeta } from "./audit/catalog";
|
|
25
25
|
import type { ReferenceCatalog } from "./graph-refs";
|
|
26
|
-
import type { IREdge } from "./graph-ir";
|
|
26
|
+
import type { IREdge, LexiconGraphEdges } from "./graph-ir";
|
|
27
27
|
import type { DescribeResourcesResult, UnobservedReason } from "./observation";
|
|
28
28
|
import type { DescribeIdentityOptions, DescribeIdentityResult } from "./identity";
|
|
29
29
|
import type { DeepNormalizationHooks, DeepObservationResult } from "./deep-observation";
|
|
@@ -1433,6 +1433,23 @@ export interface LexiconPlugin {
|
|
|
1433
1433
|
*/
|
|
1434
1434
|
graphMeta?(entities: ReadonlyMap<string, Declarable>): Record<string, unknown> | undefined;
|
|
1435
1435
|
|
|
1436
|
+
/**
|
|
1437
|
+
* Edges this lexicon's entities declare as strings (#3910). A typed lexicon
|
|
1438
|
+
* gets its edges from `AttrRef`s for free; a CI lexicon writes its
|
|
1439
|
+
* dependencies as job names (`needs: ["build"]`), workflow paths (`uses:
|
|
1440
|
+
* ./.github/workflows/ci.yml`) and file names (`include:`), which only the
|
|
1441
|
+
* lexicon can resolve. It resolves them here, against the whole entity map,
|
|
1442
|
+
* and reports each as a `{ from, to, kind }` between entity keys, or as
|
|
1443
|
+
* `dangling` with the string as written when nothing declared matches.
|
|
1444
|
+
* `pipelines` says which entities run in which workflow or pipeline.
|
|
1445
|
+
*
|
|
1446
|
+
* Called by `chant graph` with the discovered entities, after the plugins
|
|
1447
|
+
* are loaded; merged by `applyLexiconGraphEdges` (./graph-ir.ts). Pure: no
|
|
1448
|
+
* I/O. Return `undefined` when the project declares nothing this lexicon
|
|
1449
|
+
* reads. Omit for lexicons whose references are typed.
|
|
1450
|
+
*/
|
|
1451
|
+
graphEdges?(entities: ReadonlyMap<string, Declarable>): LexiconGraphEdges | undefined;
|
|
1452
|
+
|
|
1436
1453
|
// LSP
|
|
1437
1454
|
/** Provide completions for LSP */
|
|
1438
1455
|
completionProvider?(ctx: CompletionContext): CompletionItem[];
|
|
@@ -2051,6 +2068,10 @@ export interface LexiconPlugin {
|
|
|
2051
2068
|
* (the form a user would have authored). `verbatim: true` keeps them. Targets
|
|
2052
2069
|
* whose live config is already the declared shape (e.g. a CloudFormation
|
|
2053
2070
|
* original template) may ignore it.
|
|
2071
|
+
*
|
|
2072
|
+
* `skipUndeclarable` (`--skip-undeclarable`): an implementation that fails
|
|
2073
|
+
* an import for live objects no declaration can hold, naming them, imports
|
|
2074
|
+
* the rest instead and returns them as warnings.
|
|
2054
2075
|
*/
|
|
2055
2076
|
exportResources?(options: {
|
|
2056
2077
|
environment: string;
|
|
@@ -2064,6 +2085,7 @@ export interface LexiconPlugin {
|
|
|
2064
2085
|
selector?: ResourceSelector;
|
|
2065
2086
|
owned?: boolean;
|
|
2066
2087
|
verbatim?: boolean;
|
|
2088
|
+
skipUndeclarable?: boolean;
|
|
2067
2089
|
}): Promise<ExportedTemplate>;
|
|
2068
2090
|
}
|
|
2069
2091
|
|