typekro 0.2.2 → 0.3.1

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 (213) hide show
  1. package/README.md +4 -3
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/core/composition/imperative.d.ts.map +1 -1
  4. package/dist/core/composition/imperative.js +15 -2
  5. package/dist/core/composition/imperative.js.map +1 -1
  6. package/dist/core/composition/typekro-runtime/typekro-runtime.d.ts.map +1 -1
  7. package/dist/core/composition/typekro-runtime/typekro-runtime.js +24 -25
  8. package/dist/core/composition/typekro-runtime/typekro-runtime.js.map +1 -1
  9. package/dist/core/dependencies/type-guards.d.ts.map +1 -1
  10. package/dist/core/dependencies/type-guards.js +7 -2
  11. package/dist/core/dependencies/type-guards.js.map +1 -1
  12. package/dist/core/deployment/engine.d.ts +13 -1
  13. package/dist/core/deployment/engine.d.ts.map +1 -1
  14. package/dist/core/deployment/engine.js +48 -3
  15. package/dist/core/deployment/engine.js.map +1 -1
  16. package/dist/core/errors.d.ts +85 -0
  17. package/dist/core/errors.d.ts.map +1 -1
  18. package/dist/core/errors.js +135 -0
  19. package/dist/core/errors.js.map +1 -1
  20. package/dist/core/evaluation/cel-optimizer.d.ts.map +1 -1
  21. package/dist/core/evaluation/cel-optimizer.js +7 -13
  22. package/dist/core/evaluation/cel-optimizer.js.map +1 -1
  23. package/dist/core/expressions/analyzer.d.ts +584 -0
  24. package/dist/core/expressions/analyzer.d.ts.map +1 -0
  25. package/dist/core/expressions/analyzer.js +2956 -0
  26. package/dist/core/expressions/analyzer.js.map +1 -0
  27. package/dist/core/expressions/cache.d.ts +136 -0
  28. package/dist/core/expressions/cache.d.ts.map +1 -0
  29. package/dist/core/expressions/cache.js +347 -0
  30. package/dist/core/expressions/cache.js.map +1 -0
  31. package/dist/core/expressions/cel-conversion-engine.d.ts +126 -0
  32. package/dist/core/expressions/cel-conversion-engine.d.ts.map +1 -0
  33. package/dist/core/expressions/cel-conversion-engine.js +293 -0
  34. package/dist/core/expressions/cel-conversion-engine.js.map +1 -0
  35. package/dist/core/expressions/compile-time-validation.d.ts +270 -0
  36. package/dist/core/expressions/compile-time-validation.d.ts.map +1 -0
  37. package/dist/core/expressions/compile-time-validation.js +506 -0
  38. package/dist/core/expressions/compile-time-validation.js.map +1 -0
  39. package/dist/core/expressions/composition-integration.d.ts +315 -0
  40. package/dist/core/expressions/composition-integration.d.ts.map +1 -0
  41. package/dist/core/expressions/composition-integration.js +936 -0
  42. package/dist/core/expressions/composition-integration.js.map +1 -0
  43. package/dist/core/expressions/conditional-expression-processor.d.ts +154 -0
  44. package/dist/core/expressions/conditional-expression-processor.d.ts.map +1 -0
  45. package/dist/core/expressions/conditional-expression-processor.js +479 -0
  46. package/dist/core/expressions/conditional-expression-processor.js.map +1 -0
  47. package/dist/core/expressions/conditional-integration.d.ts +133 -0
  48. package/dist/core/expressions/conditional-integration.d.ts.map +1 -0
  49. package/dist/core/expressions/conditional-integration.js +293 -0
  50. package/dist/core/expressions/conditional-integration.js.map +1 -0
  51. package/dist/core/expressions/conditional-validation.d.ts +181 -0
  52. package/dist/core/expressions/conditional-validation.d.ts.map +1 -0
  53. package/dist/core/expressions/conditional-validation.js +460 -0
  54. package/dist/core/expressions/conditional-validation.js.map +1 -0
  55. package/dist/core/expressions/context-aware-generator.d.ts +127 -0
  56. package/dist/core/expressions/context-aware-generator.d.ts.map +1 -0
  57. package/dist/core/expressions/context-aware-generator.js +500 -0
  58. package/dist/core/expressions/context-aware-generator.js.map +1 -0
  59. package/dist/core/expressions/context-detector.d.ts +148 -0
  60. package/dist/core/expressions/context-detector.d.ts.map +1 -0
  61. package/dist/core/expressions/context-detector.js +546 -0
  62. package/dist/core/expressions/context-detector.js.map +1 -0
  63. package/dist/core/expressions/context-switcher.d.ts +185 -0
  64. package/dist/core/expressions/context-switcher.d.ts.map +1 -0
  65. package/dist/core/expressions/context-switcher.js +515 -0
  66. package/dist/core/expressions/context-switcher.js.map +1 -0
  67. package/dist/core/expressions/context-validator.d.ts +176 -0
  68. package/dist/core/expressions/context-validator.d.ts.map +1 -0
  69. package/dist/core/expressions/context-validator.js +452 -0
  70. package/dist/core/expressions/context-validator.js.map +1 -0
  71. package/dist/core/expressions/custom-context-manager.d.ts +194 -0
  72. package/dist/core/expressions/custom-context-manager.d.ts.map +1 -0
  73. package/dist/core/expressions/custom-context-manager.js +390 -0
  74. package/dist/core/expressions/custom-context-manager.js.map +1 -0
  75. package/dist/core/expressions/expression-proxy.d.ts +80 -0
  76. package/dist/core/expressions/expression-proxy.d.ts.map +1 -0
  77. package/dist/core/expressions/expression-proxy.js +227 -0
  78. package/dist/core/expressions/expression-proxy.js.map +1 -0
  79. package/dist/core/expressions/factory-integration.d.ts +132 -0
  80. package/dist/core/expressions/factory-integration.d.ts.map +1 -0
  81. package/dist/core/expressions/factory-integration.js +327 -0
  82. package/dist/core/expressions/factory-integration.js.map +1 -0
  83. package/dist/core/expressions/factory-pattern-handler.d.ts +88 -0
  84. package/dist/core/expressions/factory-pattern-handler.d.ts.map +1 -0
  85. package/dist/core/expressions/factory-pattern-handler.js +336 -0
  86. package/dist/core/expressions/factory-pattern-handler.js.map +1 -0
  87. package/dist/core/expressions/field-hydration-processor.d.ts +188 -0
  88. package/dist/core/expressions/field-hydration-processor.d.ts.map +1 -0
  89. package/dist/core/expressions/field-hydration-processor.js +562 -0
  90. package/dist/core/expressions/field-hydration-processor.js.map +1 -0
  91. package/dist/core/expressions/imperative-analyzer.d.ts +21 -0
  92. package/dist/core/expressions/imperative-analyzer.d.ts.map +1 -0
  93. package/dist/core/expressions/imperative-analyzer.js +457 -0
  94. package/dist/core/expressions/imperative-analyzer.js.map +1 -0
  95. package/dist/core/expressions/index.d.ts +54 -0
  96. package/dist/core/expressions/index.d.ts.map +1 -0
  97. package/dist/core/expressions/index.js +50 -0
  98. package/dist/core/expressions/index.js.map +1 -0
  99. package/dist/core/expressions/lazy-analysis.d.ts +1128 -0
  100. package/dist/core/expressions/lazy-analysis.d.ts.map +1 -0
  101. package/dist/core/expressions/lazy-analysis.js +2443 -0
  102. package/dist/core/expressions/lazy-analysis.js.map +1 -0
  103. package/dist/core/expressions/magic-assignable-analyzer.d.ts +123 -0
  104. package/dist/core/expressions/magic-assignable-analyzer.d.ts.map +1 -0
  105. package/dist/core/expressions/magic-assignable-analyzer.js +352 -0
  106. package/dist/core/expressions/magic-assignable-analyzer.js.map +1 -0
  107. package/dist/core/expressions/magic-proxy-analyzer.d.ts +206 -0
  108. package/dist/core/expressions/magic-proxy-analyzer.d.ts.map +1 -0
  109. package/dist/core/expressions/magic-proxy-analyzer.js +639 -0
  110. package/dist/core/expressions/magic-proxy-analyzer.js.map +1 -0
  111. package/dist/core/expressions/magic-proxy-detector.d.ts +154 -0
  112. package/dist/core/expressions/magic-proxy-detector.d.ts.map +1 -0
  113. package/dist/core/expressions/magic-proxy-detector.js +242 -0
  114. package/dist/core/expressions/magic-proxy-detector.js.map +1 -0
  115. package/dist/core/expressions/migration-helpers.d.ts +133 -0
  116. package/dist/core/expressions/migration-helpers.d.ts.map +1 -0
  117. package/dist/core/expressions/migration-helpers.js +443 -0
  118. package/dist/core/expressions/migration-helpers.js.map +1 -0
  119. package/dist/core/expressions/optionality-handler.d.ts +503 -0
  120. package/dist/core/expressions/optionality-handler.d.ts.map +1 -0
  121. package/dist/core/expressions/optionality-handler.js +1306 -0
  122. package/dist/core/expressions/optionality-handler.js.map +1 -0
  123. package/dist/core/expressions/readiness-integration.d.ts +119 -0
  124. package/dist/core/expressions/readiness-integration.d.ts.map +1 -0
  125. package/dist/core/expressions/readiness-integration.js +386 -0
  126. package/dist/core/expressions/readiness-integration.js.map +1 -0
  127. package/dist/core/expressions/resource-analyzer.d.ts +486 -0
  128. package/dist/core/expressions/resource-analyzer.d.ts.map +1 -0
  129. package/dist/core/expressions/resource-analyzer.js +1086 -0
  130. package/dist/core/expressions/resource-analyzer.js.map +1 -0
  131. package/dist/core/expressions/resource-validation.d.ts +187 -0
  132. package/dist/core/expressions/resource-validation.d.ts.map +1 -0
  133. package/dist/core/expressions/resource-validation.js +552 -0
  134. package/dist/core/expressions/resource-validation.js.map +1 -0
  135. package/dist/core/expressions/runtime-error-mapper.d.ts +138 -0
  136. package/dist/core/expressions/runtime-error-mapper.d.ts.map +1 -0
  137. package/dist/core/expressions/runtime-error-mapper.js +412 -0
  138. package/dist/core/expressions/runtime-error-mapper.js.map +1 -0
  139. package/dist/core/expressions/source-map.d.ts +168 -0
  140. package/dist/core/expressions/source-map.d.ts.map +1 -0
  141. package/dist/core/expressions/source-map.js +350 -0
  142. package/dist/core/expressions/source-map.js.map +1 -0
  143. package/dist/core/expressions/status-builder-analyzer.d.ts +353 -0
  144. package/dist/core/expressions/status-builder-analyzer.d.ts.map +1 -0
  145. package/dist/core/expressions/status-builder-analyzer.js +1311 -0
  146. package/dist/core/expressions/status-builder-analyzer.js.map +1 -0
  147. package/dist/core/expressions/type-inference.d.ts +184 -0
  148. package/dist/core/expressions/type-inference.d.ts.map +1 -0
  149. package/dist/core/expressions/type-inference.js +838 -0
  150. package/dist/core/expressions/type-inference.js.map +1 -0
  151. package/dist/core/expressions/type-safety.d.ts +203 -0
  152. package/dist/core/expressions/type-safety.d.ts.map +1 -0
  153. package/dist/core/expressions/type-safety.js +442 -0
  154. package/dist/core/expressions/type-safety.js.map +1 -0
  155. package/dist/core/expressions/types.d.ts +282 -0
  156. package/dist/core/expressions/types.d.ts.map +1 -0
  157. package/dist/core/expressions/types.js +8 -0
  158. package/dist/core/expressions/types.js.map +1 -0
  159. package/dist/core/kubernetes/client-provider.js +2 -2
  160. package/dist/core/kubernetes/client-provider.js.map +1 -1
  161. package/dist/core/references/cel.d.ts +13 -1
  162. package/dist/core/references/cel.d.ts.map +1 -1
  163. package/dist/core/references/cel.js +50 -0
  164. package/dist/core/references/cel.js.map +1 -1
  165. package/dist/core/references/schema-proxy.d.ts.map +1 -1
  166. package/dist/core/references/schema-proxy.js +13 -8
  167. package/dist/core/references/schema-proxy.js.map +1 -1
  168. package/dist/core/serialization/core.d.ts.map +1 -1
  169. package/dist/core/serialization/core.js +573 -9
  170. package/dist/core/serialization/core.js.map +1 -1
  171. package/dist/core/types/deployment.d.ts +7 -0
  172. package/dist/core/types/deployment.d.ts.map +1 -1
  173. package/dist/core/types/deployment.js +7 -0
  174. package/dist/core/types/deployment.js.map +1 -1
  175. package/dist/core/types/index.d.ts +1 -0
  176. package/dist/core/types/index.d.ts.map +1 -1
  177. package/dist/core/types/index.js.map +1 -1
  178. package/dist/core/validation/cel-validator.d.ts.map +1 -1
  179. package/dist/core/validation/cel-validator.js +4 -8
  180. package/dist/core/validation/cel-validator.js.map +1 -1
  181. package/dist/core.d.ts +1 -1
  182. package/dist/core.d.ts.map +1 -1
  183. package/dist/core.js +1 -1
  184. package/dist/core.js.map +1 -1
  185. package/dist/factories/helm/helm-release.d.ts.map +1 -1
  186. package/dist/factories/helm/helm-release.js +0 -5
  187. package/dist/factories/helm/helm-release.js.map +1 -1
  188. package/dist/factories/helm/types.d.ts +1 -1
  189. package/dist/factories/helm/types.d.ts.map +1 -1
  190. package/dist/factories/index.js +1 -0
  191. package/dist/factories/index.js.map +1 -1
  192. package/dist/factories/shared.d.ts.map +1 -1
  193. package/dist/factories/shared.js +21 -1
  194. package/dist/factories/shared.js.map +1 -1
  195. package/dist/factories/simple/index.d.ts +2 -2
  196. package/dist/factories/simple/index.d.ts.map +1 -1
  197. package/dist/factories/simple/workloads/deployment.d.ts +3 -3
  198. package/dist/factories/simple/workloads/deployment.d.ts.map +1 -1
  199. package/dist/factories/simple/workloads/deployment.js +37 -11
  200. package/dist/factories/simple/workloads/deployment.js.map +1 -1
  201. package/dist/index.d.ts +1 -1
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +1 -1
  204. package/dist/index.js.map +1 -1
  205. package/dist/utils/index.d.ts +1 -1
  206. package/dist/utils/index.d.ts.map +1 -1
  207. package/dist/utils/index.js +1 -1
  208. package/dist/utils/index.js.map +1 -1
  209. package/dist/utils/type-guards.d.ts +6 -0
  210. package/dist/utils/type-guards.d.ts.map +1 -1
  211. package/dist/utils/type-guards.js +25 -2
  212. package/dist/utils/type-guards.js.map +1 -1
  213. package/package.json +6 -1
@@ -8,11 +8,18 @@ import { DependencyResolver } from '../dependencies/index.js';
8
8
  import { createDirectResourceFactory } from '../deployment/direct-factory.js';
9
9
  import { createKroResourceFactory } from '../deployment/kro-factory.js';
10
10
  import { optimizeStatusMappings } from '../evaluation/cel-optimizer.js';
11
+ import { analyzeStatusBuilderForToResourceGraph } from '../expressions/status-builder-analyzer.js';
12
+ import { analyzeImperativeComposition } from '../expressions/imperative-analyzer.js';
11
13
  import { getComponentLogger } from '../logging/index.js';
12
14
  import { createSchemaProxy, externalRef } from '../references/index.js';
13
15
  import { validateResourceGraphDefinition } from '../validation/cel-validator.js';
14
16
  import { generateKroSchemaFromArktype } from './schema.js';
15
17
  import { serializeResourceGraphToYaml } from './yaml.js';
18
+ import { StatusBuilderAnalyzer } from '../expressions/status-builder-analyzer.js';
19
+ import { containsKubernetesRefs } from '../../utils/type-guards.js';
20
+ import { isCelExpression } from '../../utils/type-guards.js';
21
+ import { CelToJavaScriptMigrationHelper } from '../expressions/migration-helpers.js';
22
+ import { CelConversionEngine } from '../expressions/cel-conversion-engine.js';
16
23
  /**
17
24
  * Separate Enhanced<> resources from deployment closures in the builder result
18
25
  */
@@ -35,6 +42,274 @@ function separateResourcesAndClosures(builderResult) {
35
42
  }
36
43
  return { resources, closures };
37
44
  }
45
+ /**
46
+ * Detect and preserve existing CEL expressions for backward compatibility
47
+ *
48
+ * This function recursively checks status mappings for existing CEL expressions
49
+ * and preserves them without conversion, ensuring backward compatibility.
50
+ */
51
+ function detectAndPreserveCelExpressions(statusMappings, preservedExpressions = {}, path = '') {
52
+ let hasExistingCel = false;
53
+ const preservedMappings = { ...preservedExpressions };
54
+ if (!statusMappings || typeof statusMappings !== 'object') {
55
+ return { hasExistingCel, preservedMappings };
56
+ }
57
+ for (const [key, value] of Object.entries(statusMappings)) {
58
+ const currentPath = path ? `${path}.${key}` : key;
59
+ if (isCelExpression(value)) {
60
+ // Found existing CEL expression - preserve it
61
+ hasExistingCel = true;
62
+ preservedMappings[currentPath] = value;
63
+ }
64
+ else if (value && typeof value === 'object' && !Array.isArray(value)) {
65
+ // Recursively check nested objects
66
+ const nestedResult = detectAndPreserveCelExpressions(value, preservedMappings, currentPath);
67
+ hasExistingCel = hasExistingCel || nestedResult.hasExistingCel;
68
+ Object.assign(preservedMappings, nestedResult.preservedMappings);
69
+ }
70
+ }
71
+ return { hasExistingCel, preservedMappings };
72
+ }
73
+ /**
74
+ * Check if a value contains any CelExpression objects
75
+ */
76
+ function containsCelExpressions(value) {
77
+ if (isCelExpression(value)) {
78
+ return true;
79
+ }
80
+ if (Array.isArray(value)) {
81
+ return value.some(item => containsCelExpressions(item));
82
+ }
83
+ if (value && typeof value === 'object') {
84
+ return Object.values(value).some(val => containsCelExpressions(val));
85
+ }
86
+ return false;
87
+ }
88
+ /**
89
+ * Merge preserved CEL expressions with analyzed mappings
90
+ *
91
+ * This ensures that existing CEL expressions take precedence over
92
+ * newly analyzed JavaScript expressions for backward compatibility.
93
+ */
94
+ function mergePreservedCelExpressions(analyzedMappings, preservedMappings) {
95
+ const mergedMappings = { ...analyzedMappings };
96
+ // Preserved CEL expressions take precedence
97
+ for (const [path, celExpression] of Object.entries(preservedMappings)) {
98
+ // Handle nested paths by setting the value at the correct location
99
+ const pathParts = path.split('.');
100
+ let current = mergedMappings;
101
+ for (let i = 0; i < pathParts.length - 1; i++) {
102
+ const part = pathParts[i];
103
+ if (!part)
104
+ continue;
105
+ if (!current[part] || typeof current[part] !== 'object') {
106
+ current[part] = {};
107
+ }
108
+ current = current[part];
109
+ }
110
+ const finalKey = pathParts[pathParts.length - 1];
111
+ if (finalKey) {
112
+ current[finalKey] = celExpression;
113
+ }
114
+ }
115
+ return mergedMappings;
116
+ }
117
+ /**
118
+ * Comprehensive analysis of status mappings to categorize different types of expressions
119
+ *
120
+ * This function provides detailed analysis of status mappings to determine:
121
+ * - Which fields contain KubernetesRef objects (need conversion)
122
+ * - Which fields are existing CEL expressions (preserve as-is)
123
+ * - Which fields are static values (no conversion needed)
124
+ * - Which fields are complex expressions that might need analysis
125
+ */
126
+ function analyzeStatusMappingTypes(statusMappings, path = '') {
127
+ const kubernetesRefFields = [];
128
+ const celExpressionFields = [];
129
+ const staticValueFields = [];
130
+ const complexExpressionFields = [];
131
+ const analysisDetails = {};
132
+ if (!statusMappings || typeof statusMappings !== 'object') {
133
+ return {
134
+ kubernetesRefFields,
135
+ celExpressionFields,
136
+ staticValueFields,
137
+ complexExpressionFields,
138
+ analysisDetails
139
+ };
140
+ }
141
+ for (const [key, value] of Object.entries(statusMappings)) {
142
+ const currentPath = path ? `${path}.${key}` : key;
143
+ // Analyze the value type and requirements
144
+ const analysis = analyzeValueType(value);
145
+ analysisDetails[currentPath] = analysis;
146
+ switch (analysis.type) {
147
+ case 'kubernetesRef':
148
+ kubernetesRefFields.push(currentPath);
149
+ break;
150
+ case 'celExpression':
151
+ celExpressionFields.push(currentPath);
152
+ break;
153
+ case 'staticValue':
154
+ staticValueFields.push(currentPath);
155
+ break;
156
+ case 'complexExpression':
157
+ complexExpressionFields.push(currentPath);
158
+ break;
159
+ }
160
+ // Recursively analyze nested objects
161
+ if (value && typeof value === 'object' && !Array.isArray(value) && !isCelExpression(value) && !containsKubernetesRefs(value)) {
162
+ const nestedAnalysis = analyzeStatusMappingTypes(value, currentPath);
163
+ kubernetesRefFields.push(...nestedAnalysis.kubernetesRefFields);
164
+ celExpressionFields.push(...nestedAnalysis.celExpressionFields);
165
+ staticValueFields.push(...nestedAnalysis.staticValueFields);
166
+ complexExpressionFields.push(...nestedAnalysis.complexExpressionFields);
167
+ Object.assign(analysisDetails, nestedAnalysis.analysisDetails);
168
+ }
169
+ }
170
+ return {
171
+ kubernetesRefFields,
172
+ celExpressionFields,
173
+ staticValueFields,
174
+ complexExpressionFields,
175
+ analysisDetails
176
+ };
177
+ }
178
+ /**
179
+ * Analyze a single value to determine its type and conversion requirements
180
+ */
181
+ function analyzeValueType(value) {
182
+ // Check for existing CEL expressions first (highest priority)
183
+ if (isCelExpression(value)) {
184
+ return {
185
+ type: 'celExpression',
186
+ value,
187
+ requiresConversion: false,
188
+ confidence: 1.0
189
+ };
190
+ }
191
+ // Check for KubernetesRef objects (need conversion)
192
+ if (containsKubernetesRefs(value)) {
193
+ return {
194
+ type: 'kubernetesRef',
195
+ value,
196
+ requiresConversion: true,
197
+ confidence: 1.0
198
+ };
199
+ }
200
+ // Check for primitive static values
201
+ if (value === null ||
202
+ value === undefined ||
203
+ typeof value === 'string' ||
204
+ typeof value === 'number' ||
205
+ typeof value === 'boolean') {
206
+ return {
207
+ type: 'staticValue',
208
+ value,
209
+ requiresConversion: false,
210
+ confidence: 1.0
211
+ };
212
+ }
213
+ // Check for arrays of static values
214
+ if (Array.isArray(value)) {
215
+ const hasKubernetesRefs = value.some(item => containsKubernetesRefs(item));
216
+ const hasCelExpressions = value.some(item => isCelExpression(item));
217
+ if (hasKubernetesRefs) {
218
+ return {
219
+ type: 'kubernetesRef',
220
+ value,
221
+ requiresConversion: true,
222
+ confidence: 0.9
223
+ };
224
+ }
225
+ else if (hasCelExpressions) {
226
+ return {
227
+ type: 'celExpression',
228
+ value,
229
+ requiresConversion: false,
230
+ confidence: 0.9
231
+ };
232
+ }
233
+ else {
234
+ return {
235
+ type: 'staticValue',
236
+ value,
237
+ requiresConversion: false,
238
+ confidence: 0.8
239
+ };
240
+ }
241
+ }
242
+ // Check for plain objects (might be complex expressions or static data)
243
+ if (value && typeof value === 'object') {
244
+ const hasKubernetesRefs = containsKubernetesRefs(value);
245
+ const hasCelExpressions = Object.values(value).some(v => isCelExpression(v));
246
+ if (hasKubernetesRefs) {
247
+ return {
248
+ type: 'kubernetesRef',
249
+ value,
250
+ requiresConversion: true,
251
+ confidence: 0.8
252
+ };
253
+ }
254
+ else if (hasCelExpressions) {
255
+ return {
256
+ type: 'celExpression',
257
+ value,
258
+ requiresConversion: false,
259
+ confidence: 0.8
260
+ };
261
+ }
262
+ else {
263
+ // Could be static data or complex expression - analyze further
264
+ const isLikelyStatic = isLikelyStaticObject(value);
265
+ if (isLikelyStatic) {
266
+ return {
267
+ type: 'staticValue',
268
+ value,
269
+ requiresConversion: false,
270
+ confidence: 0.7
271
+ };
272
+ }
273
+ else {
274
+ return {
275
+ type: 'complexExpression',
276
+ value,
277
+ requiresConversion: false, // Conservative - don't convert unless we're sure
278
+ confidence: 0.5
279
+ };
280
+ }
281
+ }
282
+ }
283
+ // Unknown type - treat as complex expression
284
+ return {
285
+ type: 'complexExpression',
286
+ value,
287
+ requiresConversion: false,
288
+ confidence: 0.3
289
+ };
290
+ }
291
+ /**
292
+ * Determine if an object is likely to be static data rather than an expression
293
+ */
294
+ function isLikelyStaticObject(obj) {
295
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
296
+ return false;
297
+ }
298
+ // Check if all values are primitive types
299
+ const values = Object.values(obj);
300
+ const allPrimitive = values.every(value => value === null ||
301
+ value === undefined ||
302
+ typeof value === 'string' ||
303
+ typeof value === 'number' ||
304
+ typeof value === 'boolean');
305
+ if (allPrimitive) {
306
+ return true;
307
+ }
308
+ // Check for common static object patterns
309
+ const keys = Object.keys(obj);
310
+ const hasCommonStaticKeys = keys.some(key => ['name', 'id', 'type', 'kind', 'version', 'label', 'tag'].includes(key.toLowerCase()));
311
+ return hasCommonStaticKeys && values.length <= 10; // Reasonable size for static config
312
+ }
38
313
  /**
39
314
  * Create a ResourceGraph from resources for deployment
40
315
  */
@@ -110,10 +385,261 @@ function createTypedResourceGraph(definition, resourceBuilder, statusBuilder, op
110
385
  const builderResult = resourceBuilder(schema);
111
386
  // Separate Enhanced<> resources from deployment closures
112
387
  const { resources: resourcesWithKeys, closures } = separateResourcesAndClosures(builderResult);
113
- // Pass Enhanced resources directly to StatusBuilder - they already have proper MagicProxy types
114
- const statusMappings = statusBuilder(schema, resourcesWithKeys);
388
+ // NEW: Analyze status builder for JavaScript expressions with KubernetesRef detection
389
+ let statusMappings;
390
+ let analyzedStatusMappings = {};
391
+ let mappingAnalysis;
392
+ let imperativeAnalysisSucceeded = false;
393
+ try {
394
+ // Execute the status builder to get the return object
395
+ globalThis.__TYPEKRO_STATUS_BUILDER_CONTEXT__ = true;
396
+ try {
397
+ statusMappings = statusBuilder(schema, resourcesWithKeys);
398
+ }
399
+ finally {
400
+ delete globalThis.__TYPEKRO_STATUS_BUILDER_CONTEXT__;
401
+ }
402
+ // Check if this is from an imperative composition with original expressions
403
+ const originalCompositionFn = statusMappings.__originalCompositionFn;
404
+ // Debug logging removed for cleaner output
405
+ if (originalCompositionFn) {
406
+ serializationLogger.debug('Detected imperative composition, checking for existing KubernetesRef objects');
407
+ // First, check if the status object already contains KubernetesRef objects or CelExpression objects
408
+ // If so, we can use those directly instead of parsing the JavaScript source code
409
+ let hasKubernetesRefs = containsKubernetesRefs(statusMappings);
410
+ let hasCelExpressions = containsCelExpressions(statusMappings);
411
+ serializationLogger.debug('Imperative composition analysis', {
412
+ hasKubernetesRefs,
413
+ hasCelExpressions,
414
+ statusMappings: JSON.stringify(statusMappings, null, 2)
415
+ });
416
+ if (hasKubernetesRefs || hasCelExpressions) {
417
+ serializationLogger.debug('Status object already contains KubernetesRef objects or CelExpression objects, using direct analysis');
418
+ // Use the status builder analyzer to process the existing KubernetesRef objects
419
+ try {
420
+ const statusBuilderAnalysis = analyzeStatusBuilderForToResourceGraph(statusBuilder, resourcesWithKeys, schema, 'kro');
421
+ if (statusBuilderAnalysis.requiresConversion) {
422
+ analyzedStatusMappings = statusBuilderAnalysis.statusMappings;
423
+ imperativeAnalysisSucceeded = true;
424
+ serializationLogger.debug('Using status builder analysis for imperative composition', {
425
+ fieldCount: Object.keys(analyzedStatusMappings).length
426
+ });
427
+ }
428
+ else {
429
+ analyzedStatusMappings = statusMappings;
430
+ serializationLogger.debug('No conversion required, using original status mappings');
431
+ }
432
+ }
433
+ catch (statusAnalysisError) {
434
+ serializationLogger.debug('Status builder analysis failed, falling back to imperative analysis', {
435
+ error: statusAnalysisError.message
436
+ });
437
+ // Fall back to imperative analysis
438
+ hasKubernetesRefs = false;
439
+ hasCelExpressions = false;
440
+ }
441
+ }
442
+ if (!hasKubernetesRefs && !hasCelExpressions) {
443
+ serializationLogger.debug('No KubernetesRef objects or CelExpression objects found, analyzing original composition function');
444
+ // For imperative compositions, we need to analyze the original composition function
445
+ // to detect JavaScript expressions that should be converted to CEL
446
+ try {
447
+ const imperativeAnalysis = analyzeImperativeComposition(originalCompositionFn, resourcesWithKeys, { factoryType: 'kro' });
448
+ serializationLogger.debug('Imperative analysis result', {
449
+ statusFieldCount: Object.keys(imperativeAnalysis.statusMappings).length,
450
+ hasJavaScriptExpressions: imperativeAnalysis.hasJavaScriptExpressions,
451
+ errorCount: imperativeAnalysis.errors.length
452
+ });
453
+ serializationLogger.debug('Imperative composition analysis complete', {
454
+ statusFieldCount: Object.keys(imperativeAnalysis.statusMappings).length,
455
+ hasJavaScriptExpressions: imperativeAnalysis.hasJavaScriptExpressions
456
+ });
457
+ if (imperativeAnalysis.hasJavaScriptExpressions) {
458
+ analyzedStatusMappings = imperativeAnalysis.statusMappings;
459
+ imperativeAnalysisSucceeded = true;
460
+ serializationLogger.debug('Using analyzed imperative composition mappings with CEL expressions', {
461
+ fieldCount: Object.keys(analyzedStatusMappings).length
462
+ });
463
+ }
464
+ else {
465
+ analyzedStatusMappings = statusMappings;
466
+ serializationLogger.debug('No JavaScript expressions found, using original status mappings');
467
+ }
468
+ }
469
+ catch (imperativeAnalysisError) {
470
+ serializationLogger.debug('Imperative composition analysis failed, using executed status mappings', {
471
+ error: imperativeAnalysisError.message
472
+ });
473
+ analyzedStatusMappings = statusMappings;
474
+ }
475
+ }
476
+ }
477
+ else {
478
+ // Regular status builder - try to analyze it directly
479
+ try {
480
+ const statusBuilderAnalysis = analyzeStatusBuilderForToResourceGraph(statusBuilder, resourcesWithKeys, schema, 'kro');
481
+ serializationLogger.debug('Status builder analysis complete', {
482
+ statusFieldCount: Object.keys(statusBuilderAnalysis.statusMappings).length,
483
+ dependencyCount: statusBuilderAnalysis.dependencies.length,
484
+ hasJavaScriptExpressions: statusBuilderAnalysis.dependencies.length > 0
485
+ });
486
+ if (statusBuilderAnalysis.dependencies.length > 0) {
487
+ analyzedStatusMappings = statusBuilderAnalysis.statusMappings;
488
+ serializationLogger.debug('Using analyzed status mappings with CEL expressions', {
489
+ fieldCount: Object.keys(analyzedStatusMappings).length
490
+ });
491
+ }
492
+ else {
493
+ analyzedStatusMappings = statusMappings;
494
+ }
495
+ }
496
+ catch (analysisError) {
497
+ serializationLogger.debug('Status builder analysis failed, using executed status mappings', {
498
+ error: analysisError.message
499
+ });
500
+ analyzedStatusMappings = statusMappings;
501
+ }
502
+ }
503
+ // COMPREHENSIVE ANALYSIS: Analyze the final status mappings
504
+ mappingAnalysis = analyzeStatusMappingTypes(analyzedStatusMappings);
505
+ serializationLogger.debug('Final mapping analysis result', {
506
+ kubernetesRefFields: mappingAnalysis.kubernetesRefFields.length,
507
+ celExpressionFields: mappingAnalysis.celExpressionFields.length,
508
+ staticValueFields: mappingAnalysis.staticValueFields.length,
509
+ complexExpressionFields: mappingAnalysis.complexExpressionFields.length
510
+ });
511
+ serializationLogger.debug('Status mapping analysis complete', {
512
+ kubernetesRefFields: mappingAnalysis.kubernetesRefFields.length,
513
+ celExpressionFields: mappingAnalysis.celExpressionFields.length,
514
+ staticValueFields: mappingAnalysis.staticValueFields.length,
515
+ complexExpressionFields: mappingAnalysis.complexExpressionFields.length
516
+ });
517
+ // BACKWARD COMPATIBILITY: Detect and preserve existing CEL expressions
518
+ const { hasExistingCel, preservedMappings } = detectAndPreserveCelExpressions(statusMappings);
519
+ if (hasExistingCel) {
520
+ serializationLogger.debug('Found existing CEL expressions, preserving for backward compatibility', {
521
+ preservedCount: Object.keys(preservedMappings).length
522
+ });
523
+ // MIGRATION HELPER: Provide migration suggestions for existing CEL expressions
524
+ try {
525
+ const migrationHelper = new CelToJavaScriptMigrationHelper();
526
+ const migrationAnalysis = migrationHelper.analyzeMigrationOpportunities(statusMappings);
527
+ if (migrationAnalysis.migrationFeasibility.migratableExpressions > 0) {
528
+ serializationLogger.info('Migration opportunities detected for CEL expressions', {
529
+ totalExpressions: migrationAnalysis.migrationFeasibility.totalExpressions,
530
+ migratableExpressions: migrationAnalysis.migrationFeasibility.migratableExpressions,
531
+ overallConfidence: Math.round(migrationAnalysis.migrationFeasibility.overallConfidence * 100)
532
+ });
533
+ // Log migration suggestions for high-confidence migrations
534
+ const highConfidenceSuggestions = migrationAnalysis.suggestions.filter(s => s.confidence >= 0.8 && s.isSafe);
535
+ if (highConfidenceSuggestions.length > 0) {
536
+ serializationLogger.info('High-confidence migration suggestions available', {
537
+ suggestions: highConfidenceSuggestions.map(s => ({
538
+ original: s.originalCel,
539
+ suggested: s.suggestedJavaScript,
540
+ confidence: Math.round(s.confidence * 100)
541
+ }))
542
+ });
543
+ }
544
+ }
545
+ }
546
+ catch (migrationError) {
547
+ serializationLogger.warn('Failed to analyze migration opportunities', migrationError);
548
+ }
549
+ }
550
+ // The issue is that JavaScript expressions are evaluated before we can analyze them
551
+ // We need to re-execute the status builder with a special proxy that intercepts expressions
552
+ // and converts them to CEL expressions before evaluation
553
+ // For now, let's use a simpler approach: detect KubernetesRef objects in the raw status mappings
554
+ // and convert them directly to CEL expressions
555
+ const celConversionEngine = new CelConversionEngine();
556
+ // Convert the status mappings to CEL expressions for Kro factories
557
+ const convertedStatusMappings = {};
558
+ let hasConversions = false;
559
+ for (const [fieldName, fieldValue] of Object.entries(statusMappings)) {
560
+ // Check if this field contains KubernetesRef objects
561
+ if (containsKubernetesRefs(fieldValue)) {
562
+ // Convert to CEL expression
563
+ const conversionResult = celConversionEngine.convertValue(fieldValue, { factoryType: 'kro', factoryName: definition.name, analysisEnabled: true }, { factoryType: 'kro', preserveStatic: false });
564
+ if (conversionResult.wasConverted) {
565
+ convertedStatusMappings[fieldName] = conversionResult.converted;
566
+ hasConversions = true;
567
+ serializationLogger.debug('Converted field to CEL expression', {
568
+ fieldName,
569
+ strategy: conversionResult.strategy,
570
+ referencesConverted: conversionResult.metrics.referencesConverted
571
+ });
572
+ }
573
+ else {
574
+ convertedStatusMappings[fieldName] = fieldValue;
575
+ }
576
+ }
577
+ else {
578
+ // Keep static values as-is
579
+ convertedStatusMappings[fieldName] = fieldValue;
580
+ }
581
+ }
582
+ if (hasConversions) {
583
+ // Only overwrite if imperative analysis hasn't already provided CEL expressions
584
+ if (!imperativeAnalysisSucceeded) {
585
+ // Merge converted CEL expressions with preserved ones (preserved take precedence)
586
+ analyzedStatusMappings = mergePreservedCelExpressions(convertedStatusMappings, preservedMappings);
587
+ }
588
+ serializationLogger.debug('Successfully converted JavaScript expressions to CEL', {
589
+ convertedFields: Object.keys(convertedStatusMappings).filter(key => convertedStatusMappings[key] !== statusMappings[key]).length,
590
+ preservedFields: Object.keys(preservedMappings).length,
591
+ staticFields: mappingAnalysis.staticValueFields.length
592
+ });
593
+ }
594
+ else {
595
+ // No KubernetesRef objects found, but may have existing CEL expressions or static values
596
+ if (hasExistingCel) {
597
+ // Only overwrite if imperative analysis hasn't already provided CEL expressions
598
+ if (!imperativeAnalysisSucceeded) {
599
+ // Merge original mappings with preserved CEL expressions
600
+ analyzedStatusMappings = mergePreservedCelExpressions(statusMappings, preservedMappings);
601
+ }
602
+ serializationLogger.debug('Preserved existing CEL expressions without conversion', {
603
+ preservedFields: Object.keys(preservedMappings).length,
604
+ staticFields: mappingAnalysis.staticValueFields.length,
605
+ complexFields: mappingAnalysis.complexExpressionFields.length
606
+ });
607
+ }
608
+ else {
609
+ // No KubernetesRef objects or CEL expressions, use status mappings as-is
610
+ if (!imperativeAnalysisSucceeded) {
611
+ analyzedStatusMappings = statusMappings;
612
+ }
613
+ serializationLogger.debug('Status builder contains only static values and complex expressions', {
614
+ staticFields: mappingAnalysis.staticValueFields.length,
615
+ complexFields: mappingAnalysis.complexExpressionFields.length,
616
+ totalFields: Object.keys(mappingAnalysis.analysisDetails).length
617
+ });
618
+ }
619
+ }
620
+ }
621
+ catch (error) {
622
+ serializationLogger.error('Failed to analyze status builder', error);
623
+ // Fallback to executing status builder normally
624
+ globalThis.__TYPEKRO_STATUS_BUILDER_CONTEXT__ = true;
625
+ try {
626
+ statusMappings = statusBuilder(schema, resourcesWithKeys);
627
+ }
628
+ finally {
629
+ delete globalThis.__TYPEKRO_STATUS_BUILDER_CONTEXT__;
630
+ }
631
+ analyzedStatusMappings = statusMappings;
632
+ // Create empty analysis for fallback
633
+ mappingAnalysis = {
634
+ kubernetesRefFields: [],
635
+ celExpressionFields: [],
636
+ staticValueFields: [],
637
+ complexExpressionFields: [],
638
+ analysisDetails: {}
639
+ };
640
+ }
115
641
  // Validate resource IDs and CEL expressions
116
- const validation = validateResourceGraphDefinition(resourcesWithKeys, statusMappings);
642
+ const validation = validateResourceGraphDefinition(resourcesWithKeys, analyzedStatusMappings);
117
643
  if (!validation.isValid) {
118
644
  const errorMessages = validation.errors.map((err) => `${err.field}: ${err.error}`).join('\n');
119
645
  throw new Error(`ResourceGraphDefinition validation failed:\n${errorMessages}`);
@@ -130,7 +656,7 @@ function createTypedResourceGraph(definition, resourceBuilder, statusBuilder, op
130
656
  }
131
657
  // Evaluate and optimize CEL expressions
132
658
  const evaluationContext = { resources: resourcesWithKeys, schema };
133
- const { mappings: optimizedStatusMappings, optimizations } = optimizeStatusMappings(statusMappings, evaluationContext);
659
+ const { mappings: optimizedStatusMappings, optimizations } = optimizeStatusMappings(analyzedStatusMappings, evaluationContext);
134
660
  // Log optimizations if any
135
661
  if (optimizations.length > 0) {
136
662
  serializationLogger.info('CEL expression optimizations applied', { optimizations });
@@ -213,15 +739,53 @@ function createTypedResourceGraph(definition, resourceBuilder, statusBuilder, op
213
739
  schema,
214
740
  // Store closures for access during factory creation
215
741
  closures,
742
+ // Store analysis results for factory-specific processing
743
+ _analysisResults: {
744
+ mappingAnalysis,
745
+ hasKubernetesRefs: mappingAnalysis.kubernetesRefFields.length > 0,
746
+ statusMappings,
747
+ analyzedStatusMappings
748
+ },
216
749
  factory(mode, factoryOptions) {
217
750
  if (mode === 'direct') {
218
- const directFactory = createDirectResourceFactory(definition.name, resourcesWithKeys, schemaDefinition, statusBuilder, { ...factoryOptions, closures } // Pass closures to factory
219
- );
751
+ // For direct factory, we need to re-analyze status mappings with direct factory context
752
+ let directStatusMappings = analyzedStatusMappings;
753
+ if (this._analysisResults.hasKubernetesRefs) {
754
+ try {
755
+ serializationLogger.debug('Re-analyzing status mappings for direct factory pattern');
756
+ const directStatusAnalyzer = new StatusBuilderAnalyzer(undefined, {
757
+ factoryType: 'direct',
758
+ performOptionalityAnalysis: true,
759
+ includeSourceMapping: true
760
+ });
761
+ const directAnalysisResult = directStatusAnalyzer.analyzeReturnObjectWithMagicProxy(this._analysisResults.statusMappings, resourcesWithKeys, schema);
762
+ if (directAnalysisResult.errors.length === 0) {
763
+ // Merge with preserved CEL expressions
764
+ const { preservedMappings: directPreservedMappings } = detectAndPreserveCelExpressions(this._analysisResults.statusMappings);
765
+ directStatusMappings = mergePreservedCelExpressions(directAnalysisResult.statusMappings, directPreservedMappings);
766
+ serializationLogger.debug('Successfully re-analyzed status mappings for direct factory');
767
+ }
768
+ }
769
+ catch (error) {
770
+ serializationLogger.warn('Failed to re-analyze status mappings for direct factory, using default analysis', error);
771
+ }
772
+ }
773
+ const directFactory = createDirectResourceFactory(definition.name, resourcesWithKeys, schemaDefinition, statusBuilder, {
774
+ ...factoryOptions,
775
+ closures,
776
+ // Pass the factory-specific status mappings
777
+ statusMappings: directStatusMappings
778
+ });
220
779
  return directFactory;
221
780
  }
222
781
  else if (mode === 'kro') {
223
- const kroFactory = createKroResourceFactory(definition.name, resourcesWithKeys, schemaDefinition, statusMappings, { ...factoryOptions, closures } // Pass closures to Kro factory for validation and execution
224
- );
782
+ // For Kro factory, use the already analyzed status mappings (which default to Kro pattern)
783
+ const kroFactory = createKroResourceFactory(definition.name, resourcesWithKeys, schemaDefinition, analyzedStatusMappings, {
784
+ ...factoryOptions,
785
+ closures,
786
+ // Indicate this is for Kro factory pattern
787
+ factoryType: 'kro'
788
+ });
225
789
  return kroFactory;
226
790
  }
227
791
  else {
@@ -243,7 +807,7 @@ function createTypedResourceGraph(definition, resourceBuilder, statusBuilder, op
243
807
  }
244
808
  // For unknown properties, check if it's a resource key and create external ref
245
809
  const matchingResource = findResourceByKey(prop);
246
- if (matchingResource && matchingResource.metadata.name) {
810
+ if (matchingResource?.metadata.name) {
247
811
  return externalRef(matchingResource.apiVersion, matchingResource.kind, matchingResource.metadata.name, matchingResource.metadata.namespace);
248
812
  }
249
813
  // Return undefined for non-existent properties (standard JavaScript behavior)