alchemy 2.0.0-beta.60 → 2.0.0-beta.61
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.
- package/bin/cli.js +9 -1
- package/bin/exec.js +15 -5
- package/bin/exec.js.map +1 -1
- package/lib/AWS/ACM/Certificate.d.ts.map +1 -1
- package/lib/AWS/ACM/Certificate.js +9 -2
- package/lib/AWS/ACM/Certificate.js.map +1 -1
- package/lib/AWS/AutoScaling/AutoScalingGroup.d.ts.map +1 -1
- package/lib/AWS/AutoScaling/AutoScalingGroup.js +18 -11
- package/lib/AWS/AutoScaling/AutoScalingGroup.js.map +1 -1
- package/lib/AWS/AutoScaling/LaunchTemplate.js +6 -1
- package/lib/AWS/AutoScaling/LaunchTemplate.js.map +1 -1
- package/lib/AWS/AutoScaling/ScalingPolicy.d.ts.map +1 -1
- package/lib/AWS/AutoScaling/ScalingPolicy.js +28 -10
- package/lib/AWS/AutoScaling/ScalingPolicy.js.map +1 -1
- package/lib/AWS/CloudFront/PublicKey.d.ts.map +1 -1
- package/lib/AWS/CloudFront/PublicKey.js +5 -1
- package/lib/AWS/CloudFront/PublicKey.js.map +1 -1
- package/lib/AWS/DynamoDB/Table.js +1 -1
- package/lib/AWS/DynamoDB/Table.js.map +1 -1
- package/lib/AWS/ECS/Service.d.ts.map +1 -1
- package/lib/AWS/ECS/Service.js +29 -4
- package/lib/AWS/ECS/Service.js.map +1 -1
- package/lib/AWS/IAM/OpenIDConnectProvider.d.ts.map +1 -1
- package/lib/AWS/IAM/OpenIDConnectProvider.js +9 -1
- package/lib/AWS/IAM/OpenIDConnectProvider.js.map +1 -1
- package/lib/AWS/Lambda/Alias.d.ts +26 -0
- package/lib/AWS/Lambda/Alias.d.ts.map +1 -1
- package/lib/AWS/Lambda/Alias.js +31 -0
- package/lib/AWS/Lambda/Alias.js.map +1 -1
- package/lib/AWS/Lambda/EventInvokeConfig.d.ts +36 -0
- package/lib/AWS/Lambda/EventInvokeConfig.d.ts.map +1 -0
- package/lib/AWS/Lambda/EventInvokeConfig.js +76 -0
- package/lib/AWS/Lambda/EventInvokeConfig.js.map +1 -0
- package/lib/AWS/Lambda/Function.d.ts +27 -2
- package/lib/AWS/Lambda/Function.d.ts.map +1 -1
- package/lib/AWS/Lambda/Function.js +23 -2
- package/lib/AWS/Lambda/Function.js.map +1 -1
- package/lib/AWS/Lambda/index.d.ts +1 -0
- package/lib/AWS/Lambda/index.d.ts.map +1 -1
- package/lib/AWS/Lambda/index.js +1 -0
- package/lib/AWS/Lambda/index.js.map +1 -1
- package/lib/AWS/Organizations/DelegatedAdministrator.d.ts.map +1 -1
- package/lib/AWS/Organizations/DelegatedAdministrator.js +10 -2
- package/lib/AWS/Organizations/DelegatedAdministrator.js.map +1 -1
- package/lib/AWS/Organizations/PolicyAttachment.d.ts.map +1 -1
- package/lib/AWS/Organizations/PolicyAttachment.js +10 -4
- package/lib/AWS/Organizations/PolicyAttachment.js.map +1 -1
- package/lib/AWS/Organizations/RootPolicyType.d.ts.map +1 -1
- package/lib/AWS/Organizations/RootPolicyType.js +9 -4
- package/lib/AWS/Organizations/RootPolicyType.js.map +1 -1
- package/lib/AWS/Organizations/TrustedServiceAccess.d.ts.map +1 -1
- package/lib/AWS/Organizations/TrustedServiceAccess.js +8 -1
- package/lib/AWS/Organizations/TrustedServiceAccess.js.map +1 -1
- package/lib/AWS/Route53/HostedZone.d.ts.map +1 -1
- package/lib/AWS/Route53/HostedZone.js +20 -4
- package/lib/AWS/Route53/HostedZone.js.map +1 -1
- package/lib/AWS/Route53/Record.d.ts.map +1 -1
- package/lib/AWS/Route53/Record.js +32 -9
- package/lib/AWS/Route53/Record.js.map +1 -1
- package/lib/Apply.js +7 -1
- package/lib/Apply.js.map +1 -1
- package/lib/Auth/Lock.d.ts +17 -0
- package/lib/Auth/Lock.d.ts.map +1 -1
- package/lib/Auth/Lock.js +53 -18
- package/lib/Auth/Lock.js.map +1 -1
- package/lib/Bundle/PurePlugin.d.ts.map +1 -1
- package/lib/Bundle/PurePlugin.js +15 -2
- package/lib/Bundle/PurePlugin.js.map +1 -1
- package/lib/Cli/commands/sync.d.ts +22 -0
- package/lib/Cli/commands/sync.d.ts.map +1 -0
- package/lib/Cli/commands/sync.js +64 -0
- package/lib/Cli/commands/sync.js.map +1 -0
- package/lib/Cli/main.d.ts.map +1 -1
- package/lib/Cli/main.js +2 -0
- package/lib/Cli/main.js.map +1 -1
- package/lib/Cloudflare/AI/CustomTopics.d.ts.map +1 -1
- package/lib/Cloudflare/AI/CustomTopics.js +3 -1
- package/lib/Cloudflare/AI/CustomTopics.js.map +1 -1
- package/lib/Cloudflare/AI/Dataset.d.ts.map +1 -1
- package/lib/Cloudflare/AI/Dataset.js +3 -1
- package/lib/Cloudflare/AI/Dataset.js.map +1 -1
- package/lib/Cloudflare/AI/Evaluation.d.ts.map +1 -1
- package/lib/Cloudflare/AI/Evaluation.js +3 -1
- package/lib/Cloudflare/AI/Evaluation.js.map +1 -1
- package/lib/Cloudflare/AI/Gateway.d.ts.map +1 -1
- package/lib/Cloudflare/AI/Gateway.js +5 -6
- package/lib/Cloudflare/AI/Gateway.js.map +1 -1
- package/lib/Cloudflare/AI/GatewayDynamicRouting.d.ts.map +1 -1
- package/lib/Cloudflare/AI/GatewayDynamicRouting.js +3 -1
- package/lib/Cloudflare/AI/GatewayDynamicRouting.js.map +1 -1
- package/lib/Cloudflare/AI/GatewayProvider.d.ts +2 -1
- package/lib/Cloudflare/AI/GatewayProvider.d.ts.map +1 -1
- package/lib/Cloudflare/AI/GatewayProvider.js +5 -2
- package/lib/Cloudflare/AI/GatewayProvider.js.map +1 -1
- package/lib/Cloudflare/AI/ProviderKey.d.ts +135 -0
- package/lib/Cloudflare/AI/ProviderKey.d.ts.map +1 -0
- package/lib/Cloudflare/AI/ProviderKey.js +90 -0
- package/lib/Cloudflare/AI/ProviderKey.js.map +1 -0
- package/lib/Cloudflare/AI/SearchInstance.d.ts.map +1 -1
- package/lib/Cloudflare/AI/SearchInstance.js +5 -4
- package/lib/Cloudflare/AI/SearchInstance.js.map +1 -1
- package/lib/Cloudflare/AI/SearchNamespace.d.ts.map +1 -1
- package/lib/Cloudflare/AI/SearchNamespace.js +5 -4
- package/lib/Cloudflare/AI/SearchNamespace.js.map +1 -1
- package/lib/Cloudflare/AI/SearchToken.d.ts.map +1 -1
- package/lib/Cloudflare/AI/SearchToken.js +3 -1
- package/lib/Cloudflare/AI/SearchToken.js.map +1 -1
- package/lib/Cloudflare/AI/SecuritySettings.d.ts.map +1 -1
- package/lib/Cloudflare/AI/SecuritySettings.js +3 -1
- package/lib/Cloudflare/AI/SecuritySettings.js.map +1 -1
- package/lib/Cloudflare/AI/index.d.ts +1 -0
- package/lib/Cloudflare/AI/index.d.ts.map +1 -1
- package/lib/Cloudflare/AI/index.js +1 -0
- package/lib/Cloudflare/AI/index.js.map +1 -1
- package/lib/Cloudflare/Access/InfrastructureTarget.d.ts.map +1 -1
- package/lib/Cloudflare/Access/InfrastructureTarget.js +3 -1
- package/lib/Cloudflare/Access/InfrastructureTarget.js.map +1 -1
- package/lib/Cloudflare/Access/Organization.d.ts.map +1 -1
- package/lib/Cloudflare/Access/Organization.js +1 -1
- package/lib/Cloudflare/Access/Organization.js.map +1 -1
- package/lib/Cloudflare/Access/Policy.d.ts.map +1 -1
- package/lib/Cloudflare/Access/Policy.js +3 -1
- package/lib/Cloudflare/Access/Policy.js.map +1 -1
- package/lib/Cloudflare/Account/Account.d.ts.map +1 -1
- package/lib/Cloudflare/Account/Account.js +3 -1
- package/lib/Cloudflare/Account/Account.js.map +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.d.ts.map +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.js +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.js.map +1 -1
- package/lib/Cloudflare/ApiToken/UserApiToken.d.ts.map +1 -1
- package/lib/Cloudflare/ApiToken/UserApiToken.js +1 -1
- package/lib/Cloudflare/ApiToken/UserApiToken.js.map +1 -1
- package/lib/Cloudflare/Auth/AuthProvider.d.ts +3 -0
- package/lib/Cloudflare/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Auth/AuthProvider.js +51 -14
- package/lib/Cloudflare/Auth/AuthProvider.js.map +1 -1
- package/lib/Cloudflare/BotManagement/BotManagement.d.ts.map +1 -1
- package/lib/Cloudflare/BotManagement/BotManagement.js +3 -1
- package/lib/Cloudflare/BotManagement/BotManagement.js.map +1 -1
- package/lib/Cloudflare/Cache/Reserve.d.ts.map +1 -1
- package/lib/Cloudflare/Cache/Reserve.js +3 -1
- package/lib/Cloudflare/Cache/Reserve.js.map +1 -1
- package/lib/Cloudflare/ClientCertificate/ClientCertificate.d.ts.map +1 -1
- package/lib/Cloudflare/ClientCertificate/ClientCertificate.js +3 -1
- package/lib/Cloudflare/ClientCertificate/ClientCertificate.js.map +1 -1
- package/lib/Cloudflare/Containers/Container.d.ts +2 -2
- package/lib/Cloudflare/Containers/Container.js +2 -2
- package/lib/Cloudflare/ContentScanning/ContentScanning.d.ts.map +1 -1
- package/lib/Cloudflare/ContentScanning/ContentScanning.js +3 -1
- package/lib/Cloudflare/ContentScanning/ContentScanning.js.map +1 -1
- package/lib/Cloudflare/CustomCertificate/CustomCertificate.d.ts.map +1 -1
- package/lib/Cloudflare/CustomCertificate/CustomCertificate.js +3 -1
- package/lib/Cloudflare/CustomCertificate/CustomCertificate.js.map +1 -1
- package/lib/Cloudflare/CustomHostname/CustomHostname.d.ts.map +1 -1
- package/lib/Cloudflare/CustomHostname/CustomHostname.js +1 -1
- package/lib/Cloudflare/CustomHostname/CustomHostname.js.map +1 -1
- package/lib/Cloudflare/CustomHostname/FallbackOrigin.d.ts.map +1 -1
- package/lib/Cloudflare/CustomHostname/FallbackOrigin.js +1 -1
- package/lib/Cloudflare/CustomHostname/FallbackOrigin.js.map +1 -1
- package/lib/Cloudflare/CustomNameserver/CustomNameserver.d.ts.map +1 -1
- package/lib/Cloudflare/CustomNameserver/CustomNameserver.js +3 -1
- package/lib/Cloudflare/CustomNameserver/CustomNameserver.js.map +1 -1
- package/lib/Cloudflare/D1/Database.d.ts.map +1 -1
- package/lib/Cloudflare/D1/Database.js +2 -2
- package/lib/Cloudflare/D1/Database.js.map +1 -1
- package/lib/Cloudflare/DNS/AccountSettings.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/AccountSettings.js +3 -1
- package/lib/Cloudflare/DNS/AccountSettings.js.map +1 -1
- package/lib/Cloudflare/DNS/Dnssec.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/Dnssec.js +3 -1
- package/lib/Cloudflare/DNS/Dnssec.js.map +1 -1
- package/lib/Cloudflare/DNS/Firewall.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/Firewall.js +3 -1
- package/lib/Cloudflare/DNS/Firewall.js.map +1 -1
- package/lib/Cloudflare/DNS/Record.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/Record.js +3 -1
- package/lib/Cloudflare/DNS/Record.js.map +1 -1
- package/lib/Cloudflare/DNS/View.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/View.js +3 -1
- package/lib/Cloudflare/DNS/View.js.map +1 -1
- package/lib/Cloudflare/DNS/ZoneSettings.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/ZoneSettings.js +3 -1
- package/lib/Cloudflare/DNS/ZoneSettings.js.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferAcl.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferAcl.js +3 -1
- package/lib/Cloudflare/DNS/ZoneTransferAcl.js.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferIncoming.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferIncoming.js +3 -1
- package/lib/Cloudflare/DNS/ZoneTransferIncoming.js.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferOutgoing.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferOutgoing.js +3 -1
- package/lib/Cloudflare/DNS/ZoneTransferOutgoing.js.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferPeer.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferPeer.js +3 -1
- package/lib/Cloudflare/DNS/ZoneTransferPeer.js.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferTsig.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/ZoneTransferTsig.js +3 -1
- package/lib/Cloudflare/DNS/ZoneTransferTsig.js.map +1 -1
- package/lib/Cloudflare/Email/Address.d.ts.map +1 -1
- package/lib/Cloudflare/Email/Address.js +3 -1
- package/lib/Cloudflare/Email/Address.js.map +1 -1
- package/lib/Cloudflare/Email/AllowPolicy.d.ts.map +1 -1
- package/lib/Cloudflare/Email/AllowPolicy.js +1 -1
- package/lib/Cloudflare/Email/AllowPolicy.js.map +1 -1
- package/lib/Cloudflare/Email/BlockSender.d.ts.map +1 -1
- package/lib/Cloudflare/Email/BlockSender.js +1 -1
- package/lib/Cloudflare/Email/BlockSender.js.map +1 -1
- package/lib/Cloudflare/Email/CatchAll.d.ts.map +1 -1
- package/lib/Cloudflare/Email/CatchAll.js +8 -2
- package/lib/Cloudflare/Email/CatchAll.js.map +1 -1
- package/lib/Cloudflare/Email/Domain.d.ts.map +1 -1
- package/lib/Cloudflare/Email/Domain.js +3 -1
- package/lib/Cloudflare/Email/Domain.js.map +1 -1
- package/lib/Cloudflare/Email/ImpersonationRegistryEntry.d.ts.map +1 -1
- package/lib/Cloudflare/Email/ImpersonationRegistryEntry.js +1 -1
- package/lib/Cloudflare/Email/ImpersonationRegistryEntry.js.map +1 -1
- package/lib/Cloudflare/Email/Routing.d.ts.map +1 -1
- package/lib/Cloudflare/Email/Routing.js +3 -1
- package/lib/Cloudflare/Email/Routing.js.map +1 -1
- package/lib/Cloudflare/Email/Rule.d.ts.map +1 -1
- package/lib/Cloudflare/Email/Rule.js +3 -1
- package/lib/Cloudflare/Email/Rule.js.map +1 -1
- package/lib/Cloudflare/Email/SendingSubdomain.d.ts.map +1 -1
- package/lib/Cloudflare/Email/SendingSubdomain.js +1 -1
- package/lib/Cloudflare/Email/SendingSubdomain.js.map +1 -1
- package/lib/Cloudflare/Email/TrustedDomain.d.ts.map +1 -1
- package/lib/Cloudflare/Email/TrustedDomain.js +1 -1
- package/lib/Cloudflare/Email/TrustedDomain.js.map +1 -1
- package/lib/Cloudflare/Fetcher.d.ts.map +1 -1
- package/lib/Cloudflare/Fetcher.js +10 -3
- package/lib/Cloudflare/Fetcher.js.map +1 -1
- package/lib/Cloudflare/Flagship/App.d.ts.map +1 -1
- package/lib/Cloudflare/Flagship/App.js +2 -3
- package/lib/Cloudflare/Flagship/App.js.map +1 -1
- package/lib/Cloudflare/Fraud/DetectionSettings.d.ts.map +1 -1
- package/lib/Cloudflare/Fraud/DetectionSettings.js +3 -1
- package/lib/Cloudflare/Fraud/DetectionSettings.js.map +1 -1
- package/lib/Cloudflare/GoogleTagGateway/GoogleTagGateway.d.ts.map +1 -1
- package/lib/Cloudflare/GoogleTagGateway/GoogleTagGateway.js +8 -2
- package/lib/Cloudflare/GoogleTagGateway/GoogleTagGateway.js.map +1 -1
- package/lib/Cloudflare/Healthcheck/Healthcheck.d.ts.map +1 -1
- package/lib/Cloudflare/Healthcheck/Healthcheck.js +3 -1
- package/lib/Cloudflare/Healthcheck/Healthcheck.js.map +1 -1
- package/lib/Cloudflare/HostnameTlsSetting/HostnameTlsSetting.d.ts.map +1 -1
- package/lib/Cloudflare/HostnameTlsSetting/HostnameTlsSetting.js +3 -1
- package/lib/Cloudflare/HostnameTlsSetting/HostnameTlsSetting.js.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Connection.d.ts.map +1 -1
- package/lib/Cloudflare/Hyperdrive/Connection.js +2 -4
- package/lib/Cloudflare/Hyperdrive/Connection.js.map +1 -1
- package/lib/Cloudflare/KV/Namespace.d.ts.map +1 -1
- package/lib/Cloudflare/KV/Namespace.js +5 -4
- package/lib/Cloudflare/KV/Namespace.js.map +1 -1
- package/lib/Cloudflare/KeylessCertificate/KeylessCertificate.d.ts.map +1 -1
- package/lib/Cloudflare/KeylessCertificate/KeylessCertificate.js +3 -1
- package/lib/Cloudflare/KeylessCertificate/KeylessCertificate.js.map +1 -1
- package/lib/Cloudflare/LeakedCredentialCheck/LeakedCredentialCheck.d.ts.map +1 -1
- package/lib/Cloudflare/LeakedCredentialCheck/LeakedCredentialCheck.js +3 -1
- package/lib/Cloudflare/LeakedCredentialCheck/LeakedCredentialCheck.js.map +1 -1
- package/lib/Cloudflare/LoadBalancer/LoadBalancer.d.ts.map +1 -1
- package/lib/Cloudflare/LoadBalancer/LoadBalancer.js +3 -1
- package/lib/Cloudflare/LoadBalancer/LoadBalancer.js.map +1 -1
- package/lib/Cloudflare/ManagedTransforms/ManagedTransforms.d.ts.map +1 -1
- package/lib/Cloudflare/ManagedTransforms/ManagedTransforms.js +3 -1
- package/lib/Cloudflare/ManagedTransforms/ManagedTransforms.js.map +1 -1
- package/lib/Cloudflare/MtlsCertificate/MtlsCertificate.d.ts.map +1 -1
- package/lib/Cloudflare/MtlsCertificate/MtlsCertificate.js +3 -1
- package/lib/Cloudflare/MtlsCertificate/MtlsCertificate.js.map +1 -1
- package/lib/Cloudflare/Organization/Organization.d.ts.map +1 -1
- package/lib/Cloudflare/Organization/Organization.js +3 -1
- package/lib/Cloudflare/Organization/Organization.js.map +1 -1
- package/lib/Cloudflare/OriginCaCertificate/OriginCaCertificate.d.ts.map +1 -1
- package/lib/Cloudflare/OriginCaCertificate/OriginCaCertificate.js +7 -2
- package/lib/Cloudflare/OriginCaCertificate/OriginCaCertificate.js.map +1 -1
- package/lib/Cloudflare/OriginPostQuantumEncryption/OriginPostQuantumEncryption.d.ts.map +1 -1
- package/lib/Cloudflare/OriginPostQuantumEncryption/OriginPostQuantumEncryption.js +3 -1
- package/lib/Cloudflare/OriginPostQuantumEncryption/OriginPostQuantumEncryption.js.map +1 -1
- package/lib/Cloudflare/OriginTlsClientAuth/HostnameCertificate.d.ts.map +1 -1
- package/lib/Cloudflare/OriginTlsClientAuth/HostnameCertificate.js +5 -1
- package/lib/Cloudflare/OriginTlsClientAuth/HostnameCertificate.js.map +1 -1
- package/lib/Cloudflare/PageRule/PageRule.d.ts.map +1 -1
- package/lib/Cloudflare/PageRule/PageRule.js +3 -1
- package/lib/Cloudflare/PageRule/PageRule.js.map +1 -1
- package/lib/Cloudflare/Providers.d.ts +29 -0
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +30 -19
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Queues/Consumer.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Consumer.js +3 -1
- package/lib/Cloudflare/Queues/Consumer.js.map +1 -1
- package/lib/Cloudflare/Queues/Queue.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Queue.js +5 -4
- package/lib/Cloudflare/Queues/Queue.js.map +1 -1
- package/lib/Cloudflare/Queues/Subscription.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Subscription.js +3 -1
- package/lib/Cloudflare/Queues/Subscription.js.map +1 -1
- package/lib/Cloudflare/R2/Bucket.d.ts +98 -0
- package/lib/Cloudflare/R2/Bucket.d.ts.map +1 -1
- package/lib/Cloudflare/R2/Bucket.js +141 -3
- package/lib/Cloudflare/R2/Bucket.js.map +1 -1
- package/lib/Cloudflare/RegionalHostname/RegionalHostname.d.ts.map +1 -1
- package/lib/Cloudflare/RegionalHostname/RegionalHostname.js +3 -1
- package/lib/Cloudflare/RegionalHostname/RegionalHostname.js.map +1 -1
- package/lib/Cloudflare/Ruleset/Ruleset.d.ts.map +1 -1
- package/lib/Cloudflare/Ruleset/Ruleset.js +8 -3
- package/lib/Cloudflare/Ruleset/Ruleset.js.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
- package/lib/Cloudflare/SecretsStore/Secret.js +31 -5
- package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
- package/lib/Cloudflare/SecurityTxt/SecurityTxt.d.ts.map +1 -1
- package/lib/Cloudflare/SecurityTxt/SecurityTxt.js +3 -1
- package/lib/Cloudflare/SecurityTxt/SecurityTxt.js.map +1 -1
- package/lib/Cloudflare/StateStore/Api.d.ts +15 -0
- package/lib/Cloudflare/StateStore/State.d.ts +30 -1
- package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
- package/lib/Cloudflare/StateStore/State.js +85 -16
- package/lib/Cloudflare/StateStore/State.js.map +1 -1
- package/lib/Cloudflare/Tags/AccountResourceTags.d.ts.map +1 -1
- package/lib/Cloudflare/Tags/AccountResourceTags.js +8 -3
- package/lib/Cloudflare/Tags/AccountResourceTags.js.map +1 -1
- package/lib/Cloudflare/Tunnel/Route.d.ts.map +1 -1
- package/lib/Cloudflare/Tunnel/Route.js +3 -1
- package/lib/Cloudflare/Tunnel/Route.js.map +1 -1
- package/lib/Cloudflare/Tunnel/Tunnel.d.ts.map +1 -1
- package/lib/Cloudflare/Tunnel/Tunnel.js +3 -1
- package/lib/Cloudflare/Tunnel/Tunnel.js.map +1 -1
- package/lib/Cloudflare/UrlNormalization/UrlNormalization.d.ts.map +1 -1
- package/lib/Cloudflare/UrlNormalization/UrlNormalization.js +3 -1
- package/lib/Cloudflare/UrlNormalization/UrlNormalization.js.map +1 -1
- package/lib/Cloudflare/Vectorize/VectorizeIndex.d.ts.map +1 -1
- package/lib/Cloudflare/Vectorize/VectorizeIndex.js +2 -3
- package/lib/Cloudflare/Vectorize/VectorizeIndex.js.map +1 -1
- package/lib/Cloudflare/VpcService/VpcService.d.ts.map +1 -1
- package/lib/Cloudflare/VpcService/VpcService.js +1 -1
- package/lib/Cloudflare/VpcService/VpcService.js.map +1 -1
- package/lib/Cloudflare/WaitingRoom/WaitingRoom.d.ts.map +1 -1
- package/lib/Cloudflare/WaitingRoom/WaitingRoom.js +3 -1
- package/lib/Cloudflare/WaitingRoom/WaitingRoom.js.map +1 -1
- package/lib/Cloudflare/Web3/ContentList.d.ts.map +1 -1
- package/lib/Cloudflare/Web3/ContentList.js +3 -1
- package/lib/Cloudflare/Web3/ContentList.js.map +1 -1
- package/lib/Cloudflare/Web3/Hostname.d.ts.map +1 -1
- package/lib/Cloudflare/Web3/Hostname.js +3 -1
- package/lib/Cloudflare/Web3/Hostname.js.map +1 -1
- package/lib/Cloudflare/Workers/Cache.d.ts +71 -0
- package/lib/Cloudflare/Workers/Cache.d.ts.map +1 -0
- package/lib/Cloudflare/Workers/Cache.js +64 -0
- package/lib/Cloudflare/Workers/Cache.js.map +1 -0
- package/lib/Cloudflare/Workers/CronEventSource.d.ts +180 -6
- package/lib/Cloudflare/Workers/CronEventSource.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/CronEventSource.js +180 -6
- package/lib/Cloudflare/Workers/CronEventSource.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObject.d.ts +36 -1
- package/lib/Cloudflare/Workers/DurableObject.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObject.js +36 -1
- package/lib/Cloudflare/Workers/DurableObject.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectState.d.ts +11 -0
- package/lib/Cloudflare/Workers/DurableObjectState.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectState.js +7 -0
- package/lib/Cloudflare/Workers/DurableObjectState.js.map +1 -1
- package/lib/Cloudflare/Workers/Fetch.js +2 -2
- package/lib/Cloudflare/Workers/Fetch.js.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +3 -0
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +230 -4
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +161 -7
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts +9 -0
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +15 -0
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +30 -0
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBridge.js +27 -5
- package/lib/Cloudflare/Workers/WorkerBridge.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerLoader.js +9 -1
- package/lib/Cloudflare/Workers/WorkerLoader.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.js +365 -18
- package/lib/Cloudflare/Workers/WorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerRuntimeContext.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerRuntimeContext.js +20 -3
- package/lib/Cloudflare/Workers/WorkerRuntimeContext.js.map +1 -1
- package/lib/Cloudflare/Workers/index.d.ts +1 -0
- package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/index.js +1 -0
- package/lib/Cloudflare/Workers/index.js.map +1 -1
- package/lib/Cloudflare/WorkersForPlatforms/DispatchNamespace.d.ts.map +1 -1
- package/lib/Cloudflare/WorkersForPlatforms/DispatchNamespace.js +2 -3
- package/lib/Cloudflare/WorkersForPlatforms/DispatchNamespace.js.map +1 -1
- package/lib/Cloudflare/Workflows/Workflow.d.ts +200 -24
- package/lib/Cloudflare/Workflows/Workflow.d.ts.map +1 -1
- package/lib/Cloudflare/Workflows/Workflow.js +126 -28
- package/lib/Cloudflare/Workflows/Workflow.js.map +1 -1
- package/lib/Cloudflare/Workflows/WorkflowBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workflows/WorkflowBridge.js +42 -3
- package/lib/Cloudflare/Workflows/WorkflowBridge.js.map +1 -1
- package/lib/Cloudflare/Zaraz/Config.d.ts +1 -0
- package/lib/Cloudflare/Zaraz/Config.d.ts.map +1 -1
- package/lib/Cloudflare/Zaraz/Config.js +8 -2
- package/lib/Cloudflare/Zaraz/Config.js.map +1 -1
- package/lib/Cloudflare/Zone/Zone.d.ts.map +1 -1
- package/lib/Cloudflare/Zone/Zone.js +1 -0
- package/lib/Cloudflare/Zone/Zone.js.map +1 -1
- package/lib/Docker/Container.d.ts.map +1 -1
- package/lib/Docker/Container.js +11 -1
- package/lib/Docker/Container.js.map +1 -1
- package/lib/Drizzle/Schema.d.ts.map +1 -1
- package/lib/Drizzle/Schema.js +12 -5
- package/lib/Drizzle/Schema.js.map +1 -1
- package/lib/Neon/Branch.d.ts.map +1 -1
- package/lib/Neon/Branch.js +15 -3
- package/lib/Neon/Branch.js.map +1 -1
- package/lib/Output.d.ts +13 -1
- package/lib/Output.d.ts.map +1 -1
- package/lib/Output.js +17 -3
- package/lib/Output.js.map +1 -1
- package/lib/Planetscale/Postgres/PostgresRole.js +2 -2
- package/lib/Planetscale/Postgres/PostgresRole.js.map +1 -1
- package/lib/Provider.d.ts +8 -0
- package/lib/Provider.d.ts.map +1 -1
- package/lib/Provider.js +38 -3
- package/lib/Provider.js.map +1 -1
- package/lib/Ref.d.ts +9 -1
- package/lib/Ref.d.ts.map +1 -1
- package/lib/Ref.js +2 -1
- package/lib/Ref.js.map +1 -1
- package/lib/Resource.d.ts +44 -0
- package/lib/Resource.d.ts.map +1 -1
- package/lib/Resource.js +22 -1
- package/lib/Resource.js.map +1 -1
- package/lib/Stack.js +1 -1
- package/lib/Stack.js.map +1 -1
- package/lib/State/HttpStateApi.d.ts +4 -4
- package/lib/State/HttpStateStore.d.ts +12 -0
- package/lib/State/HttpStateStore.d.ts.map +1 -1
- package/lib/State/HttpStateStore.js +46 -5
- package/lib/State/HttpStateStore.js.map +1 -1
- package/lib/Sync.d.ts +109 -0
- package/lib/Sync.d.ts.map +1 -0
- package/lib/Sync.js +312 -0
- package/lib/Sync.js.map +1 -0
- package/lib/Test/Bun.d.ts +1 -1
- package/lib/Test/Bun.d.ts.map +1 -1
- package/lib/Test/Bun.js +1 -1
- package/lib/Test/Bun.js.map +1 -1
- package/lib/Test/Http.d.ts +67 -0
- package/lib/Test/Http.d.ts.map +1 -1
- package/lib/Test/Http.js +69 -0
- package/lib/Test/Http.js.map +1 -1
- package/lib/Test/Vitest.d.ts +1 -1
- package/lib/Test/Vitest.d.ts.map +1 -1
- package/lib/Test/Vitest.js +1 -0
- package/lib/Test/Vitest.js.map +1 -1
- package/lib/Util/proxy-chain.js +14 -15
- package/lib/Util/proxy-chain.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +19 -19
- package/src/AWS/ACM/Certificate.ts +13 -2
- package/src/AWS/AutoScaling/AutoScalingGroup.ts +21 -15
- package/src/AWS/AutoScaling/LaunchTemplate.ts +6 -1
- package/src/AWS/AutoScaling/ScalingPolicy.ts +31 -17
- package/src/AWS/CloudFront/PublicKey.ts +4 -0
- package/src/AWS/DynamoDB/Table.ts +1 -1
- package/src/AWS/ECS/Service.ts +35 -6
- package/src/AWS/IAM/OpenIDConnectProvider.ts +9 -1
- package/src/AWS/Lambda/Alias.ts +42 -0
- package/src/AWS/Lambda/EventInvokeConfig.ts +150 -0
- package/src/AWS/Lambda/Function.ts +35 -2
- package/src/AWS/Lambda/index.ts +1 -0
- package/src/AWS/Organizations/DelegatedAdministrator.ts +11 -3
- package/src/AWS/Organizations/PolicyAttachment.ts +10 -4
- package/src/AWS/Organizations/RootPolicyType.ts +9 -4
- package/src/AWS/Organizations/TrustedServiceAccess.ts +9 -3
- package/src/AWS/Route53/HostedZone.ts +30 -13
- package/src/AWS/Route53/Record.ts +44 -22
- package/src/Apply.ts +7 -1
- package/src/Auth/Lock.ts +62 -18
- package/src/Bundle/PurePlugin.ts +15 -2
- package/src/Cli/commands/sync.ts +123 -0
- package/src/Cli/main.ts +2 -0
- package/src/Cloudflare/AI/CustomTopics.ts +3 -1
- package/src/Cloudflare/AI/Dataset.ts +3 -1
- package/src/Cloudflare/AI/Evaluation.ts +3 -1
- package/src/Cloudflare/AI/Gateway.ts +5 -6
- package/src/Cloudflare/AI/GatewayDynamicRouting.ts +3 -1
- package/src/Cloudflare/AI/GatewayProvider.ts +5 -2
- package/src/Cloudflare/AI/ProviderKey.ts +161 -0
- package/src/Cloudflare/AI/SearchInstance.ts +5 -4
- package/src/Cloudflare/AI/SearchNamespace.ts +5 -4
- package/src/Cloudflare/AI/SearchToken.ts +3 -1
- package/src/Cloudflare/AI/SecuritySettings.ts +3 -0
- package/src/Cloudflare/AI/index.ts +1 -0
- package/src/Cloudflare/Access/InfrastructureTarget.ts +4 -1
- package/src/Cloudflare/Access/Organization.ts +1 -0
- package/src/Cloudflare/Access/Policy.ts +3 -1
- package/src/Cloudflare/Account/Account.ts +3 -1
- package/src/Cloudflare/ApiToken/AccountApiToken.ts +1 -0
- package/src/Cloudflare/ApiToken/UserApiToken.ts +1 -0
- package/src/Cloudflare/Auth/AuthProvider.ts +69 -8
- package/src/Cloudflare/BotManagement/BotManagement.ts +3 -1
- package/src/Cloudflare/Cache/Reserve.ts +3 -1
- package/src/Cloudflare/ClientCertificate/ClientCertificate.ts +3 -1
- package/src/Cloudflare/Containers/Container.ts +2 -2
- package/src/Cloudflare/ContentScanning/ContentScanning.ts +3 -1
- package/src/Cloudflare/CustomCertificate/CustomCertificate.ts +3 -1
- package/src/Cloudflare/CustomHostname/CustomHostname.ts +1 -0
- package/src/Cloudflare/CustomHostname/FallbackOrigin.ts +1 -0
- package/src/Cloudflare/CustomNameserver/CustomNameserver.ts +3 -1
- package/src/Cloudflare/D1/Database.ts +2 -2
- package/src/Cloudflare/DNS/AccountSettings.ts +3 -1
- package/src/Cloudflare/DNS/Dnssec.ts +3 -1
- package/src/Cloudflare/DNS/Firewall.ts +3 -1
- package/src/Cloudflare/DNS/Record.ts +3 -1
- package/src/Cloudflare/DNS/View.ts +3 -1
- package/src/Cloudflare/DNS/ZoneSettings.ts +3 -1
- package/src/Cloudflare/DNS/ZoneTransferAcl.ts +3 -1
- package/src/Cloudflare/DNS/ZoneTransferIncoming.ts +3 -1
- package/src/Cloudflare/DNS/ZoneTransferOutgoing.ts +3 -1
- package/src/Cloudflare/DNS/ZoneTransferPeer.ts +3 -1
- package/src/Cloudflare/DNS/ZoneTransferTsig.ts +3 -1
- package/src/Cloudflare/Email/Address.ts +3 -1
- package/src/Cloudflare/Email/AllowPolicy.ts +1 -0
- package/src/Cloudflare/Email/BlockSender.ts +1 -0
- package/src/Cloudflare/Email/CatchAll.ts +7 -2
- package/src/Cloudflare/Email/Domain.ts +3 -1
- package/src/Cloudflare/Email/ImpersonationRegistryEntry.ts +1 -0
- package/src/Cloudflare/Email/Routing.ts +3 -1
- package/src/Cloudflare/Email/Rule.ts +3 -1
- package/src/Cloudflare/Email/SendingSubdomain.ts +1 -0
- package/src/Cloudflare/Email/TrustedDomain.ts +1 -0
- package/src/Cloudflare/Fetcher.ts +12 -5
- package/src/Cloudflare/Flagship/App.ts +2 -3
- package/src/Cloudflare/Fraud/DetectionSettings.ts +3 -1
- package/src/Cloudflare/GoogleTagGateway/GoogleTagGateway.ts +7 -2
- package/src/Cloudflare/Healthcheck/Healthcheck.ts +3 -1
- package/src/Cloudflare/HostnameTlsSetting/HostnameTlsSetting.ts +3 -1
- package/src/Cloudflare/Hyperdrive/Connection.ts +2 -4
- package/src/Cloudflare/KV/Namespace.ts +5 -4
- package/src/Cloudflare/KeylessCertificate/KeylessCertificate.ts +3 -1
- package/src/Cloudflare/LeakedCredentialCheck/LeakedCredentialCheck.ts +3 -1
- package/src/Cloudflare/LoadBalancer/LoadBalancer.ts +3 -1
- package/src/Cloudflare/ManagedTransforms/ManagedTransforms.ts +3 -1
- package/src/Cloudflare/MtlsCertificate/MtlsCertificate.ts +3 -1
- package/src/Cloudflare/Organization/Organization.ts +3 -1
- package/src/Cloudflare/OriginCaCertificate/OriginCaCertificate.ts +7 -2
- package/src/Cloudflare/OriginPostQuantumEncryption/OriginPostQuantumEncryption.ts +3 -1
- package/src/Cloudflare/OriginTlsClientAuth/HostnameCertificate.ts +5 -1
- package/src/Cloudflare/PageRule/PageRule.ts +3 -1
- package/src/Cloudflare/Providers.ts +34 -19
- package/src/Cloudflare/Queues/Consumer.ts +3 -1
- package/src/Cloudflare/Queues/Queue.ts +5 -4
- package/src/Cloudflare/Queues/Subscription.ts +3 -1
- package/src/Cloudflare/R2/Bucket.ts +230 -3
- package/src/Cloudflare/RegionalHostname/RegionalHostname.ts +3 -1
- package/src/Cloudflare/Ruleset/Ruleset.ts +9 -4
- package/src/Cloudflare/SecretsStore/Secret.ts +46 -5
- package/src/Cloudflare/SecurityTxt/SecurityTxt.ts +3 -1
- package/src/Cloudflare/StateStore/State.ts +89 -24
- package/src/Cloudflare/Tags/AccountResourceTags.ts +9 -5
- package/src/Cloudflare/Tunnel/Route.ts +3 -1
- package/src/Cloudflare/Tunnel/Tunnel.ts +3 -1
- package/src/Cloudflare/UrlNormalization/UrlNormalization.ts +3 -1
- package/src/Cloudflare/Vectorize/VectorizeIndex.ts +2 -3
- package/src/Cloudflare/VpcService/VpcService.ts +1 -0
- package/src/Cloudflare/WaitingRoom/WaitingRoom.ts +3 -1
- package/src/Cloudflare/Web3/ContentList.ts +3 -1
- package/src/Cloudflare/Web3/Hostname.ts +3 -1
- package/src/Cloudflare/Workers/Cache.ts +102 -0
- package/src/Cloudflare/Workers/CronEventSource.ts +180 -6
- package/src/Cloudflare/Workers/DurableObject.ts +36 -1
- package/src/Cloudflare/Workers/DurableObjectState.ts +25 -0
- package/src/Cloudflare/Workers/Fetch.ts +2 -2
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +3 -0
- package/src/Cloudflare/Workers/Worker.ts +315 -9
- package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +18 -0
- package/src/Cloudflare/Workers/WorkerBridge.ts +37 -10
- package/src/Cloudflare/Workers/WorkerLoader.ts +10 -1
- package/src/Cloudflare/Workers/WorkerProvider.ts +576 -40
- package/src/Cloudflare/Workers/WorkerRuntimeContext.ts +23 -2
- package/src/Cloudflare/Workers/index.ts +1 -0
- package/src/Cloudflare/WorkersForPlatforms/DispatchNamespace.ts +2 -4
- package/src/Cloudflare/Workflows/Workflow.ts +296 -38
- package/src/Cloudflare/Workflows/WorkflowBridge.ts +62 -12
- package/src/Cloudflare/Zaraz/Config.ts +7 -2
- package/src/Cloudflare/Zone/Zone.ts +1 -0
- package/src/Docker/Container.ts +10 -1
- package/src/Drizzle/Schema.ts +12 -5
- package/src/Neon/Branch.ts +15 -3
- package/src/Output.ts +18 -2
- package/src/Planetscale/Postgres/PostgresRole.ts +2 -2
- package/src/Provider.ts +53 -3
- package/src/Ref.ts +10 -0
- package/src/Resource.ts +50 -1
- package/src/Stack.ts +1 -1
- package/src/State/HttpStateStore.ts +47 -5
- package/src/Sync.ts +494 -0
- package/src/Test/Bun.ts +4 -0
- package/src/Test/Http.ts +133 -0
- package/src/Test/Vitest.ts +11 -0
- package/src/Util/proxy-chain.ts +9 -12
- package/src/index.ts +1 -0
package/src/Sync.ts
ADDED
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
/** @effect-diagnostics anyUnknownInErrorContext:off */
|
|
2
|
+
import * as Cause from "effect/Cause";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Option from "effect/Option";
|
|
5
|
+
import { stripUnowned } from "./AdoptPolicy.ts";
|
|
6
|
+
import {
|
|
7
|
+
Artifacts,
|
|
8
|
+
ArtifactStore,
|
|
9
|
+
createArtifactStore,
|
|
10
|
+
ensureArtifactStore,
|
|
11
|
+
makeScopedArtifacts,
|
|
12
|
+
} from "./Artifacts.ts";
|
|
13
|
+
import type { PlanStatusSession, ScopedPlanStatusSession } from "./Cli/Cli.ts";
|
|
14
|
+
import { deepEqual } from "./Diff.ts";
|
|
15
|
+
import { InstanceId } from "./InstanceId.ts";
|
|
16
|
+
import type { Apply, Plan } from "./Plan.ts";
|
|
17
|
+
import { findProviderByType, Provider } from "./Provider.ts";
|
|
18
|
+
import type { ResourceLike } from "./Resource.ts";
|
|
19
|
+
import {
|
|
20
|
+
isActionState,
|
|
21
|
+
State,
|
|
22
|
+
type CreatedResourceState,
|
|
23
|
+
type ResourceState,
|
|
24
|
+
type UpdatedResourceState,
|
|
25
|
+
} from "./State/index.ts";
|
|
26
|
+
import { type ResourceOp, recordResourceOp } from "./Telemetry/Metrics.ts";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The outcome of syncing a single resource.
|
|
30
|
+
*
|
|
31
|
+
* - `unchanged` — the observed cloud state matches the persisted attributes.
|
|
32
|
+
* - `drifted` — (dry-run only) the cloud state diverged from the persisted
|
|
33
|
+
* attributes; a non-dry-run sync would repair it.
|
|
34
|
+
* - `missing` — (dry-run only) the resource no longer exists in the cloud;
|
|
35
|
+
* a non-dry-run sync would recreate it.
|
|
36
|
+
* - `repaired` — drift was detected and the resource was reconciled back to
|
|
37
|
+
* its desired (last-deployed) state.
|
|
38
|
+
* - `recreated` — the resource was missing from the cloud and was reconciled
|
|
39
|
+
* from scratch, reusing the persisted instance id so
|
|
40
|
+
* deterministic physical names converge to the same values.
|
|
41
|
+
* - `skipped` — the resource was not synced; see `reason` (provider has no
|
|
42
|
+
* `read`, or the persisted status is not stable).
|
|
43
|
+
*/
|
|
44
|
+
export type SyncAction =
|
|
45
|
+
| "unchanged"
|
|
46
|
+
| "drifted"
|
|
47
|
+
| "missing"
|
|
48
|
+
| "repaired"
|
|
49
|
+
| "recreated"
|
|
50
|
+
| "skipped";
|
|
51
|
+
|
|
52
|
+
export interface SyncResourceResult {
|
|
53
|
+
fqn: string;
|
|
54
|
+
logicalId: string;
|
|
55
|
+
resourceType: string;
|
|
56
|
+
action: SyncAction;
|
|
57
|
+
/** Why the resource was skipped (only set when `action === "skipped"`). */
|
|
58
|
+
reason?: string;
|
|
59
|
+
/**
|
|
60
|
+
* The resource's attributes after the sync: the reconciled attributes for
|
|
61
|
+
* `repaired`/`recreated`, the observed cloud attributes for `drifted`, and
|
|
62
|
+
* the persisted attributes for `unchanged`. Unset for `missing`/`skipped`.
|
|
63
|
+
*/
|
|
64
|
+
attr?: any;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SyncResult {
|
|
68
|
+
resources: Record<string, SyncResourceResult>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface SyncOptions {
|
|
72
|
+
/**
|
|
73
|
+
* Detect and report drift without repairing it. No provider `reconcile`
|
|
74
|
+
* runs and no state is persisted — resources report `drifted`/`missing`
|
|
75
|
+
* instead of `repaired`/`recreated`.
|
|
76
|
+
*/
|
|
77
|
+
dryRun?: boolean;
|
|
78
|
+
/** Optional progress session (the CLI passes one; tests usually don't). */
|
|
79
|
+
session?: PlanStatusSession;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const noopSession: PlanStatusSession = {
|
|
83
|
+
emit: () => Effect.void,
|
|
84
|
+
done: () => Effect.void,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Reconcile state drift for every resource persisted under `stack`/`stage`.
|
|
89
|
+
*
|
|
90
|
+
* Unlike `deploy` (which converges the cloud to a *new* desired state
|
|
91
|
+
* computed from the stack program), `sync` converges the cloud back to the
|
|
92
|
+
* *last-deployed* desired state recorded in the state store. It needs no
|
|
93
|
+
* stack program — only the state store and the resource providers.
|
|
94
|
+
*
|
|
95
|
+
* The algorithm, per resource, is observe → compare → converge:
|
|
96
|
+
*
|
|
97
|
+
* 1. **Read** — call `provider.read` with the persisted props/attributes to
|
|
98
|
+
* observe the live cloud state.
|
|
99
|
+
* 2. **Compare** — deep-compare the observed attributes against the
|
|
100
|
+
* persisted attributes. Equal ⇒ `unchanged`.
|
|
101
|
+
* 3. **Reconcile** — on drift, call `provider.reconcile` with the persisted
|
|
102
|
+
* props as the desired state (`news`) and the *observed* attributes as
|
|
103
|
+
* `output`, so the provider diffs against reality rather than a stale
|
|
104
|
+
* snapshot. When the resource is missing entirely, reconcile runs
|
|
105
|
+
* greenfield (`olds`/`output` undefined) under the *same* instance id so
|
|
106
|
+
* deterministic physical names regenerate identically.
|
|
107
|
+
* 4. **Persist** — write the fresh attributes back to the state store.
|
|
108
|
+
*
|
|
109
|
+
* Resources are synced concurrently and independently — persisted props are
|
|
110
|
+
* fully resolved values, so there are no upstream/downstream data edges to
|
|
111
|
+
* order by. A failure syncing one resource does not interrupt the others;
|
|
112
|
+
* all failures are aggregated into a single combined cause after every
|
|
113
|
+
* resource has been attempted.
|
|
114
|
+
*
|
|
115
|
+
* Resources that cannot be synced are reported as `skipped` rather than
|
|
116
|
+
* failing the run: providers without `read` (nothing to observe), and
|
|
117
|
+
* resources whose persisted status is not stable (`creating`, `updating`,
|
|
118
|
+
* `replacing`, `replaced`, `deleting`) — those represent an interrupted
|
|
119
|
+
* deploy and must be recovered by `deploy`, which owns replacement chains
|
|
120
|
+
* and dependency ordering. Action rows have no cloud state and are ignored.
|
|
121
|
+
*/
|
|
122
|
+
export const sync = (
|
|
123
|
+
stack: { name: string; stage: string },
|
|
124
|
+
options: SyncOptions = {},
|
|
125
|
+
): Effect.Effect<SyncResult, any, State> =>
|
|
126
|
+
Effect.gen(function* () {
|
|
127
|
+
const state = yield* yield* State;
|
|
128
|
+
const session = options.session ?? noopSession;
|
|
129
|
+
const stackName = stack.name;
|
|
130
|
+
const stage = stack.stage;
|
|
131
|
+
const dryRun = options.dryRun ?? false;
|
|
132
|
+
|
|
133
|
+
const syncResource = Effect.fn("sync.resource")(function* (fqn: string) {
|
|
134
|
+
const persisted = yield* state.get({ stack: stackName, stage, fqn });
|
|
135
|
+
// Action rows have no cloud state to drift.
|
|
136
|
+
if (!persisted || isActionState(persisted)) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
const old = persisted as ResourceState;
|
|
140
|
+
const { logicalId, instanceId, resourceType, namespace } = old;
|
|
141
|
+
|
|
142
|
+
const result = (
|
|
143
|
+
partial: Pick<SyncResourceResult, "action" | "reason" | "attr">,
|
|
144
|
+
): SyncResourceResult => ({
|
|
145
|
+
fqn,
|
|
146
|
+
logicalId,
|
|
147
|
+
resourceType,
|
|
148
|
+
...partial,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const scopedSession = {
|
|
152
|
+
...session,
|
|
153
|
+
note: (note: string) =>
|
|
154
|
+
session.emit({ id: logicalId, kind: "annotate", message: note }),
|
|
155
|
+
} satisfies ScopedPlanStatusSession;
|
|
156
|
+
|
|
157
|
+
const report = (
|
|
158
|
+
status: "updating" | "updated" | "creating" | "created" | "skipped",
|
|
159
|
+
) =>
|
|
160
|
+
session.emit({
|
|
161
|
+
kind: "status-change",
|
|
162
|
+
id: logicalId,
|
|
163
|
+
type: resourceType,
|
|
164
|
+
status,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Surface the skip reason through the session (the TUI renders it as a
|
|
168
|
+
// note under the row; the logging CLI prints it) and settle the row
|
|
169
|
+
// with a terminal `skipped` status so it never shows as in-progress.
|
|
170
|
+
const skip = (reason: string) =>
|
|
171
|
+
Effect.gen(function* () {
|
|
172
|
+
yield* scopedSession.note(reason);
|
|
173
|
+
yield* report("skipped");
|
|
174
|
+
return result({ action: "skipped", reason });
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (old.status !== "created" && old.status !== "updated") {
|
|
178
|
+
// Anything mid-flight (or with a pending replacement chain) belongs
|
|
179
|
+
// to `deploy`'s recovery machinery — replacement generations and
|
|
180
|
+
// dependency ordering are not sync's to drive.
|
|
181
|
+
return yield* skip(
|
|
182
|
+
old.status === "replaced" || old.status === "replacing"
|
|
183
|
+
? `resource has a pending replacement (status '${old.status}'); run deploy to finish it`
|
|
184
|
+
: `resource status '${old.status}' is not stable; run deploy to recover`,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const provider = yield* findProviderByType(resourceType);
|
|
189
|
+
if (!provider.read) {
|
|
190
|
+
return yield* skip(
|
|
191
|
+
`provider '${resourceType}' does not implement read`,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const commit = (value: Omit<ResourceState, "namespace">) =>
|
|
196
|
+
state.set({
|
|
197
|
+
stack: stackName,
|
|
198
|
+
stage,
|
|
199
|
+
fqn,
|
|
200
|
+
value: { ...value, namespace } as ResourceState,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const observed = yield* provider
|
|
204
|
+
.read({
|
|
205
|
+
id: logicalId,
|
|
206
|
+
instanceId,
|
|
207
|
+
olds: old.props as never,
|
|
208
|
+
output: old.attr as never,
|
|
209
|
+
})
|
|
210
|
+
.pipe(
|
|
211
|
+
instrumentLifecycle("read", fqn, resourceType, logicalId, instanceId),
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// ── missing — recreate under the same instance id ──
|
|
215
|
+
if (observed === undefined) {
|
|
216
|
+
if (dryRun) {
|
|
217
|
+
return result({ action: "missing" });
|
|
218
|
+
}
|
|
219
|
+
yield* report("creating");
|
|
220
|
+
const attr = yield* provider
|
|
221
|
+
.reconcile({
|
|
222
|
+
id: logicalId,
|
|
223
|
+
instanceId,
|
|
224
|
+
news: old.props as never,
|
|
225
|
+
olds: undefined,
|
|
226
|
+
output: undefined,
|
|
227
|
+
session: scopedSession,
|
|
228
|
+
bindings: old.bindings as never,
|
|
229
|
+
})
|
|
230
|
+
.pipe(
|
|
231
|
+
instrumentLifecycle(
|
|
232
|
+
"create",
|
|
233
|
+
fqn,
|
|
234
|
+
resourceType,
|
|
235
|
+
logicalId,
|
|
236
|
+
instanceId,
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
yield* commit({
|
|
240
|
+
status: "created",
|
|
241
|
+
fqn,
|
|
242
|
+
logicalId,
|
|
243
|
+
instanceId,
|
|
244
|
+
resourceType,
|
|
245
|
+
props: old.props!,
|
|
246
|
+
attr,
|
|
247
|
+
providerVersion: provider.version ?? 0,
|
|
248
|
+
bindings: old.bindings,
|
|
249
|
+
downstream: old.downstream,
|
|
250
|
+
removalPolicy: old.removalPolicy,
|
|
251
|
+
} satisfies Omit<CreatedResourceState, "namespace">);
|
|
252
|
+
yield* report("created");
|
|
253
|
+
return result({ action: "recreated", attr });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// `read` may brand the attributes as Unowned when ownership markers
|
|
257
|
+
// (tags) have drifted out from under us — the brand is a plan-time
|
|
258
|
+
// routing hint, never persisted, and here the state store already
|
|
259
|
+
// records the resource as ours. Tag drift then surfaces through the
|
|
260
|
+
// attribute comparison below and repairs like any other drift.
|
|
261
|
+
const live = stripUnowned(observed);
|
|
262
|
+
|
|
263
|
+
if (deepEqual(live, old.attr)) {
|
|
264
|
+
return result({ action: "unchanged", attr: old.attr });
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (dryRun) {
|
|
268
|
+
return result({ action: "drifted", attr: live });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ── drifted — converge the cloud back to the last-deployed props ──
|
|
272
|
+
yield* report("updating");
|
|
273
|
+
const attr = yield* provider
|
|
274
|
+
.reconcile({
|
|
275
|
+
id: logicalId,
|
|
276
|
+
instanceId,
|
|
277
|
+
news: old.props as never,
|
|
278
|
+
olds: old.props as never,
|
|
279
|
+
// Hand reconcile the OBSERVED attributes, not the stale persisted
|
|
280
|
+
// snapshot, so its observed-vs-desired diffing works from reality.
|
|
281
|
+
output: live as never,
|
|
282
|
+
session: scopedSession,
|
|
283
|
+
bindings: old.bindings as never,
|
|
284
|
+
})
|
|
285
|
+
.pipe(
|
|
286
|
+
instrumentLifecycle(
|
|
287
|
+
"update",
|
|
288
|
+
fqn,
|
|
289
|
+
resourceType,
|
|
290
|
+
logicalId,
|
|
291
|
+
instanceId,
|
|
292
|
+
),
|
|
293
|
+
);
|
|
294
|
+
yield* commit({
|
|
295
|
+
status: "updated",
|
|
296
|
+
fqn,
|
|
297
|
+
logicalId,
|
|
298
|
+
instanceId,
|
|
299
|
+
resourceType,
|
|
300
|
+
props: old.props!,
|
|
301
|
+
attr,
|
|
302
|
+
providerVersion: provider.version ?? 0,
|
|
303
|
+
bindings: old.bindings,
|
|
304
|
+
downstream: old.downstream,
|
|
305
|
+
removalPolicy: old.removalPolicy,
|
|
306
|
+
} satisfies Omit<UpdatedResourceState, "namespace">);
|
|
307
|
+
yield* report("updated");
|
|
308
|
+
return result({ action: "repaired", attr });
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const fqns = yield* state.list({ stack: stackName, stage });
|
|
312
|
+
|
|
313
|
+
// Sync every resource even if some fail, then surface all failures as
|
|
314
|
+
// one combined cause (mirrors Apply's failure aggregation).
|
|
315
|
+
const failures: Cause.Cause<unknown>[] = [];
|
|
316
|
+
const results = yield* Effect.all(
|
|
317
|
+
fqns.map((fqn) =>
|
|
318
|
+
syncResource(fqn).pipe(
|
|
319
|
+
Effect.catchCause((cause) =>
|
|
320
|
+
Effect.gen(function* () {
|
|
321
|
+
failures.push(cause);
|
|
322
|
+
const persisted = yield* state
|
|
323
|
+
.get({ stack: stackName, stage, fqn })
|
|
324
|
+
.pipe(Effect.orElseSucceed(() => undefined));
|
|
325
|
+
if (persisted && !isActionState(persisted)) {
|
|
326
|
+
yield* session.emit({
|
|
327
|
+
kind: "status-change",
|
|
328
|
+
id: persisted.logicalId,
|
|
329
|
+
type: persisted.resourceType,
|
|
330
|
+
status: "fail",
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
return undefined;
|
|
334
|
+
}),
|
|
335
|
+
),
|
|
336
|
+
),
|
|
337
|
+
),
|
|
338
|
+
{ concurrency: "unbounded" },
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
yield* session.done();
|
|
342
|
+
|
|
343
|
+
if (failures.length > 0) {
|
|
344
|
+
return yield* Effect.failCause(
|
|
345
|
+
failures.reduce(Cause.combine) as Cause.Cause<never>,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
resources: Object.fromEntries(
|
|
351
|
+
results
|
|
352
|
+
.filter((r): r is SyncResourceResult => r !== undefined)
|
|
353
|
+
.map((r) => [r.fqn, r]),
|
|
354
|
+
),
|
|
355
|
+
} satisfies SyncResult;
|
|
356
|
+
}).pipe(
|
|
357
|
+
ensureArtifactStore,
|
|
358
|
+
Effect.withSpan("sync", {
|
|
359
|
+
attributes: {
|
|
360
|
+
"alchemy.stack": stack.name,
|
|
361
|
+
"alchemy.stage": stack.stage,
|
|
362
|
+
"alchemy.dry_run": !!options.dryRun,
|
|
363
|
+
},
|
|
364
|
+
}),
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Same shape as Apply's lifecycle instrumentation: scoped artifacts +
|
|
369
|
+
* instance id, the resource op metrics, and a `provider.<op>` span.
|
|
370
|
+
*/
|
|
371
|
+
const instrumentLifecycle =
|
|
372
|
+
(
|
|
373
|
+
op: ResourceOp,
|
|
374
|
+
fqn: string,
|
|
375
|
+
resourceType: string,
|
|
376
|
+
logicalId: string,
|
|
377
|
+
instanceId: string,
|
|
378
|
+
) =>
|
|
379
|
+
<A, E, R>(
|
|
380
|
+
effect: Effect.Effect<A, E, R>,
|
|
381
|
+
): Effect.Effect<A, E, Exclude<R, InstanceId | Artifacts>> =>
|
|
382
|
+
Effect.serviceOption(ArtifactStore).pipe(
|
|
383
|
+
Effect.map(Option.getOrElse(createArtifactStore)),
|
|
384
|
+
Effect.flatMap((store) =>
|
|
385
|
+
effect.pipe(
|
|
386
|
+
Effect.provideService(Artifacts, makeScopedArtifacts(store, fqn)),
|
|
387
|
+
Effect.provideService(InstanceId, instanceId),
|
|
388
|
+
),
|
|
389
|
+
),
|
|
390
|
+
recordResourceOp(resourceType, op),
|
|
391
|
+
Effect.withSpan(`provider.${op}`, {
|
|
392
|
+
attributes: {
|
|
393
|
+
"alchemy.resource.fqn": fqn,
|
|
394
|
+
"alchemy.resource.type": resourceType,
|
|
395
|
+
"alchemy.resource.logical_id": logicalId,
|
|
396
|
+
"alchemy.resource.instance_id": instanceId,
|
|
397
|
+
"alchemy.resource.op": op,
|
|
398
|
+
},
|
|
399
|
+
}),
|
|
400
|
+
) as Effect.Effect<A, E, Exclude<R, InstanceId | Artifacts>>;
|
|
401
|
+
|
|
402
|
+
export interface SyncPlan {
|
|
403
|
+
/** Per-resource detection outcome (a dry-run {@link SyncResult}). */
|
|
404
|
+
result: SyncResult;
|
|
405
|
+
/**
|
|
406
|
+
* The detection outcome projected onto the engine's {@link Plan} shape so
|
|
407
|
+
* the CLI renders a sync exactly like a deploy plan (ink TUI when
|
|
408
|
+
* interactive, plain logging otherwise): `drifted` → `update`, `missing` →
|
|
409
|
+
* `create`, `unchanged`/`skipped` → `noop`.
|
|
410
|
+
*/
|
|
411
|
+
plan: Plan;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Run the drift-detection pass (a dry-run {@link sync}) and project the
|
|
416
|
+
* outcome onto a {@link Plan} for display/approval. The plan is a read-only
|
|
417
|
+
* view — repair happens by calling {@link sync} (without `dryRun`), which
|
|
418
|
+
* re-observes the cloud rather than trusting the detection snapshot.
|
|
419
|
+
*/
|
|
420
|
+
export const plan = (stack: {
|
|
421
|
+
name: string;
|
|
422
|
+
stage: string;
|
|
423
|
+
}): Effect.Effect<SyncPlan, any, State> =>
|
|
424
|
+
Effect.gen(function* () {
|
|
425
|
+
const result = yield* sync(stack, { dryRun: true });
|
|
426
|
+
const state = yield* yield* State;
|
|
427
|
+
|
|
428
|
+
const resources: Plan["resources"] = {};
|
|
429
|
+
for (const [fqn, r] of Object.entries(result.resources)) {
|
|
430
|
+
const persisted = yield* state.get({
|
|
431
|
+
stack: stack.name,
|
|
432
|
+
stage: stack.stage,
|
|
433
|
+
fqn,
|
|
434
|
+
});
|
|
435
|
+
if (!persisted || isActionState(persisted)) continue;
|
|
436
|
+
const provider = yield* findProviderByType(persisted.resourceType);
|
|
437
|
+
const action =
|
|
438
|
+
r.action === "drifted"
|
|
439
|
+
? ("update" as const)
|
|
440
|
+
: r.action === "missing"
|
|
441
|
+
? ("create" as const)
|
|
442
|
+
: ("noop" as const);
|
|
443
|
+
resources[fqn] = {
|
|
444
|
+
action,
|
|
445
|
+
props: persisted.props,
|
|
446
|
+
state: persisted,
|
|
447
|
+
provider,
|
|
448
|
+
// Synthetic ResourceLike reconstructed from persisted state, the
|
|
449
|
+
// same way Plan.make builds its deletion nodes.
|
|
450
|
+
resource: {
|
|
451
|
+
Namespace: persisted.namespace,
|
|
452
|
+
FQN: fqn,
|
|
453
|
+
LogicalId: persisted.logicalId,
|
|
454
|
+
Type: persisted.resourceType,
|
|
455
|
+
Attributes: persisted.attr,
|
|
456
|
+
Props: persisted.props,
|
|
457
|
+
Binding: undefined!,
|
|
458
|
+
Provider: Provider(persisted.resourceType),
|
|
459
|
+
RemovalPolicy: persisted.removalPolicy,
|
|
460
|
+
Adopt: undefined,
|
|
461
|
+
RuntimeContext: undefined!,
|
|
462
|
+
Providers: undefined,
|
|
463
|
+
} as ResourceLike,
|
|
464
|
+
// Sync repairs from the persisted bindings verbatim — surface them
|
|
465
|
+
// as noop rows so the renderer shows the binding topology without
|
|
466
|
+
// implying binding changes.
|
|
467
|
+
bindings: (persisted.bindings ?? []).map((binding) => ({
|
|
468
|
+
sid: binding.sid,
|
|
469
|
+
action: "noop" as const,
|
|
470
|
+
data: binding.data,
|
|
471
|
+
})),
|
|
472
|
+
downstream: persisted.downstream ?? [],
|
|
473
|
+
} as Apply;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return {
|
|
477
|
+
result,
|
|
478
|
+
plan: {
|
|
479
|
+
resources,
|
|
480
|
+
actions: {},
|
|
481
|
+
deletions: {},
|
|
482
|
+
actionDeletions: {},
|
|
483
|
+
output: undefined,
|
|
484
|
+
cycleMembers: new Set<string>(),
|
|
485
|
+
},
|
|
486
|
+
} satisfies SyncPlan;
|
|
487
|
+
}).pipe(
|
|
488
|
+
Effect.withSpan("sync.plan", {
|
|
489
|
+
attributes: {
|
|
490
|
+
"alchemy.stack": stack.name,
|
|
491
|
+
"alchemy.stage": stack.stage,
|
|
492
|
+
},
|
|
493
|
+
}),
|
|
494
|
+
);
|
package/src/Test/Bun.ts
CHANGED
package/src/Test/Http.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import * as Data from "effect/Data";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
3
4
|
import * as Schedule from "effect/Schedule";
|
|
5
|
+
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
4
6
|
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
7
|
+
import {
|
|
8
|
+
DecodeError,
|
|
9
|
+
HttpClientError,
|
|
10
|
+
} from "effect/unstable/http/HttpClientError";
|
|
5
11
|
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
|
|
6
12
|
import type { HttpClientResponse } from "effect/unstable/http/HttpClientResponse";
|
|
13
|
+
import * as RpcClient from "effect/unstable/rpc/RpcClient";
|
|
14
|
+
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
7
15
|
|
|
8
16
|
/**
|
|
9
17
|
* A freshly-deployed Cloudflare Worker is not instantly reachable over HTTP.
|
|
@@ -72,3 +80,128 @@ export const getWhenReady = (
|
|
|
72
80
|
options?: WhenReadyOptions,
|
|
73
81
|
): Effect.Effect<HttpClientResponse, unknown, HttpClient.HttpClient> =>
|
|
74
82
|
executeWhenReady(HttpClientRequest.get(url), options);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Options for the edge-transient response guard applied by
|
|
86
|
+
* {@link guardContentType} / {@link rpcClientLayer}. Pass per suite via
|
|
87
|
+
* `Test.make({ http: { ... } })` or per call site.
|
|
88
|
+
*/
|
|
89
|
+
export interface EdgeGuardOptions {
|
|
90
|
+
/**
|
|
91
|
+
* Retry schedule for edge-transient responses (and transport errors).
|
|
92
|
+
* Default: exponential from 500ms capped at 3s.
|
|
93
|
+
*/
|
|
94
|
+
schedule?: Schedule.Schedule<unknown, unknown>;
|
|
95
|
+
/** Max transport-level retry attempts. Default `5`. */
|
|
96
|
+
times?: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const defaultGuardSchedule = Schedule.exponential("500 millis").pipe(
|
|
100
|
+
Schedule.either(Schedule.spaced("3 seconds")),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Guard an `HttpClient` against edge-generated bodies on a freshly deployed
|
|
105
|
+
* Worker URL.
|
|
106
|
+
*
|
|
107
|
+
* Protocol clients like effect RPC's `layerProtocolHttp` never inspect the
|
|
108
|
+
* response status or content-type — they pipe the raw body straight into the
|
|
109
|
+
* serialization parser, so every edge-generated HTML page (the workers.dev
|
|
110
|
+
* placeholder, which serves with HTTP **200**; 1101/1102 error pages;
|
|
111
|
+
* 429/1015 rate limits) surfaces as an opaque decode defect (e.g.
|
|
112
|
+
* `RpcClientDefect: Error decoding HTTP response`).
|
|
113
|
+
*
|
|
114
|
+
* This transform rejects any response whose `content-type` doesn't match the
|
|
115
|
+
* expected one as a typed `HttpClientError` that records the status + a body
|
|
116
|
+
* snippet — so a failure names its cause — and retries the request through a
|
|
117
|
+
* bounded schedule so callers ride out the cold-start window
|
|
118
|
+
* ({@link WorkerNotReady} documents why this belongs at the call site).
|
|
119
|
+
*/
|
|
120
|
+
export const guardContentType =
|
|
121
|
+
(contentType: string, options?: EdgeGuardOptions) =>
|
|
122
|
+
(client: HttpClient.HttpClient): HttpClient.HttpClient =>
|
|
123
|
+
client.pipe(
|
|
124
|
+
HttpClient.transform((effect, request) =>
|
|
125
|
+
Effect.flatMap(effect, (response) => {
|
|
126
|
+
const observed = response.headers["content-type"] ?? "";
|
|
127
|
+
if (observed.includes(contentType)) {
|
|
128
|
+
return Effect.succeed(response);
|
|
129
|
+
}
|
|
130
|
+
return response.text.pipe(
|
|
131
|
+
Effect.orElseSucceed(() => "<unreadable body>"),
|
|
132
|
+
Effect.flatMap((body) =>
|
|
133
|
+
Effect.fail(
|
|
134
|
+
new HttpClientError({
|
|
135
|
+
reason: new DecodeError({
|
|
136
|
+
request,
|
|
137
|
+
response,
|
|
138
|
+
description: `expected "${contentType}", got "${observed}" (status ${response.status}): ${body.slice(0, 200)}`,
|
|
139
|
+
}),
|
|
140
|
+
}),
|
|
141
|
+
),
|
|
142
|
+
),
|
|
143
|
+
);
|
|
144
|
+
}),
|
|
145
|
+
),
|
|
146
|
+
HttpClient.retry({
|
|
147
|
+
schedule: options?.schedule ?? defaultGuardSchedule,
|
|
148
|
+
times: options?.times ?? 5,
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* A fetch-backed `HttpClient` layer wrapped with {@link guardContentType}.
|
|
154
|
+
*
|
|
155
|
+
* Deliberately a standalone layer rather than a transform of the ambient
|
|
156
|
+
* test `HttpClient`: the ambient client also serves the engine's own cloud
|
|
157
|
+
* API calls during `deploy`/`destroy` and distilled SDK calls in
|
|
158
|
+
* `test.provider` bodies, which must NOT be subjected to this guard.
|
|
159
|
+
*/
|
|
160
|
+
export const guardedFetchLayer = (
|
|
161
|
+
contentType: string,
|
|
162
|
+
options?: EdgeGuardOptions,
|
|
163
|
+
): Layer.Layer<HttpClient.HttpClient> =>
|
|
164
|
+
Layer.effect(HttpClient.HttpClient)(
|
|
165
|
+
Effect.gen(function* () {
|
|
166
|
+
const client = yield* HttpClient.HttpClient;
|
|
167
|
+
return guardContentType(contentType, options)(client);
|
|
168
|
+
}),
|
|
169
|
+
).pipe(Layer.provide(FetchHttpClient.layer));
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Complete RPC-over-HTTP client transport for driving a deployed Worker:
|
|
173
|
+
* `RpcClient.layerProtocolHttp` + the given serialization (ndjson by
|
|
174
|
+
* default) + a {@link guardedFetchLayer} expecting that serialization's
|
|
175
|
+
* content-type.
|
|
176
|
+
*
|
|
177
|
+
* ```ts
|
|
178
|
+
* const client = yield* RpcClient.make(WorkerRpcs);
|
|
179
|
+
* // ...
|
|
180
|
+
* }).pipe(Effect.scoped, Effect.provide(Test.Http.rpcClientLayer(url)));
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export const rpcClientLayer = (
|
|
184
|
+
url: string,
|
|
185
|
+
options?: EdgeGuardOptions & {
|
|
186
|
+
/** RPC wire serialization. Default {@link RpcSerialization.ndjson}. */
|
|
187
|
+
serialization?: RpcSerialization.RpcSerialization["Service"];
|
|
188
|
+
/**
|
|
189
|
+
* Set `false` to skip the edge guard entirely and use a plain fetch
|
|
190
|
+
* transport — e.g. for a test that asserts on the raw edge behavior
|
|
191
|
+
* itself. Default `true`.
|
|
192
|
+
*/
|
|
193
|
+
guard?: boolean;
|
|
194
|
+
},
|
|
195
|
+
): Layer.Layer<RpcClient.Protocol> => {
|
|
196
|
+
const serialization = options?.serialization ?? RpcSerialization.ndjson;
|
|
197
|
+
return RpcClient.layerProtocolHttp({ url }).pipe(
|
|
198
|
+
Layer.provide(
|
|
199
|
+
options?.guard === false
|
|
200
|
+
? FetchHttpClient.layer
|
|
201
|
+
: guardedFetchLayer(serialization.contentType, options),
|
|
202
|
+
),
|
|
203
|
+
Layer.provide(
|
|
204
|
+
Layer.succeed(RpcSerialization.RpcSerialization, serialization),
|
|
205
|
+
),
|
|
206
|
+
);
|
|
207
|
+
};
|
package/src/Test/Vitest.ts
CHANGED
|
@@ -15,6 +15,17 @@ import type { CompiledStack } from "../Stack.ts";
|
|
|
15
15
|
import type { Stage } from "../Stage.ts";
|
|
16
16
|
import * as Core from "./Core.ts";
|
|
17
17
|
|
|
18
|
+
export {
|
|
19
|
+
executeWhenReady,
|
|
20
|
+
getWhenReady,
|
|
21
|
+
guardContentType,
|
|
22
|
+
guardedFetchLayer,
|
|
23
|
+
rpcClientLayer,
|
|
24
|
+
WorkerNotReady,
|
|
25
|
+
type EdgeGuardOptions,
|
|
26
|
+
type WhenReadyOptions,
|
|
27
|
+
} from "./Http.ts";
|
|
28
|
+
|
|
18
29
|
export type MakeOptions<ROut = any> = Core.MakeOptions<ROut>;
|
|
19
30
|
export type ScratchStack = Core.ScratchStack;
|
|
20
31
|
export type TestEffect<A, R = never> = Core.TestEffect<A, R>;
|
package/src/Util/proxy-chain.ts
CHANGED
|
@@ -59,19 +59,15 @@ export const proxyChain = <T>(cached: Effect.Effect<T, any, any>): T =>
|
|
|
59
59
|
const chain = (
|
|
60
60
|
cached: Effect.Effect<unknown, any, any>,
|
|
61
61
|
ops: ReadonlyArray<Op> = [],
|
|
62
|
-
): unknown =>
|
|
63
|
-
|
|
62
|
+
): unknown => {
|
|
63
|
+
const effect = Effect.flatMap(
|
|
64
|
+
cached,
|
|
65
|
+
(root) => replay(root, ops) as Effect.Effect<unknown, unknown, unknown>,
|
|
66
|
+
);
|
|
67
|
+
return new Proxy(function () {}, {
|
|
64
68
|
get(_, prop) {
|
|
65
|
-
if (prop
|
|
66
|
-
|
|
67
|
-
return function () {
|
|
68
|
-
const eff = Effect.flatMap(
|
|
69
|
-
cached,
|
|
70
|
-
(root) =>
|
|
71
|
-
replay(root, ops) as Effect.Effect<unknown, unknown, unknown>,
|
|
72
|
-
);
|
|
73
|
-
return (eff as any)[Symbol.iterator]();
|
|
74
|
-
};
|
|
69
|
+
if (Reflect.has(effect, prop)) {
|
|
70
|
+
return Reflect.get(effect, prop);
|
|
75
71
|
}
|
|
76
72
|
return chain(cached, [...ops, { kind: "get", prop }]);
|
|
77
73
|
},
|
|
@@ -79,3 +75,4 @@ const chain = (
|
|
|
79
75
|
return chain(cached, [...ops, { kind: "call", args }]);
|
|
80
76
|
},
|
|
81
77
|
});
|
|
78
|
+
};
|