| 1 | import type { NamespaceNode } from "../Namespace.ts"; |
| 2 | import type { ProviderMode } from "../ProviderMode.ts"; |
| 3 | import type { RemovalPolicy } from "../RemovalPolicy.ts"; |
| 4 | import type { ResourceBinding } from "../Resource.ts"; |
| 5 | |
| 6 | export type ResourceState = |
| 7 | | CreatingResourceState |
| 8 | | CreatedResourceState |
| 9 | | UpdatingReourceState |
| 10 | | UpdatedResourceState |
| 11 | | DeletingResourceState |
| 12 | | ReplacingResourceState |
| 13 | | ReplacedResourceState; |
| 14 | |
| 15 | export type Props = Record<string, any>; |
| 16 | export type Attr = Record<string, any>; |
| 17 | |
| 18 | export type ResourceStatus = ResourceState["status"]; |
| 19 | export type ReplacementResourceState = |
| 20 | | ReplacingResourceState |
| 21 | | ReplacedResourceState; |
| 22 | export type ReplacementOldResourceState = |
| 23 | | CreatingResourceState |
| 24 | | CreatedResourceState |
| 25 | | UpdatingReourceState |
| 26 | | UpdatedResourceState |
| 27 | | DeletingResourceState |
| 28 | | ReplacementResourceState; |
| 29 | |
| 30 | interface BaseResourceState { |
| 31 | /** |
| 32 | * Discriminator vs {@link ActionState}. Optional for back-compat: legacy |
| 33 | * persisted rows have no `kind` field and are implicitly resources. |
| 34 | */ |
| 35 | readonly kind?: "resource"; |
| 36 | /** Type of the Resource (e.g. AWS.Lambda.Function) */ |
| 37 | resourceType: string; |
| 38 | /** Namespace of the Resource */ |
| 39 | namespace: NamespaceNode | undefined; |
| 40 | /** Fully Qualified Name (namespace path + logical ID) */ |
| 41 | fqn: string; |
| 42 | /** Logical ID of the Resource (stable across creates, updates, deletes and replaces) */ |
| 43 | logicalId: string; |
| 44 | /** A unique randomly generated token used to seed ID generation (only changes when replaced) */ |
| 45 | instanceId: string; |
| 46 | /** The version of the provider that was used to create/update the resource. */ |
| 47 | providerVersion: number; |
| 48 | /** Current status of the logical Resource */ |
| 49 | status: ResourceStatus; |
| 50 | /** List of FQNs of resources that depend on this resource */ |
| 51 | downstream: string[]; |
| 52 | /** List of Bindings attached to this Resource */ |
| 53 | bindings: ResourceBinding[]; |
| 54 | /** Desired state (input props) of this Resource */ |
| 55 | props?: Props; |
| 56 | /** The output attributes of this Resource (if it has been created) */ |
| 57 | attr?: Attr; |
| 58 | /** The removal policy of the resource */ |
| 59 | removalPolicy?: RemovalPolicy["Service"]; |
| 60 | /** Attr-less lookup could recover the predecessor migrated away from this FQN. */ |
| 61 | adoptionBlocked?: "migrated-fqn"; |
| 62 | /** |
| 63 | * The {@link ProviderMode} this resource was last reconciled with. |
| 64 | * |
| 65 | * Stamped by Apply on every commit for resources whose provider |
| 66 | * distinguishes modes (`ProviderLayer.dual`). Plan treats a mismatch |
| 67 | * between the persisted mode and the resolved desired mode as a |
| 68 | * **replacement**, and deletion always uses the provider variant of the |
| 69 | * mode that created the row. |
| 70 | * |
| 71 | * `undefined` means either a mode-agnostic provider (single |
| 72 | * implementation serves both dev and deploy) or a legacy row written |
| 73 | * before modes were persisted — both acted on the real cloud, so an |
| 74 | * unstamped row is assumed **live**, unless its attrs carry a local |
| 75 | * identity marker (`dev:`-prefixed ids) proving it was reconciled |
| 76 | * locally, in which case it is assumed **local** (see `stampedMode`). |
| 77 | * Same-mode runs see no churn; a run in the other mode replaces it like |
| 78 | * any stamped row. |
| 79 | */ |
| 80 | providerMode?: ProviderMode; |
| 81 | } |
| 82 | |
| 83 | export interface CreatingResourceState extends BaseResourceState { |
| 84 | status: "creating"; |
| 85 | /** The new resource properties that are being (or have been) applied. */ |
| 86 | props: Props; |
| 87 | } |
| 88 | |
| 89 | export interface CreatedResourceState extends BaseResourceState { |
| 90 | status: "created"; |
| 91 | /** The new resource properties that have been applied. */ |
| 92 | props: Props; |
| 93 | /** The output attributes of the created resource */ |
| 94 | attr: Attr; |
| 95 | } |
| 96 | |
| 97 | export interface UpdatingReourceState extends BaseResourceState { |
| 98 | status: "updating"; |
| 99 | /** Persisted until the first post-adoption reconcile succeeds. */ |
| 100 | adopting?: true; |
| 101 | /** The new resource properties that are being (or have been) applied. */ |
| 102 | props: Props; |
| 103 | old: { |
| 104 | /** The old resource properties that have been successfully applied. */ |
| 105 | props: Props; |
| 106 | /** List of Bindings attached to this Resource */ |
| 107 | bindings: any[]; |
| 108 | /** The old output properties that have been successfully applied. */ |
| 109 | attr: Attr; |
| 110 | // TODO(sam): do I need to track the old downstream edges? |
| 111 | // downstream: string[]; |
| 112 | }; |
| 113 | } |
| 114 | |
| 115 | export interface UpdatedResourceState extends BaseResourceState { |
| 116 | status: "updated"; |
| 117 | /** The new resource properties that are being (or have been) applied. */ |
| 118 | props: Props; |
| 119 | /** The output attributes of the created resource */ |
| 120 | attr: Attr; |
| 121 | } |
| 122 | |
| 123 | export interface DeletingResourceState extends BaseResourceState { |
| 124 | status: "deleting"; |
| 125 | /** Attributes of the resource being deleted */ |
| 126 | attr: Attr | undefined; |
| 127 | } |
| 128 | |
| 129 | export interface ReplacingResourceState extends BaseResourceState { |
| 130 | status: "replacing"; |
| 131 | /** Desired properties of the new resource (the replacement) */ |
| 132 | props: Props; |
| 133 | /** Reference to the state of the old resource (the one being replaced) */ |
| 134 | old: ReplacementOldResourceState; |
| 135 | /** Whether the resource should be deleted before or after replacements */ |
| 136 | deleteFirst: boolean; |
| 137 | } |
| 138 | |
| 139 | export interface ReplacedResourceState extends BaseResourceState { |
| 140 | status: "replaced"; |
| 141 | /** Desired properties of the new resource (the replacement) */ |
| 142 | props: Props; |
| 143 | /** Output attributes of the new resource (the replacement) */ |
| 144 | attr: Attr; |
| 145 | /** Reference to the state of the old resource (the one being replaced) */ |
| 146 | old: ReplacementOldResourceState; |
| 147 | /** Whether the resource should be deleted before or after replacements */ |
| 148 | deleteFirst: boolean; |
| 149 | // .. will (finally) transition to `CreatedResourceState` after finalizing |
| 150 | } |