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
@@ -0,0 +1,838 @@
1
+ /**
2
+ * Type Inference for CEL Expressions
3
+ *
4
+ * This module provides type inference capabilities for CEL expressions
5
+ * generated from JavaScript expressions. It analyzes CEL expressions
6
+ * to determine their result types and validates type compatibility.
7
+ */
8
+ /**
9
+ * Type inference error
10
+ */
11
+ export class TypeInferenceError extends Error {
12
+ celExpression;
13
+ location;
14
+ constructor(message, celExpression, location) {
15
+ super(message);
16
+ this.celExpression = celExpression;
17
+ this.location = location;
18
+ this.name = 'TypeInferenceError';
19
+ }
20
+ static forUnknownFunction(celExpression, functionName, location) {
21
+ return new TypeInferenceError(`Unknown CEL function: ${functionName}`, celExpression, location);
22
+ }
23
+ static forIncompatibleOperands(celExpression, operator, leftType, rightType, location) {
24
+ return new TypeInferenceError(`Incompatible operands for operator '${operator}': ${leftType.typeName} and ${rightType.typeName}`, celExpression, location);
25
+ }
26
+ static forUnresolvableReference(celExpression, reference, location) {
27
+ return new TypeInferenceError(`Cannot resolve reference: ${reference}`, celExpression, location);
28
+ }
29
+ }
30
+ /**
31
+ * Type inference warning
32
+ */
33
+ export class TypeInferenceWarning {
34
+ message;
35
+ celExpression;
36
+ location;
37
+ constructor(message, celExpression, location) {
38
+ this.message = message;
39
+ this.celExpression = celExpression;
40
+ this.location = location;
41
+ }
42
+ static forPotentialNullDereference(celExpression, reference, location) {
43
+ return new TypeInferenceWarning(`Potential null dereference: ${reference}`, celExpression, location);
44
+ }
45
+ static forImplicitTypeConversion(celExpression, fromType, toType, location) {
46
+ return new TypeInferenceWarning(`Implicit type conversion from ${fromType} to ${toType}`, celExpression, location);
47
+ }
48
+ }
49
+ /**
50
+ * CEL type inference engine
51
+ */
52
+ export class CelTypeInferenceEngine {
53
+ functionTypes = new Map();
54
+ operatorTypes = new Map();
55
+ constructor() {
56
+ this.initializeBuiltinTypes();
57
+ }
58
+ /**
59
+ * Infer the type of a CEL expression
60
+ */
61
+ inferType(celExpression, context) {
62
+ try {
63
+ const expression = celExpression.expression;
64
+ const result = this.analyzeExpression(expression, context);
65
+ return {
66
+ resultType: result.type,
67
+ success: true,
68
+ errors: result.errors,
69
+ warnings: result.warnings,
70
+ confidence: result.confidence,
71
+ metadata: result.metadata
72
+ };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ resultType: { typeName: 'unknown', optional: false, nullable: false },
77
+ success: false,
78
+ errors: [new TypeInferenceError(`Type inference failed: ${error instanceof Error ? error.message : String(error)}`, celExpression.expression)],
79
+ warnings: [],
80
+ confidence: 0,
81
+ metadata: this.createEmptyMetadata()
82
+ };
83
+ }
84
+ }
85
+ /**
86
+ * Infer types for multiple CEL expressions
87
+ */
88
+ inferTypes(celExpressions, context) {
89
+ return celExpressions.map(expr => this.inferType(expr, context));
90
+ }
91
+ /**
92
+ * Validate type compatibility between expressions
93
+ */
94
+ validateTypeCompatibility(sourceType, targetType) {
95
+ const errors = [];
96
+ const warnings = [];
97
+ // Check exact type match
98
+ if (sourceType.typeName === targetType.typeName) {
99
+ return {
100
+ valid: true,
101
+ resultType: targetType,
102
+ errors: [],
103
+ warnings: [],
104
+ suggestions: []
105
+ };
106
+ }
107
+ // Check assignability
108
+ if (this.isAssignable(sourceType, targetType)) {
109
+ if (this.requiresImplicitConversion(sourceType, targetType)) {
110
+ warnings.push(TypeInferenceWarning.forImplicitTypeConversion('', sourceType.typeName, targetType.typeName));
111
+ }
112
+ return {
113
+ valid: true,
114
+ resultType: targetType,
115
+ errors: [],
116
+ warnings: warnings.map(w => ({ message: w.message, expression: w.celExpression })),
117
+ suggestions: []
118
+ };
119
+ }
120
+ // Type mismatch
121
+ errors.push(TypeInferenceError.forIncompatibleOperands('', '=', sourceType, targetType));
122
+ return {
123
+ valid: false,
124
+ resultType: targetType,
125
+ errors: errors.map(e => ({
126
+ message: e.message,
127
+ expression: e.celExpression,
128
+ expectedType: targetType,
129
+ actualType: sourceType,
130
+ name: 'TypeValidationError'
131
+ })),
132
+ warnings: [],
133
+ suggestions: [`Convert ${sourceType.typeName} to ${targetType.typeName}`]
134
+ };
135
+ }
136
+ /**
137
+ * Analyze a CEL expression and infer its type
138
+ */
139
+ analyzeExpression(expression, context) {
140
+ const errors = [];
141
+ const warnings = [];
142
+ const metadata = this.createEmptyMetadata();
143
+ // First, extract all resource references from the expression
144
+ this.extractResourceReferences(expression, metadata);
145
+ // Parse the expression into tokens
146
+ const tokens = this.tokenizeExpression(expression);
147
+ // Analyze different expression patterns
148
+ if (this.isBinaryOperation(tokens)) {
149
+ return this.analyzeBinaryOperation(tokens, context, metadata);
150
+ }
151
+ if (this.isFunctionCall(tokens)) {
152
+ return this.analyzeFunctionCall(tokens, context, metadata);
153
+ }
154
+ if (this.isResourceReference(tokens)) {
155
+ return this.analyzeResourceReference(tokens, context, metadata);
156
+ }
157
+ if (this.isSchemaReference(tokens)) {
158
+ return this.analyzeSchemaReference(tokens, context, metadata);
159
+ }
160
+ if (this.isLiteral(tokens)) {
161
+ return this.analyzeLiteral(tokens, context, metadata);
162
+ }
163
+ if (this.isConditionalExpression(tokens)) {
164
+ return this.analyzeConditionalExpression(tokens, context, metadata);
165
+ }
166
+ // Default to unknown type
167
+ return {
168
+ type: { typeName: 'unknown', optional: false, nullable: false },
169
+ errors,
170
+ warnings,
171
+ confidence: 0.1,
172
+ metadata
173
+ };
174
+ }
175
+ /**
176
+ * Analyze binary operations (>, <, ==, !=, &&, ||, +, -, *, /)
177
+ */
178
+ analyzeBinaryOperation(tokens, context, metadata) {
179
+ const errors = [];
180
+ const warnings = [];
181
+ // Find the operator
182
+ const operatorIndex = this.findMainOperator(tokens);
183
+ if (operatorIndex === -1) {
184
+ errors.push(TypeInferenceError.forUnknownFunction('', 'binary operator'));
185
+ return {
186
+ type: { typeName: 'unknown', optional: false, nullable: false },
187
+ errors,
188
+ warnings,
189
+ confidence: 0,
190
+ metadata
191
+ };
192
+ }
193
+ const operator = tokens[operatorIndex];
194
+ if (!operator) {
195
+ errors.push(TypeInferenceError.forUnknownFunction('', 'unknown_operator'));
196
+ return {
197
+ type: { typeName: 'unknown', optional: false, nullable: false },
198
+ errors,
199
+ warnings,
200
+ confidence: 0,
201
+ metadata
202
+ };
203
+ }
204
+ const leftTokens = tokens.slice(0, operatorIndex);
205
+ const rightTokens = tokens.slice(operatorIndex + 1);
206
+ // Analyze operands
207
+ const leftResult = this.analyzeExpression(leftTokens.join(' '), context);
208
+ const rightResult = this.analyzeExpression(rightTokens.join(' '), context);
209
+ // Determine result type based on operator
210
+ const operatorSignature = this.operatorTypes.get(operator);
211
+ if (!operatorSignature) {
212
+ errors.push(TypeInferenceError.forUnknownFunction('', operator));
213
+ return {
214
+ type: { typeName: 'unknown', optional: false, nullable: false },
215
+ errors,
216
+ warnings,
217
+ confidence: 0,
218
+ metadata
219
+ };
220
+ }
221
+ // Validate operand types
222
+ const resultType = this.getOperatorResultType(operator, leftResult.type, rightResult.type);
223
+ if (!resultType) {
224
+ errors.push(TypeInferenceError.forIncompatibleOperands('', operator, leftResult.type, rightResult.type));
225
+ return {
226
+ type: { typeName: 'unknown', optional: false, nullable: false },
227
+ errors,
228
+ warnings,
229
+ confidence: 0,
230
+ metadata
231
+ };
232
+ }
233
+ // Combine metadata
234
+ metadata.complexityScore += 1;
235
+ metadata.canReturnNull = leftResult.type.nullable || rightResult.type.nullable;
236
+ return {
237
+ type: resultType,
238
+ errors: [...errors, ...leftResult.errors, ...rightResult.errors],
239
+ warnings: [...warnings, ...leftResult.warnings, ...rightResult.warnings],
240
+ confidence: Math.min(leftResult.confidence, rightResult.confidence) * 0.9,
241
+ metadata
242
+ };
243
+ }
244
+ /**
245
+ * Analyze function calls
246
+ */
247
+ analyzeFunctionCall(tokens, _context, metadata) {
248
+ const errors = [];
249
+ const warnings = [];
250
+ // Extract function name - look for function call pattern
251
+ const expression = tokens.join(' ');
252
+ const functionMatch = expression.match(/(\w+)\s*\(/);
253
+ if (!functionMatch) {
254
+ errors.push(TypeInferenceError.forUnknownFunction('', 'unknown'));
255
+ return {
256
+ type: { typeName: 'unknown', optional: false, nullable: false },
257
+ errors,
258
+ warnings,
259
+ confidence: 0,
260
+ metadata
261
+ };
262
+ }
263
+ const functionName = functionMatch[1];
264
+ if (!functionName) {
265
+ errors.push(TypeInferenceError.forUnknownFunction('', 'unknown_function'));
266
+ return {
267
+ type: { typeName: 'unknown', optional: false, nullable: false },
268
+ errors,
269
+ warnings,
270
+ confidence: 0,
271
+ metadata
272
+ };
273
+ }
274
+ const functionSignature = this.functionTypes.get(functionName);
275
+ if (!functionSignature) {
276
+ errors.push(TypeInferenceError.forUnknownFunction('', functionName));
277
+ return {
278
+ type: { typeName: 'unknown', optional: false, nullable: false },
279
+ errors,
280
+ warnings,
281
+ confidence: 0,
282
+ metadata
283
+ };
284
+ }
285
+ metadata.functionsUsed.push(functionName);
286
+ metadata.complexityScore += 2;
287
+ return {
288
+ type: functionSignature.returnType,
289
+ errors,
290
+ warnings,
291
+ confidence: 0.8,
292
+ metadata
293
+ };
294
+ }
295
+ /**
296
+ * Analyze resource references (resources.name.field)
297
+ */
298
+ analyzeResourceReference(tokens, context, metadata) {
299
+ const errors = [];
300
+ const warnings = [];
301
+ const reference = tokens.join('').replace(/\s+/g, '');
302
+ metadata.resourceReferences.push(reference);
303
+ // Extract resource ID and field path
304
+ const match = reference.match(/^resources\.([^.]+)\.(.+)$/);
305
+ if (!match) {
306
+ errors.push(TypeInferenceError.forUnresolvableReference('', reference));
307
+ return {
308
+ type: { typeName: 'unknown', optional: false, nullable: false },
309
+ errors,
310
+ warnings,
311
+ confidence: 0,
312
+ metadata
313
+ };
314
+ }
315
+ const [, resourceId, fieldPath] = match;
316
+ if (!resourceId || !fieldPath) {
317
+ errors.push(TypeInferenceError.forUnresolvableReference('', reference));
318
+ return {
319
+ type: { typeName: 'unknown', optional: false, nullable: false },
320
+ errors,
321
+ warnings,
322
+ confidence: 0,
323
+ metadata
324
+ };
325
+ }
326
+ // Look up resource type
327
+ const resource = context.availableResources[resourceId];
328
+ if (!resource) {
329
+ errors.push(TypeInferenceError.forUnresolvableReference('', reference));
330
+ return {
331
+ type: { typeName: 'unknown', optional: false, nullable: false },
332
+ errors,
333
+ warnings,
334
+ confidence: 0,
335
+ metadata
336
+ };
337
+ }
338
+ // Infer field type
339
+ const fieldType = this.inferResourceFieldType(resource, fieldPath);
340
+ // Check for optional chaining
341
+ if (reference.includes('?')) {
342
+ metadata.usesOptionalChaining = true;
343
+ metadata.canReturnNull = true;
344
+ }
345
+ return {
346
+ type: fieldType,
347
+ errors,
348
+ warnings,
349
+ confidence: 0.9,
350
+ metadata
351
+ };
352
+ }
353
+ /**
354
+ * Analyze schema references (schema.spec.field)
355
+ */
356
+ analyzeSchemaReference(tokens, context, metadata) {
357
+ const errors = [];
358
+ const warnings = [];
359
+ const reference = tokens.join('');
360
+ metadata.schemaReferences.push(reference);
361
+ // Extract field path
362
+ const match = reference.match(/^schema\.(.+)$/);
363
+ if (!match) {
364
+ errors.push(TypeInferenceError.forUnresolvableReference('', reference));
365
+ return {
366
+ type: { typeName: 'unknown', optional: false, nullable: false },
367
+ errors,
368
+ warnings,
369
+ confidence: 0,
370
+ metadata
371
+ };
372
+ }
373
+ const [, fieldPath] = match;
374
+ if (!fieldPath) {
375
+ errors.push(TypeInferenceError.forUnresolvableReference('', reference));
376
+ return {
377
+ type: { typeName: 'unknown', optional: false, nullable: false },
378
+ errors,
379
+ warnings,
380
+ confidence: 0,
381
+ metadata
382
+ };
383
+ }
384
+ // Infer schema field type
385
+ const fieldType = this.inferSchemaFieldType(context.schemaProxy, fieldPath);
386
+ return {
387
+ type: fieldType,
388
+ errors,
389
+ warnings,
390
+ confidence: 0.9,
391
+ metadata
392
+ };
393
+ }
394
+ /**
395
+ * Analyze literal values
396
+ */
397
+ analyzeLiteral(tokens, _context, metadata) {
398
+ const literal = tokens.join(' ');
399
+ // String literals
400
+ if (literal.match(/^["'].*["']$/)) {
401
+ return {
402
+ type: { typeName: 'string', optional: false, nullable: false },
403
+ errors: [],
404
+ warnings: [],
405
+ confidence: 1.0,
406
+ metadata
407
+ };
408
+ }
409
+ // Number literals
410
+ if (literal.match(/^\d+(\.\d+)?$/)) {
411
+ return {
412
+ type: { typeName: 'number', optional: false, nullable: false },
413
+ errors: [],
414
+ warnings: [],
415
+ confidence: 1.0,
416
+ metadata
417
+ };
418
+ }
419
+ // Boolean literals
420
+ if (literal === 'true' || literal === 'false') {
421
+ return {
422
+ type: { typeName: 'boolean', optional: false, nullable: false },
423
+ errors: [],
424
+ warnings: [],
425
+ confidence: 1.0,
426
+ metadata
427
+ };
428
+ }
429
+ // Null literal
430
+ if (literal === 'null') {
431
+ return {
432
+ type: { typeName: 'null', optional: false, nullable: true },
433
+ errors: [],
434
+ warnings: [],
435
+ confidence: 1.0,
436
+ metadata
437
+ };
438
+ }
439
+ // Unknown literal
440
+ return {
441
+ type: { typeName: 'unknown', optional: false, nullable: false },
442
+ errors: [],
443
+ warnings: [],
444
+ confidence: 0.5,
445
+ metadata
446
+ };
447
+ }
448
+ /**
449
+ * Analyze conditional expressions (condition ? true : false)
450
+ */
451
+ analyzeConditionalExpression(tokens, context, metadata) {
452
+ const errors = [];
453
+ const warnings = [];
454
+ // Find ? and : operators
455
+ const questionIndex = tokens.indexOf('?');
456
+ const colonIndex = tokens.indexOf(':');
457
+ if (questionIndex === -1 || colonIndex === -1) {
458
+ errors.push(TypeInferenceError.forUnknownFunction('', 'conditional'));
459
+ return {
460
+ type: { typeName: 'unknown', optional: false, nullable: false },
461
+ errors,
462
+ warnings,
463
+ confidence: 0,
464
+ metadata
465
+ };
466
+ }
467
+ const conditionTokens = tokens.slice(0, questionIndex);
468
+ const trueTokens = tokens.slice(questionIndex + 1, colonIndex);
469
+ const falseTokens = tokens.slice(colonIndex + 1);
470
+ // Analyze each part
471
+ const conditionResult = this.analyzeExpression(conditionTokens.join(' '), context);
472
+ const trueResult = this.analyzeExpression(trueTokens.join(' '), context);
473
+ const falseResult = this.analyzeExpression(falseTokens.join(' '), context);
474
+ // Result type is the union of true and false branches
475
+ const resultType = this.unifyTypes(trueResult.type, falseResult.type);
476
+ metadata.complexityScore += 2;
477
+ metadata.canReturnNull = trueResult.type.nullable || falseResult.type.nullable;
478
+ return {
479
+ type: resultType,
480
+ errors: [...errors, ...conditionResult.errors, ...trueResult.errors, ...falseResult.errors],
481
+ warnings: [...warnings, ...conditionResult.warnings, ...trueResult.warnings, ...falseResult.warnings],
482
+ confidence: Math.min(conditionResult.confidence, trueResult.confidence, falseResult.confidence) * 0.9,
483
+ metadata
484
+ };
485
+ }
486
+ /**
487
+ * Initialize builtin CEL function and operator types
488
+ */
489
+ initializeBuiltinTypes() {
490
+ // Comparison operators
491
+ this.operatorTypes.set('>', {
492
+ leftType: { typeName: 'number', optional: false, nullable: false },
493
+ rightType: { typeName: 'number', optional: false, nullable: false },
494
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
495
+ });
496
+ this.operatorTypes.set('<', {
497
+ leftType: { typeName: 'number', optional: false, nullable: false },
498
+ rightType: { typeName: 'number', optional: false, nullable: false },
499
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
500
+ });
501
+ this.operatorTypes.set('==', {
502
+ leftType: { typeName: 'any', optional: false, nullable: false },
503
+ rightType: { typeName: 'any', optional: false, nullable: false },
504
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
505
+ });
506
+ this.operatorTypes.set('!=', {
507
+ leftType: { typeName: 'any', optional: false, nullable: false },
508
+ rightType: { typeName: 'any', optional: false, nullable: false },
509
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
510
+ });
511
+ // Logical operators
512
+ this.operatorTypes.set('&&', {
513
+ leftType: { typeName: 'boolean', optional: false, nullable: false },
514
+ rightType: { typeName: 'boolean', optional: false, nullable: false },
515
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
516
+ });
517
+ this.operatorTypes.set('||', {
518
+ leftType: { typeName: 'boolean', optional: false, nullable: false },
519
+ rightType: { typeName: 'boolean', optional: false, nullable: false },
520
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
521
+ });
522
+ // Arithmetic operators
523
+ this.operatorTypes.set('+', {
524
+ leftType: { typeName: 'number', optional: false, nullable: false },
525
+ rightType: { typeName: 'number', optional: false, nullable: false },
526
+ returnType: { typeName: 'number', optional: false, nullable: false }
527
+ });
528
+ // CEL functions
529
+ this.functionTypes.set('has', {
530
+ parameters: [{ typeName: 'string', optional: false, nullable: false }],
531
+ returnType: { typeName: 'boolean', optional: false, nullable: false }
532
+ });
533
+ this.functionTypes.set('size', {
534
+ parameters: [{ typeName: 'any', optional: false, nullable: false }],
535
+ returnType: { typeName: 'number', optional: false, nullable: false }
536
+ });
537
+ }
538
+ /**
539
+ * Utility methods
540
+ */
541
+ tokenizeExpression(expression) {
542
+ // Simple tokenization - would need more sophisticated parsing for production
543
+ return expression.split(/\s+/).filter(token => token.length > 0);
544
+ }
545
+ isBinaryOperation(tokens) {
546
+ return tokens.some(token => ['>', '<', '>=', '<=', '==', '!=', '&&', '||', '+', '-', '*', '/'].includes(token));
547
+ }
548
+ isFunctionCall(tokens) {
549
+ const expression = tokens.join(' ');
550
+ return expression.includes('(') && expression.includes(')');
551
+ }
552
+ isResourceReference(tokens) {
553
+ const expression = tokens.join('').replace(/\s+/g, '');
554
+ return expression.startsWith('resources.');
555
+ }
556
+ isSchemaReference(tokens) {
557
+ return tokens.join('').startsWith('schema.');
558
+ }
559
+ isLiteral(tokens) {
560
+ const joined = tokens.join(' ');
561
+ return joined.match(/^(["'].*["']|\d+(\.\d+)?|true|false|null)$/) !== null;
562
+ }
563
+ isConditionalExpression(tokens) {
564
+ return tokens.includes('?') && tokens.includes(':');
565
+ }
566
+ findMainOperator(tokens) {
567
+ // Find the main operator (simplified - would need proper precedence parsing)
568
+ const operators = ['||', '&&', '==', '!=', '>', '<', '>=', '<=', '+', '-', '*', '/'];
569
+ for (const op of operators) {
570
+ const index = tokens.indexOf(op);
571
+ if (index !== -1)
572
+ return index;
573
+ }
574
+ return -1;
575
+ }
576
+ getOperatorResultType(operator, _leftType, _rightType) {
577
+ const signature = this.operatorTypes.get(operator);
578
+ if (!signature)
579
+ return null;
580
+ // Simplified type checking
581
+ return signature.returnType;
582
+ }
583
+ isAssignable(sourceType, targetType) {
584
+ if (sourceType.typeName === targetType.typeName)
585
+ return true;
586
+ if (targetType.typeName === 'any')
587
+ return true;
588
+ if (sourceType.typeName === 'null' && targetType.nullable)
589
+ return true;
590
+ if (sourceType.typeName === 'undefined' && targetType.optional)
591
+ return true;
592
+ return false;
593
+ }
594
+ requiresImplicitConversion(sourceType, targetType) {
595
+ return sourceType.typeName !== targetType.typeName &&
596
+ targetType.typeName !== 'any';
597
+ }
598
+ inferResourceFieldType(resource, fieldPath) {
599
+ try {
600
+ const parts = fieldPath.split('.');
601
+ // Handle common Kubernetes resource field patterns
602
+ if (parts[0] === 'metadata') {
603
+ return this.getMetadataFieldType(parts.slice(1));
604
+ }
605
+ if (parts[0] === 'spec') {
606
+ return this.getSpecFieldType(resource, parts.slice(1));
607
+ }
608
+ if (parts[0] === 'status') {
609
+ return this.getStatusFieldType(resource, parts.slice(1));
610
+ }
611
+ return { typeName: 'unknown', optional: true, nullable: false };
612
+ }
613
+ catch (_error) {
614
+ return { typeName: 'unknown', optional: true, nullable: false };
615
+ }
616
+ }
617
+ getMetadataFieldType(fieldParts) {
618
+ const fieldName = fieldParts[0];
619
+ if (!fieldName) {
620
+ return { typeName: 'unknown', optional: true, nullable: false };
621
+ }
622
+ // Common metadata fields
623
+ const metadataTypes = {
624
+ 'name': { typeName: 'string', optional: false, nullable: false },
625
+ 'namespace': { typeName: 'string', optional: true, nullable: false },
626
+ 'labels': { typeName: 'Record<string, string>', optional: true, nullable: false },
627
+ 'annotations': { typeName: 'Record<string, string>', optional: true, nullable: false },
628
+ 'uid': { typeName: 'string', optional: true, nullable: false },
629
+ 'resourceVersion': { typeName: 'string', optional: true, nullable: false },
630
+ 'generation': { typeName: 'number', optional: true, nullable: false },
631
+ 'creationTimestamp': { typeName: 'string', optional: true, nullable: false }
632
+ };
633
+ if (fieldName in metadataTypes) {
634
+ const baseType = metadataTypes[fieldName];
635
+ if (!baseType) {
636
+ return { typeName: 'string', optional: true, nullable: false };
637
+ }
638
+ // Handle nested access (e.g., labels.app)
639
+ if (fieldParts.length > 1) {
640
+ if (baseType.typeName.startsWith('Record<')) {
641
+ return { typeName: 'string', optional: true, nullable: false };
642
+ }
643
+ }
644
+ return baseType;
645
+ }
646
+ return { typeName: 'string', optional: true, nullable: false };
647
+ }
648
+ getSpecFieldType(resource, fieldParts) {
649
+ const resourceKind = resource.constructor.name;
650
+ const fieldName = fieldParts[0];
651
+ if (!fieldName) {
652
+ return { typeName: 'unknown', optional: true, nullable: false };
653
+ }
654
+ // Common spec fields by resource type
655
+ const specFieldTypes = {
656
+ 'Deployment': {
657
+ 'replicas': { typeName: 'number', optional: true, nullable: false },
658
+ 'selector': { typeName: 'object', optional: false, nullable: false },
659
+ 'template': { typeName: 'object', optional: false, nullable: false },
660
+ 'strategy': { typeName: 'object', optional: true, nullable: false }
661
+ },
662
+ 'Service': {
663
+ 'type': { typeName: 'string', optional: true, nullable: false },
664
+ 'ports': { typeName: 'array', optional: false, nullable: false },
665
+ 'selector': { typeName: 'Record<string, string>', optional: true, nullable: false },
666
+ 'clusterIP': { typeName: 'string', optional: true, nullable: false }
667
+ },
668
+ 'ConfigMap': {
669
+ 'data': { typeName: 'Record<string, string>', optional: true, nullable: false },
670
+ 'binaryData': { typeName: 'Record<string, string>', optional: true, nullable: false }
671
+ }
672
+ };
673
+ const resourceFields = specFieldTypes[resourceKind];
674
+ if (resourceFields && fieldName in resourceFields) {
675
+ const baseType = resourceFields[fieldName];
676
+ // Handle nested access
677
+ if (fieldParts.length > 1 && baseType) {
678
+ if (baseType.typeName.startsWith('Record<')) {
679
+ return { typeName: 'string', optional: true, nullable: false };
680
+ }
681
+ if (baseType.typeName === 'array') {
682
+ return { typeName: 'object', optional: true, nullable: false };
683
+ }
684
+ if (baseType.typeName === 'object') {
685
+ return { typeName: 'unknown', optional: true, nullable: false };
686
+ }
687
+ }
688
+ return baseType || { typeName: 'unknown', optional: true, nullable: false };
689
+ }
690
+ return { typeName: 'unknown', optional: true, nullable: false };
691
+ }
692
+ getStatusFieldType(resource, fieldParts) {
693
+ const resourceKind = resource.constructor.name;
694
+ const fieldName = fieldParts[0];
695
+ if (!fieldName) {
696
+ return { typeName: 'unknown', optional: true, nullable: false };
697
+ }
698
+ // Common status fields by resource type
699
+ const statusFieldTypes = {
700
+ 'Deployment': {
701
+ 'replicas': { typeName: 'number', optional: true, nullable: false },
702
+ 'readyReplicas': { typeName: 'number', optional: true, nullable: false },
703
+ 'availableReplicas': { typeName: 'number', optional: true, nullable: false },
704
+ 'unavailableReplicas': { typeName: 'number', optional: true, nullable: false },
705
+ 'updatedReplicas': { typeName: 'number', optional: true, nullable: false },
706
+ 'conditions': { typeName: 'array', optional: true, nullable: false },
707
+ 'observedGeneration': { typeName: 'number', optional: true, nullable: false }
708
+ },
709
+ 'Service': {
710
+ 'loadBalancer': { typeName: 'object', optional: true, nullable: false },
711
+ 'conditions': { typeName: 'array', optional: true, nullable: false }
712
+ },
713
+ 'Pod': {
714
+ 'phase': { typeName: 'string', optional: true, nullable: false },
715
+ 'conditions': { typeName: 'array', optional: true, nullable: false },
716
+ 'hostIP': { typeName: 'string', optional: true, nullable: false },
717
+ 'podIP': { typeName: 'string', optional: true, nullable: false },
718
+ 'startTime': { typeName: 'string', optional: true, nullable: false },
719
+ 'containerStatuses': { typeName: 'array', optional: true, nullable: false }
720
+ }
721
+ };
722
+ const resourceFields = statusFieldTypes[resourceKind];
723
+ if (resourceFields && fieldName in resourceFields) {
724
+ const baseType = resourceFields[fieldName];
725
+ // Handle nested access
726
+ if (fieldParts.length > 1 && baseType) {
727
+ if (baseType.typeName === 'object') {
728
+ // Handle specific nested objects
729
+ if (fieldName === 'loadBalancer' && fieldParts[1] === 'ingress') {
730
+ return { typeName: 'array', optional: true, nullable: false };
731
+ }
732
+ return { typeName: 'unknown', optional: true, nullable: false };
733
+ }
734
+ if (baseType.typeName === 'array') {
735
+ // Array access like conditions[0] or length
736
+ if (fieldParts[1] === 'length') {
737
+ return { typeName: 'number', optional: false, nullable: false };
738
+ }
739
+ return { typeName: 'object', optional: true, nullable: false };
740
+ }
741
+ }
742
+ return baseType || { typeName: 'unknown', optional: true, nullable: true };
743
+ }
744
+ // Status fields are generally optional and may be null during resource creation
745
+ return { typeName: 'unknown', optional: true, nullable: true };
746
+ }
747
+ inferSchemaFieldType(schemaProxy, fieldPath) {
748
+ if (!schemaProxy) {
749
+ return { typeName: 'unknown', optional: false, nullable: false };
750
+ }
751
+ try {
752
+ // Extract the field from the schema proxy
753
+ const parts = fieldPath.split('.');
754
+ let current = schemaProxy;
755
+ for (const part of parts) {
756
+ if (current && typeof current === 'object' && part in current) {
757
+ current = current[part];
758
+ }
759
+ else {
760
+ return { typeName: 'unknown', optional: true, nullable: false };
761
+ }
762
+ }
763
+ // Infer type from the schema field
764
+ if (current !== undefined) {
765
+ return this.inferTypeFromValue(current);
766
+ }
767
+ return { typeName: 'unknown', optional: true, nullable: false };
768
+ }
769
+ catch (_error) {
770
+ return { typeName: 'unknown', optional: true, nullable: false };
771
+ }
772
+ }
773
+ inferTypeFromValue(value) {
774
+ if (value === null) {
775
+ return { typeName: 'null', optional: false, nullable: true };
776
+ }
777
+ if (value === undefined) {
778
+ return { typeName: 'undefined', optional: true, nullable: false };
779
+ }
780
+ const type = typeof value;
781
+ switch (type) {
782
+ case 'string':
783
+ return { typeName: 'string', optional: false, nullable: false };
784
+ case 'number':
785
+ return { typeName: 'number', optional: false, nullable: false };
786
+ case 'boolean':
787
+ return { typeName: 'boolean', optional: false, nullable: false };
788
+ case 'object':
789
+ if (Array.isArray(value)) {
790
+ return { typeName: 'array', optional: false, nullable: false };
791
+ }
792
+ return { typeName: 'object', optional: false, nullable: false };
793
+ default:
794
+ return { typeName: 'unknown', optional: false, nullable: false };
795
+ }
796
+ }
797
+ unifyTypes(type1, type2) {
798
+ if (type1.typeName === type2.typeName)
799
+ return type1;
800
+ // Create union type
801
+ return {
802
+ typeName: `${type1.typeName} | ${type2.typeName}`,
803
+ optional: type1.optional || type2.optional,
804
+ nullable: type1.nullable || type2.nullable,
805
+ unionTypes: [type1, type2]
806
+ };
807
+ }
808
+ createEmptyMetadata() {
809
+ return {
810
+ functionsUsed: [],
811
+ resourceReferences: [],
812
+ schemaReferences: [],
813
+ usesOptionalChaining: false,
814
+ canReturnNull: false,
815
+ complexityScore: 0
816
+ };
817
+ }
818
+ /**
819
+ * Extract resource references from the expression
820
+ */
821
+ extractResourceReferences(expression, metadata) {
822
+ // Find all resource references (resources.name.field)
823
+ const resourceMatches = expression.match(/resources\.\w+\.[a-zA-Z0-9_.]+/g);
824
+ if (resourceMatches) {
825
+ metadata.resourceReferences.push(...resourceMatches);
826
+ }
827
+ // Find all schema references (schema.field)
828
+ const schemaMatches = expression.match(/schema\.[a-zA-Z0-9_.]+/g);
829
+ if (schemaMatches) {
830
+ metadata.schemaReferences.push(...schemaMatches);
831
+ }
832
+ // Check for optional chaining
833
+ if (expression.includes('?.')) {
834
+ metadata.usesOptionalChaining = true;
835
+ }
836
+ }
837
+ }
838
+ //# sourceMappingURL=type-inference.js.map