@shepherdjerred/helm-types 1.7.0 → 2.0.0

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 (96) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +674 -0
  3. package/README.md +82 -63
  4. package/demos/argo-cd-cli.cast +50 -0
  5. package/demos/record-cli-demo.sh +132 -0
  6. package/dist/chart-fetcher.d.ts +14 -0
  7. package/dist/chart-fetcher.d.ts.map +1 -0
  8. package/dist/chart-fetcher.js +105 -0
  9. package/dist/chart-fetcher.js.map +1 -0
  10. package/dist/chart-info-parser.d.ts +6 -0
  11. package/dist/chart-info-parser.d.ts.map +1 -0
  12. package/dist/chart-info-parser.js +50 -0
  13. package/dist/chart-info-parser.js.map +1 -0
  14. package/dist/cli.d.ts +7 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +140 -22841
  17. package/dist/cli.js.map +1 -0
  18. package/dist/comment-parser.d.ts +10 -0
  19. package/dist/comment-parser.d.ts.map +1 -0
  20. package/dist/comment-parser.js +150 -0
  21. package/dist/comment-parser.js.map +1 -0
  22. package/dist/config.d.ts +24 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +169 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/helm-types.d.ts +16 -0
  27. package/dist/helm-types.d.ts.map +1 -0
  28. package/{src/helm-types.ts → dist/helm-types.js} +1 -1
  29. package/dist/helm-types.js.map +1 -0
  30. package/dist/index.d.ts +25 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +22 -23
  33. package/dist/index.js.map +1 -0
  34. package/dist/interface-generator.d.ts +6 -0
  35. package/dist/interface-generator.d.ts.map +1 -0
  36. package/dist/interface-generator.js +181 -0
  37. package/dist/interface-generator.js.map +1 -0
  38. package/dist/schemas.d.ts +13 -0
  39. package/dist/schemas.d.ts.map +1 -0
  40. package/{src/schemas.ts → dist/schemas.js} +12 -23
  41. package/dist/schemas.js.map +1 -0
  42. package/dist/type-converter-helpers.d.ts +20 -0
  43. package/dist/type-converter-helpers.d.ts.map +1 -0
  44. package/dist/type-converter-helpers.js +75 -0
  45. package/dist/type-converter-helpers.js.map +1 -0
  46. package/dist/type-converter.d.ts +26 -0
  47. package/dist/type-converter.d.ts.map +1 -0
  48. package/dist/type-converter.js +378 -0
  49. package/dist/type-converter.js.map +1 -0
  50. package/dist/types.d.ts +35 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +3 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/utils.d.ts +17 -0
  55. package/dist/utils.d.ts.map +1 -0
  56. package/dist/utils.js +69 -0
  57. package/dist/utils.js.map +1 -0
  58. package/dist/yaml-comment-filters.d.ts +7 -0
  59. package/dist/yaml-comment-filters.d.ts.map +1 -0
  60. package/dist/yaml-comment-filters.js +91 -0
  61. package/dist/yaml-comment-filters.js.map +1 -0
  62. package/dist/yaml-comment-regex-parser.d.ts +8 -0
  63. package/dist/yaml-comment-regex-parser.d.ts.map +1 -0
  64. package/dist/yaml-comment-regex-parser.js +120 -0
  65. package/dist/yaml-comment-regex-parser.js.map +1 -0
  66. package/dist/yaml-comments.d.ts +74 -0
  67. package/dist/yaml-comments.d.ts.map +1 -0
  68. package/dist/yaml-comments.js +406 -0
  69. package/dist/yaml-comments.js.map +1 -0
  70. package/dist/yaml-preprocess.d.ts +15 -0
  71. package/dist/yaml-preprocess.d.ts.map +1 -0
  72. package/dist/yaml-preprocess.js +170 -0
  73. package/dist/yaml-preprocess.js.map +1 -0
  74. package/examples/argo-cd/generate.mjs +23 -0
  75. package/package.json +17 -12
  76. package/src/__fixtures__/sample-chart/Chart.yaml +0 -6
  77. package/src/__fixtures__/sample-chart/values.schema.json +0 -32
  78. package/src/__fixtures__/sample-chart/values.yaml +0 -22
  79. package/src/chart-fetcher.ts +0 -221
  80. package/src/chart-info-parser.ts +0 -64
  81. package/src/cli.ts +0 -217
  82. package/src/code-generator.ts +0 -226
  83. package/src/comment-parser.ts +0 -180
  84. package/src/config.ts +0 -195
  85. package/src/index.ts +0 -28
  86. package/src/interface-generator.ts +0 -238
  87. package/src/reset.d.ts +0 -1
  88. package/src/type-converter-helpers.ts +0 -108
  89. package/src/type-converter.ts +0 -520
  90. package/src/type-inference.ts +0 -548
  91. package/src/types.ts +0 -41
  92. package/src/utils.ts +0 -76
  93. package/src/yaml-comment-filters.ts +0 -103
  94. package/src/yaml-comment-regex-parser.ts +0 -150
  95. package/src/yaml-comments.ts +0 -507
  96. package/src/yaml-preprocess.ts +0 -235
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Pre-process YAML to uncomment commented-out keys
3
+ * In Helm charts, commented-out keys are documentation of available options
4
+ * e.g., "## key: value" or "# key: value"
5
+ *
6
+ * This allows us to parse them as real keys and associate their comments
7
+ *
8
+ * Only uncomments keys that are:
9
+ * - At root level or similar indentation to real keys
10
+ * - Not part of "Example:" blocks
11
+ * - Not part of documentation prose (have their own dedicated comment block)
12
+ * - Not deeply nested (which would indicate example YAML)
13
+ */
14
+ /**
15
+ * Check if a line is an "Example:" marker
16
+ */
17
+ function isExampleMarker(trimmed) {
18
+ return /^##?\s*Example:?$/i.test(trimmed);
19
+ }
20
+ /**
21
+ * Check if an example block should end
22
+ */
23
+ function shouldExitExampleBlock(trimmed) {
24
+ return (!trimmed ||
25
+ trimmed.startsWith("For more information") ||
26
+ trimmed.startsWith("Ref:"));
27
+ }
28
+ /**
29
+ * Check if the previous line had a block scalar indicator
30
+ */
31
+ function prevLineHasBlockScalar(lines, i) {
32
+ if (i <= 0) {
33
+ return false;
34
+ }
35
+ const prevTrimmed = lines[i - 1]?.trim() ?? "";
36
+ return /^#+\s*[\w.-]+:\s*[|>]\s*$/.test(prevTrimmed);
37
+ }
38
+ /**
39
+ * Check if a line is still in a block scalar (indented content)
40
+ */
41
+ function isBlockScalarContent(line, trimmed) {
42
+ if (trimmed.length === 0) {
43
+ return false;
44
+ }
45
+ return (line.startsWith(" ") || line.startsWith("\t") || /^#\s{2,}/.test(line));
46
+ }
47
+ /**
48
+ * Check if a commented key value looks like it should be excluded
49
+ */
50
+ function isExcludedCommentedKey(keyValue) {
51
+ const isDocReference = /^ref:/i.test(keyValue) &&
52
+ (keyValue.includes("http://") || keyValue.includes("https://"));
53
+ const isURL = keyValue.trim().startsWith("http://") ||
54
+ keyValue.trim().startsWith("https://");
55
+ return isDocReference || isURL;
56
+ }
57
+ /**
58
+ * Determine if a commented key looks like a YAML example based on context
59
+ */
60
+ function isLikelyExample(lines, i) {
61
+ const prevLine = i > 0 ? lines[i - 1] : "";
62
+ const prevTrimmed = prevLine?.trim() ?? "";
63
+ const prevIsCommentedKey = /^#+\s*[\w.-]+:\s/.test(prevTrimmed);
64
+ const prevIsBlank = !prevTrimmed;
65
+ const prevIsListItem = prevTrimmed.startsWith("#") && prevTrimmed.slice(1).trim().startsWith("-");
66
+ return ((!prevIsBlank && !prevIsCommentedKey && prevTrimmed.startsWith("#")) ||
67
+ prevIsListItem);
68
+ }
69
+ /**
70
+ * Update consecutive commented key count based on context
71
+ */
72
+ function updateConsecutiveCount(lines, i, current) {
73
+ const prevLine = i > 0 ? lines[i - 1] : "";
74
+ const prevTrimmed = prevLine?.trim() ?? "";
75
+ const prevIsCommentedKey = /^#+\s*[\w.-]+:\s/.test(prevTrimmed);
76
+ const prevIsBlank = !prevTrimmed;
77
+ if (prevIsCommentedKey) {
78
+ return current + 1;
79
+ }
80
+ if (!prevIsBlank) {
81
+ return 0;
82
+ }
83
+ return current;
84
+ }
85
+ /**
86
+ * Try to uncomment a commented YAML key line. Returns the uncommented line or null.
87
+ */
88
+ function tryUncommentLine(line, lines, i, state) {
89
+ const commentedKeyMatch = /^([ \t]*)#+\s*([\w.-]+:\s*(?:\S.*)?)$/.exec(line);
90
+ if (!commentedKeyMatch) {
91
+ return { uncommented: null, newConsecutive: 0 };
92
+ }
93
+ const [, indent, keyValue] = commentedKeyMatch;
94
+ if (keyValue === "" || indent === "" || keyValue == null || indent == null) {
95
+ return {
96
+ uncommented: null,
97
+ newConsecutive: state.consecutiveCommentedKeys,
98
+ };
99
+ }
100
+ const keyPart = keyValue.split(":")[0]?.trim() ?? "";
101
+ const isValidKey = /^[\w.-]+$/.test(keyPart);
102
+ if (!isValidKey || isExcludedCommentedKey(keyValue)) {
103
+ return {
104
+ uncommented: null,
105
+ newConsecutive: state.consecutiveCommentedKeys,
106
+ };
107
+ }
108
+ const keyIndent = indent.length;
109
+ const newConsecutive = updateConsecutiveCount(lines, i, state.consecutiveCommentedKeys);
110
+ const likelyExampleCtx = isLikelyExample(lines, i);
111
+ const shouldUncomment = !likelyExampleCtx &&
112
+ (state.lastRealKeyIndent === -1 ||
113
+ Math.abs(keyIndent - state.lastRealKeyIndent) <= 4 ||
114
+ newConsecutive >= 2);
115
+ if (shouldUncomment) {
116
+ return { uncommented: `${indent}${keyValue}`, newConsecutive };
117
+ }
118
+ return { uncommented: null, newConsecutive };
119
+ }
120
+ export function preprocessYAMLComments(yamlContent) {
121
+ const lines = yamlContent.split("\n");
122
+ const processedLines = [];
123
+ const state = {
124
+ inExampleBlock: false,
125
+ inBlockScalar: false,
126
+ lastRealKeyIndent: -1,
127
+ consecutiveCommentedKeys: 0,
128
+ };
129
+ for (let i = 0; i < lines.length; i++) {
130
+ const line = lines[i] ?? "";
131
+ const trimmed = line.trim();
132
+ if (isExampleMarker(trimmed)) {
133
+ state.inExampleBlock = true;
134
+ processedLines.push(line);
135
+ continue;
136
+ }
137
+ if (state.inExampleBlock && shouldExitExampleBlock(trimmed)) {
138
+ state.inExampleBlock = false;
139
+ }
140
+ if (prevLineHasBlockScalar(lines, i)) {
141
+ state.inBlockScalar = true;
142
+ }
143
+ if (state.inBlockScalar && !isBlockScalarContent(line, trimmed)) {
144
+ state.inBlockScalar = false;
145
+ }
146
+ if (!trimmed.startsWith("#") && /^[\w.-]+:/.test(trimmed)) {
147
+ state.lastRealKeyIndent = line.search(/\S/);
148
+ state.consecutiveCommentedKeys = 0;
149
+ }
150
+ if (state.inExampleBlock || state.inBlockScalar) {
151
+ processedLines.push(line);
152
+ state.consecutiveCommentedKeys = 0;
153
+ continue;
154
+ }
155
+ const { uncommented, newConsecutive } = tryUncommentLine(line, lines, i, state);
156
+ state.consecutiveCommentedKeys = newConsecutive;
157
+ if (uncommented != null) {
158
+ processedLines.push(uncommented);
159
+ continue;
160
+ }
161
+ // Reset consecutive count if not a commented key
162
+ const isCommentedKey = /^[ \t]*#+\s*[\w.-]+:\s*(?:\S.*)?$/.test(line);
163
+ if (!isCommentedKey) {
164
+ state.consecutiveCommentedKeys = 0;
165
+ }
166
+ processedLines.push(line);
167
+ }
168
+ return processedLines.join("\n");
169
+ }
170
+ //# sourceMappingURL=yaml-preprocess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-preprocess.js","sourceRoot":"","sources":["../src/yaml-preprocess.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import {
2
+ convertToTypeScriptInterface,
3
+ fetchHelmChart,
4
+ generateTypeScriptCode,
5
+ } from "@shepherdjerred/helm-types";
6
+
7
+ const chart = {
8
+ name: "argo-cd",
9
+ chartName: "argo-cd",
10
+ repoUrl: "https://argoproj.github.io/argo-helm",
11
+ version: "7.7.16",
12
+ };
13
+
14
+ const { schema, values, yamlComments } = await fetchHelmChart(chart);
15
+ const types = convertToTypeScriptInterface({
16
+ values,
17
+ interfaceName: "ArgoCdValues",
18
+ schema,
19
+ yamlComments,
20
+ chartName: chart.name,
21
+ });
22
+
23
+ process.stdout.write(generateTypeScriptCode(types, chart.name));
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@shepherdjerred/helm-types",
3
- "version": "1.7.0",
3
+ "version": "2.0.0",
4
4
  "description": "Generate TypeScript types from Helm chart values.yaml and values.schema.json",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
- "types": "src/index.ts",
7
+ "types": "dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "types": "./src/index.ts",
10
+ "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js"
12
12
  }
13
13
  },
@@ -16,12 +16,14 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
- "src",
20
- "!src/**/*.test.ts",
21
- "!src/__snapshots__"
19
+ "examples",
20
+ "demos",
21
+ "README.md",
22
+ "LICENSE",
23
+ "CHANGELOG.md"
22
24
  ],
23
25
  "scripts": {
24
- "build": "bun build src/index.ts src/cli.ts --outdir dist --target node",
26
+ "build": "PATH=node_modules/@typescript/native/bin:$PATH tsc -p tsconfig.build.json",
25
27
  "test": "bun --no-install --bun vitest --config ../../../../vitest.config.ts run",
26
28
  "test:helm-types": "bun --no-install --bun vitest --config ../../../../vitest.config.ts run src/helm-types.test.ts",
27
29
  "test:cli": "bun --no-install --bun vitest --config ../../../../vitest.config.ts run src/cli.test.ts",
@@ -30,9 +32,9 @@
30
32
  "typecheck": "PATH=node_modules/@typescript/native/bin:$PATH tsc --noEmit",
31
33
  "prepublishOnly": "bun run build",
32
34
  "generate:live": "bun run src/cli.ts",
33
- "publish:npm": "bun ../../../../scripts/publish-npm.ts .",
34
- "test:ci": "bun ../../../../scripts/run-ci-test.ts",
35
- "test:report": "CI_TEST_COVERAGE=1 bun ../../../../scripts/run-ci-test.ts"
35
+ "publish:npm": "bun ../../../../scripts/release/publish-npm.ts .",
36
+ "test:ci": "bun ../../../../scripts/ci/run-ci-test.ts",
37
+ "test:report": "CI_TEST_COVERAGE=1 bun ../../../../scripts/ci/run-ci-test.ts"
36
38
  },
37
39
  "keywords": [
38
40
  "helm",
@@ -43,7 +45,7 @@
43
45
  "k8s"
44
46
  ],
45
47
  "author": "Jerred Shepherd",
46
- "license": "GPL-3.0",
48
+ "license": "GPL-3.0-only",
47
49
  "repository": {
48
50
  "type": "git",
49
51
  "url": "git+https://github.com/shepherdjerred/monorepo.git",
@@ -57,7 +59,7 @@
57
59
  "access": "public"
58
60
  },
59
61
  "engines": {
60
- "node": ">=18"
62
+ "node": ">=24"
61
63
  },
62
64
  "dependencies": {
63
65
  "yaml": "^2.8.3",
@@ -65,7 +67,10 @@
65
67
  },
66
68
  "devDependencies": {
67
69
  "@shepherdjerred/eslint-config": "0.3.0",
70
+ "@tsconfig/node24": "^24.0.4",
71
+ "@tsconfig/strictest": "^2.0.8",
68
72
  "@types/bun": "1.4.0",
73
+ "@types/node": "^26.1.1",
69
74
  "eslint": "^10.3.0",
70
75
  "jiti": "^2.7.0",
71
76
  "@typescript/native": "npm:typescript@7.0.2",
@@ -1,6 +0,0 @@
1
- apiVersion: v2
2
- name: sample-chart
3
- description: A minimal local chart fixture for helm-types CLI tests (no network)
4
- type: application
5
- version: "1.2.3"
6
- appVersion: "4.5.6"
@@ -1,32 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "type": "object",
4
- "properties": {
5
- "replicaCount": {
6
- "type": "integer",
7
- "description": "Number of pod replicas to run."
8
- },
9
- "image": {
10
- "type": "object",
11
- "properties": {
12
- "repository": { "type": "string" },
13
- "pullPolicy": {
14
- "type": "string",
15
- "enum": ["Always", "IfNotPresent", "Never"]
16
- },
17
- "tag": { "type": "string" }
18
- }
19
- },
20
- "serviceEnabled": {
21
- "type": "boolean",
22
- "description": "Whether the service is enabled."
23
- },
24
- "service": {
25
- "type": "object",
26
- "properties": {
27
- "type": { "type": "string" },
28
- "port": { "type": "integer" }
29
- }
30
- }
31
- }
32
- }
@@ -1,22 +0,0 @@
1
- # -- Number of pod replicas to run.
2
- replicaCount: 2
3
-
4
- image:
5
- # -- Container image repository.
6
- repository: nginx
7
- # -- Image pull policy.
8
- pullPolicy: IfNotPresent
9
- # -- Image tag; defaults to the chart appVersion when empty.
10
- tag: "@sha256:5a88c9c45479443d7be2eadc894b4ed0a9801bae03d97a5760ae13b5c2005942"
11
-
12
- # -- Whether the service is enabled.
13
- serviceEnabled: true
14
-
15
- service:
16
- # -- Kubernetes service type.
17
- type: ClusterIP
18
- # -- Service port.
19
- port: 80
20
-
21
- # -- Extra environment variables passed to the container.
22
- extraEnv: []
@@ -1,221 +0,0 @@
1
- // Using Bun.$ for path operations instead of node:path
2
- import { parse as yamlParse } from "yaml";
3
- import type { ChartInfo, JSONSchemaProperty } from "./types.ts";
4
- import { HelmValueSchema, RecordSchema, ErrorSchema } from "./schemas.ts";
5
- import type { HelmValue } from "./schemas.ts";
6
- import { parseYAMLComments } from "./yaml-comments.ts";
7
-
8
- /**
9
- * Load JSON schema if it exists in the chart
10
- */
11
- async function loadJSONSchema(
12
- chartPath: string,
13
- ): Promise<JSONSchemaProperty | null> {
14
- try {
15
- const schemaPath = `${chartPath}/values.schema.json`;
16
- const schemaContent = await Bun.file(schemaPath).text();
17
- const parsed: unknown = JSON.parse(schemaContent);
18
- // Validate that parsed is an object
19
- const recordCheck = RecordSchema.safeParse(parsed);
20
- if (!recordCheck.success) {
21
- return null;
22
- }
23
- // Note: JSONSchemaProperty is a structural type
24
- const schema: JSONSchemaProperty = recordCheck.data;
25
- console.log(` 📋 Loaded values.schema.json`);
26
- return schema;
27
- } catch {
28
- // Schema doesn't exist or couldn't be parsed - that's okay
29
- return null;
30
- }
31
- }
32
-
33
- /**
34
- * Run a command and return its output using Bun
35
- */
36
- async function runCommand(command: string, args: string[]): Promise<string> {
37
- try {
38
- const proc = Bun.spawn([command, ...args], {
39
- stdout: "pipe",
40
- stderr: "inherit",
41
- });
42
-
43
- const output = await new Response(proc.stdout).text();
44
- const exitCode = await proc.exited;
45
-
46
- if (exitCode === 0) {
47
- return output;
48
- } else {
49
- throw new Error(
50
- `Command "${command} ${args.join(" ")}" failed with code ${exitCode.toString()}`,
51
- );
52
- }
53
- } catch (error) {
54
- const parseResult = ErrorSchema.safeParse(error);
55
- const errorMessage = parseResult.success
56
- ? parseResult.data.message
57
- : String(error);
58
- throw new Error(
59
- `Failed to spawn command "${command} ${args.join(" ")}": ${errorMessage}`,
60
- { cause: error },
61
- );
62
- }
63
- }
64
-
65
- /**
66
- * Locate the directory `helm pull --untar` created. helm names it after the
67
- * Chart.yaml `name`, which can differ from the OCI artifact path (e.g.
68
- * a chart at `foo/charts/foo` untars to `foo/`), so prefer the version-key fallback
69
- * but fall back to scanning for the extracted Chart.yaml.
70
- */
71
- async function resolveUntarredChartDir(
72
- tempDir: string,
73
- fallbackName: string,
74
- ): Promise<string> {
75
- const fallback = `${tempDir}/${fallbackName}`;
76
- if (await Bun.file(`${fallback}/Chart.yaml`).exists()) {
77
- return fallback;
78
- }
79
- const lsOutput = await runCommand("ls", ["-1", tempDir]);
80
- for (const entry of lsOutput.split("\n").map((s) => s.trim())) {
81
- if (entry === "") {
82
- continue;
83
- }
84
- if (await Bun.file(`${tempDir}/${entry}/Chart.yaml`).exists()) {
85
- return `${tempDir}/${entry}`;
86
- }
87
- }
88
- return fallback;
89
- }
90
-
91
- /**
92
- * Fetch a Helm chart and extract its values.yaml and optional schema
93
- */
94
- export async function fetchHelmChart(chart: ChartInfo): Promise<{
95
- values: HelmValue;
96
- schema: JSONSchemaProperty | null;
97
- yamlComments: Map<string, string>;
98
- }> {
99
- const pwd = Bun.env["PWD"] ?? process.cwd();
100
- const tempDir = `${pwd}/temp/helm-${chart.name}`;
101
- const repoName = `temp-repo-${chart.name}-${String(Date.now())}`;
102
-
103
- try {
104
- // Ensure temp directory exists
105
- await Bun.$`mkdir -p ${tempDir}`.quiet();
106
-
107
- let chartDir: string;
108
- if (chart.oci === true) {
109
- // OCI registry: pull directly, no `helm repo add` needed.
110
- const ociRef = `oci://${chart.repoUrl}/${chart.chartName}`;
111
- console.log(` ⬇️ Pulling OCI chart ${ociRef}:${chart.version}...`);
112
- await runCommand("helm", [
113
- "pull",
114
- ociRef,
115
- "--version",
116
- chart.version,
117
- "--destination",
118
- tempDir,
119
- "--untar",
120
- ]);
121
- chartDir = await resolveUntarredChartDir(tempDir, chart.name);
122
- } else {
123
- console.log(` 📦 Adding Helm repo: ${chart.repoUrl}`);
124
- // Add the helm repo
125
- await runCommand("helm", ["repo", "add", repoName, chart.repoUrl]);
126
-
127
- console.log(` 🔄 Updating Helm repo ${repoName}...`);
128
- // Update ONLY the repo we just added. `helm repo update` with no args
129
- // refreshes every repo in the local helm config — including unrelated
130
- // stale entries (e.g. the retired public bitnami repo) whose failure
131
- // would abort an otherwise-fine fetch.
132
- await runCommand("helm", ["repo", "update", repoName]);
133
-
134
- console.log(` ⬇️ Pulling chart ${chart.chartName}:${chart.version}...`);
135
- // Pull the chart
136
- await runCommand("helm", [
137
- "pull",
138
- `${repoName}/${chart.chartName}`,
139
- "--version",
140
- chart.version,
141
- "--destination",
142
- tempDir,
143
- "--untar",
144
- ]);
145
- chartDir = `${tempDir}/${chart.chartName}`;
146
- }
147
-
148
- // Read values.yaml
149
- const valuesPath = `${chartDir}/values.yaml`;
150
- console.log(` 📖 Reading values.yaml from ${valuesPath}`);
151
-
152
- try {
153
- const valuesContent = await Bun.file(valuesPath).text();
154
-
155
- // Parse YAML comments
156
- const yamlComments = parseYAMLComments(valuesContent);
157
- console.log(
158
- ` 💬 Extracted ${String(yamlComments.size)} comments from values.yaml`,
159
- );
160
-
161
- // Parse YAML using yaml package
162
- const parsedValues = yamlParse(valuesContent) as unknown;
163
- console.log(` ✅ Successfully parsed values.yaml`);
164
- const recordParseResult = RecordSchema.safeParse(parsedValues);
165
- if (recordParseResult.success) {
166
- console.log(
167
- ` 🔍 Parsed values keys: ${Object.keys(recordParseResult.data)
168
- .slice(0, 10)
169
- .join(
170
- ", ",
171
- )}${Object.keys(recordParseResult.data).length > 10 ? "..." : ""}`,
172
- );
173
- }
174
-
175
- // Check if parsedValues is a valid object using Zod before validation
176
- if (!recordParseResult.success) {
177
- console.warn(
178
- ` ⚠️ Parsed values is not a valid record object: ${String(parsedValues)}`,
179
- );
180
- return { values: {}, schema: null, yamlComments: new Map() };
181
- }
182
-
183
- // Validate and parse with Zod for runtime type safety
184
- const parseResult = HelmValueSchema.safeParse(recordParseResult.data);
185
-
186
- // Try to load JSON schema
187
- const schema = await loadJSONSchema(chartDir);
188
-
189
- if (parseResult.success) {
190
- console.log(` ✅ Zod validation successful`);
191
- return { values: parseResult.data, schema, yamlComments };
192
- } else {
193
- console.warn(` ⚠️ Zod validation failed for ${chart.name}:`);
194
- console.warn(
195
- ` First few errors:`,
196
- parseResult.error.issues.slice(0, 3),
197
- );
198
- console.warn(
199
- ` ⚠️ Falling back to unvalidated object for type generation`,
200
- );
201
- // Return the validated record data from the successful parse result
202
- return { values: recordParseResult.data, schema, yamlComments };
203
- }
204
- } catch (error) {
205
- console.warn(` ⚠️ Failed to read/parse values.yaml: ${String(error)}`);
206
- return { values: {}, schema: null, yamlComments: new Map() };
207
- }
208
- } finally {
209
- // Cleanup
210
- try {
211
- console.log(` 🧹 Cleaning up...`);
212
- // OCI charts never added a named repo, so only remove for HTTP repos.
213
- if (chart.oci !== true) {
214
- await runCommand("helm", ["repo", "remove", repoName]);
215
- }
216
- await Bun.$`rm -rf ${tempDir}`.quiet();
217
- } catch (cleanupError) {
218
- console.warn(`Cleanup failed for ${chart.name}:`, String(cleanupError));
219
- }
220
- }
221
- }
@@ -1,64 +0,0 @@
1
- import type { ChartInfo } from "./types.ts";
2
-
3
- /**
4
- * Parse chart information from versions.ts comments and values
5
- */
6
- export async function parseChartInfoFromVersions(
7
- versionsPath = "src/versions.ts",
8
- ): Promise<ChartInfo[]> {
9
- const content = await Bun.file(versionsPath).text();
10
- const lines = content.split("\n");
11
- const charts: ChartInfo[] = [];
12
-
13
- for (let i = 0; i < lines.length; i++) {
14
- const line = lines[i];
15
- const nextLine = lines[i + 1];
16
-
17
- // Look for renovate comments that indicate Helm charts
18
- if (
19
- line == null ||
20
- nextLine == null ||
21
- nextLine === "" ||
22
- !line.includes("renovate: datasource=helm")
23
- ) {
24
- continue;
25
- }
26
-
27
- const repoUrlMatch = /registryUrl=(\S+)/.exec(line);
28
- const versionKeyMatch = /^\s*"?([^":\s]+)"?:/.exec(nextLine);
29
- if (!repoUrlMatch || !versionKeyMatch) {
30
- continue;
31
- }
32
-
33
- const repoUrl = repoUrlMatch[1];
34
- const versionKey = versionKeyMatch[1];
35
- if (
36
- repoUrl === "" ||
37
- versionKey === "" ||
38
- repoUrl == null ||
39
- versionKey == null
40
- ) {
41
- continue;
42
- }
43
-
44
- // Extract version value
45
- const versionMatch = /:\s*"([^"]+)"/.exec(nextLine);
46
- if (!versionMatch) {
47
- continue;
48
- }
49
-
50
- const version = versionMatch[1];
51
- if (version === "" || version == null) {
52
- continue;
53
- }
54
-
55
- charts.push({
56
- name: versionKey,
57
- repoUrl: repoUrl.replace(/\/$/, ""), // Remove trailing slash
58
- version,
59
- chartName: versionKey,
60
- });
61
- }
62
-
63
- return charts;
64
- }