openlore 2.0.3 → 2.0.5
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/README.md +20 -9
- package/dist/cli/commands/analyze.d.ts.map +1 -1
- package/dist/cli/commands/analyze.js +68 -54
- package/dist/cli/commands/analyze.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +1 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/orient.d.ts +15 -0
- package/dist/cli/commands/orient.d.ts.map +1 -0
- package/dist/cli/commands/orient.js +156 -0
- package/dist/cli/commands/orient.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/install/index.d.ts +6 -0
- package/dist/cli/install/index.d.ts.map +1 -1
- package/dist/cli/install/index.js +71 -1
- package/dist/cli/install/index.js.map +1 -1
- package/dist/core/analyzer/artifact-generator.d.ts.map +1 -1
- package/dist/core/analyzer/artifact-generator.js +37 -3
- package/dist/core/analyzer/artifact-generator.js.map +1 -1
- package/dist/core/analyzer/call-graph.d.ts +9 -2
- package/dist/core/analyzer/call-graph.d.ts.map +1 -1
- package/dist/core/analyzer/call-graph.js +534 -1
- package/dist/core/analyzer/call-graph.js.map +1 -1
- package/dist/core/analyzer/embedding-service.d.ts +2 -0
- package/dist/core/analyzer/embedding-service.d.ts.map +1 -1
- package/dist/core/analyzer/embedding-service.js +4 -0
- package/dist/core/analyzer/embedding-service.js.map +1 -1
- package/dist/core/analyzer/fixtures/regression/sample.d.ts +9 -0
- package/dist/core/analyzer/fixtures/regression/sample.d.ts.map +1 -0
- package/dist/core/analyzer/fixtures/regression/sample.js +26 -0
- package/dist/core/analyzer/fixtures/regression/sample.js.map +1 -0
- package/dist/core/analyzer/iac/ansible.d.ts +18 -0
- package/dist/core/analyzer/iac/ansible.d.ts.map +1 -0
- package/dist/core/analyzer/iac/ansible.js +219 -0
- package/dist/core/analyzer/iac/ansible.js.map +1 -0
- package/dist/core/analyzer/iac/cdk.d.ts +26 -0
- package/dist/core/analyzer/iac/cdk.d.ts.map +1 -0
- package/dist/core/analyzer/iac/cdk.js +204 -0
- package/dist/core/analyzer/iac/cdk.js.map +1 -0
- package/dist/core/analyzer/iac/classify-yaml.d.ts +20 -0
- package/dist/core/analyzer/iac/classify-yaml.d.ts.map +1 -0
- package/dist/core/analyzer/iac/classify-yaml.js +81 -0
- package/dist/core/analyzer/iac/classify-yaml.js.map +1 -0
- package/dist/core/analyzer/iac/cloudformation.d.ts +15 -0
- package/dist/core/analyzer/iac/cloudformation.d.ts.map +1 -0
- package/dist/core/analyzer/iac/cloudformation.js +189 -0
- package/dist/core/analyzer/iac/cloudformation.js.map +1 -0
- package/dist/core/analyzer/iac/helm.d.ts +20 -0
- package/dist/core/analyzer/iac/helm.d.ts.map +1 -0
- package/dist/core/analyzer/iac/helm.js +229 -0
- package/dist/core/analyzer/iac/helm.js.map +1 -0
- package/dist/core/analyzer/iac/index.d.ts +23 -0
- package/dist/core/analyzer/iac/index.d.ts.map +1 -0
- package/dist/core/analyzer/iac/index.js +40 -0
- package/dist/core/analyzer/iac/index.js.map +1 -0
- package/dist/core/analyzer/iac/kubernetes.d.ts +14 -0
- package/dist/core/analyzer/iac/kubernetes.d.ts.map +1 -0
- package/dist/core/analyzer/iac/kubernetes.js +226 -0
- package/dist/core/analyzer/iac/kubernetes.js.map +1 -0
- package/dist/core/analyzer/iac/project.d.ts +16 -0
- package/dist/core/analyzer/iac/project.d.ts.map +1 -0
- package/dist/core/analyzer/iac/project.js +97 -0
- package/dist/core/analyzer/iac/project.js.map +1 -0
- package/dist/core/analyzer/iac/pulumi.d.ts +21 -0
- package/dist/core/analyzer/iac/pulumi.d.ts.map +1 -0
- package/dist/core/analyzer/iac/pulumi.js +190 -0
- package/dist/core/analyzer/iac/pulumi.js.map +1 -0
- package/dist/core/analyzer/iac/terraform.d.ts +19 -0
- package/dist/core/analyzer/iac/terraform.d.ts.map +1 -0
- package/dist/core/analyzer/iac/terraform.js +546 -0
- package/dist/core/analyzer/iac/terraform.js.map +1 -0
- package/dist/core/analyzer/iac/types.d.ts +67 -0
- package/dist/core/analyzer/iac/types.d.ts.map +1 -0
- package/dist/core/analyzer/iac/types.js +39 -0
- package/dist/core/analyzer/iac/types.js.map +1 -0
- package/dist/core/analyzer/signature-extractor.d.ts +6 -0
- package/dist/core/analyzer/signature-extractor.d.ts.map +1 -1
- package/dist/core/analyzer/signature-extractor.js +112 -2
- package/dist/core/analyzer/signature-extractor.js.map +1 -1
- package/dist/core/analyzer/spec-vector-index.d.ts +9 -2
- package/dist/core/analyzer/spec-vector-index.d.ts.map +1 -1
- package/dist/core/analyzer/spec-vector-index.js +111 -10
- package/dist/core/analyzer/spec-vector-index.js.map +1 -1
- package/dist/core/analyzer/vector-index.d.ts +33 -1
- package/dist/core/analyzer/vector-index.d.ts.map +1 -1
- package/dist/core/analyzer/vector-index.js +99 -10
- package/dist/core/analyzer/vector-index.js.map +1 -1
- package/dist/core/services/edge-store.d.ts +6 -0
- package/dist/core/services/edge-store.d.ts.map +1 -1
- package/dist/core/services/edge-store.js +8 -0
- package/dist/core/services/edge-store.js.map +1 -1
- package/dist/core/services/mcp-handlers/graph.d.ts.map +1 -1
- package/dist/core/services/mcp-handlers/graph.js +12 -0
- package/dist/core/services/mcp-handlers/graph.js.map +1 -1
- package/dist/core/services/mcp-handlers/orient.js +2 -2
- package/dist/core/services/mcp-handlers/orient.js.map +1 -1
- package/dist/core/services/mcp-handlers/semantic.d.ts.map +1 -1
- package/dist/core/services/mcp-handlers/semantic.js +23 -30
- package/dist/core/services/mcp-handlers/semantic.js.map +1 -1
- package/dist/core/services/mcp-watcher.d.ts +9 -0
- package/dist/core/services/mcp-watcher.d.ts.map +1 -1
- package/dist/core/services/mcp-watcher.js +72 -20
- package/dist/core/services/mcp-watcher.js.map +1 -1
- package/package.json +10 -1
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubernetes manifest extraction (spec-07).
|
|
3
|
+
*
|
|
4
|
+
* One node per YAML document (`---`-separated). Edges follow the typed
|
|
5
|
+
* references that operators reason about: label selectors, *KeyRef / envFrom,
|
|
6
|
+
* volume refs, serviceName, ownerReferences, Ingress→Service, serviceAccount.
|
|
7
|
+
* Unknown kinds (CRDs) still become nodes — only unresolved edges are dropped.
|
|
8
|
+
*/
|
|
9
|
+
import { LineCounter, parseAllDocuments } from 'yaml';
|
|
10
|
+
import { emptyIacGraph } from './types.js';
|
|
11
|
+
const WORKLOAD_KINDS = new Set([
|
|
12
|
+
'Deployment', 'StatefulSet', 'DaemonSet', 'ReplicaSet', 'ReplicationController',
|
|
13
|
+
'Pod', 'Job', 'CronJob',
|
|
14
|
+
]);
|
|
15
|
+
export function extractKubernetes(files) {
|
|
16
|
+
const graph = emptyIacGraph();
|
|
17
|
+
const objects = [];
|
|
18
|
+
for (const file of files) {
|
|
19
|
+
const lc = new LineCounter();
|
|
20
|
+
let docs;
|
|
21
|
+
try {
|
|
22
|
+
docs = parseAllDocuments(file.content, { lineCounter: lc });
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
for (const doc of docs) {
|
|
28
|
+
const obj = doc.toJS();
|
|
29
|
+
if (!obj || typeof obj !== 'object')
|
|
30
|
+
continue;
|
|
31
|
+
const kind = typeof obj.kind === 'string' ? obj.kind : '';
|
|
32
|
+
const meta = (obj.metadata ?? {});
|
|
33
|
+
const name = typeof meta.name === 'string' ? meta.name : '';
|
|
34
|
+
if (!kind || !name)
|
|
35
|
+
continue;
|
|
36
|
+
const namespace = typeof meta.namespace === 'string' ? meta.namespace : undefined;
|
|
37
|
+
const address = namespace ? `${namespace}/${kind}/${name}` : `${kind}/${name}`;
|
|
38
|
+
const start = doc.range?.[0] ?? 0;
|
|
39
|
+
const startLine = lc.linePos(start).line;
|
|
40
|
+
const resource = {
|
|
41
|
+
address,
|
|
42
|
+
type: kind,
|
|
43
|
+
kind: 'manifest',
|
|
44
|
+
filePath: file.path,
|
|
45
|
+
startLine,
|
|
46
|
+
module: namespace,
|
|
47
|
+
signature: `${kind}/${name}${namespace ? ` (ns: ${namespace})` : ''}`,
|
|
48
|
+
language: 'Kubernetes',
|
|
49
|
+
};
|
|
50
|
+
graph.resources.push(resource);
|
|
51
|
+
objects.push({
|
|
52
|
+
kind,
|
|
53
|
+
name,
|
|
54
|
+
namespace,
|
|
55
|
+
labels: asStringMap((meta.labels ?? {})),
|
|
56
|
+
templateLabels: asStringMap(podTemplateLabels(obj)),
|
|
57
|
+
raw: obj,
|
|
58
|
+
resource,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
resolveEdges(objects, graph);
|
|
63
|
+
return graph;
|
|
64
|
+
}
|
|
65
|
+
function resolveEdges(objects, graph) {
|
|
66
|
+
// Index by (namespace, kind, name) → address for name-based refs.
|
|
67
|
+
const byKindName = new Map();
|
|
68
|
+
const key = (ns, kind, name) => `${ns ?? ''}\0${kind}\0${name}`;
|
|
69
|
+
for (const o of objects)
|
|
70
|
+
byKindName.set(key(o.namespace, o.kind, o.name), o.resource.address);
|
|
71
|
+
const ref = (from, to, kind = 'references') => {
|
|
72
|
+
if (!to || to === from)
|
|
73
|
+
return;
|
|
74
|
+
graph.references.push({ fromAddress: from, toAddress: to, kind });
|
|
75
|
+
};
|
|
76
|
+
const lookup = (ns, kind, name) => byKindName.get(key(ns, kind, name));
|
|
77
|
+
for (const o of objects) {
|
|
78
|
+
const ns = o.namespace;
|
|
79
|
+
const addr = o.resource.address;
|
|
80
|
+
// Service selector → matching workloads (Service depends on the pods it routes to).
|
|
81
|
+
if (o.kind === 'Service') {
|
|
82
|
+
const sel = asStringMap(((o.raw.spec ?? {}).selector ?? {}));
|
|
83
|
+
if (Object.keys(sel).length > 0) {
|
|
84
|
+
for (const target of objects) {
|
|
85
|
+
if (!WORKLOAD_KINDS.has(target.kind) || target.namespace !== ns)
|
|
86
|
+
continue;
|
|
87
|
+
const labels = { ...target.labels, ...target.templateLabels };
|
|
88
|
+
if (selectorMatches(sel, labels))
|
|
89
|
+
ref(addr, target.resource.address);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Workload references to ConfigMaps / Secrets / PVCs / ServiceAccount.
|
|
94
|
+
if (WORKLOAD_KINDS.has(o.kind)) {
|
|
95
|
+
const podSpec = findPodSpec(o.raw);
|
|
96
|
+
if (podSpec) {
|
|
97
|
+
for (const cm of collectRefs(podSpec, 'configMap', 'configMapKeyRef', 'configMapRef')) {
|
|
98
|
+
ref(addr, lookup(ns, 'ConfigMap', cm));
|
|
99
|
+
}
|
|
100
|
+
for (const sec of collectRefs(podSpec, 'secret', 'secretKeyRef', 'secretRef', 'secretName')) {
|
|
101
|
+
ref(addr, lookup(ns, 'Secret', sec));
|
|
102
|
+
}
|
|
103
|
+
for (const pvc of collectRefs(podSpec, 'persistentVolumeClaim')) {
|
|
104
|
+
ref(addr, lookup(ns, 'PersistentVolumeClaim', pvc));
|
|
105
|
+
}
|
|
106
|
+
const sa = (podSpec.serviceAccountName ?? podSpec.serviceAccount);
|
|
107
|
+
if (typeof sa === 'string')
|
|
108
|
+
ref(addr, lookup(ns, 'ServiceAccount', sa));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// StatefulSet.spec.serviceName → Service.
|
|
112
|
+
if (o.kind === 'StatefulSet') {
|
|
113
|
+
const svcName = ((o.raw.spec ?? {}).serviceName);
|
|
114
|
+
if (typeof svcName === 'string')
|
|
115
|
+
ref(addr, lookup(ns, 'Service', svcName));
|
|
116
|
+
}
|
|
117
|
+
// ownerReferences → owner (dependent child → owner).
|
|
118
|
+
const ownerRefs = (o.raw.metadata ?? {}).ownerReferences;
|
|
119
|
+
if (Array.isArray(ownerRefs)) {
|
|
120
|
+
for (const owner of ownerRefs) {
|
|
121
|
+
if (typeof owner.kind === 'string' && typeof owner.name === 'string') {
|
|
122
|
+
ref(addr, lookup(ns, owner.kind, owner.name), 'depends_on');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Ingress backend.service.name → Service.
|
|
127
|
+
if (o.kind === 'Ingress') {
|
|
128
|
+
for (const svc of ingressServices(o.raw))
|
|
129
|
+
ref(addr, lookup(ns, 'Service', svc));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
function podTemplateLabels(obj) {
|
|
135
|
+
const spec = (obj.spec ?? {});
|
|
136
|
+
const template = (spec.template ?? {});
|
|
137
|
+
const meta = (template.metadata ?? {});
|
|
138
|
+
// CronJob nests one level deeper.
|
|
139
|
+
if (obj.kind === 'CronJob') {
|
|
140
|
+
const jobSpec = (spec.jobTemplate ?? {}).spec;
|
|
141
|
+
const jt = (jobSpec?.template ?? {}).metadata;
|
|
142
|
+
return (jt?.labels ?? {});
|
|
143
|
+
}
|
|
144
|
+
return (meta.labels ?? {});
|
|
145
|
+
}
|
|
146
|
+
function findPodSpec(obj) {
|
|
147
|
+
const spec = (obj.spec ?? {});
|
|
148
|
+
if (obj.kind === 'Pod')
|
|
149
|
+
return spec;
|
|
150
|
+
if (obj.kind === 'CronJob') {
|
|
151
|
+
const jobSpec = spec.jobTemplate?.spec;
|
|
152
|
+
return (jobSpec?.template?.spec ?? null);
|
|
153
|
+
}
|
|
154
|
+
const template = spec.template;
|
|
155
|
+
return (template?.spec ?? null);
|
|
156
|
+
}
|
|
157
|
+
/** Recursively collect string values stored under any of the given keys. */
|
|
158
|
+
function collectRefs(node, ...keys) {
|
|
159
|
+
const out = [];
|
|
160
|
+
const keySet = new Set(keys);
|
|
161
|
+
const walk = (n) => {
|
|
162
|
+
if (Array.isArray(n)) {
|
|
163
|
+
for (const x of n)
|
|
164
|
+
walk(x);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (n && typeof n === 'object') {
|
|
168
|
+
for (const [k, v] of Object.entries(n)) {
|
|
169
|
+
if (keySet.has(k)) {
|
|
170
|
+
if (typeof v === 'string')
|
|
171
|
+
out.push(v);
|
|
172
|
+
else if (v && typeof v === 'object') {
|
|
173
|
+
const name = v.name;
|
|
174
|
+
if (typeof name === 'string')
|
|
175
|
+
out.push(name);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
walk(v);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
walk(node);
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
185
|
+
function ingressServices(obj) {
|
|
186
|
+
const out = [];
|
|
187
|
+
const walk = (n) => {
|
|
188
|
+
if (Array.isArray(n)) {
|
|
189
|
+
for (const x of n)
|
|
190
|
+
walk(x);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (n && typeof n === 'object') {
|
|
194
|
+
const rec = n;
|
|
195
|
+
// networking.k8s.io/v1: backend.service.name
|
|
196
|
+
const svc = (rec.service ?? {});
|
|
197
|
+
if (typeof svc.name === 'string')
|
|
198
|
+
out.push(svc.name);
|
|
199
|
+
// extensions/v1beta1: backend.serviceName
|
|
200
|
+
if (typeof rec.serviceName === 'string')
|
|
201
|
+
out.push(rec.serviceName);
|
|
202
|
+
for (const v of Object.values(rec))
|
|
203
|
+
walk(v);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
walk(obj.spec);
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
function selectorMatches(selector, labels) {
|
|
210
|
+
for (const [k, v] of Object.entries(selector)) {
|
|
211
|
+
if (labels[k] !== v)
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
function asStringMap(obj) {
|
|
217
|
+
const out = {};
|
|
218
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
219
|
+
if (typeof v === 'string')
|
|
220
|
+
out[k] = v;
|
|
221
|
+
else if (typeof v === 'number' || typeof v === 'boolean')
|
|
222
|
+
out[k] = String(v);
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=kubernetes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kubernetes.js","sourceRoot":"","sources":["../../../../src/core/analyzer/iac/kubernetes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAY3C,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,uBAAuB;IAC/E,KAAK,EAAE,KAAK,EAAE,SAAS;CACxB,CAAC,CAAC;AAEH,MAAM,UAAU,iBAAiB,CAC/B,KAA+C;IAE/C,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAgB,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC;QACT,IAAI,CAAC;YACH,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,EAAoC,CAAC;YACzD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,SAAS;YAC9C,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;YAC7D,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;gBAAE,SAAS;YAC7B,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YAClF,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;YAC/E,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;YACzC,MAAM,QAAQ,GAAgB;gBAC5B,OAAO;gBACP,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,SAAS;gBACT,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,GAAG,IAAI,IAAI,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACrE,QAAQ,EAAE,YAAY;aACvB,CAAC;YACF,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI;gBACJ,IAAI;gBACJ,SAAS;gBACT,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAA4B,CAAC;gBACnE,cAAc,EAAE,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBACnD,GAAG,EAAE,GAAG;gBACR,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,OAAoB,EAAE,KAAe;IACzD,kEAAkE;IAClE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,MAAM,GAAG,GAAG,CAAC,EAAsB,EAAE,IAAY,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,CAAC;IACpG,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE9F,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAsB,EAAE,OAA6B,YAAY,EAAE,EAAE;QAC9F,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI;YAAE,OAAO;QAC/B,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,EAAsB,EAAE,IAAY,EAAE,IAAY,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAE3G,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QAEhC,oFAAoF;QACpF,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,WAAW,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA6B,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC,CAAC;YACrH,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;oBAC7B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,SAAS,KAAK,EAAE;wBAAE,SAAS;oBAC1E,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;oBAC9D,IAAI,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC;wBAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;QAED,uEAAuE;QACvE,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,MAAM,EAAE,IAAI,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,CAAC,EAAE,CAAC;oBACtF,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;gBACzC,CAAC;gBACD,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,CAAC;oBAC5F,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;gBACvC,CAAC;gBACD,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,uBAAuB,CAAC,EAAE,CAAC;oBAChE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,uBAAuB,EAAE,GAAG,CAAC,CAAC,CAAC;gBACtD,CAAC;gBACD,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAuB,CAAC;gBACxF,IAAI,OAAO,EAAE,KAAK,QAAQ;oBAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA6B,CAAC,WAAW,CAAuB,CAAC;YACpG,IAAI,OAAO,OAAO,KAAK,QAAQ;gBAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAC7E,CAAC;QAED,qDAAqD;QACrD,MAAM,SAAS,GAAI,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAA6B,CAAC,eAAe,CAAC;QACtF,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,KAAK,MAAM,KAAK,IAAI,SAA2C,EAAE,CAAC;gBAChE,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACrE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC;gBAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;AACH,CAAC;AAED,8EAA8E;AAE9E,SAAS,iBAAiB,CAAC,GAA4B;IACrD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IACzD,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;IAClE,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;IAClE,kCAAkC;IAClC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAI,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAA6B,CAAC,IAA2C,CAAC;QAClH,MAAM,EAAE,GAAI,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAA6B,CAAC,QAA+C,CAAC;QAClH,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,CAA4B,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAA4B,CAAC;AACxD,CAAC;AAED,SAAS,WAAW,CAAC,GAA4B;IAC/C,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IACzD,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAI,IAAI,CAAC,WAAmD,EAAE,IAA2C,CAAC;QACvH,OAAO,CAAE,OAAO,EAAE,QAAgD,EAAE,IAAI,IAAI,IAAI,CAAmC,CAAC;IACtH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAA+C,CAAC;IACtE,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,IAAI,CAAmC,CAAC;AACpE,CAAC;AAED,4EAA4E;AAC5E,SAAS,WAAW,CAAC,IAAa,EAAE,GAAG,IAAc;IACnD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,CAAU,EAAE,EAAE;QAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,KAAK,MAAM,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAA4B,CAAC,EAAE,CAAC;gBAClE,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClB,IAAI,OAAO,CAAC,KAAK,QAAQ;wBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;yBAClC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;wBACpC,MAAM,IAAI,GAAI,CAA6B,CAAC,IAAI,CAAC;wBACjD,IAAI,OAAO,IAAI,KAAK,QAAQ;4BAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;gBACD,IAAI,CAAC,CAAC,CAAC,CAAC;YACV,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,eAAe,CAAC,GAA4B;IACnD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,CAAC,CAAU,EAAE,EAAE;QAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,KAAK,MAAM,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,CAA4B,CAAC;YACzC,6CAA6C;YAC7C,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAA4B,CAAC;YAC3D,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACrD,0CAA0C;YAC1C,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACnE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACf,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,eAAe,CAAC,QAAgC,EAAE,MAA8B;IACvF,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,GAA4B;IAC/C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;aACjC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Projection: normalized IaC graph → existing FunctionNode/CallEdge/ClassNode (spec-07).
|
|
3
|
+
*
|
|
4
|
+
* This is the single place where infrastructure becomes ordinary graph nodes.
|
|
5
|
+
* Because we reuse the existing primitives, orient/search_code/get_subgraph/
|
|
6
|
+
* analyze_impact and the SCIP + federation exports all work on IaC unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import type { CallEdge, ClassNode, FunctionNode } from '../call-graph.js';
|
|
9
|
+
import type { IacGraph } from './types.js';
|
|
10
|
+
export interface ProjectedIac {
|
|
11
|
+
nodes: FunctionNode[];
|
|
12
|
+
edges: CallEdge[];
|
|
13
|
+
classes: ClassNode[];
|
|
14
|
+
}
|
|
15
|
+
export declare function projectIacGraph(graph: IacGraph): ProjectedIac;
|
|
16
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../../src/core/analyzer/iac/project.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAOD,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,YAAY,CA4F7D"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Projection: normalized IaC graph → existing FunctionNode/CallEdge/ClassNode (spec-07).
|
|
3
|
+
*
|
|
4
|
+
* This is the single place where infrastructure becomes ordinary graph nodes.
|
|
5
|
+
* Because we reuse the existing primitives, orient/search_code/get_subgraph/
|
|
6
|
+
* analyze_impact and the SCIP + federation exports all work on IaC unchanged.
|
|
7
|
+
*/
|
|
8
|
+
/** Stable node id for a resource address. */
|
|
9
|
+
function nodeId(filePath, address, isExternal, language) {
|
|
10
|
+
return isExternal ? `iac-external::${language}::${address}` : `${filePath}::${address}`;
|
|
11
|
+
}
|
|
12
|
+
export function projectIacGraph(graph) {
|
|
13
|
+
// address → FunctionNode (first declaration wins; deterministic via sorted input).
|
|
14
|
+
const byAddress = new Map();
|
|
15
|
+
const nodes = new Map();
|
|
16
|
+
const sortedResources = [...graph.resources].sort((a, b) => a.filePath.localeCompare(b.filePath) ||
|
|
17
|
+
a.startLine - b.startLine ||
|
|
18
|
+
a.address.localeCompare(b.address));
|
|
19
|
+
for (const r of sortedResources) {
|
|
20
|
+
const id = nodeId(r.filePath, r.address, !!r.isExternal, r.language);
|
|
21
|
+
if (!nodes.has(id)) {
|
|
22
|
+
const node = {
|
|
23
|
+
id,
|
|
24
|
+
name: r.address,
|
|
25
|
+
filePath: r.filePath,
|
|
26
|
+
className: r.type,
|
|
27
|
+
isAsync: false,
|
|
28
|
+
language: r.language,
|
|
29
|
+
startIndex: 0,
|
|
30
|
+
endIndex: 0,
|
|
31
|
+
fanIn: 0,
|
|
32
|
+
fanOut: 0,
|
|
33
|
+
signature: r.signature,
|
|
34
|
+
startLine: r.startLine,
|
|
35
|
+
endLine: r.endLine ?? r.startLine,
|
|
36
|
+
isExternal: r.isExternal || undefined,
|
|
37
|
+
};
|
|
38
|
+
nodes.set(id, node);
|
|
39
|
+
}
|
|
40
|
+
// First resource to claim an address owns it (for reference resolution).
|
|
41
|
+
if (!byAddress.has(r.address))
|
|
42
|
+
byAddress.set(r.address, nodes.get(id));
|
|
43
|
+
}
|
|
44
|
+
// References → edges (dependent → dependency). Drop unresolved targets.
|
|
45
|
+
const edgeSeen = new Set();
|
|
46
|
+
const edges = [];
|
|
47
|
+
const sortedRefs = [...graph.references].sort((a, b) => a.fromAddress.localeCompare(b.fromAddress) ||
|
|
48
|
+
a.toAddress.localeCompare(b.toAddress) ||
|
|
49
|
+
a.kind.localeCompare(b.kind) ||
|
|
50
|
+
(a.line ?? 0) - (b.line ?? 0));
|
|
51
|
+
for (const ref of sortedRefs) {
|
|
52
|
+
const from = byAddress.get(ref.fromAddress);
|
|
53
|
+
const to = byAddress.get(ref.toAddress);
|
|
54
|
+
if (!from || !to || from.id === to.id)
|
|
55
|
+
continue;
|
|
56
|
+
const key = `${from.id}\0${to.id}\0${ref.kind}`;
|
|
57
|
+
if (edgeSeen.has(key))
|
|
58
|
+
continue;
|
|
59
|
+
edgeSeen.add(key);
|
|
60
|
+
edges.push({
|
|
61
|
+
callerId: from.id,
|
|
62
|
+
calleeId: to.id,
|
|
63
|
+
calleeName: to.name,
|
|
64
|
+
line: ref.line,
|
|
65
|
+
confidence: 'import',
|
|
66
|
+
kind: ref.kind,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// Modules → ClassNodes (module-style grouping).
|
|
70
|
+
const classes = [];
|
|
71
|
+
const sortedModules = [...graph.modules].sort((a, b) => a.address.localeCompare(b.address));
|
|
72
|
+
for (const m of sortedModules) {
|
|
73
|
+
const id = nodeId(m.filePath, m.address, !!m.isExternal, m.language);
|
|
74
|
+
const methodIds = m.members
|
|
75
|
+
.map((addr) => byAddress.get(addr)?.id)
|
|
76
|
+
.filter((x) => !!x)
|
|
77
|
+
.sort();
|
|
78
|
+
classes.push({
|
|
79
|
+
id,
|
|
80
|
+
name: m.address,
|
|
81
|
+
filePath: m.filePath,
|
|
82
|
+
language: m.language,
|
|
83
|
+
parentClasses: [],
|
|
84
|
+
interfaces: [],
|
|
85
|
+
methodIds,
|
|
86
|
+
fanIn: 0,
|
|
87
|
+
fanOut: 0,
|
|
88
|
+
isModule: true,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
nodes: [...nodes.values()].sort((a, b) => a.id.localeCompare(b.id)),
|
|
93
|
+
edges,
|
|
94
|
+
classes: classes.sort((a, b) => a.id.localeCompare(b.id)),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../../src/core/analyzer/iac/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pulumi framework detector (spec-07, lightest ecosystem).
|
|
3
|
+
*
|
|
4
|
+
* Pulumi programs are written in TS/JS/Python/Go — already parsed for the call
|
|
5
|
+
* graph. We do NOT add a grammar; we recognize Pulumi resource constructions
|
|
6
|
+
* over the existing source and emit extra `Pulumi` resource nodes + reference
|
|
7
|
+
* edges, without touching the normal call graph for those files.
|
|
8
|
+
*
|
|
9
|
+
* Scope conservatively: only the common provider SDKs (@pulumi/aws, /gcp,
|
|
10
|
+
* /azure-native, /kubernetes). Unknown SDKs → no resource nodes.
|
|
11
|
+
* CDK / CDKTF are intentionally out of scope (deferred to a future spec).
|
|
12
|
+
*/
|
|
13
|
+
import type { IacGraph } from './types.js';
|
|
14
|
+
interface InFile {
|
|
15
|
+
path: string;
|
|
16
|
+
content: string;
|
|
17
|
+
language: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function extractPulumi(files: InFile[]): IacGraph;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=pulumi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pulumi.d.ts","sourceRoot":"","sources":["../../../../src/core/analyzer/iac/pulumi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,YAAY,CAAC;AAGxD,UAAU,MAAM;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE;AAepE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAYvD"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pulumi framework detector (spec-07, lightest ecosystem).
|
|
3
|
+
*
|
|
4
|
+
* Pulumi programs are written in TS/JS/Python/Go — already parsed for the call
|
|
5
|
+
* graph. We do NOT add a grammar; we recognize Pulumi resource constructions
|
|
6
|
+
* over the existing source and emit extra `Pulumi` resource nodes + reference
|
|
7
|
+
* edges, without touching the normal call graph for those files.
|
|
8
|
+
*
|
|
9
|
+
* Scope conservatively: only the common provider SDKs (@pulumi/aws, /gcp,
|
|
10
|
+
* /azure-native, /kubernetes). Unknown SDKs → no resource nodes.
|
|
11
|
+
* CDK / CDKTF are intentionally out of scope (deferred to a future spec).
|
|
12
|
+
*/
|
|
13
|
+
import { emptyIacGraph } from './types.js';
|
|
14
|
+
const PROVIDER_PKGS = ['@pulumi/aws', '@pulumi/gcp', '@pulumi/azure', '@pulumi/azure-native', '@pulumi/kubernetes', '@pulumi/pulumi'];
|
|
15
|
+
const PY_PROVIDER_MODS = ['pulumi_aws', 'pulumi_gcp', 'pulumi_azure', 'pulumi_azure_native', 'pulumi_kubernetes', 'pulumi'];
|
|
16
|
+
const GO_PROVIDER_PATHS = ['pulumi-aws', 'pulumi-gcp', 'pulumi-azure', 'pulumi-azure-native', 'pulumi-kubernetes', 'pulumi/pulumi/sdk'];
|
|
17
|
+
export function extractPulumi(files) {
|
|
18
|
+
const graph = emptyIacGraph();
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
if (file.language === 'TypeScript' || file.language === 'JavaScript') {
|
|
21
|
+
ingest(file, detectTsProviderNames(file.content), true, graph);
|
|
22
|
+
}
|
|
23
|
+
else if (file.language === 'Python') {
|
|
24
|
+
ingest(file, detectPyProviderNames(file.content), false, graph);
|
|
25
|
+
}
|
|
26
|
+
else if (file.language === 'Go') {
|
|
27
|
+
ingestGo(file, detectGoProviderNames(file.content), graph);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return graph;
|
|
31
|
+
}
|
|
32
|
+
/** Go: `bucket, _ := s3.NewBucket(ctx, "logs", &s3.BucketArgs{…})`. */
|
|
33
|
+
function ingestGo(file, providerNames, graph) {
|
|
34
|
+
if (providerNames.size === 0)
|
|
35
|
+
return;
|
|
36
|
+
const re = /(?:(\w+)\s*(?:,\s*\w+\s*)?:?=\s*)?([A-Za-z_]\w*)\.New([A-Z]\w*)\(\s*[\w.]+\s*,\s*"([^"]+)"/g;
|
|
37
|
+
const constructions = [];
|
|
38
|
+
for (const m of file.content.matchAll(re)) {
|
|
39
|
+
const [, varName, pkg, service, name] = m;
|
|
40
|
+
if (!providerNames.has(pkg))
|
|
41
|
+
continue;
|
|
42
|
+
const callParen = (m.index ?? 0) + m[0].indexOf('(');
|
|
43
|
+
constructions.push({
|
|
44
|
+
address: `${service}:${name}`, service, name,
|
|
45
|
+
line: lineOf(file.content, m.index ?? 0), varName, argsText: sliceArgs(file.content, callParen),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
emitConstructions(constructions, file, graph);
|
|
49
|
+
}
|
|
50
|
+
/** Go provider package local names (alias or last import-path segment). */
|
|
51
|
+
function detectGoProviderNames(content) {
|
|
52
|
+
const names = new Set();
|
|
53
|
+
for (const m of content.matchAll(/(?:(\w+)\s+)?"(github\.com\/pulumi\/[^"]+)"/g)) {
|
|
54
|
+
const alias = m[1];
|
|
55
|
+
const path = m[2];
|
|
56
|
+
if (!GO_PROVIDER_PATHS.some((p) => path.includes(p)))
|
|
57
|
+
continue;
|
|
58
|
+
names.add(alias ?? path.split('/').pop());
|
|
59
|
+
}
|
|
60
|
+
return names;
|
|
61
|
+
}
|
|
62
|
+
function ingest(file, providerNames, isTs, graph) {
|
|
63
|
+
if (providerNames.size === 0)
|
|
64
|
+
return;
|
|
65
|
+
emitConstructions(findConstructions(file.content, providerNames, isTs), file, graph);
|
|
66
|
+
}
|
|
67
|
+
/** Emit resource nodes + variable-reference edges for detected constructions. */
|
|
68
|
+
function emitConstructions(constructions, file, graph) {
|
|
69
|
+
const byVar = new Map();
|
|
70
|
+
for (const c of constructions) {
|
|
71
|
+
if (c.varName)
|
|
72
|
+
byVar.set(c.varName, c.address);
|
|
73
|
+
}
|
|
74
|
+
for (const c of constructions) {
|
|
75
|
+
const r = {
|
|
76
|
+
address: c.address, type: c.service, kind: 'resource', filePath: file.path,
|
|
77
|
+
startLine: c.line, signature: `new ${c.service}("${c.name}")`, language: 'Pulumi',
|
|
78
|
+
};
|
|
79
|
+
graph.resources.push(r);
|
|
80
|
+
}
|
|
81
|
+
// Reference edges: a construction's args mention another resource's variable.
|
|
82
|
+
for (const c of constructions) {
|
|
83
|
+
const seen = new Set();
|
|
84
|
+
for (const tok of c.argsText.matchAll(/\b([A-Za-z_]\w*)\b/g)) {
|
|
85
|
+
const target = byVar.get(tok[1]);
|
|
86
|
+
if (target && target !== c.address && !seen.has(target)) {
|
|
87
|
+
seen.add(target);
|
|
88
|
+
graph.references.push({ fromAddress: c.address, toAddress: target, kind: 'references', line: c.line });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function findConstructions(content, providerNames, isTs) {
|
|
94
|
+
const out = [];
|
|
95
|
+
// TS: `new aws.s3.Bucket("logs", {...})`; Py: `aws.s3.Bucket("logs", ...)`.
|
|
96
|
+
const re = isTs
|
|
97
|
+
? /(?:(?:const|let|var)\s+(\w+)\s*=\s*)?new\s+([A-Za-z_]\w*(?:\.\w+)*)\s*\(\s*["']([^"']+)["']/g
|
|
98
|
+
: /(?:(\w+)\s*=\s*)?([A-Za-z_]\w*(?:\.\w+)*)\s*\(\s*["']([^"']+)["']/g;
|
|
99
|
+
for (const m of content.matchAll(re)) {
|
|
100
|
+
const varName = m[1];
|
|
101
|
+
const dotted = m[2];
|
|
102
|
+
const name = m[3];
|
|
103
|
+
const segs = dotted.split('.');
|
|
104
|
+
const root = segs[0];
|
|
105
|
+
const service = segs[segs.length - 1];
|
|
106
|
+
if (!providerNames.has(root))
|
|
107
|
+
continue;
|
|
108
|
+
// Service must be a class-like capitalized identifier.
|
|
109
|
+
if (!/^[A-Z]/.test(service))
|
|
110
|
+
continue;
|
|
111
|
+
const callParen = (m.index ?? 0) + m[0].lastIndexOf('(');
|
|
112
|
+
out.push({
|
|
113
|
+
address: `${service}:${name}`,
|
|
114
|
+
service,
|
|
115
|
+
name,
|
|
116
|
+
line: lineOf(content, m.index ?? 0),
|
|
117
|
+
varName,
|
|
118
|
+
argsText: sliceArgs(content, callParen),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
/** Local names bound to a Pulumi provider import (TS/JS). */
|
|
124
|
+
function detectTsProviderNames(content) {
|
|
125
|
+
const names = new Set();
|
|
126
|
+
for (const pkg of PROVIDER_PKGS) {
|
|
127
|
+
const esc = pkg.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
128
|
+
// import * as aws from "@pulumi/aws"; / import aws from "@pulumi/aws";
|
|
129
|
+
for (const m of content.matchAll(new RegExp(`import\\s+(?:\\*\\s+as\\s+)?(\\w+)\\s+from\\s+["']${esc}["']`, 'g')))
|
|
130
|
+
names.add(m[1]);
|
|
131
|
+
// import { s3 } from "@pulumi/aws";
|
|
132
|
+
for (const m of content.matchAll(new RegExp(`import\\s+\\{([^}]+)\\}\\s+from\\s+["']${esc}["']`, 'g'))) {
|
|
133
|
+
for (const part of m[1].split(',')) {
|
|
134
|
+
const n = (part.match(/\bas\s+(\w+)/) ?? part.match(/(\w+)/))?.[1]?.trim();
|
|
135
|
+
if (n)
|
|
136
|
+
names.add(n);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// const aws = require("@pulumi/aws");
|
|
140
|
+
for (const m of content.matchAll(new RegExp(`(\\w+)\\s*=\\s*require\\(\\s*["']${esc}["']`, 'g')))
|
|
141
|
+
names.add(m[1]);
|
|
142
|
+
}
|
|
143
|
+
return names;
|
|
144
|
+
}
|
|
145
|
+
/** Local names bound to a Pulumi provider import (Python). */
|
|
146
|
+
function detectPyProviderNames(content) {
|
|
147
|
+
const names = new Set();
|
|
148
|
+
for (const mod of PY_PROVIDER_MODS) {
|
|
149
|
+
const esc = mod.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
150
|
+
// import pulumi_aws as aws / import pulumi_aws
|
|
151
|
+
for (const m of content.matchAll(new RegExp(`import\\s+${esc}(?:\\s+as\\s+(\\w+))?`, 'g'))) {
|
|
152
|
+
names.add(m[1] ?? mod);
|
|
153
|
+
}
|
|
154
|
+
// from pulumi_aws import s3, ec2
|
|
155
|
+
for (const m of content.matchAll(new RegExp(`from\\s+${esc}\\s+import\\s+([^\\n#]+)`, 'g'))) {
|
|
156
|
+
for (const part of m[1].split(',')) {
|
|
157
|
+
const n = (part.match(/\bas\s+(\w+)/) ?? part.match(/(\w+)/))?.[1]?.trim();
|
|
158
|
+
if (n)
|
|
159
|
+
names.add(n);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return names;
|
|
164
|
+
}
|
|
165
|
+
/** Slice the argument list starting at the opening paren (paren-matched). */
|
|
166
|
+
function sliceArgs(content, parenIndex) {
|
|
167
|
+
let depth = 0;
|
|
168
|
+
let i = parenIndex;
|
|
169
|
+
for (; i < content.length; i++) {
|
|
170
|
+
const c = content[i];
|
|
171
|
+
if (c === '(')
|
|
172
|
+
depth++;
|
|
173
|
+
else if (c === ')') {
|
|
174
|
+
depth--;
|
|
175
|
+
if (depth === 0) {
|
|
176
|
+
i++;
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return content.slice(parenIndex, i);
|
|
182
|
+
}
|
|
183
|
+
function lineOf(content, index) {
|
|
184
|
+
let n = 1;
|
|
185
|
+
for (let i = 0; i < index && i < content.length; i++)
|
|
186
|
+
if (content[i] === '\n')
|
|
187
|
+
n++;
|
|
188
|
+
return n;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=pulumi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pulumi.js","sourceRoot":"","sources":["../../../../src/core/analyzer/iac/pulumi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terraform / HCL extraction (spec-07, reference implementation).
|
|
3
|
+
*
|
|
4
|
+
* Parser choice: a tolerant, hand-rolled HCL block scanner rather than a
|
|
5
|
+
* tree-sitter grammar. Rationale (per spec): `tree-sitter-hcl` is a native
|
|
6
|
+
* addon with an extra build/install surface, and IaC extraction only needs
|
|
7
|
+
* block boundaries + dotted-reference detection — not a full AST. A pure-JS
|
|
8
|
+
* scanner keeps the dependency tree flat and install-clean, and is fully
|
|
9
|
+
* deterministic. We never evaluate HCL; we only read declared blocks + refs.
|
|
10
|
+
*
|
|
11
|
+
* Files: *.tf, *.tf.json, *.tfvars. (The JSON variant is handled tolerantly by
|
|
12
|
+
* the same reference scan; structural JSON parsing is a spec-07 follow-up.)
|
|
13
|
+
*/
|
|
14
|
+
import type { IacGraph } from './types.js';
|
|
15
|
+
export declare function extractTerraform(files: Array<{
|
|
16
|
+
path: string;
|
|
17
|
+
content: string;
|
|
18
|
+
}>): IacGraph;
|
|
19
|
+
//# sourceMappingURL=terraform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["../../../../src/core/analyzer/iac/terraform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAwC,MAAM,YAAY,CAAC;AAiBjF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9C,QAAQ,CAgCV"}
|