typekro 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/alchemy/deployers.d.ts +2 -2
  3. package/dist/alchemy/deployers.d.ts.map +1 -1
  4. package/dist/alchemy/deployers.js +12 -5
  5. package/dist/alchemy/deployers.js.map +1 -1
  6. package/dist/alchemy/index.d.ts +4 -2
  7. package/dist/alchemy/index.d.ts.map +1 -1
  8. package/dist/alchemy/index.js +4 -3
  9. package/dist/alchemy/index.js.map +1 -1
  10. package/dist/alchemy/resource-registration.d.ts +81 -19
  11. package/dist/alchemy/resource-registration.d.ts.map +1 -1
  12. package/dist/alchemy/resource-registration.js +296 -147
  13. package/dist/alchemy/resource-registration.js.map +1 -1
  14. package/dist/alchemy/types.d.ts +76 -8
  15. package/dist/alchemy/types.d.ts.map +1 -1
  16. package/dist/alchemy/wrapper.d.ts +0 -9
  17. package/dist/alchemy/wrapper.d.ts.map +1 -1
  18. package/dist/alchemy/wrapper.js +0 -15
  19. package/dist/alchemy/wrapper.js.map +1 -1
  20. package/dist/core/deployment/direct-factory.d.ts +14 -2
  21. package/dist/core/deployment/direct-factory.d.ts.map +1 -1
  22. package/dist/core/deployment/direct-factory.js +117 -14
  23. package/dist/core/deployment/direct-factory.js.map +1 -1
  24. package/dist/core/deployment/engine.d.ts +8 -5
  25. package/dist/core/deployment/engine.d.ts.map +1 -1
  26. package/dist/core/deployment/engine.js +36 -12
  27. package/dist/core/deployment/engine.js.map +1 -1
  28. package/dist/core/deployment/kro-factory.d.ts +35 -9
  29. package/dist/core/deployment/kro-factory.d.ts.map +1 -1
  30. package/dist/core/deployment/kro-factory.js +143 -151
  31. package/dist/core/deployment/kro-factory.js.map +1 -1
  32. package/dist/core/deployment/shared-utilities.d.ts +15 -4
  33. package/dist/core/deployment/shared-utilities.d.ts.map +1 -1
  34. package/dist/core/deployment/shared-utilities.js +47 -14
  35. package/dist/core/deployment/shared-utilities.js.map +1 -1
  36. package/dist/core/deployment/strategies/direct-strategy.d.ts.map +1 -1
  37. package/dist/core/deployment/strategies/direct-strategy.js +1 -2
  38. package/dist/core/deployment/strategies/direct-strategy.js.map +1 -1
  39. package/dist/core/deployment/strategies/index.d.ts +0 -1
  40. package/dist/core/deployment/strategies/index.d.ts.map +1 -1
  41. package/dist/core/deployment/strategies/index.js +0 -1
  42. package/dist/core/deployment/strategies/index.js.map +1 -1
  43. package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts +0 -13
  44. package/dist/core/expressions/composition/composition-analyzer-helpers.d.ts.map +1 -1
  45. package/dist/core/expressions/composition/composition-analyzer-helpers.js +78 -1
  46. package/dist/core/expressions/composition/composition-analyzer-helpers.js.map +1 -1
  47. package/dist/core/expressions/composition/imperative-analyzer.d.ts.map +1 -1
  48. package/dist/core/expressions/composition/imperative-analyzer.js +34 -1
  49. package/dist/core/expressions/composition/imperative-analyzer.js.map +1 -1
  50. package/dist/core/serialization/cel-references.d.ts +1 -1
  51. package/dist/core/serialization/cel-references.d.ts.map +1 -1
  52. package/dist/core/serialization/cel-references.js +19 -3
  53. package/dist/core/serialization/cel-references.js.map +1 -1
  54. package/dist/core/serialization/core.d.ts.map +1 -1
  55. package/dist/core/serialization/core.js +19 -4
  56. package/dist/core/serialization/core.js.map +1 -1
  57. package/dist/core/types/deployment.d.ts +28 -42
  58. package/dist/core/types/deployment.d.ts.map +1 -1
  59. package/dist/core/types/resource-graph.d.ts +2 -6
  60. package/dist/core/types/resource-graph.d.ts.map +1 -1
  61. package/dist/core/types/schema.d.ts +0 -1
  62. package/dist/core/types/schema.d.ts.map +1 -1
  63. package/dist/core/types/serialization.d.ts +3 -7
  64. package/dist/core/types/serialization.d.ts.map +1 -1
  65. package/dist/factories/kubernetes/yaml/yaml-directory.d.ts.map +1 -1
  66. package/dist/factories/kubernetes/yaml/yaml-directory.js +2 -13
  67. package/dist/factories/kubernetes/yaml/yaml-directory.js.map +1 -1
  68. package/dist/factories/kubernetes/yaml/yaml-file.d.ts.map +1 -1
  69. package/dist/factories/kubernetes/yaml/yaml-file.js +2 -18
  70. package/dist/factories/kubernetes/yaml/yaml-file.js.map +1 -1
  71. package/package.json +6 -3
  72. package/dist/alchemy/deployment.d.ts +0 -12
  73. package/dist/alchemy/deployment.d.ts.map +0 -1
  74. package/dist/alchemy/deployment.js +0 -12
  75. package/dist/alchemy/deployment.js.map +0 -1
  76. package/dist/core/deployment/strategies/alchemy-strategy.d.ts +0 -109
  77. package/dist/core/deployment/strategies/alchemy-strategy.d.ts.map +0 -1
  78. package/dist/core/deployment/strategies/alchemy-strategy.js +0 -556
  79. package/dist/core/deployment/strategies/alchemy-strategy.js.map +0 -1
@@ -4,6 +4,7 @@
4
4
  * This factory handles deployment via Kro ResourceGraphDefinitions,
5
5
  * using the Kro controller for dependency resolution and resource management.
6
6
  */
7
+ import type { AlchemyResourceDeclaration } from '../../alchemy/types.js';
7
8
  import type { FactoryOptions, FactoryStatus, KroResourceFactory, RGDStatus } from '../types/deployment.js';
8
9
  import type { Enhanced, KubernetesResource } from '../types/kubernetes.js';
9
10
  import type { KroCompatibleType, MagicAssignableShape, SchemaDefinition, SchemaProxy } from '../types/serialization.js';
@@ -48,14 +49,12 @@ export declare class KroResourceFactoryImpl<TSpec extends KroCompatibleType, TSt
48
49
  readonly mode: "kro";
49
50
  readonly name: string;
50
51
  readonly namespace: string;
51
- readonly isAlchemyManaged: boolean;
52
52
  readonly rgdName: string;
53
53
  readonly schema: SchemaProxy<TSpec, TStatus>;
54
54
  private readonly resources;
55
55
  private readonly closures;
56
56
  private readonly schemaDefinition;
57
57
  private readonly statusMappings;
58
- private readonly alchemyScope;
59
58
  private readonly singletonDefinitions;
60
59
  private readonly singletonOwnerStatuses;
61
60
  private readonly logger;
@@ -84,7 +83,6 @@ export declare class KroResourceFactoryImpl<TSpec extends KroCompatibleType, TSt
84
83
  private discoveredPlural;
85
84
  private readonly kroCustomResourceProvider;
86
85
  private readonly rgdProvider;
87
- private readonly alchemyBridge;
88
86
  constructor(name: string, resources: Record<string, KubernetesResource>, schemaDefinition: SchemaDefinition<TSpec, TStatus>, statusMappings: MagicAssignableShape<TStatus>, options?: FactoryOptions);
89
87
  /** Extract nested composition status CEL mappings from the raw status object. */
90
88
  private getNestedStatusCel;
@@ -142,6 +140,14 @@ export declare class KroResourceFactoryImpl<TSpec extends KroCompatibleType, TSt
142
140
  instanceNameOverride?: string;
143
141
  singletonSpecFingerprint?: string;
144
142
  }): Promise<Enhanced<TSpec, TStatus>>;
143
+ /**
144
+ * Discover the singleton-owner definitions this composition depends on (deduped by key): from
145
+ * re-executing the composition fn under a discovery context, plus any injected definitions.
146
+ * Shared by {@link ensureSingletonOwners} (imperative deploy) and {@link toAlchemyResources}.
147
+ */
148
+ private discoverSingletonDefinitions;
149
+ /** Build the KRO factory that owns a singleton's RGD + instance (its registry namespace). */
150
+ private singletonFactoryFor;
145
151
  private ensureSingletonOwners;
146
152
  private getSingletonOwnerInstancesForDriftCheck;
147
153
  private isMissingSingletonOwnerCrdError;
@@ -154,12 +160,6 @@ export declare class KroResourceFactoryImpl<TSpec extends KroCompatibleType, TSt
154
160
  * Deploy directly to Kubernetes using DirectDeploymentEngine
155
161
  */
156
162
  private deployDirect;
157
- /**
158
- * Deploy using type-safe alchemy resource wrapping
159
- *
160
- * In alchemy mode, the RGD gets one typed alchemy Resource and each instance gets another
161
- */
162
- private deployWithAlchemy;
163
163
  /**
164
164
  * Get all deployed instances
165
165
  */
@@ -173,7 +173,33 @@ export declare class KroResourceFactoryImpl<TSpec extends KroCompatibleType, TSt
173
173
  scopes?: string[];
174
174
  includeUnscopedResources?: boolean;
175
175
  }): Promise<void>;
176
+ /**
177
+ * Emit this factory's KRO deployment as declarative alchemy **v2** resources — the v2
178
+ * analog of the removed imperative `deployWithAlchemy(scope)`. Returns, in dependency order, a
179
+ * declaration for each discovered **singleton owner** (its own RGD + instance — mirroring
180
+ * `ensureSingletonOwners` in the imperative `deploy()` path), then the **RGD** (shared, deployed
181
+ * once), then the **CR instance** (one per `spec`, which `dependsOn` the RGD + the singletons),
182
+ * matching the old integration's per-resource state granularity. The caller instantiates
183
+ * each with `KroResource` inside their Stack (RGD first so reverse-topo removes the
184
+ * instance before the shared RGD):
185
+ *
186
+ * ```ts
187
+ * for (const { id, props } of await factory.toAlchemyResources(spec)) {
188
+ * yield* KroResource(id, props);
189
+ * }
190
+ * ```
191
+ *
192
+ * Each declaration carries serialized `kubeConfigOptions` (so reconcile can reconnect to the
193
+ * cluster after state rehydration) and `kroDeletion` (so delete is finalizer-safe / shared-RGD
194
+ * aware). The actual deploy/teardown runs in `kroProvider`'s reconcile/delete.
195
+ */
196
+ toAlchemyResources(spec: TSpec, opts?: {
197
+ instanceNameOverride?: string;
198
+ singletonSpecFingerprint?: string;
199
+ }): Promise<AlchemyResourceDeclaration[]>;
200
+ /** Serialize the factory's cluster connection so an alchemy resource can reconnect after rehydration. */
176
201
  private extractKubeConfigOptionsForAlchemy;
202
+ /** Build the finalizer-safe, shared-RGD-aware deletion metadata for this factory's instances. */
177
203
  private createAlchemyKroDeletionOptions;
178
204
  /**
179
205
  * Get factory status
@@ -1 +1 @@
1
- {"version":3,"file":"kro-factory.d.ts","sourceRoot":"","sources":["../../../src/core/deployment/kro-factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kro-factory.d.ts","sourceRoot":"","sources":["../../../src/core/deployment/kro-factory.ts"],"names":[],"mappings":"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"}
@@ -18,11 +18,13 @@ import { CRDInstanceError, ensureError, ResourceGraphFactoryError, TypeKroError,
18
18
  import { applyAnalysisToResources } from '../expressions/composition/composition-analyzer.js';
19
19
  import { createBunCompatibleKubernetesObjectApi } from '../kubernetes/index.js';
20
20
  import { getComponentLogger } from '../logging/index.js';
21
+ import { createAlchemyResourceId } from '../../alchemy/utilities.js';
21
22
  // Dependency inversion: kroCustomResource, resourceGraphDefinition, and
22
23
  // alchemy bridge are injected via FactoryOptions providers (Phase 3.5)
23
24
  // instead of dynamic import() from higher layers.
24
25
  import { getMetadataField, setMetadataField } from '../metadata/index.js';
25
26
  import { createSchemaProxy, DeploymentMode } from '../references/index.js';
27
+ import { isStaticExpression } from '../serialization/cel-references.js';
26
28
  import { applyTernaryConditionalsToResources } from '../serialization/kro-post-processing.js';
27
29
  import { generateKroSchemaFromArktype } from '../serialization/schema.js';
28
30
  import { serializeResourceGraphToYaml } from '../serialization/yaml.js';
@@ -32,7 +34,7 @@ import { DirectDeploymentEngine } from './engine.js';
32
34
  import { logHandleSnapshot } from './handle-tracing.js';
33
35
  import { isNotFoundError } from './k8s-helpers.js';
34
36
  import { waitForKroInstanceReady as waitForKroInstanceReadyShared } from './kro-readiness.js';
35
- import { convertToKubernetesName, generateInstanceName, getSingletonInstanceName, pluralizeKind, validateAlchemyScope, validateSpec, } from './shared-utilities.js';
37
+ import { convertToKubernetesName, extractSerializableKubeConfigOptions, generateInstanceName, getSingletonInstanceName, pluralizeKind, validateSpec, } from './shared-utilities.js';
36
38
  import { joinYamlDocuments, singletonOwnerInstanceYamls, singletonRgdYamls, } from './singleton-gitops.js';
37
39
  import { assertNoDeployedSingletonSpecDrift, singletonSpecFingerprintAnnotationValue, } from './singleton-owner-drift.js';
38
40
  /**
@@ -104,14 +106,12 @@ export class KroResourceFactoryImpl {
104
106
  mode = 'kro';
105
107
  name;
106
108
  namespace;
107
- isAlchemyManaged;
108
109
  rgdName;
109
110
  schema;
110
111
  resources;
111
112
  closures;
112
113
  schemaDefinition;
113
114
  statusMappings;
114
- alchemyScope;
115
115
  singletonDefinitions;
116
116
  singletonOwnerStatuses = new Map();
117
117
  logger = getComponentLogger('kro-factory');
@@ -142,12 +142,9 @@ export class KroResourceFactoryImpl {
142
142
  // instead of dynamic import() from factories/ and alchemy/ layers.
143
143
  kroCustomResourceProvider;
144
144
  rgdProvider;
145
- alchemyBridge;
146
145
  constructor(name, resources, schemaDefinition, statusMappings, options = {}) {
147
146
  this.name = name;
148
147
  this.namespace = options.namespace || 'default';
149
- this.alchemyScope = options.alchemyScope;
150
- this.isAlchemyManaged = !!options.alchemyScope;
151
148
  this.rgdName = convertToKubernetesName(name); // Convert to valid Kubernetes resource name
152
149
  this.resources = resources;
153
150
  this.closures = options.closures || {};
@@ -164,7 +161,6 @@ export class KroResourceFactoryImpl {
164
161
  // Injected providers — fall back to dynamic import() for backward compatibility
165
162
  this.kroCustomResourceProvider = options.kroCustomResourceProvider;
166
163
  this.rgdProvider = options.rgdProvider;
167
- this.alchemyBridge = options.alchemyBridge;
168
164
  // Validate closures for Kro mode - detect KubernetesRef inputs and raise clear errors
169
165
  this.validateClosuresForKroMode();
170
166
  }
@@ -397,53 +393,49 @@ export class KroResourceFactoryImpl {
397
393
  // Execute closures before RGD creation (Kro mode requirement)
398
394
  await this.executeClosuresBeforeRGD(spec);
399
395
  await this.ensureSingletonOwners(spec);
400
- if (this.isAlchemyManaged) {
401
- return this.deployWithAlchemy(spec, opts?.instanceNameOverride, opts?.singletonSpecFingerprint);
402
- }
403
- else {
404
- return this.deployDirect(spec, opts?.instanceNameOverride, opts?.singletonSpecFingerprint);
405
- }
396
+ return this.deployDirect(spec, opts?.instanceNameOverride, opts?.singletonSpecFingerprint);
406
397
  }
407
- async ensureSingletonOwners(spec) {
408
- const discoveredSingletons = new Map();
398
+ /**
399
+ * Discover the singleton-owner definitions this composition depends on (deduped by key): from
400
+ * re-executing the composition fn under a discovery context, plus any injected definitions.
401
+ * Shared by {@link ensureSingletonOwners} (imperative deploy) and {@link toAlchemyResources}.
402
+ */
403
+ discoverSingletonDefinitions(spec) {
404
+ const discovered = new Map();
409
405
  if (this.factoryOptions.compositionFn) {
410
- const singletonContext = createCompositionContext('singleton-owner-discovery');
411
- runWithCompositionContext(singletonContext, () => {
406
+ const ctx = createCompositionContext('singleton-owner-discovery');
407
+ runWithCompositionContext(ctx, () => {
412
408
  this.factoryOptions.compositionFn?.(spec);
413
409
  });
414
- for (const [key, definition] of singletonContext.singletonDefinitions ?? []) {
415
- discoveredSingletons.set(key, definition);
410
+ for (const [key, definition] of ctx.singletonDefinitions ?? []) {
411
+ discovered.set(key, definition);
416
412
  }
417
413
  }
418
414
  for (const definition of this.singletonDefinitions) {
419
- if (!discoveredSingletons.has(definition.key)) {
420
- discoveredSingletons.set(definition.key, definition);
421
- }
415
+ if (!discovered.has(definition.key))
416
+ discovered.set(definition.key, definition);
422
417
  }
423
- if (discoveredSingletons.size === 0)
424
- return;
425
- const singletonRecords = new Map();
426
- for (const definition of discoveredSingletons.values()) {
427
- if (!singletonRecords.has(definition.key)) {
428
- singletonRecords.set(definition.key, definition);
429
- }
430
- }
431
- for (const definition of singletonRecords.values()) {
418
+ return Array.from(discovered.values());
419
+ }
420
+ /** Build the KRO factory that owns a singleton's RGD + instance (its registry namespace). */
421
+ singletonFactoryFor(definition) {
422
+ return definition.composition.factory('kro', {
423
+ namespace: definition.registryNamespace,
424
+ waitForReady: true,
425
+ ...(this.factoryOptions.timeout !== undefined ? { timeout: this.factoryOptions.timeout } : {}),
426
+ ...(this.factoryOptions.kubeConfig !== undefined
427
+ ? { kubeConfig: this.factoryOptions.kubeConfig }
428
+ : {}),
429
+ ...(this.factoryOptions.skipTLSVerify !== undefined
430
+ ? { skipTLSVerify: this.factoryOptions.skipTLSVerify }
431
+ : {}),
432
+ });
433
+ }
434
+ async ensureSingletonOwners(spec) {
435
+ for (const definition of this.discoverSingletonDefinitions(spec)) {
432
436
  await this.ensureTargetNamespace(definition.registryNamespace);
433
437
  const singletonInstanceName = getSingletonInstanceName(definition.id);
434
- const singletonFactory = definition.composition.factory('kro', {
435
- namespace: definition.registryNamespace,
436
- waitForReady: true,
437
- ...(this.factoryOptions.timeout !== undefined
438
- ? { timeout: this.factoryOptions.timeout }
439
- : {}),
440
- ...(this.factoryOptions.kubeConfig !== undefined
441
- ? { kubeConfig: this.factoryOptions.kubeConfig }
442
- : {}),
443
- ...(this.factoryOptions.skipTLSVerify !== undefined
444
- ? { skipTLSVerify: this.factoryOptions.skipTLSVerify }
445
- : {}),
446
- });
438
+ const singletonFactory = this.singletonFactoryFor(definition);
447
439
  try {
448
440
  this.logger.info('Ensuring singleton owner boundary', {
449
441
  singletonId: definition.id,
@@ -542,7 +534,6 @@ export class KroResourceFactoryImpl {
542
534
  const deploymentContext = {
543
535
  kubernetesApi: createBunCompatibleKubernetesObjectApi(kubeConfig),
544
536
  kubeConfig: kubeConfig,
545
- ...(this.alchemyScope && { alchemyScope: this.alchemyScope }),
546
537
  namespace: this.namespace,
547
538
  deployedResources: new Map(), // Empty for pre-RGD execution
548
539
  resolveReference: async (ref) => {
@@ -653,78 +644,6 @@ export class KroResourceFactoryImpl {
653
644
  await deploymentEngine.dispose();
654
645
  }
655
646
  }
656
- /**
657
- * Deploy using type-safe alchemy resource wrapping
658
- *
659
- * In alchemy mode, the RGD gets one typed alchemy Resource and each instance gets another
660
- */
661
- async deployWithAlchemy(spec, instanceNameOverride, singletonSpecFingerprint) {
662
- validateAlchemyScope(this.alchemyScope, 'KRO Alchemy deployment');
663
- const alchemyScope = this.alchemyScope;
664
- // Use static registration functions
665
- // Create deployer instance using DirectDeploymentEngine with KRO mode
666
- const kroEngine = new DirectDeploymentEngine(this.getKubeConfig(), undefined, undefined, DeploymentMode.KRO);
667
- const kubeConfigOptions = this.extractKubeConfigOptionsForAlchemy();
668
- const kroDeletion = this.createAlchemyKroDeletionOptions();
669
- try {
670
- // 1. Ensure RGD is deployed via alchemy (once per factory). Reuse the
671
- // normal serializer so externalRef/forEach/includeWhen/readyWhen and
672
- // singleton owner boundaries match non-Alchemy KRO deploys.
673
- const rgdManifest = yaml.load(this.buildRgdYaml());
674
- // Register RGD type dynamically
675
- const rgdFactory = this.rgdProvider ??
676
- (await import('../../factories/kro/resource-graph-definition.js')).resourceGraphDefinition;
677
- const rgdEnhanced = rgdFactory(rgdManifest);
678
- const bridge = this.alchemyBridge ?? (await import('../../alchemy/deployment.js'));
679
- const RGDProvider = bridge.ensureResourceTypeRegistered(rgdEnhanced);
680
- const rgdId = bridge.createAlchemyResourceId(rgdEnhanced, this.namespace);
681
- await alchemyScope.run(async () => {
682
- await RGDProvider(rgdId, {
683
- resource: rgdEnhanced,
684
- namespace: this.namespace,
685
- deploymentStrategy: 'kro',
686
- kubeConfigOptions,
687
- kroDeletion,
688
- options: {
689
- waitForReady: true,
690
- timeout: DEFAULT_RGD_TIMEOUT, // RGD should be ready quickly
691
- },
692
- });
693
- });
694
- await this.waitForCRDReadyWithEngine(kroEngine);
695
- // 2. Create instance via alchemy (once per deploy call)
696
- await this.ensureTargetNamespace();
697
- const instanceName = instanceNameOverride ?? generateInstanceName(spec, this.name);
698
- const crdInstanceManifest = this.createCustomResourceInstance(instanceName, spec, singletonSpecFingerprint);
699
- // Register CRD instance type dynamically
700
- // Cast required: crdInstanceManifest is a plain KubernetesResource, but alchemy functions
701
- // expect Enhanced<unknown, unknown>. They only access kind/metadata.name for type inference.
702
- const crdAsEnhanced = crdInstanceManifest;
703
- const CRDInstanceProvider = bridge.ensureResourceTypeRegistered(crdAsEnhanced);
704
- const instanceId = bridge.createAlchemyResourceId(crdAsEnhanced, this.namespace);
705
- await alchemyScope.run(async () => {
706
- await CRDInstanceProvider(instanceId, {
707
- resource: crdAsEnhanced,
708
- namespace: this.namespace,
709
- deploymentStrategy: 'kro',
710
- kubeConfigOptions,
711
- kroDeletion,
712
- options: {
713
- waitForReady: false,
714
- timeout: this.factoryOptions.timeout ?? DEFAULT_DEPLOYMENT_TIMEOUT,
715
- },
716
- });
717
- });
718
- if (this.factoryOptions.waitForReady ?? true) {
719
- await this.waitForKroInstanceReady(instanceName, this.factoryOptions.timeout || DEFAULT_KRO_INSTANCE_TIMEOUT);
720
- }
721
- // Create Enhanced proxy for the deployed instance
722
- return await this.createEnhancedProxy(spec, instanceName);
723
- }
724
- finally {
725
- await kroEngine.dispose();
726
- }
727
- }
728
647
  /**
729
648
  * Get all deployed instances
730
649
  */
@@ -969,41 +888,106 @@ export class KroResourceFactoryImpl {
969
888
  // KRO's finalizer processing handles deleting all child resources
970
889
  // (including Namespaces) via its applyset — no manual cleanup needed.
971
890
  }
972
- extractKubeConfigOptionsForAlchemy() {
973
- const kc = this.getKubeConfig();
974
- const cluster = kc.getCurrentCluster();
975
- const user = typeof kc.getCurrentUser === 'function' ? kc.getCurrentUser() : undefined;
976
- const context = typeof kc.getCurrentContext === 'function' ? kc.getCurrentContext() : undefined;
977
- const finalSkipTLS = this.factoryOptions.skipTLSVerify === true ? true : (cluster?.skipTLSVerify ?? false);
978
- return {
979
- skipTLSVerify: finalSkipTLS,
980
- ...(cluster?.server && { server: cluster.server }),
981
- ...(context && { context }),
982
- ...(cluster && {
983
- cluster: {
984
- name: cluster.name,
985
- server: cluster.server,
986
- skipTLSVerify: finalSkipTLS,
987
- ...(cluster.caData && { caData: cluster.caData }),
988
- ...(cluster.caFile && { caFile: cluster.caFile }),
989
- },
990
- }),
991
- ...(user && {
992
- user: {
993
- name: user.name,
994
- ...(user.token && { token: user.token }),
995
- ...(user.certData && { certData: user.certData }),
996
- ...(user.certFile && { certFile: user.certFile }),
997
- ...(user.keyData && { keyData: user.keyData }),
998
- ...(user.keyFile && { keyFile: user.keyFile }),
999
- ...(user.exec ? { exec: user.exec } : {}),
1000
- ...(user.authProvider
1001
- ? { authProvider: user.authProvider }
1002
- : {}),
891
+ /**
892
+ * Emit this factory's KRO deployment as declarative alchemy **v2** resources — the v2
893
+ * analog of the removed imperative `deployWithAlchemy(scope)`. Returns, in dependency order, a
894
+ * declaration for each discovered **singleton owner** (its own RGD + instance — mirroring
895
+ * `ensureSingletonOwners` in the imperative `deploy()` path), then the **RGD** (shared, deployed
896
+ * once), then the **CR instance** (one per `spec`, which `dependsOn` the RGD + the singletons),
897
+ * matching the old integration's per-resource state granularity. The caller instantiates
898
+ * each with `KroResource` inside their Stack (RGD first so reverse-topo removes the
899
+ * instance before the shared RGD):
900
+ *
901
+ * ```ts
902
+ * for (const { id, props } of await factory.toAlchemyResources(spec)) {
903
+ * yield* KroResource(id, props);
904
+ * }
905
+ * ```
906
+ *
907
+ * Each declaration carries serialized `kubeConfigOptions` (so reconcile can reconnect to the
908
+ * cluster after state rehydration) and `kroDeletion` (so delete is finalizer-safe / shared-RGD
909
+ * aware). The actual deploy/teardown runs in `kroProvider`'s reconcile/delete.
910
+ */
911
+ async toAlchemyResources(spec, opts) {
912
+ const kubeConfigOptions = this.extractKubeConfigOptionsForAlchemy();
913
+ const kroDeletion = this.createAlchemyKroDeletionOptions();
914
+ // 0. Singleton owners. The imperative `deploy()` ensures shared singleton owners (each its own
915
+ // RGD + instance, in its registry namespace) via `ensureSingletonOwners` BEFORE the main
916
+ // instance; emit them as declarations too so the declarative path has the same boundaries.
917
+ // Their deterministic ids/names mean alchemy dedupes a singleton shared across compositions.
918
+ // (The runtime spec-drift check from `ensureSingletonOwners` is omitted here — `toAlchemyResources`
919
+ // stays cluster-free — but the spec-fingerprint annotation it relied on is still emitted.)
920
+ const singletonDeclarations = [];
921
+ const singletonInstanceIds = [];
922
+ for (const definition of this.discoverSingletonDefinitions(spec)) {
923
+ const singletonFactory = this.singletonFactoryFor(definition);
924
+ try {
925
+ const decls = await singletonFactory.toAlchemyResources(definition.spec, {
926
+ instanceNameOverride: getSingletonInstanceName(definition.id),
927
+ singletonSpecFingerprint: singletonSpecFingerprintAnnotationValue(definition.specFingerprint),
928
+ });
929
+ singletonDeclarations.push(...decls);
930
+ // `toAlchemyResources` returns the owner's OWN CR instance LAST (after any of ITS nested
931
+ // singletons + its RGD), so the consumer must wait on `decls[last]` — using "first decl
932
+ // with a dependency" would wrongly point at a nested singleton's instance.
933
+ const ownerInstance = decls[decls.length - 1];
934
+ if (ownerInstance)
935
+ singletonInstanceIds.push(ownerInstance.id);
936
+ }
937
+ finally {
938
+ await singletonFactory.dispose?.();
939
+ }
940
+ }
941
+ // 1. RGD declaration (deployed once per factory; shared by all instances). Reuse the normal
942
+ // serializer so externalRef/forEach/includeWhen/readyWhen + singleton boundaries match
943
+ // non-alchemy KRO deploys.
944
+ const rgdManifest = yaml.load(this.buildRgdYaml());
945
+ const rgdFactory = this.rgdProvider ??
946
+ (await import('../../factories/kro/resource-graph-definition.js')).resourceGraphDefinition;
947
+ const rgdEnhanced = rgdFactory(rgdManifest);
948
+ const rgdId = createAlchemyResourceId(rgdEnhanced, this.namespace);
949
+ const rgdDeclaration = {
950
+ id: rgdId,
951
+ dependsOn: [],
952
+ props: {
953
+ resource: rgdEnhanced,
954
+ namespace: this.namespace,
955
+ deploymentStrategy: 'kro',
956
+ kubeConfigOptions,
957
+ kroDeletion,
958
+ options: { waitForReady: true, timeout: DEFAULT_RGD_TIMEOUT },
959
+ },
960
+ };
961
+ // 2. CR instance declaration (one per deploy call). Depends on the RGD so alchemy applies the
962
+ // instance only after the RGD's CRD is established (else the CR apply races a missing kind).
963
+ const instanceName = opts?.instanceNameOverride ?? generateInstanceName(spec, this.name);
964
+ const crdInstanceManifest = this.createCustomResourceInstance(instanceName, spec, opts?.singletonSpecFingerprint);
965
+ // Cast: a plain KubernetesResource is fine — the alchemy path only reads kind/metadata.
966
+ const crdAsEnhanced = crdInstanceManifest;
967
+ const instanceDeclaration = {
968
+ id: createAlchemyResourceId(crdAsEnhanced, this.namespace),
969
+ // Wait for the RGD's CRD AND for any singleton owners (mirrors `ensureSingletonOwners` running
970
+ // before the main deploy), so the instance applies only once its dependencies exist.
971
+ dependsOn: [rgdId, ...singletonInstanceIds],
972
+ props: {
973
+ resource: crdAsEnhanced,
974
+ namespace: this.namespace,
975
+ deploymentStrategy: 'kro',
976
+ kubeConfigOptions,
977
+ kroDeletion,
978
+ options: {
979
+ waitForReady: false,
980
+ timeout: this.factoryOptions.timeout ?? DEFAULT_DEPLOYMENT_TIMEOUT,
1003
981
  },
1004
- }),
982
+ },
1005
983
  };
984
+ return [...singletonDeclarations, rgdDeclaration, instanceDeclaration];
985
+ }
986
+ /** Serialize the factory's cluster connection so an alchemy resource can reconnect after rehydration. */
987
+ extractKubeConfigOptionsForAlchemy() {
988
+ return extractSerializableKubeConfigOptions(this.getKubeConfig(), this.factoryOptions.skipTLSVerify === true ? true : undefined);
1006
989
  }
990
+ /** Build the finalizer-safe, shared-RGD-aware deletion metadata for this factory's instances. */
1007
991
  createAlchemyKroDeletionOptions() {
1008
992
  return {
1009
993
  apiVersion: this.schemaDefinition.apiVersion,
@@ -1024,7 +1008,6 @@ export class KroResourceFactoryImpl {
1024
1008
  return {
1025
1009
  name: this.name,
1026
1010
  mode: this.mode,
1027
- isAlchemyManaged: this.isAlchemyManaged,
1028
1011
  namespace: this.namespace,
1029
1012
  instanceCount: instances.length,
1030
1013
  health: rgdStatus.phase === 'ready' ? 'healthy' : 'degraded',
@@ -1144,8 +1127,17 @@ export class KroResourceFactoryImpl {
1144
1127
  }
1145
1128
  const statusOverrides = this.factoryOptions.compositionAnalysis?.statusOverrides ?? [];
1146
1129
  if (statusOverrides.length > 0) {
1147
- kroSchema.status ??= {};
1130
+ // Only resource-referencing (dynamic) overrides belong in the KRO schema;
1131
+ // schema-only ones (e.g. `spec.x ? a : b`) are rejected by KRO ("unknown
1132
+ // identifiers: [schema]") and are hydrated client-side instead, like any
1133
+ // other static status field.
1134
+ const resourceIdList = Object.keys(aspectResources);
1135
+ const nestedCel = this.getNestedStatusCel();
1136
+ const nestedCelForClassification = nestedCel && Object.keys(nestedCel).length > 0 ? nestedCel : undefined;
1148
1137
  for (const override of statusOverrides) {
1138
+ if (isStaticExpression(override.celExpression, nestedCelForClassification, resourceIdList))
1139
+ continue;
1140
+ kroSchema.status ??= {};
1149
1141
  const yamlSafe = override.celExpression.replace(/"([^"\\]*)"/g, "'$1'");
1150
1142
  kroSchema.status[override.propertyPath] = yamlSafe;
1151
1143
  }