timonel 2.14.0-beta.1 → 3.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.
@@ -15,8 +15,16 @@ export function isValidDisruptionBudget(budget) {
15
15
  return nodePattern.test(budget.nodes);
16
16
  }
17
17
  export function isValidKubernetesDuration(duration) {
18
- const durationPattern = /^(\d+h)?(\d+m)?(\d+s)?$/;
19
- return durationPattern.test(duration) && duration.length > 0;
18
+ try {
19
+ if (typeof duration !== 'string') {
20
+ return false;
21
+ }
22
+ const durationPattern = /^(\d+h)?(\d+m)?(\d+s)?$/;
23
+ return durationPattern.test(duration) && duration.length > 0;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
20
28
  }
21
29
  export const DEFAULT_TERMINATION_GRACE_PERIOD = '30s';
22
30
  export class KarpenterResources extends BaseResourceProvider {
@@ -121,9 +129,15 @@ export class KarpenterResources extends BaseResourceProvider {
121
129
  nodePoolConfig['weight'] = spec.weight;
122
130
  }
123
131
  if (spec.labels) {
132
+ if (typeof spec.labels !== 'object' || Array.isArray(spec.labels)) {
133
+ throw new Error('Labels must be a valid object');
134
+ }
124
135
  nodePoolConfig['labels'] = spec.labels;
125
136
  }
126
137
  if (spec.annotations) {
138
+ if (typeof spec.annotations !== 'object' || Array.isArray(spec.annotations)) {
139
+ throw new Error('Annotations must be a valid object');
140
+ }
127
141
  nodePoolConfig['annotations'] = spec.annotations;
128
142
  }
129
143
  return this.addKarpenterNodePool(nodePoolConfig);
@@ -6,7 +6,7 @@ import { AWSResources } from './resources/cloud/aws/awsResources.js';
6
6
  import { createLogger } from './utils/logger.js';
7
7
  import { KarpenterResources } from './resources/cloud/aws/karpenterResources.js';
8
8
  import { isHelmExpression, isHelmConstruct } from './utils/helmControlStructures.js';
9
- import { dumpHelmAwareYaml } from './utils/helmYamlSerializer.js';
9
+ import { dumpHelmAwareYaml, preprocessHelmConstructs } from './utils/helmYamlSerializer.js';
10
10
  import { generateHelpersTemplate } from './utils/helmHelpers.js';
11
11
  export class Rutter {
12
12
  constructor(props) {
@@ -77,11 +77,12 @@ export class Rutter {
77
77
  throw new Error('addManifest() requires either a YAML string or an object');
78
78
  }
79
79
  this.validateManifestStructure(manifestObject);
80
+ const preprocessedManifest = preprocessHelmConstructs(manifestObject);
80
81
  const apiObjectProps = {
81
- apiVersion: manifestObject.apiVersion,
82
- kind: manifestObject.kind,
83
- metadata: manifestObject.metadata,
84
- ...manifestObject,
82
+ apiVersion: preprocessedManifest.apiVersion,
83
+ kind: preprocessedManifest.kind,
84
+ metadata: preprocessedManifest.metadata,
85
+ ...preprocessedManifest,
85
86
  };
86
87
  return new ApiObject(this.chart, id, apiObjectProps);
87
88
  }
@@ -217,8 +218,9 @@ ${yamlContent.trim()}
217
218
  operation: 'manifest_processing',
218
219
  });
219
220
  const enriched = manifestObjs.map((obj) => {
220
- if (obj && typeof obj === 'object') {
221
- const o = obj;
221
+ const preprocessed = preprocessHelmConstructs(obj);
222
+ if (preprocessed && typeof preprocessed === 'object') {
223
+ const o = preprocessed;
222
224
  o.metadata = o.metadata ?? {};
223
225
  o.metadata.labels = o.metadata.labels ?? {};
224
226
  const labels = o.metadata.labels;
@@ -236,7 +238,7 @@ ${yamlContent.trim()}
236
238
  }
237
239
  }
238
240
  }
239
- return obj;
241
+ return preprocessed;
240
242
  });
241
243
  const synthAssets = [];
242
244
  if (this.props.singleManifestFile) {
@@ -84,7 +84,7 @@ export class SecurityUtils {
84
84
  }
85
85
  const sanitized = env.replace(/[^a-zA-Z0-9-_]/g, '');
86
86
  if (sanitized !== env) {
87
- throw new Error(`Invalid environment name: ${this.sanitizeLogMessage(env)}`);
87
+ throw new Error(`Invalid environment name: ${SecurityUtils.sanitizeLogMessage(env)}`);
88
88
  }
89
89
  if (sanitized.length === 0 || sanitized.length > 63) {
90
90
  throw new Error('Environment name must be 1-63 characters long');
@@ -150,7 +150,7 @@ export class SecurityUtils {
150
150
  }
151
151
  const nameRegex = /^[A-Z_][A-Z0-9_]*$/;
152
152
  if (!nameRegex.test(sanitizedName)) {
153
- throw new Error(`Invalid environment variable name: ${this.sanitizeLogMessage(name)}`);
153
+ throw new Error(`Invalid environment variable name: ${SecurityUtils.sanitizeLogMessage(name)}`);
154
154
  }
155
155
  const hasDangerousPattern = (val) => {
156
156
  if (val.includes('$(') && val.includes(')'))
@@ -173,7 +173,7 @@ export class SecurityUtils {
173
173
  };
174
174
  const dangerousPattern = hasDangerousPattern(value);
175
175
  if (dangerousPattern) {
176
- throw new Error(`Environment variable value contains dangerous pattern (${dangerousPattern}): ${this.sanitizeLogMessage(value)}`);
176
+ throw new Error(`Environment variable value contains dangerous pattern (${dangerousPattern}): ${SecurityUtils.sanitizeLogMessage(value)}`);
177
177
  }
178
178
  if (value.length > 32768) {
179
179
  throw new Error('Environment variable value exceeds maximum length (32KB)');
@@ -194,7 +194,7 @@ export class SecurityUtils {
194
194
  }
195
195
  const tagRegex = /^[a-zA-Z0-9._-]+$/;
196
196
  if (!tagRegex.test(trimmedTag)) {
197
- throw new Error(`Invalid image tag format: ${this.sanitizeLogMessage(trimmedTag)}`);
197
+ throw new Error(`Invalid image tag format: ${SecurityUtils.sanitizeLogMessage(trimmedTag)}`);
198
198
  }
199
199
  if (trimmedTag.length > 128) {
200
200
  throw new Error('Image tag exceeds maximum length (128 characters)');
@@ -1,6 +1,7 @@
1
1
  import { writeFileSync, mkdirSync, existsSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { Chart } from 'cdk8s';
4
+ import { SecurityUtils } from '../security.js';
4
5
  import { dumpHelmAwareYaml } from '../utils/helmYamlSerializer.js';
5
6
  import { generateHelpersTemplate } from '../utils/helmHelpers.js';
6
7
  export class FlexibleSubchart extends Chart {
@@ -51,13 +52,19 @@ export class FlexibleSubchart extends Chart {
51
52
  version: this.config.version || '1.0.0',
52
53
  appVersion: this.config.version || '1.0.0',
53
54
  };
54
- writeFileSync(join(outputDir, 'Chart.yaml'), dumpHelmAwareYaml(subchartYaml));
55
+ const chartYamlPath = SecurityUtils.validatePath(join(outputDir, 'Chart.yaml'), process.cwd(), {
56
+ allowAbsolute: true,
57
+ });
58
+ writeFileSync(chartYamlPath, dumpHelmAwareYaml(subchartYaml));
55
59
  const subchartValues = {
56
60
  enabled: true,
57
61
  ...Object.fromEntries(Object.entries(this.config).filter(([key, value]) => key !== 'chart' && typeof value !== 'function' && value !== null && value !== undefined)),
58
62
  };
59
- writeFileSync(join(outputDir, 'values.yaml'), dumpHelmAwareYaml(subchartValues));
60
- const templatesDir = join(outputDir, 'templates');
63
+ const valuesYamlPath = SecurityUtils.validatePath(join(outputDir, 'values.yaml'), process.cwd(), { allowAbsolute: true });
64
+ writeFileSync(valuesYamlPath, dumpHelmAwareYaml(subchartValues));
65
+ const templatesDir = SecurityUtils.validatePath(join(outputDir, 'templates'), process.cwd(), {
66
+ allowAbsolute: true,
67
+ });
61
68
  if (!existsSync(templatesDir)) {
62
69
  mkdirSync(templatesDir, { recursive: true });
63
70
  }
@@ -65,13 +72,15 @@ export class FlexibleSubchart extends Chart {
65
72
  includeKubernetes: true,
66
73
  includeSprig: true,
67
74
  });
68
- writeFileSync(join(templatesDir, '_helpers.tpl'), helpersTpl);
75
+ const helpersTplPath = SecurityUtils.validatePath(join(templatesDir, '_helpers.tpl'), process.cwd(), { allowAbsolute: true });
76
+ writeFileSync(helpersTplPath, helpersTpl);
69
77
  this._manifests.forEach((item) => {
70
78
  if (item && typeof item === 'object' && 'manifest' in item && 'id' in item) {
71
79
  const { manifest, id } = item;
72
80
  if (manifest && typeof manifest === 'object') {
73
81
  const templateContent = this._generateManifestTemplate(manifest, id);
74
- writeFileSync(join(templatesDir, `${id}.yaml`), templateContent);
82
+ const manifestPath = SecurityUtils.validatePath(join(templatesDir, `${id}.yaml`), process.cwd(), { allowAbsolute: true });
83
+ writeFileSync(manifestPath, templateContent);
75
84
  }
76
85
  }
77
86
  });
@@ -2,6 +2,7 @@ import { writeFileSync, mkdirSync, existsSync, copyFileSync, readdirSync, rmSync
2
2
  import { join } from 'path';
3
3
  import { parse } from 'yaml';
4
4
  import { App, Chart, ApiObject } from 'cdk8s';
5
+ import { SecurityUtils } from '../security.js';
5
6
  import { dumpHelmAwareYaml } from '../utils/helmYamlSerializer.js';
6
7
  import { generateHelpersTemplate } from '../utils/helmHelpers.js';
7
8
  import { createFlexibleSubchart } from './flexible-subchart.js';
@@ -227,10 +228,12 @@ export class UmbrellaChartTemplate extends Chart {
227
228
  else if (subchart.chart && typeof subchart.chart === 'object') {
228
229
  this._handleObjectChart(subchart, flexibleSubchart);
229
230
  }
230
- console.log(`Added flexible subchart: ${subchart.name}`);
231
+ const sanitizedName = subchart.name.replace(/[\r\n]/g, '');
232
+ console.log(`Added flexible subchart: ${sanitizedName}`);
231
233
  }
232
234
  catch (_error) {
233
- console.warn(`Failed to add subchart ${subchart.name}:`, _error);
235
+ const sanitizedName = subchart.name.replace(/[\r\n]/g, '');
236
+ console.warn(`Failed to add subchart ${sanitizedName}:`, _error);
234
237
  this._createFallbackSubchart(subchart, index);
235
238
  }
236
239
  }
@@ -249,7 +252,8 @@ export class UmbrellaChartTemplate extends Chart {
249
252
  version: subchart.version || '1.0.0',
250
253
  description: `${subchart.name} subchart (fallback)`,
251
254
  });
252
- console.log(`Created fallback subchart: ${subchart.name}`);
255
+ const sanitizedName = subchart.name.replace(/[\r\n]/g, '');
256
+ console.log(`Created fallback subchart: ${sanitizedName}`);
253
257
  }
254
258
  _handleFunctionChart(subchart, index, flexibleSubchart) {
255
259
  try {
@@ -263,7 +267,8 @@ export class UmbrellaChartTemplate extends Chart {
263
267
  }
264
268
  }
265
269
  catch (error) {
266
- console.log(`Failed to process subchart ${subchart.name}:`, error);
270
+ const sanitizedName = subchart.name.replace(/[\r\n]/g, '');
271
+ console.log(`Failed to process subchart ${sanitizedName}:`, error);
267
272
  }
268
273
  }
269
274
  _handleObjectChart(subchart, flexibleSubchart) {
@@ -338,7 +343,8 @@ export class UmbrellaChartTemplate extends Chart {
338
343
  }
339
344
  }
340
345
  catch (error) {
341
- console.log(`Failed to parse asset ${asset.id}:`, error);
346
+ const sanitizedId = asset.id.replace(/[\r\n]/g, '');
347
+ console.log(`Failed to parse asset ${sanitizedId}:`, error);
342
348
  }
343
349
  });
344
350
  }
@@ -375,7 +381,8 @@ export class UmbrellaChartTemplate extends Chart {
375
381
  includeSprig: true,
376
382
  });
377
383
  writeFileSync(join(templatesDir, '_helpers.tpl'), helpersTpl);
378
- console.log(`Created basic Helm chart structure for subchart: ${subchartName}`);
384
+ const sanitizedName = subchartName.replace(/[\r\n]/g, '');
385
+ console.log(`Created basic Helm chart structure for subchart: ${sanitizedName}`);
379
386
  }
380
387
  writeHelmChart(outputDir) {
381
388
  if (!existsSync(outputDir)) {
@@ -412,7 +419,7 @@ export class UmbrellaChartTemplate extends Chart {
412
419
  mkdirSync(chartsDir, { recursive: true });
413
420
  }
414
421
  this.config.subcharts?.forEach((subchart) => {
415
- const subchartDir = join(chartsDir, subchart.name);
422
+ const subchartDir = SecurityUtils.validatePath(join(chartsDir, subchart.name), process.cwd(), { allowAbsolute: true });
416
423
  if (!existsSync(subchartDir)) {
417
424
  mkdirSync(subchartDir, { recursive: true });
418
425
  }
@@ -444,7 +451,8 @@ export class UmbrellaChartTemplate extends Chart {
444
451
  }
445
452
  }
446
453
  catch (fallbackError) {
447
- console.warn(`Failed to create subchart ${subchart.name}:`, fallbackError);
454
+ const sanitizedName = subchart.name.replace(/[\r\n]/g, '');
455
+ console.warn(`Failed to create subchart ${sanitizedName}:`, fallbackError);
448
456
  flexibleSubchart.writeHelmChart(subchartDir);
449
457
  }
450
458
  }
@@ -462,7 +470,9 @@ export class UmbrellaChartTemplate extends Chart {
462
470
  flexibleSubchart.writeHelmChart(subchartDir);
463
471
  }
464
472
  });
465
- const templatesDir = join(outputDir, 'templates');
473
+ const templatesDir = SecurityUtils.validatePath(join(outputDir, 'templates'), process.cwd(), {
474
+ allowAbsolute: true,
475
+ });
466
476
  if (!existsSync(templatesDir)) {
467
477
  mkdirSync(templatesDir, { recursive: true });
468
478
  }
@@ -479,7 +489,8 @@ export class UmbrellaChartTemplate extends Chart {
479
489
  },
480
490
  },
481
491
  };
482
- writeFileSync(join(templatesDir, 'namespace.yaml'), dumpHelmAwareYaml(namespaceYaml));
492
+ const namespaceYamlPath = SecurityUtils.validatePath(join(templatesDir, 'namespace.yaml'), process.cwd(), { allowAbsolute: true });
493
+ writeFileSync(namespaceYamlPath, dumpHelmAwareYaml(namespaceYaml));
483
494
  const helpersTpl = generateHelpersTemplate('aws', undefined, {
484
495
  includeKubernetes: true,
485
496
  includeSprig: true,
@@ -27,19 +27,24 @@ export class UmbrellaRutter {
27
27
  allowAbsolute: true,
28
28
  });
29
29
  mkdirSync(validatedOutDir, { recursive: true });
30
- mkdirSync(join(validatedOutDir, 'charts'), { recursive: true });
30
+ const chartsDir = SecurityUtils.validatePath(join(validatedOutDir, 'charts'), process.cwd(), {
31
+ allowAbsolute: true,
32
+ });
33
+ mkdirSync(chartsDir, { recursive: true });
31
34
  for (const subchart of this.props.subcharts) {
32
35
  if (!SecurityUtils.isValidSubchartName(subchart.name)) {
33
36
  throw new Error(`Invalid subchart name: ${SecurityUtils.sanitizeLogMessage(subchart.name)}`);
34
37
  }
35
38
  const sanitizedName = subchart.name;
36
- const subchartDir = join(validatedOutDir, 'charts', sanitizedName);
39
+ const subchartDir = SecurityUtils.validatePath(join(validatedOutDir, 'charts', sanitizedName), process.cwd(), { allowAbsolute: true });
37
40
  subchart.rutter.write(subchartDir);
38
41
  }
39
42
  this.writeParentChart(validatedOutDir);
40
43
  this.writeParentValues(validatedOutDir);
41
- mkdirSync(join(validatedOutDir, 'templates'), { recursive: true });
42
- writeFileSync(join(validatedOutDir, 'templates', 'NOTES.txt'), this.generateNotesTemplate());
44
+ const templatesDir = SecurityUtils.validatePath(join(validatedOutDir, 'templates'), process.cwd(), { allowAbsolute: true });
45
+ mkdirSync(templatesDir, { recursive: true });
46
+ const notesPath = SecurityUtils.validatePath(join(validatedOutDir, 'templates', 'NOTES.txt'), process.cwd(), { allowAbsolute: true });
47
+ writeFileSync(notesPath, this.generateNotesTemplate());
43
48
  }
44
49
  writeParentChart(outDir) {
45
50
  const chartYaml = {
@@ -63,7 +68,10 @@ export class UmbrellaRutter {
63
68
  };
64
69
  }),
65
70
  };
66
- writeFileSync(join(outDir, 'Chart.yaml'), dumpHelmAwareYaml(chartYaml));
71
+ const chartYamlPath = SecurityUtils.validatePath(join(outDir, 'Chart.yaml'), process.cwd(), {
72
+ allowAbsolute: true,
73
+ });
74
+ writeFileSync(chartYamlPath, dumpHelmAwareYaml(chartYaml));
67
75
  }
68
76
  writeParentValues(outDir) {
69
77
  const values = {
@@ -77,12 +85,16 @@ export class UmbrellaRutter {
77
85
  };
78
86
  }
79
87
  }
80
- writeFileSync(join(outDir, 'values.yaml'), dumpHelmAwareYaml(values));
88
+ const valuesYamlPath = SecurityUtils.validatePath(join(outDir, 'values.yaml'), process.cwd(), {
89
+ allowAbsolute: true,
90
+ });
91
+ writeFileSync(valuesYamlPath, dumpHelmAwareYaml(values));
81
92
  if (this.props.envValues) {
82
93
  for (const [env, envVals] of Object.entries(this.props.envValues)) {
83
94
  const sanitizedEnv = SecurityUtils.sanitizeEnvironmentName(env);
84
95
  const envValues = this.deepMerge(values, envVals);
85
- writeFileSync(join(outDir, `values-${sanitizedEnv}.yaml`), dumpHelmAwareYaml(envValues));
96
+ const envValuesPath = SecurityUtils.validatePath(join(outDir, `values-${sanitizedEnv}.yaml`), process.cwd(), { allowAbsolute: true });
97
+ writeFileSync(envValuesPath, dumpHelmAwareYaml(envValues));
86
98
  }
87
99
  }
88
100
  }
@@ -0,0 +1,19 @@
1
+ export interface EnvVarConfig {
2
+ name: string;
3
+ type: 'value' | 'secret';
4
+ scope?: string;
5
+ defaultValue?: string;
6
+ secretName?: string;
7
+ }
8
+ export interface LoadEnvVarsOptions {
9
+ configPath?: string;
10
+ defaultScope?: string;
11
+ fallbackConfig?: EnvVarConfig[];
12
+ }
13
+ export declare function loadEnvVarsConfig(options?: LoadEnvVarsOptions): EnvVarConfig[];
14
+ export declare function generateEnvVars(config: EnvVarConfig[], options?: {
15
+ defaultScope?: string;
16
+ }): Array<Record<string, unknown>>;
17
+ export declare function loadAndGenerateEnvVars(options?: LoadEnvVarsOptions & {
18
+ defaultScope?: string;
19
+ }): Array<Record<string, unknown>>;
@@ -0,0 +1,63 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import { SecurityUtils } from '../security.js';
5
+ import { createHelmExpression } from './helmControlStructures.js';
6
+ export function loadEnvVarsConfig(options = {}) {
7
+ const { configPath, fallbackConfig = [] } = options;
8
+ try {
9
+ if (configPath) {
10
+ const validatedConfigPath = SecurityUtils.validatePath(configPath, process.cwd(), {
11
+ allowAbsolute: true,
12
+ });
13
+ if (existsSync(validatedConfigPath)) {
14
+ const data = readFileSync(validatedConfigPath, 'utf-8');
15
+ return validatedConfigPath.endsWith('.yaml') || validatedConfigPath.endsWith('.yml')
16
+ ? parseYaml(data)
17
+ : JSON.parse(data);
18
+ }
19
+ }
20
+ const yamlPath = SecurityUtils.validatePath(join(process.cwd(), 'env-config.yaml'), process.cwd(), { allowAbsolute: true });
21
+ if (existsSync(yamlPath)) {
22
+ const data = readFileSync(yamlPath, 'utf-8');
23
+ return parseYaml(data);
24
+ }
25
+ const jsonPath = SecurityUtils.validatePath(join(process.cwd(), 'env-config.json'), process.cwd(), { allowAbsolute: true });
26
+ if (existsSync(jsonPath)) {
27
+ const data = readFileSync(jsonPath, 'utf-8');
28
+ return JSON.parse(data);
29
+ }
30
+ }
31
+ catch {
32
+ }
33
+ return fallbackConfig;
34
+ }
35
+ export function generateEnvVars(config, options = {}) {
36
+ const { defaultScope = 'global.env' } = options;
37
+ return config.map((item) => {
38
+ const scope = item.scope || defaultScope;
39
+ if (item.type === 'value') {
40
+ return {
41
+ name: item.name,
42
+ value: createHelmExpression(`{{ .Values.${scope}.${item.name} | default "${item.defaultValue || ''}" }}`),
43
+ };
44
+ }
45
+ else {
46
+ return {
47
+ name: item.name,
48
+ valueFrom: {
49
+ secretKeyRef: {
50
+ name: item.secretName || createHelmExpression('{{ .Values.secretName }}'),
51
+ key: item.name,
52
+ optional: true,
53
+ },
54
+ },
55
+ };
56
+ }
57
+ });
58
+ }
59
+ export function loadAndGenerateEnvVars(options = {}) {
60
+ const config = loadEnvVarsConfig(options);
61
+ const genOptions = options.defaultScope ? { defaultScope: options.defaultScope } : {};
62
+ return generateEnvVars(config, genOptions);
63
+ }
@@ -1,11 +1,8 @@
1
1
  export interface HelmConstruct {
2
2
  __helmConstruct: true;
3
- type: 'if' | 'range' | 'with' | 'include' | 'define' | 'var' | 'block' | 'comment' | 'fragment';
3
+ type: 'if' | 'range' | 'with' | 'include' | 'define' | 'var' | 'block' | 'comment' | 'fragment' | 'fieldConditional';
4
4
  data: unknown;
5
- options?: {
6
- trimLeft?: boolean;
7
- trimRight?: boolean;
8
- };
5
+ options?: HelmWhitespaceOptions;
9
6
  }
10
7
  export declare function helmFragment(...contents: HelmContent[]): HelmConstruct;
11
8
  export interface HelmExpression {
@@ -29,6 +26,8 @@ export type HelmContent = string | number | boolean | null | undefined | HelmCon
29
26
  export interface HelmWhitespaceOptions {
30
27
  trimLeft?: boolean;
31
28
  trimRight?: boolean;
29
+ inline?: boolean;
32
30
  }
33
31
  export declare function helmIf(condition: string, thenContent: HelmContent, elseContent?: HelmContent, options?: HelmWhitespaceOptions): HelmConstruct;
32
+ export declare function helmIfSimple(condition: string, thenContent: HelmContent, options?: HelmWhitespaceOptions): HelmConstruct;
34
33
  export declare function isHelmConstruct(value: unknown): value is HelmConstruct;
@@ -104,6 +104,18 @@ export function helmIf(condition, thenContent, elseContent, options) {
104
104
  ...(options ? { options } : {}),
105
105
  };
106
106
  }
107
+ export function helmIfSimple(condition, thenContent, options) {
108
+ return {
109
+ __helmConstruct: true,
110
+ type: 'if',
111
+ data: {
112
+ condition,
113
+ then: thenContent,
114
+ else: undefined,
115
+ },
116
+ ...(options ? { options } : {}),
117
+ };
118
+ }
107
119
  export function isHelmConstruct(value) {
108
120
  return (typeof value === 'object' &&
109
121
  value !== null &&
@@ -261,12 +261,20 @@ export const AWS_HELPERS = [
261
261
  ];
262
262
  export function formatHelpers(helpers) {
263
263
  return helpers
264
- .map((helper) => `{{/*
264
+ .map((helper) => {
265
+ if (!helper.name || typeof helper.name !== 'string') {
266
+ throw new Error('Helper must have a valid name property');
267
+ }
268
+ if (!helper.template || typeof helper.template !== 'string') {
269
+ throw new Error(`Helper '${helper.name}' must have a valid template property`);
270
+ }
271
+ return `{{/*
265
272
  ${helper.name}
266
273
  */}}
267
274
  {{- define "${helper.name}" -}}
268
275
  ${helper.template}
269
- {{- end }}`)
276
+ {{- end }}`;
277
+ })
270
278
  .join('\n\n');
271
279
  }
272
280
  export function getDefaultHelpers(cloudProvider, options) {
@@ -1,6 +1,8 @@
1
+ export declare function preprocessHelmConstructs(obj: unknown): unknown;
1
2
  export declare function dumpHelmAwareYaml(obj: unknown, options?: {
2
3
  lineWidth?: number;
3
4
  }): string;
5
+ export declare function postProcessFieldConditionals(yaml: string): string;
4
6
  export declare function stringify(obj: unknown, options?: {
5
7
  lineWidth?: number;
6
8
  doubleQuotedAsJSON?: boolean;