@shepherdjerred/helm-types 1.7.0-dev.14406 → 1.7.0-dev.14474

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 (94) hide show
  1. package/CHANGELOG.md +69 -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 +14 -9
  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/comment-parser.ts +0 -180
  83. package/src/config.ts +0 -195
  84. package/src/index.ts +0 -28
  85. package/src/interface-generator.ts +0 -238
  86. package/src/reset.d.ts +0 -1
  87. package/src/type-converter-helpers.ts +0 -108
  88. package/src/type-converter.ts +0 -520
  89. package/src/types.ts +0 -41
  90. package/src/utils.ts +0 -76
  91. package/src/yaml-comment-filters.ts +0 -103
  92. package/src/yaml-comment-regex-parser.ts +0 -150
  93. package/src/yaml-comments.ts +0 -507
  94. package/src/yaml-preprocess.ts +0 -235
package/src/cli.ts DELETED
@@ -1,217 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * CLI for @homelab/helm-types
4
- *
5
- * Generate TypeScript types from Helm charts
6
- */
7
- import { z } from "zod";
8
- import { fetchHelmChart } from "./chart-fetcher.ts";
9
- import { convertToTypeScriptInterface } from "./type-converter.ts";
10
- import { generateTypeScriptCode } from "./interface-generator.ts";
11
- import type { ChartInfo } from "./types.ts";
12
-
13
- const ErrorSchema = z.object({
14
- message: z.string(),
15
- });
16
-
17
- const HELP_TEXT = String.raw`
18
- helm-types - Generate TypeScript types from Helm charts
19
-
20
- USAGE:
21
- bunx @homelab/helm-types [options]
22
-
23
- OPTIONS:
24
- --name, -n Unique identifier for the chart (required)
25
- --chart, -c Chart name in the repository (defaults to --name)
26
- --repo, -r Helm repository URL (required)
27
- --version, -v Chart version (required)
28
- --output, -o Output file path (defaults to stdout)
29
- --interface, -i Interface name (auto-generated from chart name if not provided)
30
- --help, -h Show this help message
31
-
32
- EXAMPLES:
33
- # Generate types for ArgoCD and print to stdout
34
- bunx @homelab/helm-types \
35
- --name argo-cd \
36
- --repo https://argoproj.github.io/argo-helm \
37
- --version 8.3.1
38
-
39
- # Generate types with custom output file
40
- bunx @homelab/helm-types \
41
- --name argo-cd \
42
- --repo https://argoproj.github.io/argo-helm \
43
- --version 8.3.1 \
44
- --output argo-cd.types.ts
45
-
46
- # Generate types with custom chart name and interface name
47
- bunx @homelab/helm-types \
48
- --name argocd \
49
- --chart argo-cd \
50
- --repo https://argoproj.github.io/argo-helm \
51
- --version 8.3.1 \
52
- --interface ArgocdHelmValues \
53
- --output argocd.types.ts
54
- `;
55
-
56
- type CliArgs = {
57
- name?: string;
58
- chart?: string;
59
- repo?: string;
60
- version?: string;
61
- output?: string;
62
- interface?: string;
63
- help?: boolean;
64
- };
65
-
66
- /** String-valued flag names (excludes boolean 'help') */
67
- type StringCliArgsKey = Exclude<keyof CliArgs, "help">;
68
-
69
- /** Map from flag name to CliArgs key */
70
- const FLAG_MAP: Record<string, StringCliArgsKey> = {
71
- "--name": "name",
72
- "-n": "name",
73
- "--chart": "chart",
74
- "-c": "chart",
75
- "--repo": "repo",
76
- "-r": "repo",
77
- "--version": "version",
78
- "-v": "version",
79
- "--output": "output",
80
- "-o": "output",
81
- "--interface": "interface",
82
- "-i": "interface",
83
- };
84
-
85
- const HELP_FLAGS = new Set(["--help", "-h"]);
86
-
87
- /**
88
- * Simple argument parser for Bun CLI
89
- */
90
- function parseCliArgs(args: string[]): CliArgs {
91
- const result: CliArgs = {};
92
-
93
- for (let i = 0; i < args.length; i++) {
94
- const arg = args[i];
95
- if (arg === "" || arg == null) {
96
- continue;
97
- }
98
-
99
- if (HELP_FLAGS.has(arg)) {
100
- result.help = true;
101
- continue;
102
- }
103
-
104
- const key = FLAG_MAP[arg];
105
- if (key != null) {
106
- const value = args[i + 1];
107
- if (value !== "" && value != null) {
108
- result[key] = value;
109
- i += 1;
110
- }
111
- continue;
112
- }
113
-
114
- if (arg.startsWith("-")) {
115
- throw new Error(`Unknown argument: ${arg}`);
116
- }
117
- }
118
-
119
- return result;
120
- }
121
-
122
- async function main() {
123
- try {
124
- const args = parseCliArgs(Bun.argv.slice(2));
125
-
126
- // Show help
127
- if (args.help === true) {
128
- console.log(HELP_TEXT);
129
- process.exit(0);
130
- }
131
-
132
- // Validate required arguments
133
- if (
134
- args.name == null ||
135
- args.name === "" ||
136
- args.repo == null ||
137
- args.repo === "" ||
138
- args.version == null ||
139
- args.version === ""
140
- ) {
141
- console.error("Error: Missing required arguments");
142
- console.error("Required: --name, --repo, --version");
143
- console.error("\nRun with --help for usage information");
144
- process.exit(1);
145
- }
146
-
147
- // Build chart info
148
- const chartInfo: ChartInfo = {
149
- name: args.name,
150
- chartName: args.chart ?? args.name,
151
- repoUrl: args.repo,
152
- version: args.version,
153
- };
154
-
155
- // Generate interface name from chart name if not provided
156
- const interfaceName =
157
- args.interface ?? `${toPascalCase(args.name)}HelmValues`;
158
-
159
- console.error(
160
- `Fetching chart: ${chartInfo.chartName}@${chartInfo.version}`,
161
- );
162
- console.error(`Repository: ${chartInfo.repoUrl}`);
163
- console.error("");
164
-
165
- // Fetch chart
166
- const { values, schema, yamlComments } = await fetchHelmChart(chartInfo);
167
-
168
- console.error("");
169
- console.error(`Converting to TypeScript interface: ${interfaceName}`);
170
-
171
- // Convert to TypeScript interface
172
- const tsInterface = convertToTypeScriptInterface({
173
- values,
174
- interfaceName,
175
- schema,
176
- yamlComments,
177
- chartName: args.name,
178
- });
179
-
180
- // Generate TypeScript code
181
- const code = generateTypeScriptCode(tsInterface, args.name);
182
-
183
- // Write to file or stdout
184
- if (args.output != null && args.output !== "") {
185
- await Bun.write(args.output, code);
186
- console.error("");
187
- console.error(`✅ Types written to: ${args.output}`);
188
- } else {
189
- // Write to stdout (so it can be piped)
190
- console.log(code);
191
- }
192
-
193
- process.exit(0);
194
- } catch (error) {
195
- const parseResult = ErrorSchema.safeParse(error);
196
- if (parseResult.success) {
197
- console.error(`Error: ${parseResult.data.message}`);
198
- } else {
199
- console.error(`Error: ${String(error)}`);
200
- }
201
- process.exit(1);
202
- }
203
- }
204
-
205
- /**
206
- * Convert a string to PascalCase
207
- */
208
- export function toPascalCase(str: string): string {
209
- return str
210
- .split(/[-_\s]+/)
211
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
212
- .join("");
213
- }
214
-
215
- if (import.meta.main) {
216
- void main();
217
- }
@@ -1,180 +0,0 @@
1
- /**
2
- * Check if a line looks like an example/code block rather than documentation
3
- */
4
- function isExampleLine(line: string): boolean {
5
- return (
6
- /^-{3,}/.test(line) ||
7
- /^BEGIN .*(?:KEY|CERTIFICATE)/.test(line) ||
8
- /^END .*(?:KEY|CERTIFICATE)/.test(line) ||
9
- (line.startsWith("-") && (line.includes(":") || /^-\s+\|/.test(line))) ||
10
- /^\w+:$/.test(line) ||
11
- /^[\w-]+:\s*$/.test(line) ||
12
- /^[\w.-]+:\s*\|/.test(line) || // YAML multiline indicator (e.g., "policy.csv: |")
13
- line.startsWith("|") ||
14
- line.includes("$ARGOCD_") ||
15
- line.includes("$KUBE_") ||
16
- /^\s{2,}/.test(line) ||
17
- /^echo\s+/.test(line) ||
18
- /^[pg],\s*/.test(line) // Policy rules like "p, role:..." or "g, subject, ..."
19
- );
20
- }
21
-
22
- /**
23
- * Check if a line looks like normal prose (sentence case, punctuation)
24
- */
25
- function looksLikeProse(line: string): boolean {
26
- return (
27
- /^[A-Z][\w\s]+[.!?]$/.test(line) ||
28
- /^[A-Z][\w\s,'"-]+(?::\s*)?$/.test(line) ||
29
- line.startsWith("Ref:") ||
30
- line.startsWith("See:") ||
31
- line.startsWith("http://") ||
32
- line.startsWith("https://")
33
- );
34
- }
35
-
36
- /**
37
- * Strip YAML comment markers from a single line
38
- */
39
- function stripCommentMarkers(line: string): string {
40
- let result = line.replace(/^#+\s*/, "");
41
- result = result.replace(/^--\s*/, "");
42
- result = result.replace(/^##\s*/, "");
43
- return result.trim();
44
- }
45
-
46
- /**
47
- * Clean up YAML comment text for use in JSDoc
48
- */
49
- export function cleanYAMLComment(comment: string): string {
50
- const lines = comment.split("\n").map((line) => stripCommentMarkers(line));
51
-
52
- // Filter and clean lines
53
- const cleaned: string[] = [];
54
- let inCodeBlock = false;
55
-
56
- for (const currentLine of lines) {
57
- if (currentLine.length === 0) {
58
- if (inCodeBlock) {
59
- inCodeBlock = false;
60
- }
61
- continue;
62
- }
63
-
64
- if (currentLine.startsWith("@default")) {
65
- continue;
66
- }
67
-
68
- if (isExampleLine(currentLine)) {
69
- inCodeBlock = true;
70
- continue;
71
- }
72
-
73
- if (inCodeBlock) {
74
- if (looksLikeProse(currentLine)) {
75
- inCodeBlock = false;
76
- } else {
77
- continue;
78
- }
79
- }
80
-
81
- cleaned.push(currentLine);
82
- }
83
-
84
- return cleaned.join("\n").trim();
85
- }
86
-
87
- /**
88
- * Parse YAML comments and associate them with keys
89
- * Exported for testing purposes
90
- */
91
- export function parseYAMLComments(yamlContent: string): Map<string, string> {
92
- const lines = yamlContent.split("\n");
93
- const comments = new Map<string, string>();
94
- let pendingComments: { text: string; indent: number }[] = [];
95
- const indentStack: { indent: number; key: string }[] = [];
96
-
97
- for (const line of lines) {
98
- const currentLine = line;
99
- const trimmed = currentLine.trim();
100
-
101
- // Skip empty lines
102
- if (!trimmed) {
103
- // Empty lines break comment association only if we already have comments
104
- // This allows comments separated by blank lines to still be associated
105
- continue;
106
- }
107
-
108
- // Check if line is a comment
109
- if (trimmed.startsWith("#")) {
110
- const comment = trimmed.slice(1).trim();
111
- if (comment) {
112
- // Track the indentation level of the comment
113
- const commentIndent = currentLine.search(/\S/);
114
- pendingComments.push({ text: comment, indent: commentIndent });
115
- }
116
- continue;
117
- }
118
-
119
- // Check if line has a key
120
- const keyMatch = /^(\s*)([\w-]+)\s*:/.exec(currentLine);
121
- if (keyMatch) {
122
- const indent = keyMatch[1]?.length ?? 0;
123
- const key = keyMatch[2];
124
- if (key === "" || key == null) {
125
- continue;
126
- }
127
-
128
- // Update indent stack
129
- const lastIndent = indentStack.at(-1);
130
- while (
131
- lastIndent &&
132
- indentStack.length > 0 &&
133
- lastIndent.indent >= indent
134
- ) {
135
- indentStack.pop();
136
- }
137
-
138
- // Build full key path
139
- const keyPath =
140
- indentStack.length > 0
141
- ? `${indentStack.map((s) => s.key).join(".")}.${key}`
142
- : key;
143
-
144
- // Check for inline comment
145
- const inlineCommentMatch = /#\s*(\S.*)$/.exec(currentLine);
146
- if (inlineCommentMatch?.[1] != null && inlineCommentMatch[1] !== "") {
147
- pendingComments.push({ text: inlineCommentMatch[1].trim(), indent });
148
- }
149
-
150
- // Filter pending comments to only those at the same or shallower indent level as this key
151
- // This prevents comments from deeper nested properties being associated with a shallower property
152
- const relevantComments = pendingComments.filter(
153
- (c) => c.indent <= indent,
154
- );
155
-
156
- // Associate relevant comments with this key
157
- if (relevantComments.length > 0) {
158
- // Join and clean comments
159
- const commentText = cleanYAMLComment(
160
- relevantComments.map((c) => c.text).join("\n"),
161
- );
162
- if (commentText) {
163
- comments.set(keyPath, commentText);
164
- }
165
- }
166
-
167
- // Clear pending comments after processing
168
- pendingComments = [];
169
-
170
- // Add to indent stack
171
- indentStack.push({ indent, key });
172
- } else {
173
- // If we encounter a non-comment, non-key line, clear pending comments
174
- // This handles list items and other YAML structures
175
- pendingComments = [];
176
- }
177
- }
178
-
179
- return comments;
180
- }
package/src/config.ts DELETED
@@ -1,195 +0,0 @@
1
- /**
2
- * Well-known Kubernetes fields whose shape is defined by the Kubernetes API,
3
- * not by whatever subset a chart's values.yaml happens to set as defaults.
4
- *
5
- * Inferring these from defaults produces types that are too narrow — e.g. a
6
- * chart defaulting `resources: {requests: {cpu: 0.2}}` would otherwise forbid
7
- * setting a memory request at all. When a property matches one of these names
8
- * AND its default value has a compatible shape, the canonical permissive type
9
- * is emitted instead of a defaults-derived interface.
10
- */
11
- const K8S_WELL_KNOWN_FIELDS: Record<
12
- string,
13
- { type: string; allowedShapes: ("object" | "array")[]; description: string }
14
- > = {
15
- resources: {
16
- type: "{ requests?: Record<string, string | number>; limits?: Record<string, string | number> }",
17
- // RBAC rules also use a key named `resources`, but as an array of strings —
18
- // the object guard keeps those out.
19
- allowedShapes: ["object"],
20
- description:
21
- "Kubernetes container resources (standard ResourceRequirements: arbitrary resource names, string or numeric quantities)",
22
- },
23
- nodeselector: {
24
- type: "Record<string, string>",
25
- allowedShapes: ["object"],
26
- description: "Kubernetes nodeSelector (arbitrary label key/value pairs)",
27
- },
28
- tolerations: {
29
- type: "unknown[]",
30
- allowedShapes: ["array"],
31
- description: "Kubernetes tolerations (standard Toleration objects)",
32
- },
33
- affinity: {
34
- type: "Record<string, unknown>",
35
- allowedShapes: ["object"],
36
- description: "Kubernetes affinity (standard Affinity object)",
37
- },
38
- };
39
-
40
- /**
41
- * Return the canonical type for a well-known Kubernetes field, or undefined if
42
- * the property name doesn't match or the default value's shape is incompatible
43
- * (e.g. an RBAC `resources: ["secrets"]` array, which must NOT become
44
- * ResourceRequirements).
45
- */
46
- export function getWellKnownK8sFieldType(
47
- propertyName: string,
48
- value: unknown,
49
- ): { type: string; description: string } | undefined {
50
- const field = K8S_WELL_KNOWN_FIELDS[propertyName.toLowerCase()];
51
- if (!field) {
52
- return undefined;
53
- }
54
- // A null/undefined default carries no shape signal — trust the name.
55
- if (value != null) {
56
- const shape: "object" | "array" | "primitive" = Array.isArray(value)
57
- ? "array"
58
- : typeof value === "object"
59
- ? "object"
60
- : "primitive";
61
- if (shape === "primitive" || !field.allowedShapes.includes(shape)) {
62
- return undefined;
63
- }
64
- }
65
- return { type: field.type, description: field.description };
66
- }
67
-
68
- /**
69
- * Configuration for types that should allow arbitrary additional properties.
70
- * Maps chart names to array of key paths that should be extensible.
71
- *
72
- * These are typically config maps, RBAC policies, or other key-value stores
73
- * where the schema doesn't enumerate all possible keys.
74
- */
75
- export const EXTENSIBLE_TYPE_PATTERNS: Record<string, string[]> = {
76
- "argo-cd": [
77
- "configs.cm", // Allows accounts.*, and other custom config
78
- "configs.rbac", // Allows policy.*, custom RBAC rules
79
- ],
80
- "kube-prometheus-stack": [
81
- "grafana", // Allows "grafana.ini" and other quoted config keys
82
- "grafana.deploymentStrategy", // Allows Kubernetes Deployment strategy objects with flexible fields
83
- "alertmanager.config.receivers", // Allows receiver-specific config blocks on array elements
84
- "prometheus-node-exporter", // Allows extraHostVolumeMounts and other node exporter specific configs
85
- "prometheusNodeExporter", // Also support camelCase variant
86
- ],
87
- loki: [
88
- "loki.limits_config", // Allows retention_period and other limit configs (note: underscore, not camelCase)
89
- "loki.limitsConfig", // Also support camelCase variant
90
- "compactor", // Allows various compactor settings
91
- "minio.persistence", // Storage configs
92
- ],
93
- minecraft: [
94
- "persistence", // Storage class and other persistence options
95
- ],
96
- openebs: [
97
- "zfs-localpv", // ZFS-specific configs
98
- ],
99
- "postgres-operator": [
100
- "configGeneral", // General config allows various settings
101
- ],
102
- chartmuseum: [
103
- "persistence", // Storage options
104
- ],
105
- "intel-device-plugins-operator": [
106
- // Root level for device-specific settings
107
- "",
108
- ],
109
- "prometheus-adapter": [
110
- "rules", // Allows resource, custom, external and other rule configurations
111
- ],
112
- velero: [
113
- "kubectl.image", // Allows image configuration
114
- ],
115
- seaweedfs: [
116
- "volume.dataDirs", // dataDirs elements support size, storageClass when type is persistentVolumeClaim
117
- ],
118
- // OCI charts that document config keys only as commented-out examples in
119
- // values.yaml, so inference from active defaults misses valid keys.
120
- "agent-stack-k8s": [
121
- "config", // config.queue / max-in-flight / empty-job-grace-period / default-checkout-params are valid but not defaulted
122
- ],
123
- };
124
-
125
- /**
126
- * Pattern-based detection for extensible types.
127
- * Returns true if the property should allow arbitrary keys.
128
- */
129
- export function shouldAllowArbitraryProps(
130
- keyPath: string,
131
- chartName: string,
132
- propertyName: string,
133
- yamlComment?: string,
134
- ): boolean {
135
- // Check configured patterns for this chart
136
- const patterns = EXTENSIBLE_TYPE_PATTERNS[chartName];
137
- if (patterns) {
138
- for (const pattern of patterns) {
139
- if (
140
- pattern === keyPath ||
141
- (pattern === "" && keyPath.split(".").length === 1)
142
- ) {
143
- return true;
144
- }
145
- // Also match if keyPath starts with pattern
146
- if (pattern && keyPath.startsWith(`${pattern}.`)) {
147
- return true;
148
- }
149
- }
150
- }
151
-
152
- // Pattern-based detection from property names
153
- const lowerProp = propertyName.toLowerCase();
154
- const lowerPath = keyPath.toLowerCase();
155
-
156
- // Common names that suggest extensibility
157
- const extensibleNames = [
158
- "cm", // ConfigMap data
159
- "data",
160
- "config",
161
- "configs",
162
- "settings",
163
- "parameters",
164
- "options",
165
- "extraenv",
166
- "annotations",
167
- "labels",
168
- "nodeaffinity",
169
- "toleration",
170
- ];
171
-
172
- if (extensibleNames.includes(lowerProp)) {
173
- return true;
174
- }
175
-
176
- // Check for persistence/storage which often has provider-specific fields
177
- if (lowerPath.includes("persistence") || lowerPath.includes("storage")) {
178
- return true;
179
- }
180
-
181
- // Check YAML comments for hints
182
- if (yamlComment !== "" && yamlComment != null) {
183
- const commentLower = yamlComment.toLowerCase();
184
- if (
185
- /\b(?:arbitrary|custom|additional|extra|any)\s+(?:keys?|properties?|fields?|values?)\b/i.test(
186
- commentLower,
187
- ) ||
188
- /\bkey[\s-]?value\s+pairs?\b/i.test(commentLower)
189
- ) {
190
- return true;
191
- }
192
- }
193
-
194
- return false;
195
- }
package/src/index.ts DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * @homelab/helm-types
3
- *
4
- * A library for generating TypeScript types from Helm chart values.
5
- *
6
- * Core functionality:
7
- * - Fetch Helm charts from repositories
8
- * - Parse values.yaml and values.schema.json
9
- * - Generate TypeScript interfaces with JSDoc comments
10
- * - Support for nested objects, arrays, and unions
11
- *
12
- * This is a general-purpose library that can be used with any Helm chart.
13
- * Application-specific logic should be kept in your application code.
14
- *
15
- * Import directly from submodules:
16
- * - ./types.ts - Core types (ChartInfo, JSONSchemaProperty, TypeScriptInterface, TypeProperty)
17
- * - ./schemas.ts - Zod schemas (HelmValueSchema, StringSchema, etc.)
18
- * - ./config.ts - Configuration (EXTENSIBLE_TYPE_PATTERNS, shouldAllowArbitraryProps)
19
- * - ./chart-info-parser.ts - Chart info parsing (parseChartInfoFromVersions)
20
- * - ./yaml-comments.ts - YAML comments (cleanYAMLComment, parseYAMLComments)
21
- * - ./chart-fetcher.ts - Chart fetching (fetchHelmChart)
22
- * - ./type-converter.ts - Type conversion (jsonSchemaToTypeScript, inferTypeFromValue, etc.)
23
- * - ./interface-generator.ts - Code generation (generateTypeScriptCode)
24
- * - ./utils.ts - Utilities (sanitizePropertyName, sanitizeTypeName, capitalizeFirst)
25
- */
26
-
27
- /** Version marker for the helm-types package. */
28
- export const HELM_TYPES_PACKAGE_VERSION = "1.1.0";