typekro 0.8.0 → 0.10.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 (557) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/alchemy/deployers.d.ts +16 -1
  3. package/dist/alchemy/deployers.d.ts.map +1 -1
  4. package/dist/alchemy/deployers.js +131 -18
  5. package/dist/alchemy/deployers.js.map +1 -1
  6. package/dist/alchemy/deployment.d.ts +1 -1
  7. package/dist/alchemy/deployment.d.ts.map +1 -1
  8. package/dist/alchemy/deployment.js +1 -1
  9. package/dist/alchemy/deployment.js.map +1 -1
  10. package/dist/alchemy/kro-delete.d.ts +66 -0
  11. package/dist/alchemy/kro-delete.d.ts.map +1 -0
  12. package/dist/alchemy/kro-delete.js +183 -0
  13. package/dist/alchemy/kro-delete.js.map +1 -0
  14. package/dist/alchemy/resource-registration.d.ts +16 -0
  15. package/dist/alchemy/resource-registration.d.ts.map +1 -1
  16. package/dist/alchemy/resource-registration.js +138 -24
  17. package/dist/alchemy/resource-registration.js.map +1 -1
  18. package/dist/alchemy/types.d.ts +8 -4
  19. package/dist/alchemy/types.d.ts.map +1 -1
  20. package/dist/aspects.d.ts +3 -0
  21. package/dist/aspects.d.ts.map +1 -0
  22. package/dist/aspects.js +2 -0
  23. package/dist/aspects.js.map +1 -0
  24. package/dist/compositions/typekro-runtime/typekro-runtime.d.ts +1 -1
  25. package/dist/compositions/typekro-runtime/typekro-runtime.d.ts.map +1 -1
  26. package/dist/compositions/typekro-runtime/typekro-runtime.js +27 -9
  27. package/dist/compositions/typekro-runtime/typekro-runtime.js.map +1 -1
  28. package/dist/core/aspects/apply.d.ts +30 -0
  29. package/dist/core/aspects/apply.d.ts.map +1 -0
  30. package/dist/core/aspects/apply.js +369 -0
  31. package/dist/core/aspects/apply.js.map +1 -0
  32. package/dist/core/aspects/dev-aspects.d.ts +14 -0
  33. package/dist/core/aspects/dev-aspects.d.ts.map +1 -0
  34. package/dist/core/aspects/dev-aspects.js +70 -0
  35. package/dist/core/aspects/dev-aspects.js.map +1 -0
  36. package/dist/core/aspects/index.d.ts +31 -0
  37. package/dist/core/aspects/index.d.ts.map +1 -0
  38. package/dist/core/aspects/index.js +30 -0
  39. package/dist/core/aspects/index.js.map +1 -0
  40. package/dist/core/aspects/metadata-aspects.d.ts +12 -0
  41. package/dist/core/aspects/metadata-aspects.d.ts.map +1 -0
  42. package/dist/core/aspects/metadata-aspects.js +24 -0
  43. package/dist/core/aspects/metadata-aspects.js.map +1 -0
  44. package/dist/core/aspects/metadata.d.ts +16 -0
  45. package/dist/core/aspects/metadata.d.ts.map +1 -0
  46. package/dist/core/aspects/metadata.js +24 -0
  47. package/dist/core/aspects/metadata.js.map +1 -0
  48. package/dist/core/aspects/primitives.d.ts +23 -0
  49. package/dist/core/aspects/primitives.d.ts.map +1 -0
  50. package/dist/core/aspects/primitives.js +258 -0
  51. package/dist/core/aspects/primitives.js.map +1 -0
  52. package/dist/core/aspects/targets.d.ts +9 -0
  53. package/dist/core/aspects/targets.d.ts.map +1 -0
  54. package/dist/core/aspects/targets.js +23 -0
  55. package/dist/core/aspects/targets.js.map +1 -0
  56. package/dist/core/aspects/types.d.ts +361 -0
  57. package/dist/core/aspects/types.d.ts.map +1 -0
  58. package/dist/core/aspects/types.js +16 -0
  59. package/dist/core/aspects/types.js.map +1 -0
  60. package/dist/core/aspects/workload-aspects.d.ts +17 -0
  61. package/dist/core/aspects/workload-aspects.d.ts.map +1 -0
  62. package/dist/core/aspects/workload-aspects.js +40 -0
  63. package/dist/core/aspects/workload-aspects.js.map +1 -0
  64. package/dist/core/composition/context.d.ts +58 -2
  65. package/dist/core/composition/context.d.ts.map +1 -1
  66. package/dist/core/composition/context.js +4 -0
  67. package/dist/core/composition/context.js.map +1 -1
  68. package/dist/core/composition/imperative.d.ts +9 -0
  69. package/dist/core/composition/imperative.d.ts.map +1 -1
  70. package/dist/core/composition/imperative.js +538 -54
  71. package/dist/core/composition/imperative.js.map +1 -1
  72. package/dist/core/composition/nested-status-cel.d.ts +34 -1
  73. package/dist/core/composition/nested-status-cel.d.ts.map +1 -1
  74. package/dist/core/composition/nested-status-cel.js +379 -41
  75. package/dist/core/composition/nested-status-cel.js.map +1 -1
  76. package/dist/core/composition-debugger.d.ts +1 -1
  77. package/dist/core/composition-debugger.d.ts.map +1 -1
  78. package/dist/core/composition-debugger.js.map +1 -1
  79. package/dist/core/constants/brands.d.ts +1 -1
  80. package/dist/core/constants/brands.d.ts.map +1 -1
  81. package/dist/core/constants/brands.js +1 -1
  82. package/dist/core/constants/brands.js.map +1 -1
  83. package/dist/core/containers/build.d.ts.map +1 -1
  84. package/dist/core/containers/build.js +40 -12
  85. package/dist/core/containers/build.js.map +1 -1
  86. package/dist/core/dependencies/resolver.d.ts +19 -0
  87. package/dist/core/dependencies/resolver.d.ts.map +1 -1
  88. package/dist/core/dependencies/resolver.js +261 -1
  89. package/dist/core/dependencies/resolver.js.map +1 -1
  90. package/dist/core/deployment/client-provider-manager.d.ts +9 -3
  91. package/dist/core/deployment/client-provider-manager.d.ts.map +1 -1
  92. package/dist/core/deployment/client-provider-manager.js +12 -0
  93. package/dist/core/deployment/client-provider-manager.js.map +1 -1
  94. package/dist/core/deployment/crd-manager.d.ts +24 -0
  95. package/dist/core/deployment/crd-manager.d.ts.map +1 -1
  96. package/dist/core/deployment/crd-manager.js +79 -1
  97. package/dist/core/deployment/crd-manager.js.map +1 -1
  98. package/dist/core/deployment/deployment-state-discovery.d.ts +116 -0
  99. package/dist/core/deployment/deployment-state-discovery.d.ts.map +1 -0
  100. package/dist/core/deployment/deployment-state-discovery.js +400 -0
  101. package/dist/core/deployment/deployment-state-discovery.js.map +1 -0
  102. package/dist/core/deployment/direct-factory.d.ts +65 -6
  103. package/dist/core/deployment/direct-factory.d.ts.map +1 -1
  104. package/dist/core/deployment/direct-factory.js +584 -62
  105. package/dist/core/deployment/direct-factory.js.map +1 -1
  106. package/dist/core/deployment/engine.d.ts +64 -3
  107. package/dist/core/deployment/engine.d.ts.map +1 -1
  108. package/dist/core/deployment/engine.js +194 -27
  109. package/dist/core/deployment/engine.js.map +1 -1
  110. package/dist/core/deployment/event-filter.js +1 -1
  111. package/dist/core/deployment/event-filter.js.map +1 -1
  112. package/dist/core/deployment/event-monitor.d.ts +11 -0
  113. package/dist/core/deployment/event-monitor.d.ts.map +1 -1
  114. package/dist/core/deployment/event-monitor.js +14 -0
  115. package/dist/core/deployment/event-monitor.js.map +1 -1
  116. package/dist/core/deployment/handle-tracing.d.ts +14 -0
  117. package/dist/core/deployment/handle-tracing.d.ts.map +1 -0
  118. package/dist/core/deployment/handle-tracing.js +38 -0
  119. package/dist/core/deployment/handle-tracing.js.map +1 -0
  120. package/dist/core/deployment/kro-factory.d.ts +115 -3
  121. package/dist/core/deployment/kro-factory.d.ts.map +1 -1
  122. package/dist/core/deployment/kro-factory.js +922 -278
  123. package/dist/core/deployment/kro-factory.js.map +1 -1
  124. package/dist/core/deployment/kro-readiness.d.ts.map +1 -1
  125. package/dist/core/deployment/kro-readiness.js +21 -12
  126. package/dist/core/deployment/kro-readiness.js.map +1 -1
  127. package/dist/core/deployment/nested-composition-status.d.ts +1 -1
  128. package/dist/core/deployment/nested-composition-status.d.ts.map +1 -1
  129. package/dist/core/deployment/nested-composition-status.js +96 -53
  130. package/dist/core/deployment/nested-composition-status.js.map +1 -1
  131. package/dist/core/deployment/resource-applier.d.ts +15 -2
  132. package/dist/core/deployment/resource-applier.d.ts.map +1 -1
  133. package/dist/core/deployment/resource-applier.js +75 -25
  134. package/dist/core/deployment/resource-applier.js.map +1 -1
  135. package/dist/core/deployment/resource-tagging.d.ts +220 -0
  136. package/dist/core/deployment/resource-tagging.d.ts.map +1 -0
  137. package/dist/core/deployment/resource-tagging.js +292 -0
  138. package/dist/core/deployment/resource-tagging.js.map +1 -0
  139. package/dist/core/deployment/rollback-manager.d.ts +25 -4
  140. package/dist/core/deployment/rollback-manager.d.ts.map +1 -1
  141. package/dist/core/deployment/rollback-manager.js +70 -57
  142. package/dist/core/deployment/rollback-manager.js.map +1 -1
  143. package/dist/core/deployment/shared-utilities.d.ts +6 -0
  144. package/dist/core/deployment/shared-utilities.d.ts.map +1 -1
  145. package/dist/core/deployment/shared-utilities.js +32 -2
  146. package/dist/core/deployment/shared-utilities.js.map +1 -1
  147. package/dist/core/deployment/singleton-owner-drift.d.ts +16 -0
  148. package/dist/core/deployment/singleton-owner-drift.d.ts.map +1 -0
  149. package/dist/core/deployment/singleton-owner-drift.js +54 -0
  150. package/dist/core/deployment/singleton-owner-drift.js.map +1 -0
  151. package/dist/core/deployment/strategies/alchemy-strategy.d.ts +3 -1
  152. package/dist/core/deployment/strategies/alchemy-strategy.d.ts.map +1 -1
  153. package/dist/core/deployment/strategies/alchemy-strategy.js +121 -18
  154. package/dist/core/deployment/strategies/alchemy-strategy.js.map +1 -1
  155. package/dist/core/deployment/strategies/base-strategy.d.ts +9 -3
  156. package/dist/core/deployment/strategies/base-strategy.d.ts.map +1 -1
  157. package/dist/core/deployment/strategies/base-strategy.js +32 -4
  158. package/dist/core/deployment/strategies/base-strategy.js.map +1 -1
  159. package/dist/core/deployment/strategies/direct-strategy.d.ts +12 -4
  160. package/dist/core/deployment/strategies/direct-strategy.d.ts.map +1 -1
  161. package/dist/core/deployment/strategies/direct-strategy.js +112 -8
  162. package/dist/core/deployment/strategies/direct-strategy.js.map +1 -1
  163. package/dist/core/errors.d.ts +2 -2
  164. package/dist/core/errors.d.ts.map +1 -1
  165. package/dist/core/errors.js.map +1 -1
  166. package/dist/core/expressions/analysis/cache.d.ts +2 -2
  167. package/dist/core/expressions/analysis/cache.d.ts.map +1 -1
  168. package/dist/core/expressions/analysis/cache.js +4 -0
  169. package/dist/core/expressions/analysis/cache.js.map +1 -1
  170. package/dist/core/expressions/analysis/fn-toString-self-test.d.ts.map +1 -1
  171. package/dist/core/expressions/analysis/fn-toString-self-test.js +0 -1
  172. package/dist/core/expressions/analysis/fn-toString-self-test.js.map +1 -1
  173. package/dist/core/expressions/analysis/shared-types.d.ts +2 -2
  174. package/dist/core/expressions/analysis/shared-types.d.ts.map +1 -1
  175. package/dist/core/expressions/analysis/source-map.d.ts.map +1 -1
  176. package/dist/core/expressions/analysis/source-map.js +1 -0
  177. package/dist/core/expressions/analysis/source-map.js.map +1 -1
  178. package/dist/core/expressions/analysis/types.d.ts +7 -7
  179. package/dist/core/expressions/analysis/types.d.ts.map +1 -1
  180. package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts +29 -1
  181. package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts.map +1 -1
  182. package/dist/core/expressions/composition/composition-analyzer-helpers.js +348 -17
  183. package/dist/core/expressions/composition/composition-analyzer-helpers.js.map +1 -1
  184. package/dist/core/expressions/composition/composition-analyzer-ternary.d.ts +2 -2
  185. package/dist/core/expressions/composition/composition-analyzer-ternary.d.ts.map +1 -1
  186. package/dist/core/expressions/composition/composition-analyzer-ternary.js +221 -10
  187. package/dist/core/expressions/composition/composition-analyzer-ternary.js.map +1 -1
  188. package/dist/core/expressions/composition/composition-analyzer-traversal.d.ts.map +1 -1
  189. package/dist/core/expressions/composition/composition-analyzer-traversal.js +67 -2
  190. package/dist/core/expressions/composition/composition-analyzer-traversal.js.map +1 -1
  191. package/dist/core/expressions/composition/composition-analyzer-types.d.ts +52 -0
  192. package/dist/core/expressions/composition/composition-analyzer-types.d.ts.map +1 -1
  193. package/dist/core/expressions/composition/composition-analyzer.d.ts.map +1 -1
  194. package/dist/core/expressions/composition/composition-analyzer.js +150 -6
  195. package/dist/core/expressions/composition/composition-analyzer.js.map +1 -1
  196. package/dist/core/expressions/composition/expression-analyzer.d.ts.map +1 -1
  197. package/dist/core/expressions/composition/expression-analyzer.js +21 -4
  198. package/dist/core/expressions/composition/expression-analyzer.js.map +1 -1
  199. package/dist/core/expressions/composition/imperative-analyzer.d.ts +1 -1
  200. package/dist/core/expressions/composition/imperative-analyzer.d.ts.map +1 -1
  201. package/dist/core/expressions/composition/imperative-analyzer.js +31 -7
  202. package/dist/core/expressions/composition/imperative-analyzer.js.map +1 -1
  203. package/dist/core/expressions/composition/scope-manager.d.ts +2 -2
  204. package/dist/core/expressions/composition/scope-manager.d.ts.map +1 -1
  205. package/dist/core/expressions/composition/scope-manager.js.map +1 -1
  206. package/dist/core/expressions/conditional/conditional-expression-processor.d.ts +3 -3
  207. package/dist/core/expressions/conditional/conditional-expression-processor.d.ts.map +1 -1
  208. package/dist/core/expressions/conditional/conditional-expression-processor.js.map +1 -1
  209. package/dist/core/expressions/conditional/conditional-integration.d.ts.map +1 -1
  210. package/dist/core/expressions/conditional/conditional-integration.js.map +1 -1
  211. package/dist/core/expressions/context/context-aware-generator.d.ts +5 -5
  212. package/dist/core/expressions/context/context-aware-generator.d.ts.map +1 -1
  213. package/dist/core/expressions/context/context-aware-generator.js.map +1 -1
  214. package/dist/core/expressions/context/context-detector.d.ts +3 -3
  215. package/dist/core/expressions/context/context-detector.d.ts.map +1 -1
  216. package/dist/core/expressions/context/context-detector.js.map +1 -1
  217. package/dist/core/expressions/context/context-validator.d.ts +6 -6
  218. package/dist/core/expressions/context/context-validator.d.ts.map +1 -1
  219. package/dist/core/expressions/context/context-validator.js +2 -2
  220. package/dist/core/expressions/context/context-validator.js.map +1 -1
  221. package/dist/core/expressions/factory/cel-conversion-engine.d.ts +4 -4
  222. package/dist/core/expressions/factory/cel-conversion-engine.d.ts.map +1 -1
  223. package/dist/core/expressions/factory/cel-conversion-engine.js.map +1 -1
  224. package/dist/core/expressions/factory/dependency-tracker.d.ts +2 -2
  225. package/dist/core/expressions/factory/dependency-tracker.d.ts.map +1 -1
  226. package/dist/core/expressions/factory/dependency-tracker.js +21 -5
  227. package/dist/core/expressions/factory/dependency-tracker.js.map +1 -1
  228. package/dist/core/expressions/factory/factory-integration.d.ts +2 -4
  229. package/dist/core/expressions/factory/factory-integration.d.ts.map +1 -1
  230. package/dist/core/expressions/factory/factory-integration.js +0 -6
  231. package/dist/core/expressions/factory/factory-integration.js.map +1 -1
  232. package/dist/core/expressions/factory/factory-pattern-handler.d.ts +3 -3
  233. package/dist/core/expressions/factory/factory-pattern-handler.d.ts.map +1 -1
  234. package/dist/core/expressions/factory/factory-pattern-handler.js +1 -0
  235. package/dist/core/expressions/factory/factory-pattern-handler.js.map +1 -1
  236. package/dist/core/expressions/factory/migration-helpers.js.map +1 -1
  237. package/dist/core/expressions/factory/resource-analyzer.d.ts +4 -4
  238. package/dist/core/expressions/factory/resource-analyzer.d.ts.map +1 -1
  239. package/dist/core/expressions/factory/resource-analyzer.js.map +1 -1
  240. package/dist/core/expressions/factory/resource-type-validator.d.ts +5 -5
  241. package/dist/core/expressions/factory/resource-type-validator.d.ts.map +1 -1
  242. package/dist/core/expressions/factory/resource-type-validator.js.map +1 -1
  243. package/dist/core/expressions/factory/status-builder-analyzer.d.ts +6 -7
  244. package/dist/core/expressions/factory/status-builder-analyzer.d.ts.map +1 -1
  245. package/dist/core/expressions/factory/status-builder-analyzer.js +0 -3
  246. package/dist/core/expressions/factory/status-builder-analyzer.js.map +1 -1
  247. package/dist/core/expressions/factory/status-builder-types.d.ts +1 -1
  248. package/dist/core/expressions/factory/status-builder-types.d.ts.map +1 -1
  249. package/dist/core/expressions/factory/status-cel-generation.d.ts +1 -1
  250. package/dist/core/expressions/factory/status-cel-generation.d.ts.map +1 -1
  251. package/dist/core/expressions/factory/status-cel-generation.js +1 -1
  252. package/dist/core/expressions/factory/status-cel-generation.js.map +1 -1
  253. package/dist/core/expressions/factory/status-field-analysis.d.ts +3 -3
  254. package/dist/core/expressions/factory/status-field-analysis.d.ts.map +1 -1
  255. package/dist/core/expressions/factory/status-field-analysis.js.map +1 -1
  256. package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.d.ts +5 -5
  257. package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.d.ts.map +1 -1
  258. package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.js +1 -1
  259. package/dist/core/expressions/magic-proxy/magic-assignable-analyzer.js.map +1 -1
  260. package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.d.ts +10 -10
  261. package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.d.ts.map +1 -1
  262. package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.js +5 -1
  263. package/dist/core/expressions/magic-proxy/magic-proxy-analyzer.js.map +1 -1
  264. package/dist/core/expressions/magic-proxy/magic-proxy-ast.d.ts +2 -2
  265. package/dist/core/expressions/magic-proxy/magic-proxy-ast.d.ts.map +1 -1
  266. package/dist/core/expressions/magic-proxy/magic-proxy-ast.js.map +1 -1
  267. package/dist/core/expressions/magic-proxy/magic-proxy-detector.d.ts +5 -5
  268. package/dist/core/expressions/magic-proxy/magic-proxy-detector.d.ts.map +1 -1
  269. package/dist/core/expressions/magic-proxy/magic-proxy-detector.js.map +1 -1
  270. package/dist/core/expressions/magic-proxy/magic-proxy-types.d.ts +2 -2
  271. package/dist/core/expressions/magic-proxy/magic-proxy-types.d.ts.map +1 -1
  272. package/dist/core/expressions/magic-proxy/optionality-handler.d.ts +1 -2
  273. package/dist/core/expressions/magic-proxy/optionality-handler.d.ts.map +1 -1
  274. package/dist/core/expressions/magic-proxy/optionality-handler.js +2 -15
  275. package/dist/core/expressions/magic-proxy/optionality-handler.js.map +1 -1
  276. package/dist/core/expressions/validation/compile-time-checker.d.ts +1 -1
  277. package/dist/core/expressions/validation/compile-time-checker.d.ts.map +1 -1
  278. package/dist/core/expressions/validation/compile-time-checker.js.map +1 -1
  279. package/dist/core/expressions/validation/compile-time-types.d.ts +2 -2
  280. package/dist/core/expressions/validation/compile-time-types.d.ts.map +1 -1
  281. package/dist/core/expressions/validation/kubernetes-field-types.d.ts +4 -4
  282. package/dist/core/expressions/validation/kubernetes-field-types.d.ts.map +1 -1
  283. package/dist/core/expressions/validation/kubernetes-field-types.js.map +1 -1
  284. package/dist/core/expressions/validation/resource-field-utils.d.ts +10 -10
  285. package/dist/core/expressions/validation/resource-field-utils.d.ts.map +1 -1
  286. package/dist/core/expressions/validation/resource-field-utils.js.map +1 -1
  287. package/dist/core/expressions/validation/resource-validation.d.ts +3 -3
  288. package/dist/core/expressions/validation/resource-validation.d.ts.map +1 -1
  289. package/dist/core/expressions/validation/resource-validation.js.map +1 -1
  290. package/dist/core/expressions/validation/type-inference-types.d.ts +2 -2
  291. package/dist/core/expressions/validation/type-inference-types.d.ts.map +1 -1
  292. package/dist/core/expressions/validation/type-safety.d.ts +2 -2
  293. package/dist/core/expressions/validation/type-safety.d.ts.map +1 -1
  294. package/dist/core/expressions/validation/type-safety.js +1 -0
  295. package/dist/core/expressions/validation/type-safety.js.map +1 -1
  296. package/dist/core/kubernetes/bun-api-client.js.map +1 -1
  297. package/dist/core/kubernetes/bun-http-library.d.ts.map +1 -1
  298. package/dist/core/kubernetes/bun-http-library.js +29 -3
  299. package/dist/core/kubernetes/bun-http-library.js.map +1 -1
  300. package/dist/core/kubernetes/client-provider.d.ts +12 -0
  301. package/dist/core/kubernetes/client-provider.d.ts.map +1 -1
  302. package/dist/core/kubernetes/client-provider.js +35 -0
  303. package/dist/core/kubernetes/client-provider.js.map +1 -1
  304. package/dist/core/metadata/resource-metadata.d.ts +49 -1
  305. package/dist/core/metadata/resource-metadata.d.ts.map +1 -1
  306. package/dist/core/metadata/resource-metadata.js.map +1 -1
  307. package/dist/core/proxy/create-resource.d.ts +15 -0
  308. package/dist/core/proxy/create-resource.d.ts.map +1 -1
  309. package/dist/core/proxy/create-resource.js +79 -2
  310. package/dist/core/proxy/create-resource.js.map +1 -1
  311. package/dist/core/readiness/registry.js +2 -2
  312. package/dist/core/readiness/registry.js.map +1 -1
  313. package/dist/core/references/cel-evaluator.d.ts +1 -4
  314. package/dist/core/references/cel-evaluator.d.ts.map +1 -1
  315. package/dist/core/references/cel-evaluator.js +3 -7
  316. package/dist/core/references/cel-evaluator.js.map +1 -1
  317. package/dist/core/references/cel.d.ts +22 -0
  318. package/dist/core/references/cel.d.ts.map +1 -1
  319. package/dist/core/references/cel.js +106 -8
  320. package/dist/core/references/cel.js.map +1 -1
  321. package/dist/core/references/external-refs.d.ts.map +1 -1
  322. package/dist/core/references/external-refs.js +3 -0
  323. package/dist/core/references/external-refs.js.map +1 -1
  324. package/dist/core/references/resolver.d.ts.map +1 -1
  325. package/dist/core/references/resolver.js +28 -17
  326. package/dist/core/references/resolver.js.map +1 -1
  327. package/dist/core/references/schema-proxy.d.ts +18 -10
  328. package/dist/core/references/schema-proxy.d.ts.map +1 -1
  329. package/dist/core/references/schema-proxy.js +174 -23
  330. package/dist/core/references/schema-proxy.js.map +1 -1
  331. package/dist/core/runtime-patches/crd-schema-fix.d.ts.map +1 -1
  332. package/dist/core/runtime-patches/crd-schema-fix.js +4 -1
  333. package/dist/core/runtime-patches/crd-schema-fix.js.map +1 -1
  334. package/dist/core/serialization/cel-optimizer.d.ts.map +1 -1
  335. package/dist/core/serialization/cel-optimizer.js +2 -0
  336. package/dist/core/serialization/cel-optimizer.js.map +1 -1
  337. package/dist/core/serialization/cel-references.d.ts +75 -1
  338. package/dist/core/serialization/cel-references.d.ts.map +1 -1
  339. package/dist/core/serialization/cel-references.js +692 -156
  340. package/dist/core/serialization/cel-references.js.map +1 -1
  341. package/dist/core/serialization/core.d.ts +8 -8
  342. package/dist/core/serialization/core.d.ts.map +1 -1
  343. package/dist/core/serialization/core.js +672 -90
  344. package/dist/core/serialization/core.js.map +1 -1
  345. package/dist/core/serialization/kro-post-processing.d.ts +1 -1
  346. package/dist/core/serialization/kro-post-processing.d.ts.map +1 -1
  347. package/dist/core/serialization/kro-post-processing.js +69 -22
  348. package/dist/core/serialization/kro-post-processing.js.map +1 -1
  349. package/dist/core/serialization/schema.d.ts +1 -0
  350. package/dist/core/serialization/schema.d.ts.map +1 -1
  351. package/dist/core/serialization/schema.js +378 -50
  352. package/dist/core/serialization/schema.js.map +1 -1
  353. package/dist/core/serialization/status-analysis-pipeline.d.ts +1 -1
  354. package/dist/core/serialization/status-analysis-pipeline.d.ts.map +1 -1
  355. package/dist/core/serialization/status-analysis-pipeline.js.map +1 -1
  356. package/dist/core/serialization/yaml.d.ts +3 -2
  357. package/dist/core/serialization/yaml.d.ts.map +1 -1
  358. package/dist/core/serialization/yaml.js +385 -55
  359. package/dist/core/serialization/yaml.js.map +1 -1
  360. package/dist/core/singleton/singleton.d.ts +16 -0
  361. package/dist/core/singleton/singleton.d.ts.map +1 -0
  362. package/dist/core/singleton/singleton.js +135 -0
  363. package/dist/core/singleton/singleton.js.map +1 -0
  364. package/dist/core/types/common.d.ts +2 -2
  365. package/dist/core/types/common.d.ts.map +1 -1
  366. package/dist/core/types/composable.d.ts +1 -1
  367. package/dist/core/types/composable.d.ts.map +1 -1
  368. package/dist/core/types/deployment.d.ts +129 -9
  369. package/dist/core/types/deployment.d.ts.map +1 -1
  370. package/dist/core/types/deployment.js +1 -1
  371. package/dist/core/types/deployment.js.map +1 -1
  372. package/dist/core/types/kubernetes.d.ts +25 -17
  373. package/dist/core/types/kubernetes.d.ts.map +1 -1
  374. package/dist/core/types/references.d.ts +1 -1
  375. package/dist/core/types/references.d.ts.map +1 -1
  376. package/dist/core/types/references.js.map +1 -1
  377. package/dist/core/types/resource-graph.d.ts +2 -1
  378. package/dist/core/types/resource-graph.d.ts.map +1 -1
  379. package/dist/core/types/schema.d.ts +1 -1
  380. package/dist/core/types/schema.d.ts.map +1 -1
  381. package/dist/core/types/serialization.d.ts +24 -6
  382. package/dist/core/types/serialization.d.ts.map +1 -1
  383. package/dist/core/validation/cel-validator.d.ts +15 -2
  384. package/dist/core/validation/cel-validator.d.ts.map +1 -1
  385. package/dist/core/validation/cel-validator.js +144 -63
  386. package/dist/core/validation/cel-validator.js.map +1 -1
  387. package/dist/factories/apisix/compositions/apisix-bootstrap.d.ts +2 -41
  388. package/dist/factories/apisix/compositions/apisix-bootstrap.d.ts.map +1 -1
  389. package/dist/factories/apisix/compositions/apisix-bootstrap.js +262 -217
  390. package/dist/factories/apisix/compositions/apisix-bootstrap.js.map +1 -1
  391. package/dist/factories/apisix/index.d.ts +2 -2
  392. package/dist/factories/apisix/index.js +2 -2
  393. package/dist/factories/apisix/resources/helm.d.ts +2 -2
  394. package/dist/factories/apisix/resources/helm.d.ts.map +1 -1
  395. package/dist/factories/apisix/resources/helm.js.map +1 -1
  396. package/dist/factories/apisix/types.d.ts +21 -11
  397. package/dist/factories/apisix/types.d.ts.map +1 -1
  398. package/dist/factories/apisix/types.js +106 -4
  399. package/dist/factories/apisix/types.js.map +1 -1
  400. package/dist/factories/apisix/utils/admin-credentials.d.ts +5 -3
  401. package/dist/factories/apisix/utils/admin-credentials.d.ts.map +1 -1
  402. package/dist/factories/apisix/utils/admin-credentials.js +14 -10
  403. package/dist/factories/apisix/utils/admin-credentials.js.map +1 -1
  404. package/dist/factories/apisix/utils/helm-values-mapper.d.ts.map +1 -1
  405. package/dist/factories/apisix/utils/helm-values-mapper.js +4 -2
  406. package/dist/factories/apisix/utils/helm-values-mapper.js.map +1 -1
  407. package/dist/factories/cert-manager/resources/challenges.js.map +1 -1
  408. package/dist/factories/cert-manager/types.d.ts +3 -3
  409. package/dist/factories/cert-manager/types.d.ts.map +1 -1
  410. package/dist/factories/cilium/compositions/cilium-bootstrap.d.ts +4 -4
  411. package/dist/factories/cilium/types.d.ts +3 -3
  412. package/dist/factories/cilium/types.d.ts.map +1 -1
  413. package/dist/factories/cnpg/compositions/cnpg-bootstrap.d.ts +1 -0
  414. package/dist/factories/cnpg/compositions/cnpg-bootstrap.d.ts.map +1 -1
  415. package/dist/factories/cnpg/compositions/cnpg-bootstrap.js +48 -0
  416. package/dist/factories/cnpg/compositions/cnpg-bootstrap.js.map +1 -1
  417. package/dist/factories/cnpg/resources/cluster.js +1 -1
  418. package/dist/factories/cnpg/resources/cluster.js.map +1 -1
  419. package/dist/factories/cnpg/resources/helm.d.ts.map +1 -1
  420. package/dist/factories/cnpg/resources/helm.js +1 -0
  421. package/dist/factories/cnpg/resources/helm.js.map +1 -1
  422. package/dist/factories/cnpg/resources/pooler.js +1 -1
  423. package/dist/factories/cnpg/resources/pooler.js.map +1 -1
  424. package/dist/factories/cnpg/types.d.ts +9 -8
  425. package/dist/factories/cnpg/types.d.ts.map +1 -1
  426. package/dist/factories/cnpg/types.js +11 -0
  427. package/dist/factories/cnpg/types.js.map +1 -1
  428. package/dist/factories/external-dns/compositions/external-dns-bootstrap.d.ts.map +1 -1
  429. package/dist/factories/external-dns/compositions/external-dns-bootstrap.js +153 -41
  430. package/dist/factories/external-dns/compositions/external-dns-bootstrap.js.map +1 -1
  431. package/dist/factories/external-dns/resources/dns-endpoint.js +1 -1
  432. package/dist/factories/external-dns/resources/dns-endpoint.js.map +1 -1
  433. package/dist/factories/external-dns/resources/helm.d.ts +1 -1
  434. package/dist/factories/external-dns/resources/helm.d.ts.map +1 -1
  435. package/dist/factories/external-dns/resources/helm.js +17 -10
  436. package/dist/factories/external-dns/resources/helm.js.map +1 -1
  437. package/dist/factories/external-dns/types.d.ts +5 -2
  438. package/dist/factories/external-dns/types.d.ts.map +1 -1
  439. package/dist/factories/external-dns/types.js.map +1 -1
  440. package/dist/factories/flux/git-repository.d.ts.map +1 -1
  441. package/dist/factories/flux/git-repository.js +1 -1
  442. package/dist/factories/flux/git-repository.js.map +1 -1
  443. package/dist/factories/flux/kustomize/kustomization.d.ts +2 -2
  444. package/dist/factories/flux/kustomize/kustomization.d.ts.map +1 -1
  445. package/dist/factories/flux/kustomize/readiness-evaluators.d.ts +1 -1
  446. package/dist/factories/flux/kustomize/readiness-evaluators.d.ts.map +1 -1
  447. package/dist/factories/flux/kustomize/readiness-evaluators.js +1 -1
  448. package/dist/factories/flux/kustomize/readiness-evaluators.js.map +1 -1
  449. package/dist/factories/helm/helm-release.d.ts +3 -2
  450. package/dist/factories/helm/helm-release.d.ts.map +1 -1
  451. package/dist/factories/helm/helm-release.js +1 -0
  452. package/dist/factories/helm/helm-release.js.map +1 -1
  453. package/dist/factories/helm/helm-repository.d.ts +1 -1
  454. package/dist/factories/helm/helm-repository.d.ts.map +1 -1
  455. package/dist/factories/helm/helm-repository.js +6 -4
  456. package/dist/factories/helm/helm-repository.js.map +1 -1
  457. package/dist/factories/helm/readiness-evaluators.d.ts +6 -6
  458. package/dist/factories/helm/readiness-evaluators.d.ts.map +1 -1
  459. package/dist/factories/helm/readiness-evaluators.js +15 -9
  460. package/dist/factories/helm/readiness-evaluators.js.map +1 -1
  461. package/dist/factories/helm/types.d.ts +5 -1
  462. package/dist/factories/helm/types.d.ts.map +1 -1
  463. package/dist/factories/inngest/compositions/inngest-bootstrap.d.ts +1 -0
  464. package/dist/factories/inngest/compositions/inngest-bootstrap.d.ts.map +1 -1
  465. package/dist/factories/inngest/compositions/inngest-bootstrap.js +4 -3
  466. package/dist/factories/inngest/compositions/inngest-bootstrap.js.map +1 -1
  467. package/dist/factories/inngest/resources/helm.js +1 -1
  468. package/dist/factories/inngest/resources/helm.js.map +1 -1
  469. package/dist/factories/inngest/types.d.ts +5 -4
  470. package/dist/factories/inngest/types.d.ts.map +1 -1
  471. package/dist/factories/inngest/types.js +2 -0
  472. package/dist/factories/inngest/types.js.map +1 -1
  473. package/dist/factories/kro/kro-custom-resource.js +1 -1
  474. package/dist/factories/kro/kro-custom-resource.js.map +1 -1
  475. package/dist/factories/kubernetes/config/config-map.d.ts +2 -2
  476. package/dist/factories/kubernetes/config/config-map.d.ts.map +1 -1
  477. package/dist/factories/kubernetes/config/secret.d.ts +2 -2
  478. package/dist/factories/kubernetes/config/secret.d.ts.map +1 -1
  479. package/dist/factories/kubernetes/networking/service.js +1 -1
  480. package/dist/factories/kubernetes/networking/service.js.map +1 -1
  481. package/dist/factories/kubernetes/yaml/yaml-directory.d.ts.map +1 -1
  482. package/dist/factories/kubernetes/yaml/yaml-directory.js +9 -0
  483. package/dist/factories/kubernetes/yaml/yaml-directory.js.map +1 -1
  484. package/dist/factories/kubernetes/yaml/yaml-file.d.ts.map +1 -1
  485. package/dist/factories/kubernetes/yaml/yaml-file.js +9 -0
  486. package/dist/factories/kubernetes/yaml/yaml-file.js.map +1 -1
  487. package/dist/factories/pebble/resources/helm.js.map +1 -1
  488. package/dist/factories/pebble/types.d.ts +2 -2
  489. package/dist/factories/searxng/compositions/searxng-bootstrap.d.ts +3 -2
  490. package/dist/factories/searxng/compositions/searxng-bootstrap.d.ts.map +1 -1
  491. package/dist/factories/searxng/compositions/searxng-bootstrap.js +205 -167
  492. package/dist/factories/searxng/compositions/searxng-bootstrap.js.map +1 -1
  493. package/dist/factories/searxng/resources/searxng.d.ts +1 -1
  494. package/dist/factories/searxng/resources/searxng.js +1 -1
  495. package/dist/factories/searxng/types.d.ts +5 -4
  496. package/dist/factories/searxng/types.d.ts.map +1 -1
  497. package/dist/factories/searxng/types.js +8 -7
  498. package/dist/factories/searxng/types.js.map +1 -1
  499. package/dist/factories/searxng/utils/settings-builder.d.ts +4 -3
  500. package/dist/factories/searxng/utils/settings-builder.d.ts.map +1 -1
  501. package/dist/factories/searxng/utils/settings-builder.js +4 -3
  502. package/dist/factories/searxng/utils/settings-builder.js.map +1 -1
  503. package/dist/factories/simple/config/config-map.d.ts +2 -2
  504. package/dist/factories/simple/config/config-map.d.ts.map +1 -1
  505. package/dist/factories/simple/config/secret.d.ts +2 -2
  506. package/dist/factories/simple/config/secret.d.ts.map +1 -1
  507. package/dist/factories/simple/helm/index.d.ts +1 -1
  508. package/dist/factories/simple/helm/index.d.ts.map +1 -1
  509. package/dist/factories/simple/helm/index.js.map +1 -1
  510. package/dist/factories/simple/index.d.ts +3 -3
  511. package/dist/factories/simple/index.d.ts.map +1 -1
  512. package/dist/factories/simple/storage/persistent-volume.js.map +1 -1
  513. package/dist/factories/simple/types.d.ts +11 -1
  514. package/dist/factories/simple/types.d.ts.map +1 -1
  515. package/dist/factories/simple/workloads/deployment.d.ts +4 -1
  516. package/dist/factories/simple/workloads/deployment.d.ts.map +1 -1
  517. package/dist/factories/simple/workloads/deployment.js +9 -2
  518. package/dist/factories/simple/workloads/deployment.js.map +1 -1
  519. package/dist/factories/simple/workloads/stateful-set.d.ts +4 -1
  520. package/dist/factories/simple/workloads/stateful-set.d.ts.map +1 -1
  521. package/dist/factories/simple/workloads/stateful-set.js +6 -2
  522. package/dist/factories/simple/workloads/stateful-set.js.map +1 -1
  523. package/dist/factories/valkey/compositions/valkey-bootstrap.d.ts +1 -0
  524. package/dist/factories/valkey/compositions/valkey-bootstrap.d.ts.map +1 -1
  525. package/dist/factories/valkey/compositions/valkey-bootstrap.js +116 -0
  526. package/dist/factories/valkey/compositions/valkey-bootstrap.js.map +1 -1
  527. package/dist/factories/valkey/resources/valkey.js +1 -1
  528. package/dist/factories/valkey/resources/valkey.js.map +1 -1
  529. package/dist/factories/valkey/types.d.ts +6 -5
  530. package/dist/factories/valkey/types.d.ts.map +1 -1
  531. package/dist/factories/valkey/types.js +10 -0
  532. package/dist/factories/valkey/types.js.map +1 -1
  533. package/dist/factories/webapp/compositions/web-app-with-processing.d.ts +90 -6
  534. package/dist/factories/webapp/compositions/web-app-with-processing.d.ts.map +1 -1
  535. package/dist/factories/webapp/compositions/web-app-with-processing.js +180 -20
  536. package/dist/factories/webapp/compositions/web-app-with-processing.js.map +1 -1
  537. package/dist/factories/webapp/index.d.ts +3 -4
  538. package/dist/factories/webapp/index.d.ts.map +1 -1
  539. package/dist/factories/webapp/index.js +3 -4
  540. package/dist/factories/webapp/index.js.map +1 -1
  541. package/dist/factories/webapp/types.d.ts +60 -2
  542. package/dist/factories/webapp/types.d.ts.map +1 -1
  543. package/dist/factories/webapp/types.js +80 -3
  544. package/dist/factories/webapp/types.js.map +1 -1
  545. package/dist/index.d.ts +5 -1
  546. package/dist/index.d.ts.map +1 -1
  547. package/dist/index.js +3 -0
  548. package/dist/index.js.map +1 -1
  549. package/dist/shared/brands.d.ts +18 -8
  550. package/dist/shared/brands.d.ts.map +1 -1
  551. package/dist/shared/brands.js +19 -9
  552. package/dist/shared/brands.js.map +1 -1
  553. package/dist/utils/cel-escape.d.ts +12 -0
  554. package/dist/utils/cel-escape.d.ts.map +1 -0
  555. package/dist/utils/cel-escape.js +19 -0
  556. package/dist/utils/cel-escape.js.map +1 -0
  557. package/package.json +7 -2
@@ -7,18 +7,24 @@
7
7
  import * as yaml from 'js-yaml';
8
8
  import { toCamelCase } from '../../utils/string.js';
9
9
  import { isCelExpression, isKubernetesRef } from '../../utils/type-guards.js';
10
+ import { applyAspects } from '../aspects/apply.js';
10
11
  import { createCompositionContext, runWithCompositionContext } from '../composition/context.js';
12
+ import { buildNestedCompositionAliasTargets } from '../composition/nested-status-cel.js';
11
13
  import { DEFAULT_DELETE_TIMEOUT, DEFAULT_FAST_POLL_INTERVAL, DEFAULT_MAX_RECURSION_DEPTH, } from '../config/defaults.js';
14
+ import { KUBERNETES_REF_SCHEMA_MARKER_SOURCE } from '../constants/brands.js';
12
15
  import { DependencyResolver } from '../dependencies/index.js';
13
16
  import { ensureError, ResourceGraphFactoryError, TypeKroError, ValidationError, } from '../errors.js';
14
17
  import { getComponentLogger } from '../logging/index.js';
15
- import { copyResourceMetadata, getResourceId, setResourceId } from '../metadata/index.js';
18
+ import { copyResourceMetadata, getMetadataField, getResourceId, setResourceId, } from '../metadata/index.js';
19
+ import { getSingletonResourceId } from '../singleton/singleton.js';
16
20
  import { KubernetesClientManager } from './client-provider-manager.js';
21
+ import { BUILT_IN_GVKS } from './deployment-state-discovery.js';
17
22
  import { DirectDeploymentEngine } from './engine.js';
23
+ import { logHandleSnapshot } from './handle-tracing.js';
18
24
  import { synthesizeNestedCompositionStatus } from './nested-composition-status.js';
19
25
  import { ResourceReadinessChecker } from './readiness.js';
20
- import { createRollbackManagerWithKubeConfig } from './rollback-manager.js';
21
- import { generateInstanceName } from './shared-utilities.js';
26
+ import { generateInstanceName, getSingletonInstanceName, validateSpec, } from './shared-utilities.js';
27
+ import { assertNoDeployedSingletonSpecDrift, assertNoDiscoveredSingletonSpecDrift, singletonSpecFingerprintAnnotationValue, } from './singleton-owner-drift.js';
22
28
  import { AlchemyDeploymentStrategy, DirectDeploymentStrategy } from './strategies/index.js';
23
29
  /**
24
30
  * DirectResourceFactory implementation
@@ -34,14 +40,19 @@ export class DirectResourceFactoryImpl {
34
40
  resources;
35
41
  closures;
36
42
  schemaDefinition;
43
+ // biome-ignore lint/suspicious/noExplicitAny: status builders accept composition-specific resource maps that cannot be expressed more tightly here.
37
44
  statusBuilder;
38
45
  deploymentEngine;
39
46
  alchemyScope;
40
47
  factoryOptions;
48
+ singletonDefinitions;
49
+ singletonOwnerStatuses = new Map();
41
50
  deployedInstances = new Map();
42
51
  logger = getComponentLogger('direct-factory');
43
52
  clientManager;
44
- constructor(name, resources, schemaDefinition, statusBuilder, options = {}) {
53
+ constructor(name, resources, schemaDefinition,
54
+ // biome-ignore lint/suspicious/noExplicitAny: constructor must preserve the generic status-builder resource map contract.
55
+ statusBuilder, options = {}) {
45
56
  this.name = name;
46
57
  this.namespace = options.namespace || 'default';
47
58
  this.alchemyScope = options.alchemyScope;
@@ -51,6 +62,7 @@ export class DirectResourceFactoryImpl {
51
62
  this.schemaDefinition = schemaDefinition;
52
63
  this.statusBuilder = statusBuilder;
53
64
  this.factoryOptions = options;
65
+ this.singletonDefinitions = options.singletonDefinitions ?? [];
54
66
  this.clientManager = new KubernetesClientManager(options);
55
67
  }
56
68
  /**
@@ -59,6 +71,29 @@ export class DirectResourceFactoryImpl {
59
71
  getClientProvider() {
60
72
  return this.clientManager.getClientProvider();
61
73
  }
74
+ getDebugState() {
75
+ return {
76
+ mode: this.mode,
77
+ namespace: this.namespace,
78
+ deployedInstances: this.deployedInstances.size,
79
+ hasDeploymentEngine: !!this.deploymentEngine,
80
+ clientManager: this.clientManager.getDebugState(),
81
+ deploymentEngine: this.deploymentEngine?.getDebugState(),
82
+ };
83
+ }
84
+ async dispose() {
85
+ logHandleSnapshot(this.logger, 'direct-factory.dispose.before', {
86
+ factoryState: this.getDebugState(),
87
+ });
88
+ if (this.deploymentEngine) {
89
+ await this.deploymentEngine.dispose();
90
+ this.deploymentEngine = undefined;
91
+ }
92
+ this.clientManager.dispose();
93
+ logHandleSnapshot(this.logger, 'direct-factory.dispose.after', {
94
+ factoryState: this.getDebugState(),
95
+ });
96
+ }
62
97
  /**
63
98
  * Get or create the deployment engine using the centralized client provider
64
99
  */
@@ -81,17 +116,22 @@ export class DirectResourceFactoryImpl {
81
116
  /**
82
117
  * Deploy a new instance with the given spec
83
118
  */
84
- async deploy(spec) {
119
+ async deploy(spec, opts) {
85
120
  this.logger.debug('DirectResourceFactory deploy called', {
86
121
  factoryName: this.name,
87
122
  hasStatusBuilder: !!this.statusBuilder,
88
123
  });
124
+ validateSpec(spec, this.schemaDefinition, {
125
+ kind: this.schemaDefinition.kind,
126
+ name: this.name,
127
+ });
89
128
  // Use the consolidated deployment strategy
90
129
  const strategy = this.getDeploymentStrategy();
91
130
  this.logger.debug('Got deployment strategy', {
92
131
  strategyType: strategy.constructor.name,
93
132
  });
94
- const instance = await strategy.deploy(spec);
133
+ await this.ensureSingletonOwners(spec);
134
+ const instance = await strategy.deploy(spec, opts);
95
135
  // Check if deployment failed and throw for user-facing error handling
96
136
  if (instance.metadata?.annotations?.['typekro.io/deployment-status'] === 'failed') {
97
137
  const errorMessage = instance.metadata?.annotations?.['typekro.io/deployment-error'] ||
@@ -99,7 +139,7 @@ export class DirectResourceFactoryImpl {
99
139
  throw new ResourceGraphFactoryError(errorMessage, this.name, 'deployment');
100
140
  }
101
141
  // Track the deployed instance
102
- const instanceName = this.generateInstanceName(spec);
142
+ const instanceName = opts?.instanceNameOverride ?? this.generateInstanceName(spec);
103
143
  this.deployedInstances.set(instanceName, instance);
104
144
  return instance;
105
145
  }
@@ -118,35 +158,58 @@ export class DirectResourceFactoryImpl {
118
158
  }
119
159
  /**
120
160
  * Get all deployed instances
161
+ *
162
+ * Direct mode currently reports same-process instances only. Cross-process
163
+ * discovery is implemented for `deleteInstance(name)`, but reconstructing
164
+ * fully typed Enhanced instances from live tagged resources is intentionally
165
+ * not attempted here.
121
166
  */
122
167
  async getInstances() {
123
168
  return Array.from(this.deployedInstances.values());
124
169
  }
125
170
  /**
126
- * Delete a specific instance by name
171
+ * Delete a specific instance by name.
172
+ *
173
+ * Lookup order:
174
+ * 1. In-memory `deployedInstances` Map (same-process path) — uses
175
+ * the deployment-id annotation on the Enhanced instance proxy.
176
+ * 2. Cluster-side label discovery (cross-process path) — queries
177
+ * for all resources labeled `typekro.io/factory-name=<factory>,
178
+ * typekro.io/instance-name=<instance>`, reconstructs the
179
+ * dependency graph from per-resource `typekro.io/depends-on`
180
+ * annotations, and performs reverse-topological deletion.
181
+ *
182
+ * Both paths feed into the same graph-based reverse-topological
183
+ * delete via `engine.rollbackRecord`.
184
+ *
185
+ * **Scope filtering**: By default, unscoped (instance-private)
186
+ * resources are deleted and scoped resources are preserved. Pass
187
+ * `opts.scopes` to include broader-scope resources additively:
188
+ *
189
+ * ```ts
190
+ * await factory.deleteInstance('my-app'); // unscoped only (safe default)
191
+ * await factory.deleteInstance('my-app', { scopes: ['cluster'] }); // unscoped + cluster
192
+ * await factory.deleteInstance('my-app', { scopes: ['cluster'],
193
+ * includeUnscopedResources: false }); // cluster-only (leave app running)
194
+ * ```
127
195
  */
128
- async deleteInstance(name) {
129
- const instance = this.deployedInstances.get(name);
130
- if (!instance) {
131
- throw new TypeKroError(`Instance not found: ${name}`, 'INSTANCE_NOT_FOUND', {
132
- instanceName: name,
133
- factoryName: this.name,
134
- });
135
- }
196
+ async deleteInstance(name, opts) {
197
+ const engine = this.getDeploymentEngine();
136
198
  try {
137
- // Use the deployment engine to delete resources using actual deployment ID
138
- const engine = this.getDeploymentEngine();
139
- const deploymentId = instance.metadata?.annotations?.['typekro.io/deployment-id'];
140
- if (!deploymentId) {
141
- throw new TypeKroError(`Instance ${name} does not have a deployment ID annotation. Cannot perform cleanup.`, 'MISSING_DEPLOYMENT_ID', { instanceName: name, factoryName: this.name });
199
+ const rollbackResult = await this.rollbackInstanceResources(name, opts);
200
+ if (rollbackResult.status !== 'success' || rollbackResult.errors.length > 0) {
201
+ const errorSummary = rollbackResult.errors
202
+ .map((error) => `${error.resourceId}: ${ensureError(error.error).message}`)
203
+ .join('; ');
204
+ throw new Error(`Cleanup incomplete for instance ${name}: rollback ${rollbackResult.status}${errorSummary ? ` (${errorSummary})` : ''}`);
142
205
  }
143
- const rollbackResult = await engine.rollback(deploymentId);
144
206
  // Wait for any namespaces to be fully deleted before returning.
145
207
  // Namespace deletion is asynchronous (enters "Terminating" phase) and can
146
208
  // cause race conditions if the caller immediately re-creates resources.
147
209
  const deletedNamespaces = rollbackResult.rolledBackResources
148
210
  .filter((r) => r.startsWith('Namespace/'))
149
- .map((r) => r.split('/')[1]);
211
+ .map((r) => r.split('/')[1])
212
+ .filter((namespace) => namespace !== undefined);
150
213
  if (deletedNamespaces.length > 0) {
151
214
  // Delete PVCs in namespaces before waiting — StatefulSet PVCs have
152
215
  // finalizers that block namespace termination until volumes are released.
@@ -159,19 +222,24 @@ export class DirectResourceFactoryImpl {
159
222
  const pvcs = await coreApi.listNamespacedPersistentVolumeClaim({ namespace: ns });
160
223
  if (pvcs.items.length > 0) {
161
224
  this.logger.info('Deleting PVCs to unblock namespace termination', {
162
- namespace: ns, count: pvcs.items.length,
225
+ namespace: ns,
226
+ count: pvcs.items.length,
163
227
  });
164
228
  }
165
229
  for (const pvc of pvcs.items) {
166
230
  const pvcName = pvc.metadata?.name;
167
231
  if (!pvcName)
168
232
  continue;
169
- await coreApi.deleteNamespacedPersistentVolumeClaim({
233
+ await coreApi
234
+ .deleteNamespacedPersistentVolumeClaim({
170
235
  name: pvcName,
171
236
  namespace: ns,
172
- }).catch((err) => {
237
+ })
238
+ .catch((err) => {
173
239
  this.logger.info('PVC delete failed', {
174
- pvc: pvcName, namespace: ns, error: String(err),
240
+ pvc: pvcName,
241
+ namespace: ns,
242
+ error: String(err),
175
243
  });
176
244
  });
177
245
  }
@@ -192,17 +260,81 @@ export class DirectResourceFactoryImpl {
192
260
  this.deployedInstances.delete(name);
193
261
  }
194
262
  catch (error) {
195
- // If the deployment isn't found in the state, it may have already been cleaned up
196
- // or the deployment ID format changed. Log and remove from tracking anyway.
263
+ // INSTANCE_NOT_FOUND bubbles up the caller asked us to delete
264
+ // an instance that has neither in-memory state nor a persisted
265
+ // record. That's a legitimate error (wrong name, already cleaned
266
+ // up) and the caller needs to see it.
267
+ if (error instanceof TypeKroError && error.code === 'INSTANCE_NOT_FOUND') {
268
+ throw error;
269
+ }
270
+ // Soft-swallow "Cannot rollback" errors from the engine —
271
+ // they indicate the engine's in-memory deployment state has
272
+ // already been cleaned up (e.g., by a previous rollback call).
273
+ // The instance is effectively gone, so we remove from tracking.
197
274
  const errorMessage = ensureError(error).message;
198
- if (errorMessage.includes('not found') || errorMessage.includes('Cannot rollback')) {
275
+ if (errorMessage.includes('Cannot rollback')) {
199
276
  this.deployedInstances.delete(name);
200
- // Don't throw - the instance is already gone
201
277
  return;
202
278
  }
203
279
  throw new ResourceGraphFactoryError(`Failed to delete instance ${name}: ${errorMessage}`, this.name, 'cleanup');
204
280
  }
205
281
  }
282
+ buildKnownGvks() {
283
+ const crdHints = new Map();
284
+ for (const r of Object.values(this.resources)) {
285
+ if (!r.apiVersion || !r.kind)
286
+ continue;
287
+ const key = `${r.apiVersion}/${r.kind}`;
288
+ if (crdHints.has(key))
289
+ continue;
290
+ const scope = getMetadataField(r, 'scope');
291
+ crdHints.set(key, {
292
+ apiVersion: r.apiVersion,
293
+ kind: r.kind,
294
+ namespaced: scope !== 'cluster',
295
+ });
296
+ }
297
+ return [...BUILT_IN_GVKS, ...crdHints.values()];
298
+ }
299
+ async rollbackInstanceResources(name, opts) {
300
+ const engine = this.getDeploymentEngine();
301
+ const instance = this.deployedInstances.get(name);
302
+ if (instance) {
303
+ const deploymentId = instance.metadata?.annotations?.['typekro.io/deployment-id'];
304
+ if (deploymentId) {
305
+ try {
306
+ return await engine.rollback(deploymentId, {
307
+ ...(opts?.scopes && { scopes: opts.scopes }),
308
+ ...(opts?.includeUnscopedResources === false && { includeUnscopedResources: false }),
309
+ });
310
+ }
311
+ catch (error) {
312
+ const isNotFound = error instanceof ResourceGraphFactoryError && error.operation === 'cleanup';
313
+ if (!isNotFound) {
314
+ throw error;
315
+ }
316
+ }
317
+ }
318
+ }
319
+ const record = await engine.loadDeploymentByInstance({
320
+ factoryName: this.name,
321
+ instanceName: name,
322
+ knownGvks: this.buildKnownGvks(),
323
+ });
324
+ if (!record) {
325
+ throw new TypeKroError(`Instance not found: ${name} (no in-memory state and no tagged resources on the cluster). The instance may have been cleaned up already, or was deployed with a typekro version that did not tag resources.`, 'INSTANCE_NOT_FOUND', { instanceName: name, factoryName: this.name });
326
+ }
327
+ this.logger.info('Cross-process cleanup: discovered deployment from cluster labels', {
328
+ instanceName: name,
329
+ factoryName: this.name,
330
+ deploymentId: record.deploymentId,
331
+ resourceCount: record.resources.length,
332
+ });
333
+ return engine.rollbackRecord(record, {
334
+ ...(opts?.scopes && { scopes: opts.scopes }),
335
+ ...(opts?.includeUnscopedResources === false && { includeUnscopedResources: false }),
336
+ });
337
+ }
206
338
  /**
207
339
  * Poll until the given namespaces no longer exist (HTTP 404).
208
340
  * Namespaces enter a "Terminating" phase on deletion and may take time
@@ -214,6 +346,7 @@ export class DirectResourceFactoryImpl {
214
346
  for (const ns of namespaces) {
215
347
  // Each namespace gets its own timeout budget
216
348
  const nsStartTime = Date.now();
349
+ let deleted = false;
217
350
  while (Date.now() - nsStartTime < timeout) {
218
351
  try {
219
352
  await k8sApi.read({
@@ -229,20 +362,28 @@ export class DirectResourceFactoryImpl {
229
362
  const k8sErr = error;
230
363
  if (k8sErr.statusCode === 404 || k8sErr.body?.code === 404) {
231
364
  this.logger.debug('Namespace fully deleted', { namespace: ns });
365
+ deleted = true;
232
366
  break;
233
367
  }
234
- // Unexpected error — log and stop waiting for this namespace
368
+ // Unexpected error — fail loudly so callers do not assume cleanup completed.
235
369
  this.logger.warn('Error polling namespace deletion', {
236
370
  namespace: ns,
237
371
  error: ensureError(error).message,
238
372
  });
239
- break;
373
+ throw error;
240
374
  }
241
375
  }
376
+ if (!deleted) {
377
+ throw new ResourceGraphFactoryError(`Timed out waiting for namespace ${ns} to be deleted after ${timeout}ms`, this.name, 'cleanup');
378
+ }
242
379
  }
243
380
  }
244
381
  /**
245
382
  * Get factory status with real health checking using readiness evaluators
383
+ *
384
+ * Direct mode status is based on same-process instances returned by
385
+ * `getInstances()`. Use `deleteInstance(name)` for cross-process cleanup;
386
+ * status reconstruction from tagged live resources is not currently exposed.
246
387
  */
247
388
  async getStatus() {
248
389
  const instances = await this.getInstances();
@@ -460,27 +601,60 @@ export class DirectResourceFactoryImpl {
460
601
  }
461
602
  /**
462
603
  * Rollback all deployments made by this factory
604
+ *
605
+ * This rolls back same-process deployments tracked by this factory instance.
606
+ * For cross-process cleanup, call `deleteInstance(name)` with the known
607
+ * instance name so TypeKro can discover tagged resources from the cluster.
463
608
  */
464
609
  async rollback() {
465
610
  this.logger.debug('Starting rollback for all deployed instances');
466
- // Get kubeConfig from the centralized provider (lazy initialization)
467
- const clientProvider = this.getClientProvider();
468
- const kubeConfig = clientProvider.getKubeConfig();
469
- // Create rollback manager with the provider's KubeConfig
470
- const rollbackManager = createRollbackManagerWithKubeConfig(kubeConfig);
471
- // Get all deployed instances as Enhanced resources
472
- const resourcesToRollback = Array.from(this.deployedInstances.values());
611
+ const startedAt = Date.now();
612
+ const instanceNames = Array.from(this.deployedInstances.keys());
473
613
  this.logger.debug('Rolling back resources', {
474
- resourceCount: resourcesToRollback.length,
475
- instanceNames: Array.from(this.deployedInstances.keys()),
614
+ instanceCount: instanceNames.length,
615
+ instanceNames,
476
616
  });
477
- // Perform rollback using consolidated logic
478
- const result = await rollbackManager.rollbackResources(resourcesToRollback, {
479
- timeout: this.factoryOptions.timeout || undefined,
480
- emitEvent: this.factoryOptions.progressCallback || undefined,
481
- });
482
- // Clear all tracked instances after rollback
483
- this.deployedInstances.clear();
617
+ const rolledBackResources = [];
618
+ const errors = [];
619
+ let status = 'success';
620
+ for (const instanceName of instanceNames) {
621
+ try {
622
+ const result = await this.rollbackInstanceResources(instanceName);
623
+ rolledBackResources.push(...result.rolledBackResources);
624
+ errors.push(...result.errors);
625
+ if (result.status === 'failed') {
626
+ status = 'failed';
627
+ }
628
+ else if (result.status === 'partial' && status === 'success') {
629
+ status = 'partial';
630
+ }
631
+ if (result.status === 'success' && result.errors.length === 0) {
632
+ this.deployedInstances.delete(instanceName);
633
+ }
634
+ }
635
+ catch (error) {
636
+ status = 'failed';
637
+ errors.push({
638
+ resourceId: instanceName,
639
+ phase: 'rollback',
640
+ error: ensureError(error),
641
+ timestamp: new Date(),
642
+ });
643
+ }
644
+ }
645
+ if (errors.length > 0 && status === 'success') {
646
+ status = rolledBackResources.length > 0 ? 'partial' : 'failed';
647
+ }
648
+ const result = {
649
+ deploymentId: `factory-rollback-${Date.now()}`,
650
+ rolledBackResources,
651
+ duration: Date.now() - startedAt,
652
+ status,
653
+ errors,
654
+ };
655
+ if (result.status === 'success') {
656
+ this.deployedInstances.clear();
657
+ }
484
658
  this.logger.info('Rollback completed', {
485
659
  status: result.status,
486
660
  resourceCount: result.rolledBackResources.length,
@@ -517,7 +691,10 @@ export class DirectResourceFactoryImpl {
517
691
  */
518
692
  toYaml(spec) {
519
693
  // Resolve references with the actual spec values
520
- const resolvedResources = this.resolveResourcesForSpec(spec);
694
+ const resolvedResources = applyAspects(this.resolveResourcesForSpec(spec), {
695
+ mode: 'direct',
696
+ aspects: this.factoryOptions.aspects ?? [],
697
+ });
521
698
  // Validate that all values are fully resolved — no KubernetesRef or
522
699
  // CelExpression objects should remain in direct-mode YAML output.
523
700
  const unresolvedRefs = findUnresolvedReferences(resolvedResources);
@@ -551,6 +728,9 @@ export class DirectResourceFactoryImpl {
551
728
  ...(cleanResource.metadata?.labels
552
729
  ? { labels: cleanResource.metadata.labels }
553
730
  : undefined),
731
+ ...(cleanResource.metadata?.annotations
732
+ ? { annotations: cleanResource.metadata.annotations }
733
+ : undefined),
554
734
  },
555
735
  };
556
736
  // Handle different resource types
@@ -572,10 +752,13 @@ export class DirectResourceFactoryImpl {
572
752
  /**
573
753
  * Create a resource graph for a specific instance
574
754
  */
575
- createResourceGraphForInstance(spec) {
755
+ createResourceGraphForInstance(spec, instanceNameOverride) {
576
756
  const dependencyResolver = new DependencyResolver();
577
- const resolvedResources = this.resolveResourcesForSpec(spec);
578
- const instanceName = this.generateInstanceName(spec);
757
+ const resolvedResources = applyAspects(this.resolveResourcesForSpec(spec), {
758
+ mode: 'direct',
759
+ aspects: this.factoryOptions.aspects ?? [],
760
+ });
761
+ const instanceName = instanceNameOverride ?? this.generateInstanceName(spec);
579
762
  const resourceArray = Object.values(resolvedResources).map((resource, index) => {
580
763
  this.logger.debug('Processing resource for ID generation', {
581
764
  index,
@@ -662,7 +845,8 @@ export class DirectResourceFactoryImpl {
662
845
  }
663
846
  }
664
847
  catch (error) {
665
- this.logger.error('Failed to re-execute composition, falling back to reference resolution', ensureError(error));
848
+ this.logger.error('Failed to re-execute composition with actual spec values', ensureError(error));
849
+ throw error;
666
850
  }
667
851
  }
668
852
  // Fall back to the original reference resolution approach
@@ -699,6 +883,7 @@ export class DirectResourceFactoryImpl {
699
883
  // with the same id (e.g., 'regionDep') get unique keys ('regionDep', 'regionDep-1', etc.)
700
884
  const reExecutionContext = createCompositionContext('re-execution', {
701
885
  deduplicateIds: true,
886
+ isReExecution: true,
702
887
  });
703
888
  // Execute the composition function within the new context and capture both resources and status
704
889
  const { resources, status } = runWithCompositionContext(reExecutionContext, () => {
@@ -737,7 +922,7 @@ export class DirectResourceFactoryImpl {
737
922
  }
738
923
  catch (error) {
739
924
  this.logger.error('Failed to re-execute composition', ensureError(error));
740
- return null;
925
+ throw error;
741
926
  }
742
927
  }
743
928
  /**
@@ -747,6 +932,22 @@ export class DirectResourceFactoryImpl {
747
932
  getReExecutedStatus() {
748
933
  return this.reExecutedStatus;
749
934
  }
935
+ reExecuteSingletonStatus(singletonDefinition, liveStatusMap) {
936
+ const compositionFn = singletonDefinition.composition._compositionFn;
937
+ if (!compositionFn) {
938
+ return undefined;
939
+ }
940
+ const singletonContext = createCompositionContext('singleton-re-execution', {
941
+ deduplicateIds: true,
942
+ isReExecution: true,
943
+ });
944
+ singletonContext.liveStatusMap = liveStatusMap;
945
+ const status = runWithCompositionContext(singletonContext, () => compositionFn(singletonDefinition.spec));
946
+ if (status && typeof status === 'object' && !Array.isArray(status)) {
947
+ return status;
948
+ }
949
+ return undefined;
950
+ }
750
951
  /**
751
952
  * Re-execute the composition with live status data from deployed resources.
752
953
  *
@@ -773,6 +974,7 @@ export class DirectResourceFactoryImpl {
773
974
  // synthesize status entries from child resources' live data.
774
975
  const probeContext = createCompositionContext('re-execution-probe', {
775
976
  deduplicateIds: true,
977
+ isReExecution: true,
776
978
  });
777
979
  probeContext.liveStatusMap = liveStatusMap;
778
980
  runWithCompositionContext(probeContext, () => {
@@ -787,10 +989,41 @@ export class DirectResourceFactoryImpl {
787
989
  // This uses synthesizeNestedCompositionStatus which is shared between
788
990
  // direct and KRO deployment strategies — it only depends on the probe
789
991
  // context's resource keys and the liveStatusMap's deployed resource keys.
790
- const enrichedMap = synthesizeNestedCompositionStatus(probeContext.resources, liveStatusMap, this.logger, probeContext.nestedCompositionIds);
992
+ const enrichedMap = synthesizeNestedCompositionStatus(probeContext.resources, liveStatusMap, this.logger, probeContext.nestedCompositionIds, probeContext.nestedStatusSnapshots);
993
+ // Framework invariant: direct-mode re-execution must preserve the same
994
+ // cross-composition semantics as KRO-mode serialization. If a user writes
995
+ // `const stack = nestedComp(...); return { ready: stack.status.ready && ... }`,
996
+ // TypeKro must resolve that alias in the framework rather than pushing
997
+ // CEL-specific workarounds into composition code.
998
+ const aliasTargets = buildNestedCompositionAliasTargets(this.factoryOptions.compositionFn.toString(), probeContext.nestedCompositionIds);
999
+ for (const [aliasName, baseId] of Object.entries(aliasTargets)) {
1000
+ const synthesizedStatus = enrichedMap.get(baseId);
1001
+ if (synthesizedStatus && !enrichedMap.has(aliasName)) {
1002
+ enrichedMap.set(aliasName, synthesizedStatus);
1003
+ }
1004
+ }
1005
+ const singletonDefinitions = new Map();
1006
+ for (const definition of this.singletonDefinitions) {
1007
+ singletonDefinitions.set(definition.key, definition);
1008
+ }
1009
+ for (const definition of probeContext.singletonDefinitions?.values() ?? []) {
1010
+ singletonDefinitions.set(definition.key, definition);
1011
+ }
1012
+ for (const definition of singletonDefinitions.values()) {
1013
+ const singletonResourceId = getSingletonResourceId(definition.key);
1014
+ if (enrichedMap.has(singletonResourceId)) {
1015
+ continue;
1016
+ }
1017
+ const singletonStatus = this.singletonOwnerStatuses.get(singletonResourceId) ??
1018
+ this.reExecuteSingletonStatus(definition, liveStatusMap);
1019
+ if (singletonStatus) {
1020
+ enrichedMap.set(singletonResourceId, singletonStatus);
1021
+ }
1022
+ }
791
1023
  // Phase 2: Real execution with enriched live status map
792
1024
  const reExecutionContext = createCompositionContext('re-execution', {
793
1025
  deduplicateIds: true,
1026
+ isReExecution: true,
794
1027
  });
795
1028
  reExecutionContext.liveStatusMap = enrichedMap;
796
1029
  const { status } = runWithCompositionContext(reExecutionContext, () => {
@@ -920,6 +1153,19 @@ export class DirectResourceFactoryImpl {
920
1153
  }
921
1154
  return { found: true, value: currentValue };
922
1155
  }
1156
+ resolveSpecPathValue(spec, specPath, logPath) {
1157
+ const pathParts = specPath.split('.').filter(Boolean);
1158
+ return this.traverseSpec(spec, pathParts, logPath);
1159
+ }
1160
+ stringifyCelFallbackValue(value) {
1161
+ if (value === null)
1162
+ return 'null';
1163
+ if (typeof value === 'string')
1164
+ return value;
1165
+ if (typeof value === 'number' || typeof value === 'boolean')
1166
+ return String(value);
1167
+ return JSON.stringify(value);
1168
+ }
923
1169
  /**
924
1170
  * Resolve schema references and CEL expressions to actual values for direct deployment.
925
1171
  * This is the final, corrected version that handles both direct proxies and Cel.expr wrappers.
@@ -949,15 +1195,24 @@ export class DirectResourceFactoryImpl {
949
1195
  this.logger.trace('Found CEL Expression', { path, expression: resource.expression });
950
1196
  // The .expression property holds a string like "schema.spec.name-db-config"
951
1197
  let expressionString = resource.expression;
1198
+ const exactSchemaRef = expressionString.match(/^schema\.spec\.([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)$/);
1199
+ const exactSpecPath = exactSchemaRef?.[1];
1200
+ if (exactSpecPath !== undefined) {
1201
+ const resolved = this.resolveSpecPathValue(spec, exactSpecPath, path);
1202
+ if (resolved.found) {
1203
+ return resolved.value;
1204
+ }
1205
+ }
952
1206
  // Use regex to find all `schema.spec.fieldName` placeholders in the string
953
1207
  // and replace them with the corresponding values from the spec object.
954
1208
  // The 'g' flag ensures all occurrences are replaced.
955
- expressionString = expressionString.replace(/schema\.spec\.(\w+)/g, (_match, fieldName) => {
956
- const value = spec[fieldName];
957
- this.logger.trace('Replacing CEL placeholder', { fieldName, value });
1209
+ expressionString = expressionString.replace(/schema\.spec\.([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)/g, (_match, specPath) => {
1210
+ const resolved = this.resolveSpecPathValue(spec, specPath, path);
1211
+ const value = resolved.found ? resolved.value : undefined;
1212
+ this.logger.trace('Replacing CEL placeholder', { specPath, value });
958
1213
  // If the value exists in the spec, convert it to a string for concatenation.
959
1214
  // Otherwise, keep the original placeholder (though this shouldn't happen in valid cases).
960
- return value !== undefined ? String(value) : _match;
1215
+ return value !== undefined ? this.stringifyCelFallbackValue(value) : _match;
961
1216
  });
962
1217
  this.logger.trace('Resolved CEL expression to value', {
963
1218
  path,
@@ -1007,7 +1262,7 @@ export class DirectResourceFactoryImpl {
1007
1262
  // Pattern: __KUBERNETES_REF_{resourceId}_{fieldPath}__
1008
1263
  // For schema: __KUBERNETES_REF___schema___{fieldPath}__
1009
1264
  // The fieldPath for schema refs is like "spec.baseName" or "spec.nested.field"
1010
- const resolvedString = resource.replace(/__KUBERNETES_REF___schema___(.+?)__/g, (_match, fieldPath) => {
1265
+ const resolvedString = resource.replace(new RegExp(KUBERNETES_REF_SCHEMA_MARKER_SOURCE, 'g'), (_match, fieldPath) => {
1011
1266
  // fieldPath is like "spec.baseName" - we need to traverse starting from the schema root
1012
1267
  const pathParts = fieldPath.split('.');
1013
1268
  // The first part should be 'spec' or 'status'
@@ -1050,6 +1305,271 @@ export class DirectResourceFactoryImpl {
1050
1305
  // Use the imported shared utility
1051
1306
  return generateInstanceName(spec);
1052
1307
  }
1308
+ async ensureTargetNamespace(namespace = this.namespace) {
1309
+ try {
1310
+ const { createBunCompatibleKubernetesObjectApi } = await import('../kubernetes/bun-api-client.js');
1311
+ const k8sApi = createBunCompatibleKubernetesObjectApi(this.getClientProvider().getKubeConfig());
1312
+ const waitForNamespaceDeletion = async () => {
1313
+ const start = Date.now();
1314
+ while (Date.now() - start < 120000) {
1315
+ try {
1316
+ const existing = (await k8sApi.read({
1317
+ apiVersion: 'v1',
1318
+ kind: 'Namespace',
1319
+ metadata: { name: namespace },
1320
+ }));
1321
+ if (!existing.metadata?.deletionTimestamp) {
1322
+ return;
1323
+ }
1324
+ }
1325
+ catch (pollError) {
1326
+ const err = pollError;
1327
+ const code = err.statusCode ?? err.body?.code;
1328
+ if (code === 404) {
1329
+ return;
1330
+ }
1331
+ throw pollError;
1332
+ }
1333
+ await new Promise((resolve) => setTimeout(resolve, 1000));
1334
+ }
1335
+ throw new Error(`Namespace ${namespace} is still terminating after 120000ms`);
1336
+ };
1337
+ try {
1338
+ const existing = (await k8sApi.read({
1339
+ apiVersion: 'v1',
1340
+ kind: 'Namespace',
1341
+ metadata: { name: namespace },
1342
+ }));
1343
+ if (existing.metadata?.deletionTimestamp) {
1344
+ await waitForNamespaceDeletion();
1345
+ }
1346
+ else {
1347
+ return;
1348
+ }
1349
+ }
1350
+ catch (readError) {
1351
+ const k8sErr = readError;
1352
+ const code = k8sErr.statusCode ?? k8sErr.body?.code;
1353
+ if (code !== 404) {
1354
+ throw readError;
1355
+ }
1356
+ }
1357
+ try {
1358
+ await k8sApi.create({
1359
+ apiVersion: 'v1',
1360
+ kind: 'Namespace',
1361
+ metadata: {
1362
+ name: namespace,
1363
+ labels: {
1364
+ 'app.kubernetes.io/managed-by': 'typekro',
1365
+ },
1366
+ },
1367
+ });
1368
+ }
1369
+ catch (createError) {
1370
+ const k8sErr = createError;
1371
+ const code = k8sErr.statusCode ?? k8sErr.body?.code;
1372
+ const isNamespaceTerminating = k8sErr.body?.reason === 'Forbidden' &&
1373
+ k8sErr.message?.includes('NamespaceTerminating') === true;
1374
+ if (isNamespaceTerminating) {
1375
+ await waitForNamespaceDeletion();
1376
+ await k8sApi.create({
1377
+ apiVersion: 'v1',
1378
+ kind: 'Namespace',
1379
+ metadata: {
1380
+ name: namespace,
1381
+ labels: {
1382
+ 'app.kubernetes.io/managed-by': 'typekro',
1383
+ },
1384
+ },
1385
+ });
1386
+ }
1387
+ else if (code !== 409) {
1388
+ throw createError;
1389
+ }
1390
+ }
1391
+ }
1392
+ catch (error) {
1393
+ throw new ResourceGraphFactoryError(`Failed to ensure target namespace "${namespace}" exists: ${ensureError(error).message}`, this.name, 'deployment', ensureError(error));
1394
+ }
1395
+ }
1396
+ async ensureSingletonOwners(spec) {
1397
+ const discoveredSingletons = new Map();
1398
+ if (this.factoryOptions.compositionFn) {
1399
+ const singletonContext = createCompositionContext('singleton-owner-discovery');
1400
+ runWithCompositionContext(singletonContext, () => {
1401
+ this.factoryOptions.compositionFn?.(spec);
1402
+ });
1403
+ for (const [key, definition] of singletonContext.singletonDefinitions ?? []) {
1404
+ discoveredSingletons.set(key, definition);
1405
+ }
1406
+ }
1407
+ for (const definition of this.singletonDefinitions) {
1408
+ if (!discoveredSingletons.has(definition.key)) {
1409
+ discoveredSingletons.set(definition.key, definition);
1410
+ }
1411
+ }
1412
+ if (discoveredSingletons.size === 0)
1413
+ return;
1414
+ for (const definition of discoveredSingletons.values()) {
1415
+ await this.ensureTargetNamespace(definition.registryNamespace);
1416
+ const singletonInstanceName = getSingletonInstanceName(definition.id);
1417
+ const singletonFactory = definition.composition.factory('direct', {
1418
+ namespace: definition.registryNamespace,
1419
+ waitForReady: true,
1420
+ ...(this.factoryOptions.timeout !== undefined
1421
+ ? { timeout: this.factoryOptions.timeout }
1422
+ : {}),
1423
+ ...(this.factoryOptions.kubeConfig !== undefined
1424
+ ? { kubeConfig: this.factoryOptions.kubeConfig }
1425
+ : {}),
1426
+ ...(this.factoryOptions.skipTLSVerify !== undefined
1427
+ ? { skipTLSVerify: this.factoryOptions.skipTLSVerify }
1428
+ : {}),
1429
+ });
1430
+ try {
1431
+ const existingInstances = await singletonFactory.getInstances();
1432
+ assertNoDeployedSingletonSpecDrift(definition, singletonInstanceName, existingInstances);
1433
+ if ('createResourceGraphForInstance' in singletonFactory &&
1434
+ existingInstances.length === 0) {
1435
+ const discovered = await this.getDeploymentEngine().loadDeploymentByInstance({
1436
+ factoryName: singletonFactory.name,
1437
+ instanceName: singletonInstanceName,
1438
+ });
1439
+ const discoveredResources = discovered?.resources ?? [];
1440
+ const driftCheck = assertNoDiscoveredSingletonSpecDrift(definition, singletonInstanceName, discoveredResources);
1441
+ if (driftCheck.hasLegacyUnfingerprintedResources) {
1442
+ const expectedGraph = singletonFactory.createResourceGraphForInstance(definition.spec, singletonInstanceName);
1443
+ const discoveredIds = new Set(discoveredResources.map((resource) => resource.id));
1444
+ const hasAllExpectedResources = expectedGraph.resources.every((resource) => discoveredIds.has(resource.id));
1445
+ const hasHelmReleaseResources = expectedGraph.resources.some((resource) => resource.manifest.kind === 'HelmRelease');
1446
+ const legacyStatus = this.reExecuteSingletonStatusFromDiscoveredResources(definition, discoveredResources);
1447
+ if (legacyStatus) {
1448
+ this.singletonOwnerStatuses.set(getSingletonResourceId(definition.key), legacyStatus);
1449
+ }
1450
+ if (hasAllExpectedResources && !hasHelmReleaseResources) {
1451
+ this.logger.warn('Skipping direct singleton owner reconciliation for legacy resources without a spec fingerprint', {
1452
+ singletonId: definition.id,
1453
+ singletonKey: definition.key,
1454
+ singletonInstanceName,
1455
+ registryNamespace: definition.registryNamespace,
1456
+ });
1457
+ continue;
1458
+ }
1459
+ this.logger.warn('Reconciling direct singleton owner because legacy resources may need repair', {
1460
+ singletonId: definition.id,
1461
+ singletonKey: definition.key,
1462
+ singletonInstanceName,
1463
+ registryNamespace: definition.registryNamespace,
1464
+ discoveredResourceCount: discoveredResources.length,
1465
+ expectedResourceCount: expectedGraph.resources.length,
1466
+ hasAllExpectedResources,
1467
+ hasHelmReleaseResources,
1468
+ });
1469
+ }
1470
+ }
1471
+ const singletonDeployOptions = {
1472
+ instanceNameOverride: singletonInstanceName,
1473
+ singletonSpecFingerprint: singletonSpecFingerprintAnnotationValue(definition.specFingerprint),
1474
+ };
1475
+ const deployedSingleton = await singletonFactory.deploy(definition.spec, singletonDeployOptions);
1476
+ const singletonStatus = deployedSingleton.status;
1477
+ if (singletonStatus &&
1478
+ typeof singletonStatus === 'object' &&
1479
+ !Array.isArray(singletonStatus)) {
1480
+ this.singletonOwnerStatuses.set(getSingletonResourceId(definition.key), singletonStatus);
1481
+ }
1482
+ }
1483
+ finally {
1484
+ await singletonFactory.dispose?.();
1485
+ }
1486
+ }
1487
+ }
1488
+ reExecuteSingletonStatusFromDiscoveredResources(definition, resources) {
1489
+ if (resources.length === 0)
1490
+ return null;
1491
+ const liveStatusMap = new Map();
1492
+ const localIdsByLiveIdentity = this.getSingletonLocalIdsByLiveIdentity(definition);
1493
+ const singletonInstanceName = getSingletonInstanceName(definition.id);
1494
+ for (const resource of resources) {
1495
+ const manifest = resource.manifest;
1496
+ const status = manifest && typeof manifest === 'object' && 'status' in manifest
1497
+ ? manifest.status
1498
+ : undefined;
1499
+ const statusRecord = status && typeof status === 'object' && !Array.isArray(status)
1500
+ ? status
1501
+ : {};
1502
+ for (const id of this.getSingletonStatusAliases(resource.id, manifest, singletonInstanceName, localIdsByLiveIdentity)) {
1503
+ liveStatusMap.set(id, statusRecord);
1504
+ }
1505
+ }
1506
+ return this.reExecuteSingletonStatus(definition, liveStatusMap) ?? null;
1507
+ }
1508
+ getSingletonLocalIdsByLiveIdentity(definition) {
1509
+ const compositionFn = definition.composition._compositionFn;
1510
+ const idsByIdentity = new Map();
1511
+ if (!compositionFn)
1512
+ return idsByIdentity;
1513
+ const probeContext = createCompositionContext('singleton-status-discovery-probe', {
1514
+ deduplicateIds: true,
1515
+ isReExecution: true,
1516
+ });
1517
+ runWithCompositionContext(probeContext, () => compositionFn(definition.spec));
1518
+ for (const [id, resource] of Object.entries(probeContext.resources)) {
1519
+ const identity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name, resource.metadata?.namespace);
1520
+ if (identity)
1521
+ idsByIdentity.set(identity, id);
1522
+ const namespaceAgnosticIdentity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name);
1523
+ if (namespaceAgnosticIdentity)
1524
+ idsByIdentity.set(namespaceAgnosticIdentity, id);
1525
+ }
1526
+ return idsByIdentity;
1527
+ }
1528
+ getSingletonStatusAliases(discoveredId, manifest, singletonInstanceName, localIdsByLiveIdentity) {
1529
+ const aliases = new Set([discoveredId]);
1530
+ const annotationId = manifest && typeof manifest === 'object'
1531
+ ? manifest.metadata
1532
+ ?.annotations?.['typekro.io/resource-id']
1533
+ : undefined;
1534
+ if (annotationId)
1535
+ aliases.add(annotationId);
1536
+ const derivedId = this.deriveLocalIdFromDirectGraphId(discoveredId, singletonInstanceName, localIdsByLiveIdentity.values());
1537
+ if (derivedId)
1538
+ aliases.add(derivedId);
1539
+ if (manifest && typeof manifest === 'object') {
1540
+ const resource = manifest;
1541
+ const identity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name, resource.metadata?.namespace);
1542
+ const namespaceAgnosticIdentity = this.getLiveIdentityKey(resource.kind, resource.metadata?.name);
1543
+ const localId = (identity ? localIdsByLiveIdentity.get(identity) : undefined) ??
1544
+ (namespaceAgnosticIdentity
1545
+ ? localIdsByLiveIdentity.get(namespaceAgnosticIdentity)
1546
+ : undefined);
1547
+ if (localId)
1548
+ aliases.add(localId);
1549
+ }
1550
+ return [...aliases];
1551
+ }
1552
+ deriveLocalIdFromDirectGraphId(id, singletonInstanceName, candidateLocalIds = []) {
1553
+ const prefix = `${toCamelCase(singletonInstanceName)}Resource`;
1554
+ const match = id.match(new RegExp(`^${prefix}\\d+(.+)$`));
1555
+ if (!match?.[1])
1556
+ return undefined;
1557
+ const suffix = match[1].charAt(0).toLowerCase() + match[1].slice(1);
1558
+ const normalizedSuffix = suffix.toLowerCase();
1559
+ for (const candidate of candidateLocalIds) {
1560
+ if (candidate === suffix ||
1561
+ candidate.toLowerCase() === normalizedSuffix ||
1562
+ toCamelCase(candidate).toLowerCase() === normalizedSuffix) {
1563
+ return candidate;
1564
+ }
1565
+ }
1566
+ return suffix;
1567
+ }
1568
+ getLiveIdentityKey(kind, name, namespace) {
1569
+ if (!kind || !name)
1570
+ return undefined;
1571
+ return `${kind}/${namespace ?? ''}/${name}`;
1572
+ }
1053
1573
  }
1054
1574
  /**
1055
1575
  * Recursively walk a resolved resource tree and collect any remaining
@@ -1107,7 +1627,9 @@ function findUnresolvedReferences(resources) {
1107
1627
  /**
1108
1628
  * Create a DirectResourceFactory instance
1109
1629
  */
1110
- export function createDirectResourceFactory(name, resources, schemaDefinition, statusBuilder, options = {}) {
1630
+ export function createDirectResourceFactory(name, resources, schemaDefinition,
1631
+ // biome-ignore lint/suspicious/noExplicitAny: factory creation must accept status builders with composition-specific resource maps.
1632
+ statusBuilder, options = {}) {
1111
1633
  return new DirectResourceFactoryImpl(name, resources, schemaDefinition, statusBuilder, options);
1112
1634
  }
1113
1635
  //# sourceMappingURL=direct-factory.js.map