@shepherdjerred/helm-types 0.0.0-dev.706
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -0
- package/dist/cli.js +22085 -0
- package/dist/index.js +23 -0
- package/package.json +66 -0
- package/src/chart-fetcher.ts +171 -0
- package/src/chart-info-parser.ts +72 -0
- package/src/cli.ts +215 -0
- package/src/code-generator.ts +226 -0
- package/src/comment-parser.ts +180 -0
- package/src/config.ts +147 -0
- package/src/helm-types.ts +16 -0
- package/src/index.ts +28 -0
- package/src/interface-generator.ts +238 -0
- package/src/reset.d.ts +1 -0
- package/src/schemas.ts +39 -0
- package/src/type-converter-helpers.ts +180 -0
- package/src/type-converter.ts +509 -0
- package/src/type-inference.ts +548 -0
- package/src/types.ts +38 -0
- package/src/utils.ts +76 -0
- package/src/yaml-comment-filters.ts +103 -0
- package/src/yaml-comment-regex-parser.ts +150 -0
- package/src/yaml-comments.ts +507 -0
- package/src/yaml-preprocess.ts +235 -0
|
@@ -0,0 +1,235 @@
|
|
|
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
|
+
/** State for preprocessing YAML comments */
|
|
16
|
+
type PreprocessState = {
|
|
17
|
+
inExampleBlock: boolean;
|
|
18
|
+
inBlockScalar: boolean;
|
|
19
|
+
lastRealKeyIndent: number;
|
|
20
|
+
consecutiveCommentedKeys: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if a line is an "Example:" marker
|
|
25
|
+
*/
|
|
26
|
+
function isExampleMarker(trimmed: string): boolean {
|
|
27
|
+
return /^##?\s*Example:?$/i.test(trimmed);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if an example block should end
|
|
32
|
+
*/
|
|
33
|
+
function shouldExitExampleBlock(trimmed: string): boolean {
|
|
34
|
+
return (
|
|
35
|
+
!trimmed ||
|
|
36
|
+
trimmed.startsWith("For more information") ||
|
|
37
|
+
trimmed.startsWith("Ref:")
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if the previous line had a block scalar indicator
|
|
43
|
+
*/
|
|
44
|
+
function prevLineHasBlockScalar(lines: string[], i: number): boolean {
|
|
45
|
+
if (i <= 0) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const prevTrimmed = lines[i - 1]?.trim() ?? "";
|
|
49
|
+
return /^#+\s*[\w.-]+:\s*[|>]\s*$/.test(prevTrimmed);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Check if a line is still in a block scalar (indented content)
|
|
54
|
+
*/
|
|
55
|
+
function isBlockScalarContent(line: string, trimmed: string): boolean {
|
|
56
|
+
if (trimmed.length === 0) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return (
|
|
60
|
+
line.startsWith(" ") || line.startsWith("\t") || /^#\s{2,}/.test(line)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if a commented key value looks like it should be excluded
|
|
66
|
+
*/
|
|
67
|
+
function isExcludedCommentedKey(keyValue: string): boolean {
|
|
68
|
+
const isDocReference =
|
|
69
|
+
/^ref:/i.test(keyValue) &&
|
|
70
|
+
(keyValue.includes("http://") || keyValue.includes("https://"));
|
|
71
|
+
const isURL =
|
|
72
|
+
keyValue.trim().startsWith("http://") ||
|
|
73
|
+
keyValue.trim().startsWith("https://");
|
|
74
|
+
return isDocReference || isURL;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Determine if a commented key looks like a YAML example based on context
|
|
79
|
+
*/
|
|
80
|
+
function isLikelyExample(lines: string[], i: number): boolean {
|
|
81
|
+
const prevLine = i > 0 ? lines[i - 1] : "";
|
|
82
|
+
const prevTrimmed = prevLine?.trim() ?? "";
|
|
83
|
+
const prevIsCommentedKey = /^#+\s*[\w.-]+:\s/.test(prevTrimmed);
|
|
84
|
+
const prevIsBlank = !prevTrimmed;
|
|
85
|
+
const prevIsListItem =
|
|
86
|
+
prevTrimmed.startsWith("#") && prevTrimmed.slice(1).trim().startsWith("-");
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
(!prevIsBlank && !prevIsCommentedKey && prevTrimmed.startsWith("#")) ||
|
|
90
|
+
prevIsListItem
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Update consecutive commented key count based on context
|
|
96
|
+
*/
|
|
97
|
+
function updateConsecutiveCount(
|
|
98
|
+
lines: string[],
|
|
99
|
+
i: number,
|
|
100
|
+
current: number,
|
|
101
|
+
): number {
|
|
102
|
+
const prevLine = i > 0 ? lines[i - 1] : "";
|
|
103
|
+
const prevTrimmed = prevLine?.trim() ?? "";
|
|
104
|
+
const prevIsCommentedKey = /^#+\s*[\w.-]+:\s/.test(prevTrimmed);
|
|
105
|
+
const prevIsBlank = !prevTrimmed;
|
|
106
|
+
|
|
107
|
+
if (prevIsCommentedKey) {
|
|
108
|
+
return current + 1;
|
|
109
|
+
}
|
|
110
|
+
if (!prevIsBlank) {
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
return current;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Try to uncomment a commented YAML key line. Returns the uncommented line or null.
|
|
118
|
+
*/
|
|
119
|
+
function tryUncommentLine(
|
|
120
|
+
line: string,
|
|
121
|
+
lines: string[],
|
|
122
|
+
i: number,
|
|
123
|
+
state: PreprocessState,
|
|
124
|
+
): { uncommented: string | null; newConsecutive: number } {
|
|
125
|
+
const commentedKeyMatch = /^([ \t]*)#+\s*([\w.-]+:\s*(?:\S.*)?)$/.exec(line);
|
|
126
|
+
if (!commentedKeyMatch) {
|
|
127
|
+
return { uncommented: null, newConsecutive: 0 };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const [, indent, keyValue] = commentedKeyMatch;
|
|
131
|
+
if (keyValue == null || keyValue === "" || indent == null || indent === "") {
|
|
132
|
+
return {
|
|
133
|
+
uncommented: null,
|
|
134
|
+
newConsecutive: state.consecutiveCommentedKeys,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const keyPart = keyValue.split(":")[0]?.trim() ?? "";
|
|
139
|
+
const isValidKey = /^[\w.-]+$/.test(keyPart);
|
|
140
|
+
|
|
141
|
+
if (!isValidKey || isExcludedCommentedKey(keyValue)) {
|
|
142
|
+
return {
|
|
143
|
+
uncommented: null,
|
|
144
|
+
newConsecutive: state.consecutiveCommentedKeys,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const keyIndent = indent.length;
|
|
149
|
+
const newConsecutive = updateConsecutiveCount(
|
|
150
|
+
lines,
|
|
151
|
+
i,
|
|
152
|
+
state.consecutiveCommentedKeys,
|
|
153
|
+
);
|
|
154
|
+
const likelyExampleCtx = isLikelyExample(lines, i);
|
|
155
|
+
|
|
156
|
+
const shouldUncomment =
|
|
157
|
+
!likelyExampleCtx &&
|
|
158
|
+
(state.lastRealKeyIndent === -1 ||
|
|
159
|
+
Math.abs(keyIndent - state.lastRealKeyIndent) <= 4 ||
|
|
160
|
+
newConsecutive >= 2);
|
|
161
|
+
|
|
162
|
+
if (shouldUncomment) {
|
|
163
|
+
return { uncommented: `${indent}${keyValue}`, newConsecutive };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return { uncommented: null, newConsecutive };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function preprocessYAMLComments(yamlContent: string): string {
|
|
170
|
+
const lines = yamlContent.split("\n");
|
|
171
|
+
const processedLines: string[] = [];
|
|
172
|
+
const state: PreprocessState = {
|
|
173
|
+
inExampleBlock: false,
|
|
174
|
+
inBlockScalar: false,
|
|
175
|
+
lastRealKeyIndent: -1,
|
|
176
|
+
consecutiveCommentedKeys: 0,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
for (let i = 0; i < lines.length; i++) {
|
|
180
|
+
const line = lines[i] ?? "";
|
|
181
|
+
const trimmed = line.trim();
|
|
182
|
+
|
|
183
|
+
if (isExampleMarker(trimmed)) {
|
|
184
|
+
state.inExampleBlock = true;
|
|
185
|
+
processedLines.push(line);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (state.inExampleBlock && shouldExitExampleBlock(trimmed)) {
|
|
190
|
+
state.inExampleBlock = false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (prevLineHasBlockScalar(lines, i)) {
|
|
194
|
+
state.inBlockScalar = true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (state.inBlockScalar && !isBlockScalarContent(line, trimmed)) {
|
|
198
|
+
state.inBlockScalar = false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!trimmed.startsWith("#") && /^[\w.-]+:/.test(trimmed)) {
|
|
202
|
+
state.lastRealKeyIndent = line.search(/\S/);
|
|
203
|
+
state.consecutiveCommentedKeys = 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (state.inExampleBlock || state.inBlockScalar) {
|
|
207
|
+
processedLines.push(line);
|
|
208
|
+
state.consecutiveCommentedKeys = 0;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const { uncommented, newConsecutive } = tryUncommentLine(
|
|
213
|
+
line,
|
|
214
|
+
lines,
|
|
215
|
+
i,
|
|
216
|
+
state,
|
|
217
|
+
);
|
|
218
|
+
state.consecutiveCommentedKeys = newConsecutive;
|
|
219
|
+
|
|
220
|
+
if (uncommented != null) {
|
|
221
|
+
processedLines.push(uncommented);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Reset consecutive count if not a commented key
|
|
226
|
+
const isCommentedKey = /^[ \t]*#+\s*[\w.-]+:\s*(?:\S.*)?$/.test(line);
|
|
227
|
+
if (!isCommentedKey) {
|
|
228
|
+
state.consecutiveCommentedKeys = 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
processedLines.push(line);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return processedLines.join("\n");
|
|
235
|
+
}
|