kirograph 0.12.2 → 0.13.1

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.
Files changed (92) hide show
  1. package/README.md +197 -87
  2. package/dist/architecture/layers/index.js +9 -1
  3. package/dist/architecture/layers/index.js.map +2 -2
  4. package/dist/architecture/layers/ocaml.js +105 -0
  5. package/dist/architecture/layers/ocaml.js.map +7 -0
  6. package/dist/architecture/layers/scala.js +120 -0
  7. package/dist/architecture/layers/scala.js.map +7 -0
  8. package/dist/architecture/layers/solidity.js +105 -0
  9. package/dist/architecture/layers/solidity.js.map +7 -0
  10. package/dist/architecture/layers/vue.js +111 -0
  11. package/dist/architecture/layers/vue.js.map +7 -0
  12. package/dist/architecture/manifest/elm.js +91 -0
  13. package/dist/architecture/manifest/elm.js.map +7 -0
  14. package/dist/architecture/manifest/index.js +13 -2
  15. package/dist/architecture/manifest/index.js.map +2 -2
  16. package/dist/architecture/manifest/ocaml.js +166 -0
  17. package/dist/architecture/manifest/ocaml.js.map +7 -0
  18. package/dist/architecture/manifest/scala.js +117 -0
  19. package/dist/architecture/manifest/scala.js.map +7 -0
  20. package/dist/bin/commands/caveman.js +12 -0
  21. package/dist/bin/commands/caveman.js.map +2 -2
  22. package/dist/bin/commands/help.js +6 -4
  23. package/dist/bin/commands/help.js.map +2 -2
  24. package/dist/bin/commands/install.js +8 -2
  25. package/dist/bin/commands/install.js.map +2 -2
  26. package/dist/bin/commands/serve.js +2 -2
  27. package/dist/bin/commands/serve.js.map +2 -2
  28. package/dist/bin/commands/uninit.js +65 -41
  29. package/dist/bin/commands/uninit.js.map +2 -2
  30. package/dist/bin/installer/cli-agent.js +5 -25
  31. package/dist/bin/installer/cli-agent.js.map +2 -2
  32. package/dist/bin/installer/common.js +154 -0
  33. package/dist/bin/installer/common.js.map +7 -0
  34. package/dist/bin/installer/hooks.js +21 -1
  35. package/dist/bin/installer/hooks.js.map +2 -2
  36. package/dist/bin/installer/index.js +99 -86
  37. package/dist/bin/installer/index.js.map +2 -2
  38. package/dist/bin/installer/instructions.js +60 -0
  39. package/dist/bin/installer/instructions.js.map +7 -0
  40. package/dist/bin/installer/mcp.js +6 -36
  41. package/dist/bin/installer/mcp.js.map +2 -2
  42. package/dist/bin/installer/targets/claude.js +79 -0
  43. package/dist/bin/installer/targets/claude.js.map +7 -0
  44. package/dist/bin/installer/targets/codex.js +77 -0
  45. package/dist/bin/installer/targets/codex.js.map +7 -0
  46. package/dist/bin/installer/targets/index.js +57 -0
  47. package/dist/bin/installer/targets/index.js.map +7 -0
  48. package/dist/bin/installer/targets/kiro.js +61 -0
  49. package/dist/bin/installer/targets/kiro.js.map +7 -0
  50. package/dist/bin/kirograph.js +1 -1
  51. package/dist/extraction/extractor.js +65 -2
  52. package/dist/extraction/extractor.js.map +2 -2
  53. package/dist/extraction/grammars.js +22 -0
  54. package/dist/extraction/grammars.js.map +2 -2
  55. package/dist/extraction/languages.js +39 -1
  56. package/dist/extraction/languages.js.map +2 -2
  57. package/dist/extraction/wasm/tree-sitter-hcl.wasm +0 -0
  58. package/dist/extraction/wasm/tree-sitter-scss.wasm +0 -0
  59. package/dist/frameworks/amplify.js +175 -0
  60. package/dist/frameworks/amplify.js.map +7 -0
  61. package/dist/frameworks/angular.js +132 -0
  62. package/dist/frameworks/angular.js.map +7 -0
  63. package/dist/frameworks/ansible.js +151 -0
  64. package/dist/frameworks/ansible.js.map +7 -0
  65. package/dist/frameworks/cloudformation.js +148 -0
  66. package/dist/frameworks/cloudformation.js.map +7 -0
  67. package/dist/frameworks/docker.js +149 -0
  68. package/dist/frameworks/docker.js.map +7 -0
  69. package/dist/frameworks/iac.js +401 -0
  70. package/dist/frameworks/iac.js.map +7 -0
  71. package/dist/frameworks/index.js +81 -3
  72. package/dist/frameworks/index.js.map +3 -3
  73. package/dist/frameworks/kubernetes.js +176 -0
  74. package/dist/frameworks/kubernetes.js.map +7 -0
  75. package/dist/frameworks/pulumi.js +93 -0
  76. package/dist/frameworks/pulumi.js.map +7 -0
  77. package/dist/frameworks/scala.js +124 -0
  78. package/dist/frameworks/scala.js.map +7 -0
  79. package/dist/frameworks/solidity.js +93 -0
  80. package/dist/frameworks/solidity.js.map +7 -0
  81. package/dist/frameworks/terraform.js +278 -0
  82. package/dist/frameworks/terraform.js.map +7 -0
  83. package/dist/frameworks/vue.js +163 -0
  84. package/dist/frameworks/vue.js.map +7 -0
  85. package/dist/graph/queries.js +1 -1
  86. package/dist/graph/queries.js.map +1 -1
  87. package/dist/mcp/tool-names.js +48 -0
  88. package/dist/mcp/tool-names.js.map +7 -0
  89. package/dist/mcp/tools.js +3 -0
  90. package/dist/mcp/tools.js.map +2 -2
  91. package/dist/types.js.map +2 -2
  92. package/package.json +2 -2
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var cloudformation_exports = {};
20
+ __export(cloudformation_exports, {
21
+ cloudformationResolver: () => cloudformationResolver
22
+ });
23
+ module.exports = __toCommonJS(cloudformation_exports);
24
+ const cloudformationResolver = {
25
+ name: "cloudformation",
26
+ detect(context) {
27
+ for (const name of ["template.yaml", "template.yml", "template.json", "cloudformation.yaml", "cloudformation.yml"]) {
28
+ const content = context.readFile(name);
29
+ if (content && content.includes("AWSTemplateFormatVersion") && !content.includes("AWS::Serverless")) return true;
30
+ }
31
+ return context.getAllFiles().some(
32
+ (f) => (f.includes("cloudformation/") || f.includes("cfn/") || f.includes("stacks/")) && (f.endsWith(".yaml") || f.endsWith(".yml")) && !f.includes("node_modules")
33
+ );
34
+ },
35
+ resolve(ref, context) {
36
+ if (/^[A-Z][a-zA-Z0-9]+$/.test(ref.referenceName)) {
37
+ const id = resolveResource(ref.referenceName, context);
38
+ if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: "framework" };
39
+ }
40
+ return null;
41
+ },
42
+ extractNodes(filePath, content) {
43
+ const nodes = [];
44
+ const now = Date.now();
45
+ if (!content.includes("AWSTemplateFormatVersion") && !content.includes("Resources:")) return nodes;
46
+ const resourcePattern = /^\s{2}(\w+):\s*\n\s+Type:\s*['"]?([^\s'"]+)/gm;
47
+ let match;
48
+ while ((match = resourcePattern.exec(content)) !== null) {
49
+ const line = content.slice(0, match.index).split("\n").length;
50
+ const logicalId = match[1];
51
+ const resourceType = match[2];
52
+ nodes.push({
53
+ id: `cfn:${filePath}:resource:${logicalId}:${line}`,
54
+ kind: "class",
55
+ name: logicalId,
56
+ qualifiedName: `${filePath}::${logicalId}`,
57
+ filePath,
58
+ startLine: line,
59
+ endLine: line,
60
+ startColumn: 0,
61
+ endColumn: match[0].length,
62
+ language: "yaml",
63
+ updatedAt: now,
64
+ signature: resourceType
65
+ });
66
+ }
67
+ const paramSection = content.match(/^Parameters:\s*\n((?:\s{2}\w+:[\s\S]*?)(?=^\w|\Z))/m);
68
+ if (paramSection) {
69
+ const paramPattern = /^\s{2}(\w+):/gm;
70
+ let paramMatch;
71
+ const sectionStart = content.indexOf(paramSection[0]);
72
+ while ((paramMatch = paramPattern.exec(paramSection[1])) !== null) {
73
+ const line = content.slice(0, sectionStart + paramMatch.index).split("\n").length;
74
+ const paramName = paramMatch[1];
75
+ nodes.push({
76
+ id: `cfn:${filePath}:param:${paramName}:${line}`,
77
+ kind: "variable",
78
+ name: paramName,
79
+ qualifiedName: `${filePath}::param.${paramName}`,
80
+ filePath,
81
+ startLine: line,
82
+ endLine: line,
83
+ startColumn: 0,
84
+ endColumn: paramMatch[0].length,
85
+ language: "yaml",
86
+ updatedAt: now
87
+ });
88
+ }
89
+ }
90
+ const outputSection = content.match(/^Outputs:\s*\n((?:\s{2}\w+:[\s\S]*?)(?=^\w|\Z))/m);
91
+ if (outputSection) {
92
+ const outputPattern = /^\s{2}(\w+):/gm;
93
+ let outputMatch;
94
+ const sectionStart = content.indexOf(outputSection[0]);
95
+ while ((outputMatch = outputPattern.exec(outputSection[1])) !== null) {
96
+ const line = content.slice(0, sectionStart + outputMatch.index).split("\n").length;
97
+ const outputName = outputMatch[1];
98
+ nodes.push({
99
+ id: `cfn:${filePath}:output:${outputName}:${line}`,
100
+ kind: "variable",
101
+ name: `output.${outputName}`,
102
+ qualifiedName: `${filePath}::output.${outputName}`,
103
+ filePath,
104
+ startLine: line,
105
+ endLine: line,
106
+ startColumn: 0,
107
+ endColumn: outputMatch[0].length,
108
+ language: "yaml",
109
+ updatedAt: now,
110
+ isExported: true
111
+ });
112
+ }
113
+ }
114
+ const apiMethodPattern = /HttpMethod:\s*['"]?(\w+)['"]?/g;
115
+ while ((match = apiMethodPattern.exec(content)) !== null) {
116
+ if (!content.slice(Math.max(0, match.index - 200), match.index).includes("ApiGateway")) continue;
117
+ const line = content.slice(0, match.index).split("\n").length;
118
+ const method = match[1].toUpperCase();
119
+ nodes.push({
120
+ id: `route:${filePath}:${method}:cfn:${line}`,
121
+ kind: "route",
122
+ name: `${method} (CloudFormation)`,
123
+ qualifiedName: `${filePath}::${method}`,
124
+ filePath,
125
+ startLine: line,
126
+ endLine: line,
127
+ startColumn: 0,
128
+ endColumn: match[0].length,
129
+ language: "yaml",
130
+ updatedAt: now
131
+ });
132
+ }
133
+ return nodes;
134
+ }
135
+ };
136
+ function resolveResource(logicalId, context) {
137
+ for (const file of context.getAllFiles()) {
138
+ if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
139
+ const node = context.getNodesInFile(file).find((n) => n.name === logicalId && n.kind === "class");
140
+ if (node) return node.id;
141
+ }
142
+ return null;
143
+ }
144
+ // Annotate the CommonJS export names for ESM import in node:
145
+ 0 && (module.exports = {
146
+ cloudformationResolver
147
+ });
148
+ //# sourceMappingURL=cloudformation.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/frameworks/cloudformation.ts"],
4
+ "sourcesContent": ["/**\n * AWS CloudFormation Framework Resolver\n *\n * Handles raw CloudFormation templates (non-SAM).\n * Extracts resources, parameters, outputs, and cross-references.\n */\n\nimport type { Node } from '../types';\nimport type { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from './types';\n\nexport const cloudformationResolver: FrameworkResolver = {\n name: 'cloudformation',\n detect(context: ResolutionContext): boolean {\n // Look for CloudFormation templates that are NOT SAM\n for (const name of ['template.yaml', 'template.yml', 'template.json', 'cloudformation.yaml', 'cloudformation.yml']) {\n const content = context.readFile(name);\n if (content && content.includes('AWSTemplateFormatVersion') && !content.includes('AWS::Serverless')) return true;\n }\n // Check for nested stacks or cfn templates in common directories\n return context.getAllFiles().some(f =>\n (f.includes('cloudformation/') || f.includes('cfn/') || f.includes('stacks/')) &&\n (f.endsWith('.yaml') || f.endsWith('.yml')) &&\n !f.includes('node_modules')\n );\n },\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve !Ref and !GetAtt references to resources\n if (/^[A-Z][a-zA-Z0-9]+$/.test(ref.referenceName)) {\n const id = resolveResource(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.85, resolvedBy: 'framework' };\n }\n return null;\n },\n extractNodes(filePath: string, content: string): Node[] {\n const nodes: Node[] = [];\n const now = Date.now();\n\n if (!content.includes('AWSTemplateFormatVersion') && !content.includes('Resources:')) return nodes;\n\n // Extract Resources\n const resourcePattern = /^\\s{2}(\\w+):\\s*\\n\\s+Type:\\s*['\"]?([^\\s'\"]+)/gm;\n let match: RegExpExecArray | null;\n while ((match = resourcePattern.exec(content)) !== null) {\n const line = content.slice(0, match.index).split('\\n').length;\n const logicalId = match[1]!;\n const resourceType = match[2]!;\n nodes.push({\n id: `cfn:${filePath}:resource:${logicalId}:${line}`,\n kind: 'class',\n name: logicalId,\n qualifiedName: `${filePath}::${logicalId}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'yaml', updatedAt: now,\n signature: resourceType,\n });\n }\n\n // Extract Parameters\n const paramSection = content.match(/^Parameters:\\s*\\n((?:\\s{2}\\w+:[\\s\\S]*?)(?=^\\w|\\Z))/m);\n if (paramSection) {\n const paramPattern = /^\\s{2}(\\w+):/gm;\n let paramMatch: RegExpExecArray | null;\n const sectionStart = content.indexOf(paramSection[0]);\n while ((paramMatch = paramPattern.exec(paramSection[1])) !== null) {\n const line = content.slice(0, sectionStart + paramMatch.index).split('\\n').length;\n const paramName = paramMatch[1]!;\n nodes.push({\n id: `cfn:${filePath}:param:${paramName}:${line}`,\n kind: 'variable',\n name: paramName,\n qualifiedName: `${filePath}::param.${paramName}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: paramMatch[0].length,\n language: 'yaml', updatedAt: now,\n });\n }\n }\n\n // Extract Outputs\n const outputSection = content.match(/^Outputs:\\s*\\n((?:\\s{2}\\w+:[\\s\\S]*?)(?=^\\w|\\Z))/m);\n if (outputSection) {\n const outputPattern = /^\\s{2}(\\w+):/gm;\n let outputMatch: RegExpExecArray | null;\n const sectionStart = content.indexOf(outputSection[0]);\n while ((outputMatch = outputPattern.exec(outputSection[1])) !== null) {\n const line = content.slice(0, sectionStart + outputMatch.index).split('\\n').length;\n const outputName = outputMatch[1]!;\n nodes.push({\n id: `cfn:${filePath}:output:${outputName}:${line}`,\n kind: 'variable',\n name: `output.${outputName}`,\n qualifiedName: `${filePath}::output.${outputName}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: outputMatch[0].length,\n language: 'yaml', updatedAt: now,\n isExported: true,\n });\n }\n }\n\n // Extract API Gateway routes from AWS::ApiGateway::Method or AWS::ApiGatewayV2::Route\n const apiMethodPattern = /HttpMethod:\\s*['\"]?(\\w+)['\"]?/g;\n while ((match = apiMethodPattern.exec(content)) !== null) {\n if (!content.slice(Math.max(0, match.index - 200), match.index).includes('ApiGateway')) continue;\n const line = content.slice(0, match.index).split('\\n').length;\n const method = match[1]!.toUpperCase();\n nodes.push({\n id: `route:${filePath}:${method}:cfn:${line}`,\n kind: 'route',\n name: `${method} (CloudFormation)`,\n qualifiedName: `${filePath}::${method}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'yaml', updatedAt: now,\n });\n }\n\n return nodes;\n },\n};\n\nfunction resolveResource(logicalId: string, context: ResolutionContext): string | null {\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.yaml') && !file.endsWith('.yml')) continue;\n const node = context.getNodesInFile(file).find(n => n.name === logicalId && n.kind === 'class');\n if (node) return node.id;\n }\n return null;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var docker_exports = {};
20
+ __export(docker_exports, {
21
+ dockerComposeResolver: () => dockerComposeResolver
22
+ });
23
+ module.exports = __toCommonJS(docker_exports);
24
+ const dockerComposeResolver = {
25
+ name: "docker-compose",
26
+ detect(context) {
27
+ return context.fileExists("docker-compose.yml") || context.fileExists("docker-compose.yaml") || context.fileExists("compose.yml") || context.fileExists("compose.yaml");
28
+ },
29
+ resolve(ref, context) {
30
+ if (/^[a-z][a-z0-9_-]*$/.test(ref.referenceName)) {
31
+ const id = resolveService(ref.referenceName, context);
32
+ if (id) return { original: ref, targetNodeId: id, confidence: 0.8, resolvedBy: "framework" };
33
+ }
34
+ return null;
35
+ },
36
+ extractNodes(filePath, content) {
37
+ const nodes = [];
38
+ const now = Date.now();
39
+ const basename = filePath.split("/").pop() ?? "";
40
+ if (!basename.match(/^(docker-)?compose\.(ya?ml)$/)) return nodes;
41
+ const servicesMatch = content.match(/^services:\s*\n([\s\S]*?)(?=^(?:networks|volumes|configs|secrets):|$(?![\s\S]))/m);
42
+ if (servicesMatch) {
43
+ const servicePattern = /^\s{2}([a-zA-Z0-9_-]+):\s*$/gm;
44
+ let match;
45
+ const sectionStart = content.indexOf(servicesMatch[0]);
46
+ while ((match = servicePattern.exec(servicesMatch[1])) !== null) {
47
+ const line = content.slice(0, sectionStart + match.index).split("\n").length;
48
+ const serviceName = match[1];
49
+ nodes.push({
50
+ id: `docker:${filePath}:service:${serviceName}:${line}`,
51
+ kind: "component",
52
+ name: serviceName,
53
+ qualifiedName: `${filePath}::service.${serviceName}`,
54
+ filePath,
55
+ startLine: line,
56
+ endLine: line,
57
+ startColumn: 0,
58
+ endColumn: match[0].length,
59
+ language: "yaml",
60
+ updatedAt: now,
61
+ signature: `service "${serviceName}"`
62
+ });
63
+ }
64
+ }
65
+ const networksMatch = content.match(/^networks:\s*\n([\s\S]*?)(?=^(?:services|volumes|configs|secrets):|$(?![\s\S]))/m);
66
+ if (networksMatch) {
67
+ const networkPattern = /^\s{2}([a-zA-Z0-9_-]+):\s*$/gm;
68
+ let match;
69
+ const sectionStart = content.indexOf(networksMatch[0]);
70
+ while ((match = networkPattern.exec(networksMatch[1])) !== null) {
71
+ const line = content.slice(0, sectionStart + match.index).split("\n").length;
72
+ const networkName = match[1];
73
+ nodes.push({
74
+ id: `docker:${filePath}:network:${networkName}:${line}`,
75
+ kind: "variable",
76
+ name: `network.${networkName}`,
77
+ qualifiedName: `${filePath}::network.${networkName}`,
78
+ filePath,
79
+ startLine: line,
80
+ endLine: line,
81
+ startColumn: 0,
82
+ endColumn: match[0].length,
83
+ language: "yaml",
84
+ updatedAt: now
85
+ });
86
+ }
87
+ }
88
+ const volumesMatch = content.match(/^volumes:\s*\n([\s\S]*?)(?=^(?:services|networks|configs|secrets):|$(?![\s\S]))/m);
89
+ if (volumesMatch) {
90
+ const volumePattern = /^\s{2}([a-zA-Z0-9_-]+):\s*$/gm;
91
+ let match;
92
+ const sectionStart = content.indexOf(volumesMatch[0]);
93
+ while ((match = volumePattern.exec(volumesMatch[1])) !== null) {
94
+ const line = content.slice(0, sectionStart + match.index).split("\n").length;
95
+ const volumeName = match[1];
96
+ nodes.push({
97
+ id: `docker:${filePath}:volume:${volumeName}:${line}`,
98
+ kind: "variable",
99
+ name: `volume.${volumeName}`,
100
+ qualifiedName: `${filePath}::volume.${volumeName}`,
101
+ filePath,
102
+ startLine: line,
103
+ endLine: line,
104
+ startColumn: 0,
105
+ endColumn: match[0].length,
106
+ language: "yaml",
107
+ updatedAt: now
108
+ });
109
+ }
110
+ }
111
+ const portsPattern = /^\s{4}-\s*["']?(\d+):(\d+)["']?\s*$/gm;
112
+ let portMatch;
113
+ while ((portMatch = portsPattern.exec(content)) !== null) {
114
+ const line = content.slice(0, portMatch.index).split("\n").length;
115
+ const hostPort = portMatch[1];
116
+ const containerPort = portMatch[2];
117
+ const preceding = content.slice(0, portMatch.index);
118
+ const serviceMatch = preceding.match(/^\s{2}([a-zA-Z0-9_-]+):\s*$/gm);
119
+ const serviceName = serviceMatch ? serviceMatch[serviceMatch.length - 1].trim().replace(":", "") : "unknown";
120
+ nodes.push({
121
+ id: `docker:${filePath}:port:${hostPort}:${line}`,
122
+ kind: "route",
123
+ name: `${serviceName.trim()} :${hostPort}\u2192:${containerPort}`,
124
+ qualifiedName: `${filePath}::port.${hostPort}`,
125
+ filePath,
126
+ startLine: line,
127
+ endLine: line,
128
+ startColumn: 0,
129
+ endColumn: portMatch[0].length,
130
+ language: "yaml",
131
+ updatedAt: now
132
+ });
133
+ }
134
+ return nodes;
135
+ }
136
+ };
137
+ function resolveService(name, context) {
138
+ for (const file of context.getAllFiles()) {
139
+ if (!file.match(/compose\.(ya?ml)$/)) continue;
140
+ const node = context.getNodesInFile(file).find((n) => n.name === name && n.kind === "component");
141
+ if (node) return node.id;
142
+ }
143
+ return null;
144
+ }
145
+ // Annotate the CommonJS export names for ESM import in node:
146
+ 0 && (module.exports = {
147
+ dockerComposeResolver
148
+ });
149
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/frameworks/docker.ts"],
4
+ "sourcesContent": ["/**\n * Docker Compose Framework Resolver\n *\n * Extracts services, networks, volumes from docker-compose files.\n * Maps depends_on relationships as edges.\n */\n\nimport type { Node } from '../types';\nimport type { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from './types';\n\nexport const dockerComposeResolver: FrameworkResolver = {\n name: 'docker-compose',\n detect(context: ResolutionContext): boolean {\n return (\n context.fileExists('docker-compose.yml') ||\n context.fileExists('docker-compose.yaml') ||\n context.fileExists('compose.yml') ||\n context.fileExists('compose.yaml')\n );\n },\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve service name references\n if (/^[a-z][a-z0-9_-]*$/.test(ref.referenceName)) {\n const id = resolveService(ref.referenceName, context);\n if (id) return { original: ref, targetNodeId: id, confidence: 0.8, resolvedBy: 'framework' };\n }\n return null;\n },\n extractNodes(filePath: string, content: string): Node[] {\n const nodes: Node[] = [];\n const now = Date.now();\n\n const basename = filePath.split('/').pop() ?? '';\n if (!basename.match(/^(docker-)?compose\\.(ya?ml)$/)) return nodes;\n\n // Extract services\n const servicesMatch = content.match(/^services:\\s*\\n([\\s\\S]*?)(?=^(?:networks|volumes|configs|secrets):|$(?![\\s\\S]))/m);\n if (servicesMatch) {\n const servicePattern = /^\\s{2}([a-zA-Z0-9_-]+):\\s*$/gm;\n let match: RegExpExecArray | null;\n const sectionStart = content.indexOf(servicesMatch[0]);\n while ((match = servicePattern.exec(servicesMatch[1])) !== null) {\n const line = content.slice(0, sectionStart + match.index).split('\\n').length;\n const serviceName = match[1]!;\n nodes.push({\n id: `docker:${filePath}:service:${serviceName}:${line}`,\n kind: 'component',\n name: serviceName,\n qualifiedName: `${filePath}::service.${serviceName}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'yaml', updatedAt: now,\n signature: `service \"${serviceName}\"`,\n });\n }\n }\n\n // Extract networks\n const networksMatch = content.match(/^networks:\\s*\\n([\\s\\S]*?)(?=^(?:services|volumes|configs|secrets):|$(?![\\s\\S]))/m);\n if (networksMatch) {\n const networkPattern = /^\\s{2}([a-zA-Z0-9_-]+):\\s*$/gm;\n let match: RegExpExecArray | null;\n const sectionStart = content.indexOf(networksMatch[0]);\n while ((match = networkPattern.exec(networksMatch[1])) !== null) {\n const line = content.slice(0, sectionStart + match.index).split('\\n').length;\n const networkName = match[1]!;\n nodes.push({\n id: `docker:${filePath}:network:${networkName}:${line}`,\n kind: 'variable',\n name: `network.${networkName}`,\n qualifiedName: `${filePath}::network.${networkName}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'yaml', updatedAt: now,\n });\n }\n }\n\n // Extract volumes\n const volumesMatch = content.match(/^volumes:\\s*\\n([\\s\\S]*?)(?=^(?:services|networks|configs|secrets):|$(?![\\s\\S]))/m);\n if (volumesMatch) {\n const volumePattern = /^\\s{2}([a-zA-Z0-9_-]+):\\s*$/gm;\n let match: RegExpExecArray | null;\n const sectionStart = content.indexOf(volumesMatch[0]);\n while ((match = volumePattern.exec(volumesMatch[1])) !== null) {\n const line = content.slice(0, sectionStart + match.index).split('\\n').length;\n const volumeName = match[1]!;\n nodes.push({\n id: `docker:${filePath}:volume:${volumeName}:${line}`,\n kind: 'variable',\n name: `volume.${volumeName}`,\n qualifiedName: `${filePath}::volume.${volumeName}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: match[0].length,\n language: 'yaml', updatedAt: now,\n });\n }\n }\n\n // Extract exposed ports as route-like nodes\n const portsPattern = /^\\s{4}-\\s*[\"']?(\\d+):(\\d+)[\"']?\\s*$/gm;\n let portMatch: RegExpExecArray | null;\n while ((portMatch = portsPattern.exec(content)) !== null) {\n const line = content.slice(0, portMatch.index).split('\\n').length;\n const hostPort = portMatch[1]!;\n const containerPort = portMatch[2]!;\n // Find which service this port belongs to\n const preceding = content.slice(0, portMatch.index);\n const serviceMatch = preceding.match(/^\\s{2}([a-zA-Z0-9_-]+):\\s*$/gm);\n const serviceName = serviceMatch ? serviceMatch[serviceMatch.length - 1]!.trim().replace(':', '') : 'unknown';\n nodes.push({\n id: `docker:${filePath}:port:${hostPort}:${line}`,\n kind: 'route',\n name: `${serviceName.trim()} :${hostPort}\u2192:${containerPort}`,\n qualifiedName: `${filePath}::port.${hostPort}`,\n filePath, startLine: line, endLine: line, startColumn: 0, endColumn: portMatch[0].length,\n language: 'yaml', updatedAt: now,\n });\n }\n\n return nodes;\n },\n};\n\nfunction resolveService(name: string, context: ResolutionContext): string | null {\n for (const file of context.getAllFiles()) {\n if (!file.match(/compose\\.(ya?ml)$/)) continue;\n const node = context.getNodesInFile(file).find(n => n.name === name && n.kind === 'component');\n if (node) return node.id;\n }\n return null;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }