timonel 2.10.2 → 2.12.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 (35) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +8 -54
  3. package/dist/cli.js +65 -52
  4. package/dist/index.d.ts +1 -2
  5. package/dist/index.js +1 -2
  6. package/dist/lib/helmChartWriter.js +17 -2
  7. package/dist/lib/rutter.d.ts +1 -0
  8. package/dist/lib/rutter.js +64 -11
  9. package/dist/lib/templates/flexible-subchart.d.ts +1 -0
  10. package/dist/lib/templates/flexible-subchart.js +101 -0
  11. package/dist/lib/templates/umbrella-chart.d.ts +13 -2
  12. package/dist/lib/templates/umbrella-chart.js +128 -42
  13. package/dist/lib/utils/helmHelpers/envHelpers.d.ts +2 -0
  14. package/dist/lib/utils/helmHelpers/envHelpers.js +97 -0
  15. package/dist/lib/utils/helmHelpers/gitopsHelpers.d.ts +2 -0
  16. package/dist/lib/utils/helmHelpers/gitopsHelpers.js +132 -0
  17. package/dist/lib/utils/helmHelpers/index.d.ts +23 -0
  18. package/dist/lib/utils/helmHelpers/index.js +132 -0
  19. package/dist/lib/utils/helmHelpers/observabilityHelpers.d.ts +2 -0
  20. package/dist/lib/utils/helmHelpers/observabilityHelpers.js +221 -0
  21. package/dist/lib/utils/helmHelpers/types.d.ts +16 -0
  22. package/dist/lib/utils/helmHelpers/types.js +1 -0
  23. package/dist/lib/utils/helmHelpers/validationHelpers.d.ts +2 -0
  24. package/dist/lib/utils/helmHelpers/validationHelpers.js +201 -0
  25. package/dist/lib/utils/helmHelpers.d.ts +11 -1
  26. package/dist/lib/utils/helmHelpers.js +20 -7
  27. package/dist/lib/utils/helmYamlSerializer.d.ts +53 -1
  28. package/dist/lib/utils/helmYamlSerializer.js +325 -29
  29. package/dist/lib/utils/logger.d.ts +49 -0
  30. package/dist/lib/utils/logger.js +418 -0
  31. package/package.json +21 -11
  32. package/dist/lib/templates/basic-chart.d.ts +0 -19
  33. package/dist/lib/templates/basic-chart.js +0 -210
  34. package/dist/lib/templates/subchart.d.ts +0 -27
  35. package/dist/lib/templates/subchart.js +0 -219
@@ -0,0 +1,221 @@
1
+ export const OBSERVABILITY_HELPERS = [
2
+ {
3
+ name: 'monitoring.serviceMonitor',
4
+ template: `{{- if and .Values.serviceMonitor.enabled .Values.metrics.enabled -}}
5
+ apiVersion: monitoring.coreos.com/v1
6
+ kind: ServiceMonitor
7
+ metadata:
8
+ name: {{ include "chart.fullname" . }}
9
+ namespace: {{ .Release.Namespace }}
10
+ labels:
11
+ {{- include "chart.labels" . | nindent 4 }}
12
+ {{- with .Values.serviceMonitor.labels }}
13
+ {{- toYaml . | nindent 4 }}
14
+ {{- end }}
15
+ {{- with .Values.serviceMonitor.annotations }}
16
+ annotations:
17
+ {{- toYaml . | nindent 4 }}
18
+ {{- end }}
19
+ spec:
20
+ selector:
21
+ matchLabels:
22
+ {{- include "chart.selectorLabels" . | nindent 6 }}
23
+ {{- with .Values.serviceMonitor.selector }}
24
+ {{- toYaml . | nindent 6 }}
25
+ {{- end }}
26
+ endpoints:
27
+ - port: {{ .Values.metrics.port | default "metrics" }}
28
+ path: {{ .Values.metrics.path | default "/metrics" }}
29
+ interval: {{ .Values.serviceMonitor.interval | default "30s" }}
30
+ scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout | default "10s" }}
31
+ {{- with .Values.serviceMonitor.metricRelabelings }}
32
+ metricRelabelings:
33
+ {{- toYaml . | nindent 8 }}
34
+ {{- end }}
35
+ {{- with .Values.serviceMonitor.relabelings }}
36
+ relabelings:
37
+ {{- toYaml . | nindent 8 }}
38
+ {{- end }}
39
+ {{- end }}`,
40
+ },
41
+ {
42
+ name: 'monitoring.prometheusRule',
43
+ template: `{{- if .Values.prometheusRule.enabled -}}
44
+ apiVersion: monitoring.coreos.com/v1
45
+ kind: PrometheusRule
46
+ metadata:
47
+ name: {{ include "chart.fullname" . }}
48
+ namespace: {{ .Release.Namespace }}
49
+ labels:
50
+ {{- include "chart.labels" . | nindent 4 }}
51
+ {{- with .Values.prometheusRule.labels }}
52
+ {{- toYaml . | nindent 4 }}
53
+ {{- end }}
54
+ spec:
55
+ groups:
56
+ - name: {{ include "chart.fullname" . }}
57
+ rules:
58
+ {{- with .Values.prometheusRule.rules }}
59
+ {{- toYaml . | nindent 8 }}
60
+ {{- end }}
61
+ {{- end }}`,
62
+ },
63
+ {
64
+ name: 'tracing.jaegerConfig',
65
+ template: `{{- if .Values.tracing.enabled -}}
66
+ JAEGER_AGENT_HOST: {{ .Values.tracing.jaeger.agent.host | default "jaeger-agent" }}
67
+ JAEGER_AGENT_PORT: {{ .Values.tracing.jaeger.agent.port | default "6831" }}
68
+ JAEGER_ENDPOINT: {{ .Values.tracing.jaeger.endpoint | default "" }}
69
+ JAEGER_SERVICE_NAME: {{ include "chart.fullname" . }}
70
+ JAEGER_SAMPLER_TYPE: {{ .Values.tracing.jaeger.sampler.type | default "const" }}
71
+ JAEGER_SAMPLER_PARAM: {{ .Values.tracing.jaeger.sampler.param | default "1" }}
72
+ JAEGER_REPORTER_MAX_QUEUE_SIZE: {{ .Values.tracing.jaeger.reporter.maxQueueSize | default "100" }}
73
+ JAEGER_REPORTER_FLUSH_INTERVAL: {{ .Values.tracing.jaeger.reporter.flushInterval | default "1s" }}
74
+ {{- with .Values.tracing.jaeger.tags }}
75
+ JAEGER_TAGS: {{ . | join "," }}
76
+ {{- end }}
77
+ {{- end }}`,
78
+ },
79
+ {
80
+ name: 'tracing.otlpConfig',
81
+ template: `{{- if .Values.tracing.enabled -}}
82
+ OTEL_SERVICE_NAME: {{ include "chart.fullname" . }}
83
+ OTEL_SERVICE_VERSION: {{ .Chart.AppVersion }}
84
+ OTEL_RESOURCE_ATTRIBUTES: service.name={{ include "chart.fullname" . }},service.version={{ .Chart.AppVersion }},deployment.environment={{ .Values.environment | default "development" }}
85
+ {{- if .Values.tracing.otlp.endpoint }}
86
+ OTEL_EXPORTER_OTLP_ENDPOINT: {{ .Values.tracing.otlp.endpoint }}
87
+ {{- end }}
88
+ {{- if .Values.tracing.otlp.headers }}
89
+ OTEL_EXPORTER_OTLP_HEADERS: {{ .Values.tracing.otlp.headers | join "," }}
90
+ {{- end }}
91
+ OTEL_TRACES_SAMPLER: {{ .Values.tracing.otlp.sampler | default "parentbased_traceidratio" }}
92
+ OTEL_TRACES_SAMPLER_ARG: {{ .Values.tracing.otlp.samplerArg | default "1.0" }}
93
+ {{- end }}`,
94
+ },
95
+ {
96
+ name: 'logging.structured',
97
+ template: `LOG_LEVEL: {{ .Values.logging.level | default "info" }}
98
+ LOG_FORMAT: {{ .Values.logging.format | default "json" }}
99
+ {{- if .Values.logging.correlation.enabled }}
100
+ LOG_CORRELATION_ENABLED: "true"
101
+ LOG_CORRELATION_HEADER: {{ .Values.logging.correlation.header | default "X-Correlation-ID" }}
102
+ {{- end }}
103
+ {{- if .Values.logging.sampling.enabled }}
104
+ LOG_SAMPLING_ENABLED: "true"
105
+ LOG_SAMPLING_RATE: {{ .Values.logging.sampling.rate | default "0.1" }}
106
+ {{- end }}`,
107
+ },
108
+ {
109
+ name: 'logging.fluentdConfig',
110
+ template: `{{- if .Values.logging.fluentd.enabled -}}
111
+ FLUENTD_HOST: {{ .Values.logging.fluentd.host | default "fluentd" }}
112
+ FLUENTD_PORT: {{ .Values.logging.fluentd.port | default "24224" }}
113
+ FLUENTD_TAG: {{ .Values.logging.fluentd.tag | default (include "chart.fullname" .) }}
114
+ FLUENTD_BUFFER_LIMIT: {{ .Values.logging.fluentd.bufferLimit | default "8MB" }}
115
+ FLUENTD_TIMEOUT: {{ .Values.logging.fluentd.timeout | default "3.0" }}
116
+ {{- end }}`,
117
+ },
118
+ {
119
+ name: 'metrics.annotations',
120
+ template: `{{- if .Values.metrics.enabled -}}
121
+ prometheus.io/scrape: "true"
122
+ prometheus.io/port: "{{ .Values.metrics.port | default 9090 }}"
123
+ prometheus.io/path: "{{ .Values.metrics.path | default "/metrics" }}"
124
+ {{- if .Values.metrics.scheme }}
125
+ prometheus.io/scheme: "{{ .Values.metrics.scheme }}"
126
+ {{- end }}
127
+ {{- end }}`,
128
+ },
129
+ {
130
+ name: 'health.probes',
131
+ template: `{{- $healthPath := .Values.health.path | default "/health" -}}
132
+ {{- $readyPath := .Values.health.readiness.path | default "/ready" -}}
133
+ {{- $port := .Values.service.port | default 8080 -}}
134
+ livenessProbe:
135
+ httpGet:
136
+ path: {{ $healthPath }}
137
+ port: {{ $port }}
138
+ {{- if .Values.health.liveness.httpHeaders }}
139
+ httpHeaders:
140
+ {{- toYaml .Values.health.liveness.httpHeaders | nindent 6 }}
141
+ {{- end }}
142
+ initialDelaySeconds: {{ .Values.health.liveness.initialDelaySeconds | default 30 }}
143
+ periodSeconds: {{ .Values.health.liveness.periodSeconds | default 10 }}
144
+ timeoutSeconds: {{ .Values.health.liveness.timeoutSeconds | default 5 }}
145
+ successThreshold: {{ .Values.health.liveness.successThreshold | default 1 }}
146
+ failureThreshold: {{ .Values.health.liveness.failureThreshold | default 3 }}
147
+ readinessProbe:
148
+ httpGet:
149
+ path: {{ $readyPath }}
150
+ port: {{ $port }}
151
+ {{- if .Values.health.readiness.httpHeaders }}
152
+ httpHeaders:
153
+ {{- toYaml .Values.health.readiness.httpHeaders | nindent 6 }}
154
+ {{- end }}
155
+ initialDelaySeconds: {{ .Values.health.readiness.initialDelaySeconds | default 5 }}
156
+ periodSeconds: {{ .Values.health.readiness.periodSeconds | default 5 }}
157
+ timeoutSeconds: {{ .Values.health.readiness.timeoutSeconds | default 3 }}
158
+ successThreshold: {{ .Values.health.readiness.successThreshold | default 1 }}
159
+ failureThreshold: {{ .Values.health.readiness.failureThreshold | default 3 }}`,
160
+ },
161
+ {
162
+ name: 'health.startupProbe',
163
+ template: `{{- if .Values.health.startup.enabled -}}
164
+ {{- $startupPath := .Values.health.startup.path | default "/health" -}}
165
+ {{- $port := .Values.service.port | default 8080 -}}
166
+ startupProbe:
167
+ httpGet:
168
+ path: {{ $startupPath }}
169
+ port: {{ $port }}
170
+ {{- if .Values.health.startup.httpHeaders }}
171
+ httpHeaders:
172
+ {{- toYaml .Values.health.startup.httpHeaders | nindent 6 }}
173
+ {{- end }}
174
+ initialDelaySeconds: {{ .Values.health.startup.initialDelaySeconds | default 10 }}
175
+ periodSeconds: {{ .Values.health.startup.periodSeconds | default 10 }}
176
+ timeoutSeconds: {{ .Values.health.startup.timeoutSeconds | default 5 }}
177
+ successThreshold: {{ .Values.health.startup.successThreshold | default 1 }}
178
+ failureThreshold: {{ .Values.health.startup.failureThreshold | default 30 }}
179
+ {{- end }}`,
180
+ },
181
+ {
182
+ name: 'alerting.rules',
183
+ template: `{{- $serviceName := include "chart.fullname" . -}}
184
+ - alert: {{ $serviceName }}HighErrorRate
185
+ expr: rate(http_requests_total{job="{{ $serviceName }}", status=~"5.."}[5m]) > 0.1
186
+ for: 5m
187
+ labels:
188
+ severity: critical
189
+ service: {{ $serviceName }}
190
+ annotations:
191
+ summary: "High error rate detected"
192
+ description: "{{ $serviceName }} has error rate above 10% for more than 5 minutes"
193
+
194
+ - alert: {{ $serviceName }}HighLatency
195
+ expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job="{{ $serviceName }}"}[5m])) > 0.5
196
+ for: 5m
197
+ labels:
198
+ severity: warning
199
+ service: {{ $serviceName }}
200
+ annotations:
201
+ summary: "High latency detected"
202
+ description: "{{ $serviceName }} 95th percentile latency is above 500ms"
203
+
204
+ - alert: {{ $serviceName }}LowAvailability
205
+ expr: avg_over_time(up{job="{{ $serviceName }}"}[5m]) < 0.9
206
+ for: 2m
207
+ labels:
208
+ severity: critical
209
+ service: {{ $serviceName }}
210
+ annotations:
211
+ summary: "Service availability is low"
212
+ description: "{{ $serviceName }} availability is below 90%"`,
213
+ },
214
+ {
215
+ name: 'dashboard.annotations',
216
+ template: `{{- if .Values.grafana.dashboard.enabled -}}
217
+ grafana.io/dashboard: "{{ .Values.grafana.dashboard.id | default (include "chart.fullname" .) }}"
218
+ grafana.io/folder: "{{ .Values.grafana.dashboard.folder | default "applications" }}"
219
+ {{- end }}`,
220
+ },
221
+ ];
@@ -0,0 +1,16 @@
1
+ export interface HelperDefinition {
2
+ name: string;
3
+ template: string;
4
+ }
5
+ export type HelperCategory = 'standard' | 'fileAccess' | 'templateFunction' | 'sprig' | 'kubernetes' | 'aws' | 'env' | 'gitops' | 'observability' | 'validation';
6
+ export type CloudProvider = 'aws' | 'azure' | 'gcp';
7
+ export interface HelperOptions {
8
+ includeFileAccess?: boolean;
9
+ includeTemplateFunction?: boolean;
10
+ includeSprig?: boolean;
11
+ includeKubernetes?: boolean;
12
+ includeEnv?: boolean;
13
+ includeGitops?: boolean;
14
+ includeObservability?: boolean;
15
+ includeValidation?: boolean;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { HelperDefinition } from './types.js';
2
+ export declare const VALIDATION_HELPERS: HelperDefinition[];
@@ -0,0 +1,201 @@
1
+ export const VALIDATION_HELPERS = [
2
+ {
3
+ name: 'validation.semver',
4
+ template: `{{- $version := . -}}
5
+ {{- if not (regexMatch "^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$" $version) -}}
6
+ {{- fail (printf "Invalid semantic version: %s. Must follow semver format (e.g., 1.2.3, 1.0.0-alpha.1)" $version) -}}
7
+ {{- end -}}
8
+ {{- $version }}`,
9
+ },
10
+ {
11
+ name: 'validation.k8sName',
12
+ template: `{{- $name := . -}}
13
+ {{- if not (regexMatch "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" $name) -}}
14
+ {{- fail (printf "Invalid Kubernetes resource name: %s. Must be lowercase alphanumeric with hyphens, starting and ending with alphanumeric characters" $name) -}}
15
+ {{- end -}}
16
+ {{- if gt (len $name) 63 -}}
17
+ {{- fail (printf "Kubernetes resource name too long: %s. Maximum 63 characters allowed" $name) -}}
18
+ {{- end -}}
19
+ {{- $name }}`,
20
+ },
21
+ {
22
+ name: 'validation.dnsLabel',
23
+ template: `{{- $label := . -}}
24
+ {{- if not (regexMatch "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" $label) -}}
25
+ {{- fail (printf "Invalid DNS label: %s. Must be lowercase alphanumeric with hyphens" $label) -}}
26
+ {{- end -}}
27
+ {{- if gt (len $label) 63 -}}
28
+ {{- fail (printf "DNS label too long: %s. Maximum 63 characters allowed" $label) -}}
29
+ {{- end -}}
30
+ {{- $label }}`,
31
+ },
32
+ {
33
+ name: 'validation.email',
34
+ template: `{{- $email := . -}}
35
+ {{- if not (regexMatch "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}$" $email) -}}
36
+ {{- fail (printf "Invalid email address: %s" $email) -}}
37
+ {{- end -}}
38
+ {{- $email }}`,
39
+ },
40
+ {
41
+ name: 'validation.url',
42
+ template: `{{- $url := . -}}
43
+ {{- if not (regexMatch "^https?://[a-zA-Z0-9.-]+(?:[:/][^\\\\s]*)?$" $url) -}}
44
+ {{- fail (printf "Invalid URL: %s. Must be a valid HTTP or HTTPS URL" $url) -}}
45
+ {{- end -}}
46
+ {{- $url }}`,
47
+ },
48
+ {
49
+ name: 'validation.port',
50
+ template: `{{- $port := . | int -}}
51
+ {{- if or (lt $port 1) (gt $port 65535) -}}
52
+ {{- fail (printf "Invalid port number: %d. Must be between 1 and 65535" $port) -}}
53
+ {{- end -}}
54
+ {{- $port }}`,
55
+ },
56
+ {
57
+ name: 'validation.memorySize',
58
+ template: `{{- $size := . -}}
59
+ {{- if not (regexMatch "^[0-9]+(\\\\.[0-9]+)?(Ki|Mi|Gi|Ti|Pi|Ei|K|M|G|T|P|E)?$" $size) -}}
60
+ {{- fail (printf "Invalid memory size: %s. Use format like '512Mi', '2Gi', '1.5Gi'" $size) -}}
61
+ {{- end -}}
62
+ {{- $size }}`,
63
+ },
64
+ {
65
+ name: 'validation.cpuSize',
66
+ template: `{{- $cpu := . -}}
67
+ {{- if not (regexMatch "^[0-9]+(\\\\.[0-9]+)?m?$" $cpu) -}}
68
+ {{- fail (printf "Invalid CPU size: %s. Use format like '500m', '1', '1.5', '2000m'" $cpu) -}}
69
+ {{- end -}}
70
+ {{- $cpu }}`,
71
+ },
72
+ {
73
+ name: 'validation.duration',
74
+ template: `{{- $duration := . -}}
75
+ {{- if not (regexMatch "^[0-9]+(\\\\.[0-9]+)?(ns|us|µs|ms|s|m|h)$" $duration) -}}
76
+ {{- fail (printf "Invalid duration: %s. Use format like '30s', '5m', '2h', '100ms'" $duration) -}}
77
+ {{- end -}}
78
+ {{- $duration }}`,
79
+ },
80
+ {
81
+ name: 'validation.percentage',
82
+ template: `{{- $percentage := . -}}
83
+ {{- if regexMatch "^[0-9]+%$" ($percentage | toString) -}}
84
+ {{- $num := $percentage | toString | trimSuffix "%" | int -}}
85
+ {{- if or (lt $num 0) (gt $num 100) -}}
86
+ {{- fail (printf "Invalid percentage: %s. Must be between 0%% and 100%%" $percentage) -}}
87
+ {{- end -}}
88
+ {{- else -}}
89
+ {{- $num := $percentage | int -}}
90
+ {{- if or (lt $num 0) (gt $num 100) -}}
91
+ {{- fail (printf "Invalid percentage: %d. Must be between 0 and 100" $num) -}}
92
+ {{- end -}}
93
+ {{- end -}}
94
+ {{- $percentage }}`,
95
+ },
96
+ {
97
+ name: 'validation.ipAddress',
98
+ template: `{{- $ip := . -}}
99
+ {{- if not (regexMatch "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" $ip) -}}
100
+ {{- fail (printf "Invalid IP address: %s. Must be a valid IPv4 address" $ip) -}}
101
+ {{- end -}}
102
+ {{- $ip }}`,
103
+ },
104
+ {
105
+ name: 'validation.cidr',
106
+ template: `{{- $cidr := . -}}
107
+ {{- if not (regexMatch "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/([0-9]|[1-2][0-9]|3[0-2])$" $cidr) -}}
108
+ {{- fail (printf "Invalid CIDR notation: %s. Must be a valid IPv4 CIDR (e.g., 192.168.1.0/24)" $cidr) -}}
109
+ {{- end -}}
110
+ {{- $cidr }}`,
111
+ },
112
+ {
113
+ name: 'validation.base64',
114
+ template: `{{- $value := . -}}
115
+ {{- if not (regexMatch "^[A-Za-z0-9+/]*={0,2}$" $value) -}}
116
+ {{- fail (printf "Invalid base64 string: %s" $value) -}}
117
+ {{- end -}}
118
+ {{- $value }}`,
119
+ },
120
+ {
121
+ name: 'validation.uuid',
122
+ template: `{{- $uuid := . -}}
123
+ {{- if not (regexMatch "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" ($uuid | lower)) -}}
124
+ {{- fail (printf "Invalid UUID: %s. Must be a valid UUID format" $uuid) -}}
125
+ {{- end -}}
126
+ {{- $uuid }}`,
127
+ },
128
+ {
129
+ name: 'validation.cronSchedule',
130
+ template: `{{- $cron := . -}}
131
+ {{- $parts := regexSplit "\\\\s+" $cron -1 -}}
132
+ {{- if ne (len $parts) 5 -}}
133
+ {{- fail (printf "Invalid cron schedule: %s. Must have 5 parts (minute hour day month weekday)" $cron) -}}
134
+ {{- end -}}
135
+ {{- range $part := $parts -}}
136
+ {{- if not (regexMatch "^(\\\\*|[0-9,-/]+|\\\\*\\\\/[0-9]+)$" $part) -}}
137
+ {{- fail (printf "Invalid cron part: %s in schedule %s" $part $cron) -}}
138
+ {{- end -}}
139
+ {{- end -}}
140
+ {{- $cron }}`,
141
+ },
142
+ {
143
+ name: 'validation.imagePullPolicy',
144
+ template: `{{- $policy := . -}}
145
+ {{- if not (has $policy (list "Always" "IfNotPresent" "Never")) -}}
146
+ {{- fail (printf "Invalid image pull policy: %s. Must be one of: Always, IfNotPresent, Never" $policy) -}}
147
+ {{- end -}}
148
+ {{- $policy }}`,
149
+ },
150
+ {
151
+ name: 'validation.logLevel',
152
+ template: `{{- $level := . | lower -}}
153
+ {{- if not (has $level (list "trace" "debug" "info" "warn" "warning" "error" "fatal" "panic")) -}}
154
+ {{- fail (printf "Invalid log level: %s. Must be one of: trace, debug, info, warn, error, fatal, panic" .) -}}
155
+ {{- end -}}
156
+ {{- $level }}`,
157
+ },
158
+ {
159
+ name: 'validation.serviceType',
160
+ template: `{{- $type := . -}}
161
+ {{- if not (has $type (list "ClusterIP" "NodePort" "LoadBalancer" "ExternalName")) -}}
162
+ {{- fail (printf "Invalid service type: %s. Must be one of: ClusterIP, NodePort, LoadBalancer, ExternalName" $type) -}}
163
+ {{- end -}}
164
+ {{- $type }}`,
165
+ },
166
+ {
167
+ name: 'validation.storageAccessMode',
168
+ template: `{{- $mode := . -}}
169
+ {{- if not (has $mode (list "ReadWriteOnce" "ReadOnlyMany" "ReadWriteMany" "ReadWriteOncePod")) -}}
170
+ {{- fail (printf "Invalid storage access mode: %s. Must be one of: ReadWriteOnce, ReadOnlyMany, ReadWriteMany, ReadWriteOncePod" $mode) -}}
171
+ {{- end -}}
172
+ {{- $mode }}`,
173
+ },
174
+ {
175
+ name: 'validation.required',
176
+ template: `{{- $value := .value -}}
177
+ {{- $fieldName := .field | default "field" -}}
178
+ {{- if or (not $value) (and (kindIs "string" $value) (eq (trim $value) "")) -}}
179
+ {{- fail (printf "Required field '%s' is missing or empty" $fieldName) -}}
180
+ {{- end -}}
181
+ {{- $value }}`,
182
+ },
183
+ {
184
+ name: 'validation.nonEmpty',
185
+ template: `{{- $list := . -}}
186
+ {{- if not (and $list (gt (len $list) 0)) -}}
187
+ {{- fail "List cannot be empty" -}}
188
+ {{- end -}}
189
+ {{- $list }}`,
190
+ },
191
+ {
192
+ name: 'validation.range',
193
+ template: `{{- $value := .value | int -}}
194
+ {{- $min := .min | int -}}
195
+ {{- $max := .max | int -}}
196
+ {{- if or (lt $value $min) (gt $value $max) -}}
197
+ {{- fail (printf "Value %d is out of range [%d, %d]" $value $min $max) -}}
198
+ {{- end -}}
199
+ {{- $value }}`,
200
+ },
201
+ ];
@@ -14,12 +14,22 @@ export declare function getDefaultHelpers(cloudProvider?: 'aws', options?: {
14
14
  includeTemplateFunction?: boolean;
15
15
  includeSprig?: boolean;
16
16
  includeKubernetes?: boolean;
17
+ includeEnv?: boolean;
18
+ includeGitops?: boolean;
19
+ includeObservability?: boolean;
20
+ includeValidation?: boolean;
17
21
  }): HelperDefinition[];
18
22
  export declare function generateHelpersTemplate(cloudProvider?: 'aws', customHelpers?: HelperDefinition[], options?: {
19
23
  includeFileAccess?: boolean;
20
24
  includeTemplateFunction?: boolean;
21
25
  includeSprig?: boolean;
22
26
  includeKubernetes?: boolean;
27
+ includeEnv?: boolean;
28
+ includeGitops?: boolean;
29
+ includeObservability?: boolean;
30
+ includeValidation?: boolean;
23
31
  }): string;
24
- export declare function getHelpersByCategory(category: 'standard' | 'fileAccess' | 'templateFunction' | 'sprig' | 'kubernetes' | 'aws'): HelperDefinition[];
32
+ export declare function getHelpersByCategory(category: 'standard' | 'fileAccess' | 'templateFunction' | 'sprig' | 'kubernetes' | 'aws' | 'env' | 'gitops' | 'observability' | 'validation'): HelperDefinition[];
25
33
  export declare function createHelper(name: string, template: string): HelperDefinition;
34
+ export { getNewHelpersByCategory, getAvailableHelperCategories, getHelpersByCategories, getHelpersByOptions, formatNewHelpers, generateNewHelpersTemplate, getCachedNewHelpersTemplate, createNewHelper, validateHelperNames, filterHelpersByPattern, getHelperStatistics, } from './helmHelpers/index.js';
35
+ export { ENV_HELPERS, GITOPS_HELPERS, OBSERVABILITY_HELPERS, VALIDATION_HELPERS, } from './helmHelpers/index.js';
@@ -1,3 +1,4 @@
1
+ import { ENV_HELPERS, GITOPS_HELPERS, OBSERVABILITY_HELPERS, VALIDATION_HELPERS, getNewHelpersByCategory, } from './helmHelpers/index.js';
1
2
  export const STANDARD_HELPERS = [
2
3
  {
3
4
  name: 'chart.name',
@@ -87,12 +88,6 @@ export const TEMPLATE_FUNCTION_HELPERS = [
87
88
  {{- $values := .values | default dict -}}
88
89
  {{- $context := merge $values . -}}
89
90
  {{- tpl $template $context -}}`,
90
- },
91
- {
92
- name: 'validation.required',
93
- template: `{{- $value := .value -}}
94
- {{- $message := .message | default (printf "Value %s is required" .key) -}}
95
- {{- required $message $value -}}`,
96
91
  },
97
92
  {
98
93
  name: 'validation.requireAny',
@@ -131,7 +126,8 @@ export const SPRIG_HELPERS = [
131
126
  name: 'env.getOrDefault',
132
127
  template: `{{- $key := .key -}}
133
128
  {{- $default := .default | default "" -}}
134
- {{- $default }}`,
129
+ {{- $value := index .Values.env $key -}}
130
+ {{- $value | default $default }}`,
135
131
  },
136
132
  {
137
133
  name: 'list.compact',
@@ -287,6 +283,18 @@ export function getDefaultHelpers(cloudProvider, options) {
287
283
  if (options?.includeKubernetes !== false) {
288
284
  helpers.push(...KUBERNETES_HELPERS);
289
285
  }
286
+ if (options?.includeEnv !== false) {
287
+ helpers.push(...ENV_HELPERS);
288
+ }
289
+ if (options?.includeGitops !== false) {
290
+ helpers.push(...GITOPS_HELPERS);
291
+ }
292
+ if (options?.includeObservability !== false) {
293
+ helpers.push(...OBSERVABILITY_HELPERS);
294
+ }
295
+ if (options?.includeValidation !== false) {
296
+ helpers.push(...VALIDATION_HELPERS);
297
+ }
290
298
  if (cloudProvider === 'aws') {
291
299
  helpers.push(...AWS_HELPERS);
292
300
  }
@@ -300,6 +308,9 @@ export function generateHelpersTemplate(cloudProvider, customHelpers, options) {
300
308
  return formatHelpers(helpers);
301
309
  }
302
310
  export function getHelpersByCategory(category) {
311
+ if (['env', 'gitops', 'observability', 'validation'].includes(category)) {
312
+ return getNewHelpersByCategory(category);
313
+ }
303
314
  switch (category) {
304
315
  case 'standard':
305
316
  return [...STANDARD_HELPERS];
@@ -320,3 +331,5 @@ export function getHelpersByCategory(category) {
320
331
  export function createHelper(name, template) {
321
332
  return { name, template };
322
333
  }
334
+ export { getNewHelpersByCategory, getAvailableHelperCategories, getHelpersByCategories, getHelpersByOptions, formatNewHelpers, generateNewHelpersTemplate, getCachedNewHelpersTemplate, createNewHelper, validateHelperNames, filterHelpersByPattern, getHelperStatistics, } from './helmHelpers/index.js';
335
+ export { ENV_HELPERS, GITOPS_HELPERS, OBSERVABILITY_HELPERS, VALIDATION_HELPERS, } from './helmHelpers/index.js';
@@ -1,8 +1,60 @@
1
1
  import * as jsYaml from 'js-yaml';
2
+ type HelmExpressionType = 'block' | 'nested' | 'comment' | 'action-trimmed' | 'raw' | 'include-context' | 'generic';
3
+ interface HelmExpressionMatch {
4
+ type: HelmExpressionType;
5
+ expression: string;
6
+ start: number;
7
+ end: number;
8
+ }
9
+ interface HelmExpression {
10
+ __helmExpression: true;
11
+ value: string;
12
+ }
13
+ declare function createHelmExpression(value: string): HelmExpression;
14
+ declare function isHelmExpression(value: unknown): value is HelmExpression;
15
+ declare function detectHelmExpressions(str: string): HelmExpressionMatch[];
16
+ declare function preprocessHelmExpressions(obj: unknown, depth?: number): unknown;
17
+ declare function postProcessHelmExpressions(yaml: string): string;
2
18
  export declare function dumpHelmAwareYaml(obj: unknown, options?: jsYaml.DumpOptions): string;
3
19
  export declare function stringify(obj: unknown, options?: {
4
20
  lineWidth?: number;
5
21
  doubleQuotedAsJSON?: boolean;
6
22
  simpleKeys?: boolean;
7
23
  }): string;
8
- export declare function validateHelmExpressions(yaml: string): boolean;
24
+ export interface HelmValidationError {
25
+ type: 'syntax' | 'semantic' | 'reference' | 'type';
26
+ message: string;
27
+ line?: number;
28
+ column?: number;
29
+ expression?: string;
30
+ suggestion?: string;
31
+ }
32
+ export interface HelmValidationResult {
33
+ isValid: boolean;
34
+ errors: HelmValidationError[];
35
+ warnings: HelmValidationError[];
36
+ statistics: {
37
+ totalExpressions: number;
38
+ expressionsByType: Record<string, number>;
39
+ complexity: number;
40
+ };
41
+ }
42
+ export declare function validateHelmYaml(yaml: string): HelmValidationResult;
43
+ export declare function parseHelmExpressions(content: string): Array<{
44
+ type: HelmExpressionType;
45
+ expression: string;
46
+ startLine: number;
47
+ startCol: number;
48
+ endLine: number;
49
+ endCol: number;
50
+ }>;
51
+ export interface PrettifyOptions {
52
+ indentSize?: number;
53
+ alignExpressions?: boolean;
54
+ preserveComments?: boolean;
55
+ maxLineWidth?: number;
56
+ sortKeys?: boolean;
57
+ groupHelpers?: boolean;
58
+ }
59
+ export declare function prettifyHelmTemplate(yaml: string, options?: PrettifyOptions): string;
60
+ export { createHelmExpression, isHelmExpression, detectHelmExpressions, preprocessHelmExpressions, postProcessHelmExpressions, };