@intentius/chant-lexicon-helm 0.124.31 → 0.124.33

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 (111) hide show
  1. package/dist/archive-render.js +76 -0
  2. package/dist/codegen/docs-cli.js +3 -0
  3. package/dist/codegen/docs.js +113 -0
  4. package/dist/codegen/generate-cli.js +19 -0
  5. package/dist/codegen/generate.js +210 -0
  6. package/dist/codegen/naming.js +29 -0
  7. package/dist/codegen/package.js +44 -0
  8. package/dist/codegen/values-type.js +87 -0
  9. package/dist/commands.js +413 -0
  10. package/dist/components/builders.js +9 -0
  11. package/dist/components/capability-plugin.js +17 -0
  12. package/dist/components/helm-upgrade.js +109 -0
  13. package/dist/components/index.js +11 -0
  14. package/dist/composites/catalog.js +1119 -0
  15. package/dist/composites/helm-batch-job.js +148 -0
  16. package/dist/composites/helm-crd-lifecycle.js +145 -0
  17. package/dist/composites/helm-cron-job.js +130 -0
  18. package/dist/composites/helm-daemon-set.js +125 -0
  19. package/dist/composites/helm-external-secret.js +63 -0
  20. package/dist/composites/helm-library.js +24 -0
  21. package/dist/composites/helm-microservice.js +260 -0
  22. package/dist/composites/helm-monitored-service.js +188 -0
  23. package/dist/composites/helm-namespace-env.js +116 -0
  24. package/dist/composites/helm-secure-ingress.js +86 -0
  25. package/dist/composites/helm-stateful-service.js +160 -0
  26. package/dist/composites/helm-web-app.js +201 -0
  27. package/dist/composites/helm-worker.js +164 -0
  28. package/dist/composites/index.js +13 -0
  29. package/dist/config.js +161 -0
  30. package/dist/coverage.js +37 -0
  31. package/dist/deep-observe-hooks.js +19 -0
  32. package/dist/deep-observe.js +55 -0
  33. package/dist/describe-resources.js +119 -0
  34. package/dist/describe-stack-status.js +66 -0
  35. package/dist/detect.js +11 -0
  36. package/dist/generated/index.js +11 -0
  37. package/dist/helpers.js +84 -0
  38. package/dist/import/generator.js +292 -0
  39. package/dist/import/parser.js +141 -0
  40. package/dist/import/template-stripper.js +86 -0
  41. package/dist/index.js +55 -0
  42. package/dist/integrity.json +2 -2
  43. package/dist/intrinsics.js +482 -0
  44. package/dist/lint/audit-catalog.js +33 -0
  45. package/dist/lint/audit-lineage.js +53 -0
  46. package/dist/lint/post-synth/helm-helpers.js +60 -0
  47. package/dist/lint/post-synth/index.js +48 -0
  48. package/dist/lint/post-synth/whm005-no-empty-wrapper.js +47 -0
  49. package/dist/lint/post-synth/whm101.js +38 -0
  50. package/dist/lint/post-synth/whm102.js +26 -0
  51. package/dist/lint/post-synth/whm103.js +51 -0
  52. package/dist/lint/post-synth/whm104.js +29 -0
  53. package/dist/lint/post-synth/whm105.js +23 -0
  54. package/dist/lint/post-synth/whm201.js +29 -0
  55. package/dist/lint/post-synth/whm202.js +42 -0
  56. package/dist/lint/post-synth/whm203.js +32 -0
  57. package/dist/lint/post-synth/whm204.js +51 -0
  58. package/dist/lint/post-synth/whm301.js +31 -0
  59. package/dist/lint/post-synth/whm302.js +33 -0
  60. package/dist/lint/post-synth/whm401.js +52 -0
  61. package/dist/lint/post-synth/whm402.js +38 -0
  62. package/dist/lint/post-synth/whm403.js +38 -0
  63. package/dist/lint/post-synth/whm404.js +30 -0
  64. package/dist/lint/post-synth/whm405.js +47 -0
  65. package/dist/lint/post-synth/whm406.js +27 -0
  66. package/dist/lint/post-synth/whm407.js +72 -0
  67. package/dist/lint/post-synth/whm501.js +89 -0
  68. package/dist/lint/post-synth/whm502.js +85 -0
  69. package/dist/lint/post-synth/whm503.js +82 -0
  70. package/dist/lint/post-synth/whm504.js +47 -0
  71. package/dist/lint/rules/chart-metadata.js +53 -0
  72. package/dist/lint/rules/no-hardcoded-image.js +50 -0
  73. package/dist/lint/rules/values-no-helm-tpl.js +78 -0
  74. package/dist/lint/rules/values-no-secrets.js +65 -0
  75. package/dist/list-artifacts.js +134 -0
  76. package/dist/lsp/completions.d.ts.map +1 -1
  77. package/dist/lsp/completions.js +18 -0
  78. package/dist/lsp/hover.d.ts.map +1 -1
  79. package/dist/lsp/hover.js +40 -0
  80. package/dist/manifest.json +1 -1
  81. package/dist/op/activities/cluster-probe.js +116 -0
  82. package/dist/op/activities/helm.js +449 -0
  83. package/dist/op/activities/index.js +10 -0
  84. package/dist/op/builders.js +45 -0
  85. package/dist/package-cli.js +21 -0
  86. package/dist/pinnability/actions.js +207 -0
  87. package/dist/pinnability/classify.js +416 -0
  88. package/dist/pinnability/conditions.js +0 -0
  89. package/dist/pinnability/index.js +16 -0
  90. package/dist/pinnability/localize.js +518 -0
  91. package/dist/pinnability/render-stream.js +53 -0
  92. package/dist/pinnability/values.js +151 -0
  93. package/dist/plugin.js +458 -0
  94. package/dist/project-codegen.js +215 -0
  95. package/dist/release-observe.js +287 -0
  96. package/dist/render-diff.js +279 -0
  97. package/dist/render-digest.js +0 -0
  98. package/dist/render-records.js +29 -0
  99. package/dist/render-store.js +401 -0
  100. package/dist/render-wrapper.js +164 -0
  101. package/dist/render.js +394 -0
  102. package/dist/resources.js +109 -0
  103. package/dist/serializer.js +903 -0
  104. package/dist/validate-cli.js +17 -0
  105. package/dist/validate.js +30 -0
  106. package/dist/values-probe.js +504 -0
  107. package/dist/wrapper-chart.js +95 -0
  108. package/package.json +11 -11
  109. package/src/codegen/package.ts +2 -2
  110. package/src/lsp/completions.ts +2 -1
  111. package/src/lsp/hover.ts +2 -1
@@ -0,0 +1,292 @@
1
+ /**
2
+ * TypeScript code generator for Helm chart import.
3
+ *
4
+ * Converts a TemplateIR (from parsed Helm charts) into TypeScript source code
5
+ * using @intentius/chant-lexicon-helm and @intentius/chant-lexicon-k8s constructors,
6
+ * mapping Go template expressions to Helm intrinsics.
7
+ */
8
+ /** K8s type to class name mapping. */
9
+ const K8S_TYPE_TO_CLASS = {
10
+ "K8s::Core::Pod": "Pod",
11
+ "K8s::Core::Service": "Service",
12
+ "K8s::Core::ConfigMap": "ConfigMap",
13
+ "K8s::Core::Secret": "Secret",
14
+ "K8s::Core::ServiceAccount": "ServiceAccount",
15
+ "K8s::Apps::Deployment": "Deployment",
16
+ "K8s::Apps::StatefulSet": "StatefulSet",
17
+ "K8s::Apps::DaemonSet": "DaemonSet",
18
+ "K8s::Batch::Job": "Job",
19
+ "K8s::Batch::CronJob": "CronJob",
20
+ "K8s::Networking::Ingress": "Ingress",
21
+ "K8s::Networking::NetworkPolicy": "NetworkPolicy",
22
+ "K8s::Rbac::Role": "Role",
23
+ "K8s::Rbac::ClusterRole": "ClusterRole",
24
+ "K8s::Rbac::RoleBinding": "RoleBinding",
25
+ "K8s::Rbac::ClusterRoleBinding": "ClusterRoleBinding",
26
+ "K8s::Autoscaling::HorizontalPodAutoscaler": "HorizontalPodAutoscaler",
27
+ "K8s::Policy::PodDisruptionBudget": "PodDisruptionBudget",
28
+ };
29
+ /** Helm type to class name mapping. */
30
+ const HELM_TYPE_TO_CLASS = {
31
+ "Helm::Chart": "Chart",
32
+ "Helm::Values": "Values",
33
+ "Helm::Notes": "HelmNotes",
34
+ };
35
+ export class HelmGenerator {
36
+ generate(ir) {
37
+ const lines = [];
38
+ const helmImports = new Set();
39
+ const k8sImports = new Set();
40
+ const intrinsicImports = new Set();
41
+ // Classify resources and collect needed imports
42
+ for (const resource of ir.resources) {
43
+ const helmClass = HELM_TYPE_TO_CLASS[resource.type];
44
+ if (helmClass) {
45
+ helmImports.add(helmClass);
46
+ }
47
+ else {
48
+ const k8sClass = this.resolveK8sClass(resource.type);
49
+ if (k8sClass)
50
+ k8sImports.add(k8sClass);
51
+ }
52
+ // Scan for template expressions to determine intrinsic imports
53
+ this.collectIntrinsicImports(resource, intrinsicImports);
54
+ }
55
+ // Emit imports
56
+ if (helmImports.size > 0) {
57
+ lines.push(`import { ${[...helmImports].sort().join(", ")} } from "@intentius/chant-lexicon-helm";`);
58
+ }
59
+ if (intrinsicImports.size > 0) {
60
+ lines.push(`import { ${[...intrinsicImports].sort().join(", ")} } from "@intentius/chant-lexicon-helm";`);
61
+ }
62
+ if (k8sImports.size > 0) {
63
+ lines.push(`import { ${[...k8sImports].sort().join(", ")} } from "@intentius/chant-lexicon-k8s";`);
64
+ }
65
+ lines.push("");
66
+ // Emit resources
67
+ for (const resource of ir.resources) {
68
+ const cls = HELM_TYPE_TO_CLASS[resource.type] ?? this.resolveK8sClass(resource.type);
69
+ if (!cls) {
70
+ lines.push(`// TODO: unsupported type ${resource.type} (${resource.logicalId})`);
71
+ lines.push("");
72
+ continue;
73
+ }
74
+ // Replace placeholders with intrinsic calls in properties
75
+ const props = this.substituteExpressions(resource.properties, resource.metadata?.templateExpressions);
76
+ const propsStr = this.emitProps(props, 1);
77
+ lines.push(`export const ${resource.logicalId} = new ${cls}(${propsStr});`);
78
+ lines.push("");
79
+ }
80
+ return [{ path: "chart.ts", content: lines.join("\n") }];
81
+ }
82
+ resolveK8sClass(type) {
83
+ if (K8S_TYPE_TO_CLASS[type])
84
+ return K8S_TYPE_TO_CLASS[type];
85
+ const parts = type.split("::");
86
+ if (parts.length === 3 && parts[0] === "K8s")
87
+ return parts[2];
88
+ return undefined;
89
+ }
90
+ collectIntrinsicImports(resource, imports) {
91
+ const exprs = resource.metadata?.templateExpressions;
92
+ if (!exprs)
93
+ return;
94
+ for (const entry of Object.values(exprs)) {
95
+ const kind = entry.kind;
96
+ switch (kind) {
97
+ case "values":
98
+ imports.add("values");
99
+ break;
100
+ case "release":
101
+ imports.add("Release");
102
+ break;
103
+ case "chart":
104
+ imports.add("ChartRef");
105
+ break;
106
+ case "include":
107
+ imports.add("include");
108
+ break;
109
+ case "toYaml":
110
+ imports.add("toYaml");
111
+ imports.add("values");
112
+ break;
113
+ case "required":
114
+ imports.add("required");
115
+ imports.add("values");
116
+ break;
117
+ case "default":
118
+ imports.add("helmDefault");
119
+ imports.add("values");
120
+ break;
121
+ case "printf":
122
+ imports.add("printf");
123
+ break;
124
+ case "quote":
125
+ imports.add("quote");
126
+ imports.add("values");
127
+ break;
128
+ case "lookup":
129
+ imports.add("lookup");
130
+ break;
131
+ case "tpl":
132
+ imports.add("tpl");
133
+ break;
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * Walk through properties, replacing placeholder strings with intrinsic call representations.
139
+ */
140
+ substituteExpressions(props, exprs) {
141
+ if (!exprs)
142
+ return props;
143
+ return this.walkAndReplace(props, exprs);
144
+ }
145
+ walkAndReplace(value, exprs) {
146
+ if (typeof value === "string") {
147
+ // Check if the entire string is a placeholder
148
+ const expr = exprs[value];
149
+ if (expr) {
150
+ return { __intrinsicCall: this.expressionToIntrinsic(expr.expression, expr.kind) };
151
+ }
152
+ // Check if the string contains placeholders mixed with text
153
+ let result = value;
154
+ for (const [placeholder, entry] of Object.entries(exprs)) {
155
+ if (result.includes(placeholder)) {
156
+ result = result.replace(placeholder, `\${${this.expressionToIntrinsic(entry.expression, entry.kind)}}`);
157
+ }
158
+ }
159
+ if (result !== value) {
160
+ return { __intrinsicCall: result };
161
+ }
162
+ return value;
163
+ }
164
+ if (Array.isArray(value)) {
165
+ return value.map((item) => this.walkAndReplace(item, exprs));
166
+ }
167
+ if (value && typeof value === "object") {
168
+ const result = {};
169
+ for (const [k, v] of Object.entries(value)) {
170
+ result[k] = this.walkAndReplace(v, exprs);
171
+ }
172
+ return result;
173
+ }
174
+ return value;
175
+ }
176
+ /**
177
+ * Convert a Go template expression to a TypeScript intrinsic call string.
178
+ */
179
+ expressionToIntrinsic(expression, kind) {
180
+ switch (kind) {
181
+ case "values": {
182
+ const path = expression.replace(/^\.Values\./, "");
183
+ return `values.${path}`;
184
+ }
185
+ case "release": {
186
+ const field = expression.replace(/^\.Release\./, "");
187
+ return `Release.${field}`;
188
+ }
189
+ case "chart": {
190
+ const field = expression.replace(/^\.Chart\./, "");
191
+ return `ChartRef.${field}`;
192
+ }
193
+ case "include": {
194
+ const match = expression.match(/^include\s+"([^"]+)"\s+(.+)$/);
195
+ if (match)
196
+ return `include("${match[1]}")`;
197
+ return `include(${JSON.stringify(expression)})`;
198
+ }
199
+ case "toYaml": {
200
+ const match = expression.match(/toYaml\s+(.+?)(?:\s*\|\s*nindent\s+(\d+))?$/);
201
+ if (match) {
202
+ const ref = this.refToIntrinsic(match[1]);
203
+ return match[2] ? `toYaml(${ref}, ${match[2]})` : `toYaml(${ref})`;
204
+ }
205
+ return `toYaml(${JSON.stringify(expression)})`;
206
+ }
207
+ case "required": {
208
+ const match = expression.match(/^required\s+"([^"]+)"\s+(.+)$/);
209
+ if (match)
210
+ return `required("${match[1]}", ${this.refToIntrinsic(match[2])})`;
211
+ return `required(${JSON.stringify(expression)})`;
212
+ }
213
+ case "default": {
214
+ const match = expression.match(/^default\s+"([^"]+)"\s+(.+)$/);
215
+ if (match)
216
+ return `helmDefault("${match[1]}", ${this.refToIntrinsic(match[2])})`;
217
+ return `helmDefault(${JSON.stringify(expression)})`;
218
+ }
219
+ case "printf": {
220
+ const match = expression.match(/^printf\s+"([^"]+)"\s+(.+)$/);
221
+ if (match) {
222
+ const args = match[2].split(/\s+/).map((a) => this.refToIntrinsic(a));
223
+ return `printf("${match[1]}", ${args.join(", ")})`;
224
+ }
225
+ return `printf(${JSON.stringify(expression)})`;
226
+ }
227
+ case "quote":
228
+ return `quote(${this.refToIntrinsic(expression.replace(/\s*\|\s*quote\s*$/, ""))})`;
229
+ case "lookup":
230
+ return `lookup(${JSON.stringify(expression)})`;
231
+ case "tpl":
232
+ return `tpl(${JSON.stringify(expression)})`;
233
+ default:
234
+ return `/* ${expression} */`;
235
+ }
236
+ }
237
+ /**
238
+ * Convert a Go template reference to a TypeScript expression.
239
+ */
240
+ refToIntrinsic(ref) {
241
+ const trimmed = ref.trim();
242
+ if (trimmed.startsWith(".Values."))
243
+ return `values.${trimmed.slice(8)}`;
244
+ if (trimmed.startsWith(".Release."))
245
+ return `Release.${trimmed.slice(9)}`;
246
+ if (trimmed.startsWith(".Chart."))
247
+ return `ChartRef.${trimmed.slice(7)}`;
248
+ if (trimmed === ".")
249
+ return "context";
250
+ return JSON.stringify(trimmed);
251
+ }
252
+ emitProps(props, depth) {
253
+ const indent = " ".repeat(depth);
254
+ const innerIndent = " ".repeat(depth + 1);
255
+ const entries = [];
256
+ for (const [key, value] of Object.entries(props)) {
257
+ if (value === undefined || value === null)
258
+ continue;
259
+ entries.push(`${innerIndent}${key}: ${this.emitValue(value, depth + 1)},`);
260
+ }
261
+ if (entries.length === 0)
262
+ return "{}";
263
+ return `{\n${entries.join("\n")}\n${indent}}`;
264
+ }
265
+ emitValue(value, depth) {
266
+ if (value === null || value === undefined)
267
+ return "undefined";
268
+ // Intrinsic call placeholder
269
+ if (typeof value === "object" && value !== null && "__intrinsicCall" in value) {
270
+ return value.__intrinsicCall;
271
+ }
272
+ if (typeof value === "string")
273
+ return JSON.stringify(value);
274
+ if (typeof value === "number" || typeof value === "boolean")
275
+ return String(value);
276
+ if (Array.isArray(value)) {
277
+ if (value.length === 0)
278
+ return "[]";
279
+ const items = value.map((item) => this.emitValue(item, depth + 1));
280
+ const oneLine = `[${items.join(", ")}]`;
281
+ if (oneLine.length < 80)
282
+ return oneLine;
283
+ const indent = " ".repeat(depth);
284
+ const innerIndent = " ".repeat(depth + 1);
285
+ return `[\n${items.map((i) => `${innerIndent}${i},`).join("\n")}\n${indent}]`;
286
+ }
287
+ if (typeof value === "object") {
288
+ return this.emitProps(value, depth);
289
+ }
290
+ return String(value);
291
+ }
292
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Helm chart parser for `chant import`.
3
+ *
4
+ * Parses an existing Helm chart directory (Chart.yaml, values.yaml, templates/)
5
+ * into the core TemplateIR format, preserving Go template expressions as metadata
6
+ * for reconstruction as Helm intrinsics.
7
+ */
8
+ import { parseYAML } from "@intentius/chant/yaml";
9
+ import { stripTemplateExpressions, classifyExpression } from "./template-stripper.js";
10
+ /**
11
+ * Helm chart parser.
12
+ *
13
+ * Input: a map of file paths to contents (as would be read from a chart directory).
14
+ * The parse() method accepts the contents as a JSON-encoded map.
15
+ */
16
+ export class HelmParser {
17
+ parse(content) {
18
+ // Content is a JSON map of { "path": "content" }
19
+ const files = JSON.parse(content);
20
+ return this.parseFiles(files);
21
+ }
22
+ parseFiles(files) {
23
+ const resources = [];
24
+ const parameters = [];
25
+ // Parse Chart.yaml
26
+ const chartYaml = files["Chart.yaml"];
27
+ if (chartYaml) {
28
+ const chartData = parseYAML(chartYaml);
29
+ resources.push({
30
+ logicalId: "chart",
31
+ type: "Helm::Chart",
32
+ properties: chartData,
33
+ metadata: { file: "Chart.yaml" },
34
+ });
35
+ }
36
+ // Parse values.yaml → extract parameters
37
+ const valuesYaml = files["values.yaml"];
38
+ if (valuesYaml) {
39
+ const valuesData = parseYAML(valuesYaml);
40
+ if (valuesData && typeof valuesData === "object") {
41
+ resources.push({
42
+ logicalId: "valuesSchema",
43
+ type: "Helm::Values",
44
+ properties: valuesData,
45
+ metadata: { file: "values.yaml" },
46
+ });
47
+ // Flatten values into parameters
48
+ this.extractParameters(valuesData, "", parameters);
49
+ }
50
+ }
51
+ // Parse templates
52
+ for (const [path, content] of Object.entries(files)) {
53
+ if (!path.startsWith("templates/"))
54
+ continue;
55
+ if (path.endsWith("_helpers.tpl"))
56
+ continue;
57
+ if (path.endsWith("NOTES.txt")) {
58
+ resources.push({
59
+ logicalId: "notes",
60
+ type: "Helm::Notes",
61
+ properties: { content },
62
+ metadata: { file: path },
63
+ });
64
+ continue;
65
+ }
66
+ this.parseTemplate(path, content, resources);
67
+ }
68
+ return {
69
+ resources,
70
+ parameters,
71
+ metadata: {
72
+ chartName: resources.find((r) => r.type === "Helm::Chart")?.properties?.name ?? "unknown",
73
+ },
74
+ };
75
+ }
76
+ parseTemplate(path, content, resources) {
77
+ const stripped = stripTemplateExpressions(content);
78
+ const parsed = parseYAML(stripped.yaml);
79
+ if (!parsed || typeof parsed !== "object")
80
+ return;
81
+ const doc = parsed;
82
+ const apiVersion = doc.apiVersion;
83
+ const kind = doc.kind;
84
+ if (!apiVersion || !kind)
85
+ return;
86
+ // Derive a logical ID from the file path
87
+ const fileName = path.replace("templates/", "").replace(/\.yaml$/, "").replace(/[/\\-]/g, "_");
88
+ const logicalId = kind.charAt(0).toLowerCase() + kind.slice(1) + capitalize(fileName);
89
+ // Restore template expressions as metadata
90
+ const templateExpressions = {};
91
+ for (const [placeholder, expr] of stripped.expressions) {
92
+ templateExpressions[placeholder] = {
93
+ expression: expr.expression,
94
+ kind: classifyExpression(expr.expression),
95
+ };
96
+ }
97
+ // Extract properties (skip apiVersion/kind)
98
+ const properties = {};
99
+ for (const [key, value] of Object.entries(doc)) {
100
+ if (key === "apiVersion" || key === "kind")
101
+ continue;
102
+ properties[key] = value;
103
+ }
104
+ resources.push({
105
+ logicalId,
106
+ type: `K8s::${resolveGroup(apiVersion)}::${kind}`,
107
+ properties,
108
+ metadata: {
109
+ file: path,
110
+ apiVersion,
111
+ kind,
112
+ templateExpressions,
113
+ blockDirectives: stripped.blockDirectives,
114
+ },
115
+ });
116
+ }
117
+ extractParameters(obj, prefix, params) {
118
+ for (const [key, value] of Object.entries(obj)) {
119
+ const fullPath = prefix ? `${prefix}.${key}` : key;
120
+ if (value && typeof value === "object" && !Array.isArray(value)) {
121
+ this.extractParameters(value, fullPath, params);
122
+ }
123
+ else {
124
+ params.push({
125
+ name: fullPath,
126
+ type: Array.isArray(value) ? "array" : typeof value,
127
+ defaultValue: value,
128
+ });
129
+ }
130
+ }
131
+ }
132
+ }
133
+ function resolveGroup(apiVersion) {
134
+ if (!apiVersion.includes("/"))
135
+ return "Core";
136
+ const group = apiVersion.split("/")[0].split(".")[0];
137
+ return group.charAt(0).toUpperCase() + group.slice(1);
138
+ }
139
+ function capitalize(s) {
140
+ return s.split(/[_-]/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
141
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Go template expression extraction and stripping.
3
+ *
4
+ * Strips Go template expressions (`{{ ... }}`) from Helm templates,
5
+ * replacing them with placeholder values so the underlying YAML can be parsed.
6
+ * Records the original expressions for later reconstruction as Helm intrinsics.
7
+ */
8
+ /**
9
+ * Strip Go template expressions from a Helm template file.
10
+ *
11
+ * - Inline expressions (`{{ .Values.x }}`) are replaced with `__HELM_PLACEHOLDERn__`
12
+ * - Block-level directives (`{{- if ... }}`, `{{- end }}`, `{{- range ... }}`) are removed
13
+ * - Action pipelines are preserved in the expression map
14
+ */
15
+ export function stripTemplateExpressions(template) {
16
+ const expressions = new Map();
17
+ const blockDirectives = [];
18
+ let counter = 0;
19
+ const lines = template.split("\n");
20
+ const outputLines = [];
21
+ for (let i = 0; i < lines.length; i++) {
22
+ const line = lines[i];
23
+ const lineNum = i + 1;
24
+ // Check if this is a standalone block directive line
25
+ const trimmed = line.trim();
26
+ if (isBlockDirectiveLine(trimmed)) {
27
+ blockDirectives.push({ directive: trimmed, line: lineNum });
28
+ continue; // Remove entire line
29
+ }
30
+ // Replace inline expressions with placeholders
31
+ const processed = line.replace(/\{\{-?\s*(.*?)\s*-?\}\}/g, (_match, expr) => {
32
+ const placeholder = `__HELM_PLACEHOLDER${counter}__`;
33
+ counter++;
34
+ expressions.set(placeholder, { placeholder, expression: expr.trim(), line: lineNum });
35
+ return placeholder;
36
+ });
37
+ outputLines.push(processed);
38
+ }
39
+ return {
40
+ yaml: outputLines.join("\n"),
41
+ expressions,
42
+ blockDirectives,
43
+ };
44
+ }
45
+ /**
46
+ * Check if a line is a standalone block directive (if/else/end/range/with/define/block).
47
+ */
48
+ function isBlockDirectiveLine(trimmed) {
49
+ if (!trimmed.startsWith("{{"))
50
+ return false;
51
+ // Extract the directive content
52
+ const match = trimmed.match(/^\{\{-?\s*(if|else|else if|end|range|with|define|block|template)\b/);
53
+ if (!match)
54
+ return false;
55
+ // Verify the line is ONLY the directive (not mixed with YAML)
56
+ // A standalone directive line starts with {{ and ends with }}
57
+ return /\}\}\s*$/.test(trimmed);
58
+ }
59
+ export function classifyExpression(expr) {
60
+ const trimmed = expr.trim();
61
+ if (trimmed.startsWith("include "))
62
+ return "include";
63
+ if (trimmed.startsWith("toYaml ") || trimmed.includes("| toYaml"))
64
+ return "toYaml";
65
+ if (trimmed.startsWith("required "))
66
+ return "required";
67
+ if (trimmed.startsWith("default "))
68
+ return "default";
69
+ if (trimmed.startsWith("printf "))
70
+ return "printf";
71
+ if (trimmed.startsWith("lookup "))
72
+ return "lookup";
73
+ if (trimmed.startsWith("tpl "))
74
+ return "tpl";
75
+ if (trimmed.includes("| quote"))
76
+ return "quote";
77
+ if (trimmed.includes("|"))
78
+ return "pipe";
79
+ if (trimmed.startsWith(".Values."))
80
+ return "values";
81
+ if (trimmed.startsWith(".Release."))
82
+ return "release";
83
+ if (trimmed.startsWith(".Chart."))
84
+ return "chart";
85
+ return "other";
86
+ }
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ // Serializer
2
+ export { helmSerializer } from "./serializer.js";
3
+ // Plugin
4
+ export { helmPlugin } from "./plugin.js";
5
+ // #1495 piece 4 — the component surface. `helmCapabilityPlugin` exported from
6
+ // the package entry is what `loadCapabilityPluginFromLexicon` scans for, the
7
+ // same discovery the aws and k8s plugins ride.
8
+ export { helmCapabilityPlugin, HELM_VERB_FAMILIES } from "./components/capability-plugin.js";
9
+ export { helmUpgradeCapability, createHelmUpgradeCapability } from "./components/helm-upgrade.js";
10
+ // Typed Op step-builder wrappers (chant #1288 Stage 2) — helmInstall/
11
+ // helmInstallPinned with authoring-time types derived from this lexicon's
12
+ // own HelmInstallArgs (see ./op/builders.ts's module doc for why these live
13
+ // here rather than in core). Opt-in: `@intentius/chant/op`'s same-named
14
+ // exports are core's original untyped builders, unchanged, for
15
+ // cloud-agnostic authoring.
16
+ export { helmInstall, helmInstallPinned } from "./op/builders.js";
17
+ // Resources
18
+ export { Chart, Values, ValuesOverride, HelmTest, HelmNotes, HelmHook, HelmDependency, HelmMaintainer, HelmCRD } from "./resources.js";
19
+ // HelmRender — render an upstream chart at chant build time
20
+ export { HelmRender, getHelmRenderRecords, clearHelmRenderRecords } from "./render.js";
21
+ // #1237 — render canonicalization + the contentDigest/inputDigest split.
22
+ export { canonicalizeRender, helmContentDigest, helmInputDigest, renderStability } from "./render-digest.js";
23
+ // #1238 — RenderManifest + content-addressed render storage.
24
+ export { helmValuesDigest, indexRenderDocuments, renderCacheKey, renderStoreRoot, persistHelmRender, loadRenderManifest, loadRenderContent, listRenderManifests, findRenderByCacheKey, readRenderDocument, } from "./render-store.js";
25
+ // #1239 — structure-preserving render wrapper: segment-based CRD routing.
26
+ export { routeRender, routeStoredRender } from "./render-wrapper.js";
27
+ // #1242 — pinned install path: wrapper-chart materialization.
28
+ export { materializeWrapperChart, wrapperChartName } from "./wrapper-chart.js";
29
+ // #1240 — addArchiveHelmRender: fold a pinned render into a build archive.
30
+ export { addArchiveHelmRender, HELM_RENDER_MEDIA_TYPE } from "./archive-render.js";
31
+ // #1251/#1252 — build-time coalesced-values probe and its provenance products.
32
+ export { probeCoalescedValues, coalescedValuesDigest, computeValueSources, findDeadAssignments, rootCoalescedValues, getValuesProbeRecords, recordValuesProbe, clearValuesProbeRecords, } from "./values-probe.js";
33
+ // Capability profiles — per-cluster render inputs (#1235, epic #1228)
34
+ export { helmConfigSchema, helmCapabilityProfileSchema, resolveCapabilityProfile, validateCapabilityProfile, KUBE_VERSION_PATTERN, } from "./config.js";
35
+ // Intrinsics
36
+ export { HelmTpl, HELM_TPL_KEY, HELM_IF_KEY, HELM_RANGE_KEY, HELM_WITH_KEY, RuntimeSlot, RUNTIME_SLOT_KEY, runtimeSlot, values, Release, ChartRef, include, required, helmDefault, toYaml, quote, printf, tpl, lookup, Capabilities, Template, filesGet, filesGlob, filesAsConfig, filesAsSecrets, ElseIf, If, Range, With, withOrder, argoWave, } from "./intrinsics.js";
37
+ // Helpers
38
+ export { generateHelpers } from "./helpers.js";
39
+ // Code generation pipeline
40
+ export { generate, writeGeneratedFiles } from "./codegen/generate.js";
41
+ export { packageLexicon } from "./codegen/package.js";
42
+ // Composites
43
+ export { HelmWebApp, HelmStatefulService, HelmCronJob, HelmMicroservice, HelmLibrary, HelmCRDLifecycle, HelmDaemonSet, HelmWorker, HelmExternalSecret, HelmBatchJob, HelmMonitoredService, HelmSecureIngress, HelmNamespaceEnv, } from "./composites/index.js";
44
+ // Import pipeline
45
+ export { HelmParser } from "./import/parser.js";
46
+ export { HelmGenerator } from "./import/generator.js";
47
+ export { stripTemplateExpressions, classifyExpression } from "./import/template-stripper.js";
48
+ // Pinnability gate (#1234, epic #1228) — what the pinned-render pipeline
49
+ // consults before anything is pinned
50
+ export { classifyChart } from "./pinnability/index.js";
51
+ // LSP providers
52
+ export { helmCompletions } from "./lsp/completions.js";
53
+ export { helmHover } from "./lsp/hover.js";
54
+ // Docs generation
55
+ export { generateDocs } from "./codegen/docs.js";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "8d31257cc1103f2237d70f3954e8d754bf6e6303fcda9ea5777ba2c5984ac537",
4
+ "manifest.json": "835f8c4a69d90939bbbf73aa3675fa83ee0950d45455d0b2c80144391265270d",
5
5
  "meta.json": "14243c5730a07c6a6edc35ddd351438547d58df5cf345f2233a355b0c7611ccc",
6
6
  "types/index.d.ts": "5377696ca8698cd2999e4680feb8e8e4b54a7b49fb603a87b2f27356114d1794",
7
7
  "rules/chart-metadata.ts": "3ac9183a3bd42c657d1c4b7e45ddb302a75baf126d62284fa9d6f6226c2734cc",
@@ -36,5 +36,5 @@
36
36
  "skills/chant-helm-patterns.md": "9e79e6a46391da46709d8aa57e2825a7cd9eb981cd923f02ad60836c49b2561e",
37
37
  "skills/chant-helm-security.md": "bfc367eabceed2e84f1cf94501b407df78aeed963cec104f24a321d0962063c9"
38
38
  },
39
- "composite": "2464d9b2fe2c252c6333c4bedbf4a58439160f31f3377b92a4631a109c9320df"
39
+ "composite": "f261b893751784a0ec7ef517cad0deea10301b7dfbd95ce837e73c04454def0b"
40
40
  }