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