alchemy 2.0.0-beta.65 → 2.0.0-beta.67
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/exec.js +578 -224
- package/bin/exec.js.map +1 -1
- package/lib/AWS/ApiGateway/common.d.ts.map +1 -1
- package/lib/AWS/ApiGateway/common.js +8 -1
- package/lib/AWS/ApiGateway/common.js.map +1 -1
- package/lib/AWS/Bedrock/LanguageModel.d.ts +208 -0
- package/lib/AWS/Bedrock/LanguageModel.d.ts.map +1 -0
- package/lib/AWS/Bedrock/LanguageModel.js +508 -0
- package/lib/AWS/Bedrock/LanguageModel.js.map +1 -0
- package/lib/AWS/Bedrock/LanguageModelHttp.d.ts +10 -0
- package/lib/AWS/Bedrock/LanguageModelHttp.d.ts.map +1 -0
- package/lib/AWS/Bedrock/LanguageModelHttp.js +26 -0
- package/lib/AWS/Bedrock/LanguageModelHttp.js.map +1 -0
- package/lib/AWS/Bedrock/index.d.ts +2 -0
- package/lib/AWS/Bedrock/index.d.ts.map +1 -1
- package/lib/AWS/Bedrock/index.js +2 -0
- package/lib/AWS/Bedrock/index.js.map +1 -1
- package/lib/AWS/CloudFront/Distribution.d.ts +24 -0
- package/lib/AWS/CloudFront/Distribution.d.ts.map +1 -1
- package/lib/AWS/CloudFront/Distribution.js +89 -4
- package/lib/AWS/CloudFront/Distribution.js.map +1 -1
- package/lib/AWS/CostExplorer/AnomalyMonitor.d.ts +1 -1
- package/lib/AWS/CostExplorer/AnomalyMonitor.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/AnomalySubscription.d.ts +1 -1
- package/lib/AWS/CostExplorer/AnomalySubscription.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/BindingHttp.d.ts +3 -3
- package/lib/AWS/CostExplorer/BindingHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/CostCategory.d.ts +1 -1
- package/lib/AWS/CostExplorer/CostCategory.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetAnomaliesHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetAnomaliesHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetApproximateUsageRecordsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetApproximateUsageRecordsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCommitmentPurchaseAnalysisHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCommitmentPurchaseAnalysisHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCostAndUsageComparisonsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCostAndUsageComparisonsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCostAndUsageHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCostAndUsageHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCostAndUsageWithResourcesHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCostAndUsageWithResourcesHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCostCategoriesHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCostCategoriesHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCostComparisonDriversHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCostComparisonDriversHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetCostForecastHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetCostForecastHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetDimensionValuesHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetDimensionValuesHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetReservationCoverageHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetReservationCoverageHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetReservationPurchaseRecommendationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetReservationPurchaseRecommendationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetReservationUtilizationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetReservationUtilizationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetRightsizingRecommendationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetRightsizingRecommendationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlanPurchaseRecommendationDetailsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlanPurchaseRecommendationDetailsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansCoverageHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansCoverageHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansPurchaseRecommendationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansPurchaseRecommendationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansUtilizationDetailsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansUtilizationDetailsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansUtilizationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetSavingsPlansUtilizationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetTagsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetTagsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/GetUsageForecastHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/GetUsageForecastHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/ListCommitmentPurchaseAnalysesHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/ListCommitmentPurchaseAnalysesHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/ListCostAllocationTagBackfillHistoryHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/ListCostAllocationTagBackfillHistoryHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/ListCostAllocationTagsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/ListCostAllocationTagsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/ListCostCategoryResourceAssociationsHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/ListCostCategoryResourceAssociationsHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/ListSavingsPlansPurchaseRecommendationGenerationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/ListSavingsPlansPurchaseRecommendationGenerationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/ProvideAnomalyFeedbackHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/ProvideAnomalyFeedbackHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/StartCommitmentPurchaseAnalysisHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/StartCommitmentPurchaseAnalysisHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/StartCostAllocationTagBackfillHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/StartCostAllocationTagBackfillHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/StartSavingsPlansPurchaseRecommendationGenerationHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/StartSavingsPlansPurchaseRecommendationGenerationHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/UpdateCostAllocationTagsStatusHttp.d.ts +1 -1
- package/lib/AWS/CostExplorer/UpdateCostAllocationTagsStatusHttp.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/common.d.ts +5 -3
- package/lib/AWS/CostExplorer/common.d.ts.map +1 -1
- package/lib/AWS/CostExplorer/common.js +16 -1
- package/lib/AWS/CostExplorer/common.js.map +1 -1
- package/lib/AWS/DataSync/Task.d.ts.map +1 -1
- package/lib/AWS/DataSync/Task.js +16 -2
- package/lib/AWS/DataSync/Task.js.map +1 -1
- package/lib/AWS/EC2/Vpc.d.ts.map +1 -1
- package/lib/AWS/EC2/Vpc.js +15 -2
- package/lib/AWS/EC2/Vpc.js.map +1 -1
- package/lib/AWS/EC2/hosted.d.ts.map +1 -1
- package/lib/AWS/EC2/hosted.js +10 -2
- package/lib/AWS/EC2/hosted.js.map +1 -1
- package/lib/AWS/ECR/Image.d.ts +132 -13
- package/lib/AWS/ECR/Image.d.ts.map +1 -1
- package/lib/AWS/ECR/ImageSource.d.ts.map +1 -1
- package/lib/AWS/ECR/ImageSource.js +10 -2
- package/lib/AWS/ECR/ImageSource.js.map +1 -1
- package/lib/AWS/ECR/Repository.d.ts +2 -0
- package/lib/AWS/ECR/Repository.d.ts.map +1 -1
- package/lib/AWS/ECR/Repository.js +28 -3
- package/lib/AWS/ECR/Repository.js.map +1 -1
- package/lib/AWS/ECS/Service.d.ts +27 -1
- package/lib/AWS/ECS/Service.d.ts.map +1 -1
- package/lib/AWS/ECS/Service.js +184 -22
- package/lib/AWS/ECS/Service.js.map +1 -1
- package/lib/AWS/ECS/Task.d.ts +32 -8
- package/lib/AWS/ECS/Task.d.ts.map +1 -1
- package/lib/AWS/ECS/Task.js +62 -29
- package/lib/AWS/ECS/Task.js.map +1 -1
- package/lib/AWS/EKS/Deployment.d.ts.map +1 -1
- package/lib/AWS/EKS/Deployment.js +10 -2
- package/lib/AWS/EKS/Deployment.js.map +1 -1
- package/lib/AWS/EKS/Job.d.ts.map +1 -1
- package/lib/AWS/EKS/Job.js +10 -2
- package/lib/AWS/EKS/Job.js.map +1 -1
- package/lib/AWS/Lambda/Function.d.ts +15 -0
- package/lib/AWS/Lambda/Function.d.ts.map +1 -1
- package/lib/AWS/Lambda/Function.js +67 -29
- package/lib/AWS/Lambda/Function.js.map +1 -1
- package/lib/AWS/Lambda/HttpServer.d.ts.map +1 -1
- package/lib/AWS/Lambda/HttpServer.js +7 -1
- package/lib/AWS/Lambda/HttpServer.js.map +1 -1
- package/lib/AWS/Lambda/LayerVersion.d.ts +176 -0
- package/lib/AWS/Lambda/LayerVersion.d.ts.map +1 -0
- package/lib/AWS/Lambda/LayerVersion.js +288 -0
- package/lib/AWS/Lambda/LayerVersion.js.map +1 -0
- package/lib/AWS/Lambda/MicrovmBundle.d.ts.map +1 -1
- package/lib/AWS/Lambda/MicrovmBundle.js +10 -2
- package/lib/AWS/Lambda/MicrovmBundle.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/Providers.d.ts.map +1 -1
- package/lib/AWS/Providers.js +6 -1
- package/lib/AWS/Providers.js.map +1 -1
- package/lib/AWS/SES/ActiveReceiptRuleSet.d.ts +40 -0
- package/lib/AWS/SES/ActiveReceiptRuleSet.d.ts.map +1 -0
- package/lib/AWS/SES/ActiveReceiptRuleSet.js +58 -0
- package/lib/AWS/SES/ActiveReceiptRuleSet.js.map +1 -0
- package/lib/AWS/SES/ReceiptFilter.d.ts +67 -0
- package/lib/AWS/SES/ReceiptFilter.d.ts.map +1 -0
- package/lib/AWS/SES/ReceiptFilter.js +92 -0
- package/lib/AWS/SES/ReceiptFilter.js.map +1 -0
- package/lib/AWS/SES/ReceiptRule.d.ts +133 -0
- package/lib/AWS/SES/ReceiptRule.d.ts.map +1 -0
- package/lib/AWS/SES/ReceiptRule.js +178 -0
- package/lib/AWS/SES/ReceiptRule.js.map +1 -0
- package/lib/AWS/SES/ReceiptRuleSet.d.ts +55 -0
- package/lib/AWS/SES/ReceiptRuleSet.d.ts.map +1 -0
- package/lib/AWS/SES/ReceiptRuleSet.js +112 -0
- package/lib/AWS/SES/ReceiptRuleSet.js.map +1 -0
- package/lib/AWS/SES/SendBounce.d.ts +37 -0
- package/lib/AWS/SES/SendBounce.d.ts.map +1 -0
- package/lib/AWS/SES/SendBounce.js +3 -0
- package/lib/AWS/SES/SendBounce.js.map +1 -0
- package/lib/AWS/SES/SendBounceHttp.d.ts +4 -0
- package/lib/AWS/SES/SendBounceHttp.d.ts.map +1 -0
- package/lib/AWS/SES/SendBounceHttp.js +10 -0
- package/lib/AWS/SES/SendBounceHttp.js.map +1 -0
- package/lib/AWS/SES/index.d.ts +6 -0
- package/lib/AWS/SES/index.d.ts.map +1 -1
- package/lib/AWS/SES/index.js +6 -0
- package/lib/AWS/SES/index.js.map +1 -1
- package/lib/AWS/StateStore/State.d.ts +11 -0
- package/lib/AWS/StateStore/State.d.ts.map +1 -1
- package/lib/AWS/StateStore/State.js +117 -38
- package/lib/AWS/StateStore/State.js.map +1 -1
- package/lib/Apply.d.ts +37 -1
- package/lib/Apply.d.ts.map +1 -1
- package/lib/Apply.js +270 -194
- package/lib/Apply.js.map +1 -1
- package/lib/Axiom/Telemetry.d.ts +66 -0
- package/lib/Axiom/Telemetry.d.ts.map +1 -0
- package/lib/Axiom/Telemetry.js +69 -0
- package/lib/Axiom/Telemetry.js.map +1 -0
- package/lib/Axiom/index.d.ts +1 -0
- package/lib/Axiom/index.d.ts.map +1 -1
- package/lib/Axiom/index.js +1 -0
- package/lib/Axiom/index.js.map +1 -1
- package/lib/Bundle/Bundle.d.ts +1 -1
- package/lib/Bundle/Bundle.d.ts.map +1 -1
- package/lib/Bundle/Bundle.js +14 -6
- package/lib/Bundle/Bundle.js.map +1 -1
- package/lib/Bundle/BundleAnalyzerPlugin.d.ts +1 -1
- package/lib/Bundle/BundleAnalyzerPlugin.d.ts.map +1 -1
- package/lib/Bundle/BundleAnalyzerPlugin.js +10 -5
- package/lib/Bundle/BundleAnalyzerPlugin.js.map +1 -1
- package/lib/Bundle/PurePlugin.d.ts +1 -1
- package/lib/Bundle/PurePlugin.d.ts.map +1 -1
- package/lib/Bundle/PurePlugin.js +15 -7
- package/lib/Bundle/PurePlugin.js.map +1 -1
- package/lib/Cli/checkVersion.d.ts +11 -5
- package/lib/Cli/checkVersion.d.ts.map +1 -1
- package/lib/Cli/checkVersion.js +73 -12
- package/lib/Cli/checkVersion.js.map +1 -1
- package/lib/Cli/commands/_shared.d.ts.map +1 -1
- package/lib/Cli/commands/_shared.js +2 -1
- package/lib/Cli/commands/_shared.js.map +1 -1
- package/lib/Cli/commands/cloudflare.d.ts +1 -1
- package/lib/Cli/commands/deploy.d.ts.map +1 -1
- package/lib/Cli/commands/deploy.js +3 -11
- package/lib/Cli/commands/deploy.js.map +1 -1
- package/lib/Cli/commands/logs.d.ts.map +1 -1
- package/lib/Cli/commands/logs.js +3 -1
- package/lib/Cli/commands/logs.js.map +1 -1
- package/lib/Cli/commands/tail.d.ts.map +1 -1
- package/lib/Cli/commands/tail.js +3 -1
- package/lib/Cli/commands/tail.js.map +1 -1
- package/lib/Cli/main.d.ts.map +1 -1
- package/lib/Cli/main.js +5 -4
- package/lib/Cli/main.js.map +1 -1
- package/lib/Cloudflare/AI/Search.d.ts +4 -15
- package/lib/Cloudflare/AI/Search.d.ts.map +1 -1
- package/lib/Cloudflare/AI/Search.js +4 -6
- package/lib/Cloudflare/AI/Search.js.map +1 -1
- package/lib/Cloudflare/AI/SearchInstance.d.ts +7 -26
- package/lib/Cloudflare/AI/SearchInstance.d.ts.map +1 -1
- package/lib/Cloudflare/AI/SearchInstance.js +7 -26
- package/lib/Cloudflare/AI/SearchInstance.js.map +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.d.ts +3 -0
- package/lib/Cloudflare/ApiToken/AccountApiToken.d.ts.map +1 -1
- package/lib/Cloudflare/ApiToken/AccountApiToken.js +3 -0
- package/lib/Cloudflare/ApiToken/AccountApiToken.js.map +1 -1
- package/lib/Cloudflare/Auth/AuthProvider.d.ts +2 -1
- package/lib/Cloudflare/Auth/AuthProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Auth/AuthProvider.js +8 -3
- package/lib/Cloudflare/Auth/AuthProvider.js.map +1 -1
- package/lib/Cloudflare/Auth/OAuthClient.d.ts +5 -0
- package/lib/Cloudflare/Auth/OAuthClient.d.ts.map +1 -1
- package/lib/Cloudflare/Auth/OAuthClient.js +50 -4
- package/lib/Cloudflare/Auth/OAuthClient.js.map +1 -1
- package/lib/Cloudflare/Containers/Container.d.ts +81 -3
- package/lib/Cloudflare/Containers/Container.d.ts.map +1 -1
- package/lib/Cloudflare/Containers/Container.js +70 -0
- package/lib/Cloudflare/Containers/Container.js.map +1 -1
- package/lib/Cloudflare/Containers/ContainerApplication.d.ts +22 -1
- package/lib/Cloudflare/Containers/ContainerApplication.d.ts.map +1 -1
- package/lib/Cloudflare/Containers/ContainerApplication.js +4 -1
- package/lib/Cloudflare/Containers/ContainerApplication.js.map +1 -1
- package/lib/Cloudflare/Containers/ContainerBundle.d.ts.map +1 -1
- package/lib/Cloudflare/Containers/ContainerBundle.js +10 -2
- package/lib/Cloudflare/Containers/ContainerBundle.js.map +1 -1
- package/lib/Cloudflare/Containers/ContainerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Containers/ContainerProvider.js +43 -0
- package/lib/Cloudflare/Containers/ContainerProvider.js.map +1 -1
- package/lib/Cloudflare/Credentials.d.ts +21 -1
- package/lib/Cloudflare/Credentials.d.ts.map +1 -1
- package/lib/Cloudflare/Credentials.js +52 -9
- package/lib/Cloudflare/Credentials.js.map +1 -1
- package/lib/Cloudflare/D1/ApplyMigrations.d.ts +30 -5
- package/lib/Cloudflare/D1/ApplyMigrations.d.ts.map +1 -1
- package/lib/Cloudflare/D1/ApplyMigrations.js +36 -26
- package/lib/Cloudflare/D1/ApplyMigrations.js.map +1 -1
- package/lib/Cloudflare/D1/Database.d.ts +18 -1
- package/lib/Cloudflare/D1/Database.d.ts.map +1 -1
- package/lib/Cloudflare/D1/Database.js +134 -2
- package/lib/Cloudflare/D1/Database.js.map +1 -1
- package/lib/Cloudflare/D1/LocalD1Gateway.d.ts +39 -0
- package/lib/Cloudflare/D1/LocalD1Gateway.d.ts.map +1 -0
- package/lib/Cloudflare/D1/LocalD1Gateway.js +100 -0
- package/lib/Cloudflare/D1/LocalD1Gateway.js.map +1 -0
- package/lib/Cloudflare/D1/QueryDatabaseHttpClient.d.ts +31 -0
- package/lib/Cloudflare/D1/QueryDatabaseHttpClient.d.ts.map +1 -1
- package/lib/Cloudflare/D1/QueryDatabaseHttpClient.js +13 -6
- package/lib/Cloudflare/D1/QueryDatabaseHttpClient.js.map +1 -1
- package/lib/Cloudflare/D1/QueryDatabaseLocal.d.ts.map +1 -1
- package/lib/Cloudflare/D1/QueryDatabaseLocal.js +21 -2
- package/lib/Cloudflare/D1/QueryDatabaseLocal.js.map +1 -1
- package/lib/Cloudflare/DNS/Record.d.ts +3 -1
- package/lib/Cloudflare/DNS/Record.d.ts.map +1 -1
- package/lib/Cloudflare/DNS/Record.js +23 -4
- package/lib/Cloudflare/DNS/Record.js.map +1 -1
- package/lib/Cloudflare/Email/Address.d.ts.map +1 -1
- package/lib/Cloudflare/Email/Address.js +15 -1
- package/lib/Cloudflare/Email/Address.js.map +1 -1
- package/lib/Cloudflare/Email/SendBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Email/SendBinding.js +1 -0
- package/lib/Cloudflare/Email/SendBinding.js.map +1 -1
- package/lib/Cloudflare/Email/SendEmail.d.ts +12 -0
- package/lib/Cloudflare/Email/SendEmail.d.ts.map +1 -1
- package/lib/Cloudflare/Email/SendEmail.js +1 -0
- package/lib/Cloudflare/Email/SendEmail.js.map +1 -1
- package/lib/Cloudflare/Flagship/App.d.ts.map +1 -1
- package/lib/Cloudflare/Flagship/App.js +8 -3
- package/lib/Cloudflare/Flagship/App.js.map +1 -1
- package/lib/Cloudflare/KV/LocalKVGateway.d.ts +15 -0
- package/lib/Cloudflare/KV/LocalKVGateway.d.ts.map +1 -0
- package/lib/Cloudflare/KV/LocalKVGateway.js +64 -0
- package/lib/Cloudflare/KV/LocalKVGateway.js.map +1 -0
- package/lib/Cloudflare/KV/Namespace.d.ts +9 -1
- package/lib/Cloudflare/KV/Namespace.d.ts.map +1 -1
- package/lib/Cloudflare/KV/Namespace.js +45 -1
- package/lib/Cloudflare/KV/Namespace.js.map +1 -1
- package/lib/Cloudflare/KV/NamespaceLocal.d.ts +16 -5
- package/lib/Cloudflare/KV/NamespaceLocal.d.ts.map +1 -1
- package/lib/Cloudflare/KV/NamespaceLocal.js +21 -4
- package/lib/Cloudflare/KV/NamespaceLocal.js.map +1 -1
- package/lib/Cloudflare/KV/ReadNamespaceLocal.d.ts.map +1 -1
- package/lib/Cloudflare/KV/ReadNamespaceLocal.js +5 -1
- package/lib/Cloudflare/KV/ReadNamespaceLocal.js.map +1 -1
- package/lib/Cloudflare/KV/ReadWriteNamespaceLocal.d.ts.map +1 -1
- package/lib/Cloudflare/KV/ReadWriteNamespaceLocal.js +5 -1
- package/lib/Cloudflare/KV/ReadWriteNamespaceLocal.js.map +1 -1
- package/lib/Cloudflare/KV/WriteNamespaceLocal.d.ts.map +1 -1
- package/lib/Cloudflare/KV/WriteNamespaceLocal.js +5 -1
- package/lib/Cloudflare/KV/WriteNamespaceLocal.js.map +1 -1
- package/lib/Cloudflare/LocalGateway.d.ts +25 -0
- package/lib/Cloudflare/LocalGateway.d.ts.map +1 -0
- package/lib/Cloudflare/LocalGateway.js +70 -0
- package/lib/Cloudflare/LocalGateway.js.map +1 -0
- package/lib/Cloudflare/LocalRuntime.d.ts +14 -1
- package/lib/Cloudflare/LocalRuntime.d.ts.map +1 -1
- package/lib/Cloudflare/LocalRuntime.js +16 -1
- package/lib/Cloudflare/LocalRuntime.js.map +1 -1
- package/lib/Cloudflare/Logs.d.ts.map +1 -1
- package/lib/Cloudflare/Logs.js +18 -6
- package/lib/Cloudflare/Logs.js.map +1 -1
- package/lib/Cloudflare/Providers.d.ts +1 -1
- package/lib/Cloudflare/Providers.d.ts.map +1 -1
- package/lib/Cloudflare/Providers.js +6 -2
- package/lib/Cloudflare/Providers.js.map +1 -1
- package/lib/Cloudflare/Queues/Consumer.d.ts +16 -3
- package/lib/Cloudflare/Queues/Consumer.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Consumer.js +51 -3
- package/lib/Cloudflare/Queues/Consumer.js.map +1 -1
- package/lib/Cloudflare/Queues/Queue.d.ts +4 -3
- package/lib/Cloudflare/Queues/Queue.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/Queue.js +7 -17
- package/lib/Cloudflare/Queues/Queue.js.map +1 -1
- package/lib/Cloudflare/Queues/QueueBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Queues/QueueBinding.js +19 -0
- package/lib/Cloudflare/Queues/QueueBinding.js.map +1 -1
- package/lib/Cloudflare/Queues/QueueShim.d.ts +55 -0
- package/lib/Cloudflare/Queues/QueueShim.d.ts.map +1 -0
- package/lib/Cloudflare/Queues/QueueShim.js +177 -0
- package/lib/Cloudflare/Queues/QueueShim.js.map +1 -0
- package/lib/Cloudflare/R2/Bucket.d.ts +14 -1
- package/lib/Cloudflare/R2/Bucket.d.ts.map +1 -1
- package/lib/Cloudflare/R2/Bucket.js +53 -1
- package/lib/Cloudflare/R2/Bucket.js.map +1 -1
- package/lib/Cloudflare/R2/BucketBinding.d.ts +10 -0
- package/lib/Cloudflare/R2/BucketBinding.d.ts.map +1 -1
- package/lib/Cloudflare/R2/BucketBinding.js +14 -3
- package/lib/Cloudflare/R2/BucketBinding.js.map +1 -1
- package/lib/Cloudflare/R2/BucketLocal.d.ts +13 -6
- package/lib/Cloudflare/R2/BucketLocal.d.ts.map +1 -1
- package/lib/Cloudflare/R2/BucketLocal.js +19 -6
- package/lib/Cloudflare/R2/BucketLocal.js.map +1 -1
- package/lib/Cloudflare/R2/LocalR2Gateway.d.ts +15 -0
- package/lib/Cloudflare/R2/LocalR2Gateway.d.ts.map +1 -0
- package/lib/Cloudflare/R2/LocalR2Gateway.js +65 -0
- package/lib/Cloudflare/R2/LocalR2Gateway.js.map +1 -0
- package/lib/Cloudflare/R2/ReadBucketLocal.d.ts.map +1 -1
- package/lib/Cloudflare/R2/ReadBucketLocal.js +5 -1
- package/lib/Cloudflare/R2/ReadBucketLocal.js.map +1 -1
- package/lib/Cloudflare/R2/ReadWriteBucketLocal.d.ts.map +1 -1
- package/lib/Cloudflare/R2/ReadWriteBucketLocal.js +5 -1
- package/lib/Cloudflare/R2/ReadWriteBucketLocal.js.map +1 -1
- package/lib/Cloudflare/R2/WriteBucketLocal.d.ts.map +1 -1
- package/lib/Cloudflare/R2/WriteBucketLocal.js +5 -1
- package/lib/Cloudflare/R2/WriteBucketLocal.js.map +1 -1
- package/lib/Cloudflare/Ruleset/AccountEntrypoint.d.ts.map +1 -1
- package/lib/Cloudflare/Ruleset/AccountEntrypoint.js +5 -1
- package/lib/Cloudflare/Ruleset/AccountEntrypoint.js.map +1 -1
- package/lib/Cloudflare/Ruleset/Ruleset.d.ts.map +1 -1
- package/lib/Cloudflare/Ruleset/Ruleset.js +19 -6
- package/lib/Cloudflare/Ruleset/Ruleset.js.map +1 -1
- package/lib/Cloudflare/Rum/Site.js +10 -2
- package/lib/Cloudflare/Rum/Site.js.map +1 -1
- package/lib/Cloudflare/StateStore/Api.d.ts +31 -2
- package/lib/Cloudflare/StateStore/Api.js +1 -1
- package/lib/Cloudflare/StateStore/Api.js.map +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts +1 -1
- package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
- package/lib/Cloudflare/Tunnel/Tunnel.d.ts.map +1 -1
- package/lib/Cloudflare/Tunnel/Tunnel.js +20 -1
- package/lib/Cloudflare/Tunnel/Tunnel.js.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.d.ts +34 -7
- package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/StaticSite.js +108 -24
- package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
- package/lib/Cloudflare/Website/Vite.d.ts +33 -19
- package/lib/Cloudflare/Website/Vite.d.ts.map +1 -1
- package/lib/Cloudflare/Website/Vite.js +33 -19
- package/lib/Cloudflare/Website/Vite.js.map +1 -1
- package/lib/Cloudflare/Workers/Compatibility.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Compatibility.js +26 -7
- package/lib/Cloudflare/Workers/Compatibility.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObject.d.ts +22 -0
- package/lib/Cloudflare/Workers/DurableObject.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObject.js +22 -0
- package/lib/Cloudflare/Workers/DurableObject.js.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/DurableObjectBridge.js +20 -5
- package/lib/Cloudflare/Workers/DurableObjectBridge.js.map +1 -1
- package/lib/Cloudflare/Workers/InferEnv.d.ts +4 -2
- package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +7 -3
- package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js +483 -298
- package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workers/Worker.d.ts +612 -13
- package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/Worker.js +222 -1
- package/lib/Cloudflare/Workers/Worker.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts +13 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +171 -21
- package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts +130 -28
- package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBridge.d.ts +6 -2
- package/lib/Cloudflare/Workers/WorkerBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBridge.js +18 -2
- package/lib/Cloudflare/Workers/WorkerBridge.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js +4 -1
- package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.d.ts +186 -11
- package/lib/Cloudflare/Workers/WorkerProvider.d.ts.map +1 -1
- package/lib/Cloudflare/Workers/WorkerProvider.js +1765 -236
- package/lib/Cloudflare/Workers/WorkerProvider.js.map +1 -1
- package/lib/Cloudflare/Workflows/WorkflowBridge.d.ts +7 -1
- package/lib/Cloudflare/Workflows/WorkflowBridge.d.ts.map +1 -1
- package/lib/Cloudflare/Workflows/WorkflowBridge.js +14 -4
- package/lib/Cloudflare/Workflows/WorkflowBridge.js.map +1 -1
- package/lib/Command/Build.d.ts +2 -2
- package/lib/Command/Build.d.ts.map +1 -1
- package/lib/Command/Build.js +4 -7
- package/lib/Command/Build.js.map +1 -1
- package/lib/Command/Command.d.ts +34 -4
- package/lib/Command/Command.d.ts.map +1 -1
- package/lib/Command/Command.js +125 -30
- package/lib/Command/Command.js.map +1 -1
- package/lib/Command/Dev.d.ts +2 -2
- package/lib/Command/Dev.d.ts.map +1 -1
- package/lib/Command/Dev.js +51 -73
- package/lib/Command/Dev.js.map +1 -1
- package/lib/Command/Exec.d.ts +11 -2
- package/lib/Command/Exec.d.ts.map +1 -1
- package/lib/Command/Exec.js +9 -0
- package/lib/Command/Exec.js.map +1 -1
- package/lib/Command/Memo.d.ts +9 -1
- package/lib/Command/Memo.d.ts.map +1 -1
- package/lib/Command/Memo.js +14 -2
- package/lib/Command/Memo.js.map +1 -1
- package/lib/Command/Providers.d.ts +1 -1
- package/lib/Command/Providers.d.ts.map +1 -1
- package/lib/Command/Redaction.d.ts +10 -0
- package/lib/Command/Redaction.d.ts.map +1 -0
- package/lib/Command/Redaction.js +119 -0
- package/lib/Command/Redaction.js.map +1 -0
- package/lib/Deploy.d.ts +2 -1
- package/lib/Deploy.d.ts.map +1 -1
- package/lib/Destroy.d.ts +2 -1
- package/lib/Destroy.d.ts.map +1 -1
- package/lib/Destroy.js +1 -9
- package/lib/Destroy.js.map +1 -1
- package/lib/Docker/Container.d.ts +15 -1
- package/lib/Docker/Container.d.ts.map +1 -1
- package/lib/Docker/Container.js +34 -11
- package/lib/Docker/Container.js.map +1 -1
- package/lib/Docker/Context.d.ts +84 -0
- package/lib/Docker/Context.d.ts.map +1 -0
- package/lib/Docker/Context.js +145 -0
- package/lib/Docker/Context.js.map +1 -0
- package/lib/Docker/Docker.d.ts +190 -14
- package/lib/Docker/Docker.d.ts.map +1 -1
- package/lib/Docker/Docker.js +149 -28
- package/lib/Docker/Docker.js.map +1 -1
- package/lib/Docker/Image.d.ts +12 -0
- package/lib/Docker/Image.d.ts.map +1 -1
- package/lib/Docker/Image.js +24 -7
- package/lib/Docker/Image.js.map +1 -1
- package/lib/Docker/Network.d.ts +7 -0
- package/lib/Docker/Network.d.ts.map +1 -1
- package/lib/Docker/Network.js +16 -7
- package/lib/Docker/Network.js.map +1 -1
- package/lib/Docker/Providers.d.ts +1 -1
- package/lib/Docker/Providers.d.ts.map +1 -1
- package/lib/Docker/Providers.js +13 -1
- package/lib/Docker/Providers.js.map +1 -1
- package/lib/Docker/RemoteImage.d.ts +12 -0
- package/lib/Docker/RemoteImage.d.ts.map +1 -1
- package/lib/Docker/RemoteImage.js +22 -8
- package/lib/Docker/RemoteImage.js.map +1 -1
- package/lib/Docker/Service.d.ts +445 -0
- package/lib/Docker/Service.d.ts.map +1 -0
- package/lib/Docker/Service.js +578 -0
- package/lib/Docker/Service.js.map +1 -0
- package/lib/Docker/ServiceImage.d.ts +78 -0
- package/lib/Docker/ServiceImage.d.ts.map +1 -0
- package/lib/Docker/ServiceImage.js +232 -0
- package/lib/Docker/ServiceImage.js.map +1 -0
- package/lib/Docker/Swarm.d.ts +117 -0
- package/lib/Docker/Swarm.d.ts.map +1 -0
- package/lib/Docker/Swarm.js +149 -0
- package/lib/Docker/Swarm.js.map +1 -0
- package/lib/Docker/Volume.d.ts +11 -0
- package/lib/Docker/Volume.d.ts.map +1 -1
- package/lib/Docker/Volume.js +21 -6
- package/lib/Docker/Volume.js.map +1 -1
- package/lib/Docker/index.d.ts +3 -0
- package/lib/Docker/index.d.ts.map +1 -1
- package/lib/Docker/index.js +3 -0
- package/lib/Docker/index.js.map +1 -1
- package/lib/Http.d.ts +8 -1
- package/lib/Http.d.ts.map +1 -1
- package/lib/Http.js +7 -2
- package/lib/Http.js.map +1 -1
- package/lib/Local/LocalProvider.d.ts +182 -0
- package/lib/Local/LocalProvider.d.ts.map +1 -0
- package/lib/Local/LocalProvider.js +226 -0
- package/lib/Local/LocalProvider.js.map +1 -0
- package/lib/Local/ProviderLayer.d.ts +43 -2
- package/lib/Local/ProviderLayer.d.ts.map +1 -1
- package/lib/Local/ProviderLayer.js +80 -2
- package/lib/Local/ProviderLayer.js.map +1 -1
- package/lib/Local/RpcProvider.d.ts +7 -0
- package/lib/Local/RpcProvider.d.ts.map +1 -1
- package/lib/Local/RpcProvider.js +8 -3
- package/lib/Local/RpcProvider.js.map +1 -1
- package/lib/Local/RpcProviderProxy.d.ts.map +1 -1
- package/lib/Local/RpcProviderProxy.js +3 -0
- package/lib/Local/RpcProviderProxy.js.map +1 -1
- package/lib/Local/RpcServer.d.ts +8 -1
- package/lib/Local/RpcServer.d.ts.map +1 -1
- package/lib/Local/RpcServer.js +4 -1
- package/lib/Local/RpcServer.js.map +1 -1
- package/lib/Plan.d.ts +34 -0
- package/lib/Plan.d.ts.map +1 -1
- package/lib/Plan.js +127 -40
- package/lib/Plan.js.map +1 -1
- package/lib/Planetscale/AuthProvider.d.ts.map +1 -1
- package/lib/Planetscale/AuthProvider.js +6 -2
- package/lib/Planetscale/AuthProvider.js.map +1 -1
- package/lib/Planetscale/Branch.d.ts.map +1 -1
- package/lib/Planetscale/Branch.js +36 -6
- package/lib/Planetscale/Branch.js.map +1 -1
- package/lib/Planetscale/MySQL/MySQLDatabase.d.ts.map +1 -1
- package/lib/Planetscale/MySQL/MySQLDatabase.js +31 -6
- package/lib/Planetscale/MySQL/MySQLDatabase.js.map +1 -1
- package/lib/Planetscale/OAuthClient.d.ts +7 -1
- package/lib/Planetscale/OAuthClient.d.ts.map +1 -1
- package/lib/Planetscale/OAuthClient.js +51 -4
- package/lib/Planetscale/OAuthClient.js.map +1 -1
- package/lib/Planetscale/Postgres/PostgresDatabase.d.ts.map +1 -1
- package/lib/Planetscale/Postgres/PostgresDatabase.js +30 -5
- package/lib/Planetscale/Postgres/PostgresDatabase.js.map +1 -1
- package/lib/Platform.d.ts.map +1 -1
- package/lib/Platform.js +25 -14
- package/lib/Platform.js.map +1 -1
- package/lib/Prisma/App.d.ts +93 -0
- package/lib/Prisma/App.d.ts.map +1 -0
- package/lib/Prisma/App.js +251 -0
- package/lib/Prisma/App.js.map +1 -0
- package/lib/Prisma/AuthProvider.d.ts +28 -0
- package/lib/Prisma/AuthProvider.d.ts.map +1 -0
- package/lib/Prisma/AuthProvider.js +131 -0
- package/lib/Prisma/AuthProvider.js.map +1 -0
- package/lib/Prisma/Branch.d.ts +96 -0
- package/lib/Prisma/Branch.d.ts.map +1 -0
- package/lib/Prisma/Branch.js +236 -0
- package/lib/Prisma/Branch.js.map +1 -0
- package/lib/Prisma/Client.d.ts +178 -0
- package/lib/Prisma/Client.d.ts.map +1 -0
- package/lib/Prisma/Client.js +562 -0
- package/lib/Prisma/Client.js.map +1 -0
- package/lib/Prisma/Compute.d.ts +585 -0
- package/lib/Prisma/Compute.d.ts.map +1 -0
- package/lib/Prisma/Compute.js +1545 -0
- package/lib/Prisma/Compute.js.map +1 -0
- package/lib/Prisma/ComputeArchive.d.ts +63 -0
- package/lib/Prisma/ComputeArchive.d.ts.map +1 -0
- package/lib/Prisma/ComputeArchive.js +227 -0
- package/lib/Prisma/ComputeArchive.js.map +1 -0
- package/lib/Prisma/ComputeBuild.d.ts +106 -0
- package/lib/Prisma/ComputeBuild.d.ts.map +1 -0
- package/lib/Prisma/ComputeBuild.js +987 -0
- package/lib/Prisma/ComputeBuild.js.map +1 -0
- package/lib/Prisma/ComputeLifecycle.d.ts +84 -0
- package/lib/Prisma/ComputeLifecycle.d.ts.map +1 -0
- package/lib/Prisma/ComputeLifecycle.js +186 -0
- package/lib/Prisma/ComputeLifecycle.js.map +1 -0
- package/lib/Prisma/Connect.d.ts +122 -0
- package/lib/Prisma/Connect.d.ts.map +1 -0
- package/lib/Prisma/Connect.js +187 -0
- package/lib/Prisma/Connect.js.map +1 -0
- package/lib/Prisma/Connection.d.ts +219 -0
- package/lib/Prisma/Connection.d.ts.map +1 -0
- package/lib/Prisma/Connection.js +360 -0
- package/lib/Prisma/Connection.js.map +1 -0
- package/lib/Prisma/CustomDomain.d.ts +91 -0
- package/lib/Prisma/CustomDomain.d.ts.map +1 -0
- package/lib/Prisma/CustomDomain.js +184 -0
- package/lib/Prisma/CustomDomain.js.map +1 -0
- package/lib/Prisma/Database.d.ts +222 -0
- package/lib/Prisma/Database.d.ts.map +1 -0
- package/lib/Prisma/Database.js +418 -0
- package/lib/Prisma/Database.js.map +1 -0
- package/lib/Prisma/Deployment.d.ts +141 -0
- package/lib/Prisma/Deployment.d.ts.map +1 -0
- package/lib/Prisma/Deployment.js +353 -0
- package/lib/Prisma/Deployment.js.map +1 -0
- package/lib/Prisma/EnvironmentVariable.d.ts +105 -0
- package/lib/Prisma/EnvironmentVariable.d.ts.map +1 -0
- package/lib/Prisma/EnvironmentVariable.js +229 -0
- package/lib/Prisma/EnvironmentVariable.js.map +1 -0
- package/lib/Prisma/Internal/AppIdentity.d.ts +10 -0
- package/lib/Prisma/Internal/AppIdentity.d.ts.map +1 -0
- package/lib/Prisma/Internal/AppIdentity.js +6 -0
- package/lib/Prisma/Internal/AppIdentity.js.map +1 -0
- package/lib/Prisma/Internal/AppPromotion.d.ts +19 -0
- package/lib/Prisma/Internal/AppPromotion.d.ts.map +1 -0
- package/lib/Prisma/Internal/AppPromotion.js +107 -0
- package/lib/Prisma/Internal/AppPromotion.js.map +1 -0
- package/lib/Prisma/Internal/ArchivePlatform.d.ts +42 -0
- package/lib/Prisma/Internal/ArchivePlatform.d.ts.map +1 -0
- package/lib/Prisma/Internal/ArchivePlatform.js +214 -0
- package/lib/Prisma/Internal/ArchivePlatform.js.map +1 -0
- package/lib/Prisma/Internal/ArtifactFile.d.ts +58 -0
- package/lib/Prisma/Internal/ArtifactFile.d.ts.map +1 -0
- package/lib/Prisma/Internal/ArtifactFile.js +134 -0
- package/lib/Prisma/Internal/ArtifactFile.js.map +1 -0
- package/lib/Prisma/Internal/ArtifactUpload.d.ts +5 -0
- package/lib/Prisma/Internal/ArtifactUpload.d.ts.map +1 -0
- package/lib/Prisma/Internal/ArtifactUpload.js +51 -0
- package/lib/Prisma/Internal/ArtifactUpload.js.map +1 -0
- package/lib/Prisma/Internal/BundlePaths.d.ts +4 -0
- package/lib/Prisma/Internal/BundlePaths.d.ts.map +1 -0
- package/lib/Prisma/Internal/BundlePaths.js +16 -0
- package/lib/Prisma/Internal/BundlePaths.js.map +1 -0
- package/lib/Prisma/Internal/CleanupFailure.d.ts +8 -0
- package/lib/Prisma/Internal/CleanupFailure.d.ts.map +1 -0
- package/lib/Prisma/Internal/CleanupFailure.js +8 -0
- package/lib/Prisma/Internal/CleanupFailure.js.map +1 -0
- package/lib/Prisma/Internal/DatabaseSecrets.d.ts +35 -0
- package/lib/Prisma/Internal/DatabaseSecrets.d.ts.map +1 -0
- package/lib/Prisma/Internal/DatabaseSecrets.js +85 -0
- package/lib/Prisma/Internal/DatabaseSecrets.js.map +1 -0
- package/lib/Prisma/Internal/DeploymentActions.d.ts +5 -0
- package/lib/Prisma/Internal/DeploymentActions.d.ts.map +1 -0
- package/lib/Prisma/Internal/DeploymentActions.js +16 -0
- package/lib/Prisma/Internal/DeploymentActions.js.map +1 -0
- package/lib/Prisma/Internal/DeploymentIdentity.d.ts +8 -0
- package/lib/Prisma/Internal/DeploymentIdentity.d.ts.map +1 -0
- package/lib/Prisma/Internal/DeploymentIdentity.js +12 -0
- package/lib/Prisma/Internal/DeploymentIdentity.js.map +1 -0
- package/lib/Prisma/Internal/DeploymentObserve.d.ts +3 -0
- package/lib/Prisma/Internal/DeploymentObserve.d.ts.map +1 -0
- package/lib/Prisma/Internal/DeploymentObserve.js +2 -0
- package/lib/Prisma/Internal/DeploymentObserve.js.map +1 -0
- package/lib/Prisma/Internal/EnvName.d.ts +7 -0
- package/lib/Prisma/Internal/EnvName.d.ts.map +1 -0
- package/lib/Prisma/Internal/EnvName.js +23 -0
- package/lib/Prisma/Internal/EnvName.js.map +1 -0
- package/lib/Prisma/Internal/HttpClient.d.ts +21 -0
- package/lib/Prisma/Internal/HttpClient.d.ts.map +1 -0
- package/lib/Prisma/Internal/HttpClient.js +23 -0
- package/lib/Prisma/Internal/HttpClient.js.map +1 -0
- package/lib/Prisma/Operations.d.ts +143 -0
- package/lib/Prisma/Operations.d.ts.map +1 -0
- package/lib/Prisma/Operations.js +75 -0
- package/lib/Prisma/Operations.js.map +1 -0
- package/lib/Prisma/Postgres.d.ts +25 -0
- package/lib/Prisma/Postgres.d.ts.map +1 -0
- package/lib/Prisma/Postgres.js +24 -0
- package/lib/Prisma/Postgres.js.map +1 -0
- package/lib/Prisma/PostgresOrigin.d.ts +31 -0
- package/lib/Prisma/PostgresOrigin.d.ts.map +1 -0
- package/lib/Prisma/PostgresOrigin.js +30 -0
- package/lib/Prisma/PostgresOrigin.js.map +1 -0
- package/lib/Prisma/PrismaDevDatabase.d.ts +25 -0
- package/lib/Prisma/PrismaDevDatabase.d.ts.map +1 -0
- package/lib/Prisma/PrismaDevDatabase.js +280 -0
- package/lib/Prisma/PrismaDevDatabase.js.map +1 -0
- package/lib/Prisma/PrismaEnvironment.d.ts +14 -0
- package/lib/Prisma/PrismaEnvironment.d.ts.map +1 -0
- package/lib/Prisma/PrismaEnvironment.js +50 -0
- package/lib/Prisma/PrismaEnvironment.js.map +1 -0
- package/lib/Prisma/PrismaLogs.d.ts +42 -0
- package/lib/Prisma/PrismaLogs.d.ts.map +1 -0
- package/lib/Prisma/PrismaLogs.js +318 -0
- package/lib/Prisma/PrismaLogs.js.map +1 -0
- package/lib/Prisma/Project.d.ts +123 -0
- package/lib/Prisma/Project.d.ts.map +1 -0
- package/lib/Prisma/Project.js +366 -0
- package/lib/Prisma/Project.js.map +1 -0
- package/lib/Prisma/Providers.d.ts +63 -0
- package/lib/Prisma/Providers.d.ts.map +1 -0
- package/lib/Prisma/Providers.js +306 -0
- package/lib/Prisma/Providers.js.map +1 -0
- package/lib/Prisma/Refs.d.ts +19 -0
- package/lib/Prisma/Refs.d.ts.map +1 -0
- package/lib/Prisma/Refs.js +25 -0
- package/lib/Prisma/Refs.js.map +1 -0
- package/lib/Prisma/SourceRepository.d.ts +127 -0
- package/lib/Prisma/SourceRepository.d.ts.map +1 -0
- package/lib/Prisma/SourceRepository.js +239 -0
- package/lib/Prisma/SourceRepository.js.map +1 -0
- package/lib/Prisma/Types.d.ts +539 -0
- package/lib/Prisma/Types.d.ts.map +1 -0
- package/lib/Prisma/Types.js +13 -0
- package/lib/Prisma/Types.js.map +1 -0
- package/lib/Prisma/index.d.ts +25 -0
- package/lib/Prisma/index.d.ts.map +1 -0
- package/lib/Prisma/index.js +24 -0
- package/lib/Prisma/index.js.map +1 -0
- package/lib/Provider.d.ts +57 -5
- package/lib/Provider.d.ts.map +1 -1
- package/lib/Provider.js +54 -30
- package/lib/Provider.js.map +1 -1
- package/lib/ProviderMode.d.ts +93 -0
- package/lib/ProviderMode.d.ts.map +1 -0
- package/lib/ProviderMode.js +77 -0
- package/lib/ProviderMode.js.map +1 -0
- package/lib/Resource.d.ts +8 -0
- package/lib/Resource.d.ts.map +1 -1
- package/lib/Resource.js +31 -0
- package/lib/Resource.js.map +1 -1
- package/lib/RuntimeContext.d.ts +7 -0
- package/lib/RuntimeContext.d.ts.map +1 -1
- package/lib/RuntimeContext.js.map +1 -1
- package/lib/Server/Process.d.ts +8 -0
- package/lib/Server/Process.d.ts.map +1 -1
- package/lib/Server/Process.js +29 -0
- package/lib/Server/Process.js.map +1 -1
- package/lib/State/InMemoryState.d.ts.map +1 -1
- package/lib/State/InMemoryState.js +2 -0
- package/lib/State/InMemoryState.js.map +1 -1
- package/lib/State/ResourceState.d.ts +18 -0
- package/lib/State/ResourceState.d.ts.map +1 -1
- package/lib/Sync.d.ts.map +1 -1
- package/lib/Sync.js +8 -2
- package/lib/Sync.js.map +1 -1
- package/lib/Telemetry.d.ts +150 -0
- package/lib/Telemetry.d.ts.map +1 -0
- package/lib/Telemetry.js +512 -0
- package/lib/Telemetry.js.map +1 -0
- package/lib/Test/Alchemy.d.ts.map +1 -1
- package/lib/Test/Alchemy.js +3 -1
- package/lib/Test/Alchemy.js.map +1 -1
- package/lib/Test/Core.d.ts +2 -2
- package/lib/Test/Core.d.ts.map +1 -1
- package/lib/Test/Core.js +1 -8
- package/lib/Test/Core.js.map +1 -1
- package/lib/Util/Clank.d.ts +11 -6
- package/lib/Util/Clank.d.ts.map +1 -1
- package/lib/Util/Clank.js +22 -9
- package/lib/Util/Clank.js.map +1 -1
- package/lib/Util/zip.d.ts +11 -0
- package/lib/Util/zip.d.ts.map +1 -1
- package/lib/Util/zip.js +30 -0
- package/lib/Util/zip.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/package.json +46 -13
- package/src/AWS/ApiGateway/common.ts +9 -0
- package/src/AWS/Bedrock/LanguageModel.ts +883 -0
- package/src/AWS/Bedrock/LanguageModelHttp.ts +36 -0
- package/src/AWS/Bedrock/index.ts +2 -0
- package/src/AWS/CloudFront/Distribution.ts +116 -6
- package/src/AWS/CostExplorer/common.ts +23 -2
- package/src/AWS/DataSync/Task.ts +30 -15
- package/src/AWS/EC2/Vpc.ts +35 -21
- package/src/AWS/EC2/hosted.ts +10 -2
- package/src/AWS/ECR/ImageSource.ts +10 -2
- package/src/AWS/ECR/Repository.ts +39 -4
- package/src/AWS/ECS/Service.ts +322 -22
- package/src/AWS/ECS/Task.ts +82 -32
- package/src/AWS/EKS/Deployment.ts +10 -2
- package/src/AWS/EKS/Job.ts +10 -2
- package/src/AWS/Lambda/Function.ts +101 -43
- package/src/AWS/Lambda/HttpServer.ts +7 -1
- package/src/AWS/Lambda/LayerVersion.ts +490 -0
- package/src/AWS/Lambda/MicrovmBundle.ts +10 -2
- package/src/AWS/Lambda/index.ts +1 -0
- package/src/AWS/Providers.ts +10 -0
- package/src/AWS/SES/ActiveReceiptRuleSet.ts +88 -0
- package/src/AWS/SES/ReceiptFilter.ts +169 -0
- package/src/AWS/SES/ReceiptRule.ts +300 -0
- package/src/AWS/SES/ReceiptRuleSet.ts +164 -0
- package/src/AWS/SES/SendBounce.ts +44 -0
- package/src/AWS/SES/SendBounceHttp.ts +13 -0
- package/src/AWS/SES/index.ts +6 -0
- package/src/AWS/StateStore/State.ts +159 -42
- package/src/Apply.ts +199 -83
- package/src/Axiom/Telemetry.ts +119 -0
- package/src/Axiom/index.ts +1 -0
- package/src/Bundle/Bundle.ts +17 -7
- package/src/Bundle/BundleAnalyzerPlugin.ts +9 -4
- package/src/Bundle/PurePlugin.ts +19 -9
- package/src/Cli/checkVersion.ts +102 -16
- package/src/Cli/commands/_shared.ts +2 -0
- package/src/Cli/commands/deploy.ts +3 -14
- package/src/Cli/commands/logs.ts +6 -1
- package/src/Cli/commands/tail.ts +6 -1
- package/src/Cli/main.ts +5 -4
- package/src/Cloudflare/AI/Search.ts +4 -18
- package/src/Cloudflare/AI/SearchInstance.ts +7 -26
- package/src/Cloudflare/ApiToken/AccountApiToken.ts +3 -0
- package/src/Cloudflare/Auth/AuthProvider.ts +17 -3
- package/src/Cloudflare/Auth/OAuthClient.ts +58 -2
- package/src/Cloudflare/Containers/Container.ts +92 -3
- package/src/Cloudflare/Containers/ContainerApplication.ts +31 -5
- package/src/Cloudflare/Containers/ContainerBundle.ts +10 -2
- package/src/Cloudflare/Containers/ContainerProvider.ts +62 -0
- package/src/Cloudflare/Credentials.ts +69 -9
- package/src/Cloudflare/D1/ApplyMigrations.ts +72 -77
- package/src/Cloudflare/D1/Database.ts +169 -2
- package/src/Cloudflare/D1/LocalD1Gateway.ts +150 -0
- package/src/Cloudflare/D1/QueryDatabaseHttpClient.ts +49 -11
- package/src/Cloudflare/D1/QueryDatabaseLocal.ts +44 -2
- package/src/Cloudflare/DNS/Record.ts +30 -4
- package/src/Cloudflare/Email/Address.ts +18 -1
- package/src/Cloudflare/Email/SendBinding.ts +1 -0
- package/src/Cloudflare/Email/SendEmail.ts +13 -0
- package/src/Cloudflare/Flagship/App.ts +18 -6
- package/src/Cloudflare/KV/LocalKVGateway.ts +86 -0
- package/src/Cloudflare/KV/Namespace.ts +47 -1
- package/src/Cloudflare/KV/NamespaceLocal.ts +29 -6
- package/src/Cloudflare/KV/ReadNamespaceLocal.ts +5 -1
- package/src/Cloudflare/KV/ReadWriteNamespaceLocal.ts +5 -1
- package/src/Cloudflare/KV/WriteNamespaceLocal.ts +5 -1
- package/src/Cloudflare/LocalGateway.ts +86 -0
- package/src/Cloudflare/LocalRuntime.ts +21 -1
- package/src/Cloudflare/Logs.ts +58 -28
- package/src/Cloudflare/Providers.ts +4 -2
- package/src/Cloudflare/Queues/Consumer.ts +70 -2
- package/src/Cloudflare/Queues/Queue.ts +7 -16
- package/src/Cloudflare/Queues/QueueBinding.ts +21 -0
- package/src/Cloudflare/Queues/QueueShim.ts +193 -0
- package/src/Cloudflare/R2/Bucket.ts +55 -1
- package/src/Cloudflare/R2/BucketBinding.ts +17 -3
- package/src/Cloudflare/R2/BucketLocal.ts +25 -8
- package/src/Cloudflare/R2/LocalR2Gateway.ts +84 -0
- package/src/Cloudflare/R2/ReadBucketLocal.ts +7 -1
- package/src/Cloudflare/R2/ReadWriteBucketLocal.ts +7 -1
- package/src/Cloudflare/R2/WriteBucketLocal.ts +7 -1
- package/src/Cloudflare/Ruleset/AccountEntrypoint.ts +5 -1
- package/src/Cloudflare/Ruleset/Ruleset.ts +20 -6
- package/src/Cloudflare/Rum/Site.ts +11 -4
- package/src/Cloudflare/StateStore/Api.ts +1 -1
- package/src/Cloudflare/Tunnel/Tunnel.ts +23 -1
- package/src/Cloudflare/Website/StaticSite.ts +117 -28
- package/src/Cloudflare/Website/Vite.ts +33 -19
- package/src/Cloudflare/Workers/Compatibility.ts +27 -7
- package/src/Cloudflare/Workers/DurableObject.ts +22 -0
- package/src/Cloudflare/Workers/DurableObjectBridge.ts +29 -10
- package/src/Cloudflare/Workers/InferEnv.ts +74 -59
- package/src/Cloudflare/Workers/LocalWorkerProvider.ts +619 -401
- package/src/Cloudflare/Workers/Worker.ts +676 -28
- package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +209 -25
- package/src/Cloudflare/Workers/WorkerBinding.ts +67 -3
- package/src/Cloudflare/Workers/WorkerBridge.ts +26 -4
- package/src/Cloudflare/Workers/WorkerBundle.ts +6 -1
- package/src/Cloudflare/Workers/WorkerProvider.ts +2269 -277
- package/src/Cloudflare/Workflows/WorkflowBridge.ts +31 -13
- package/src/Command/Build.ts +8 -8
- package/src/Command/Command.ts +217 -42
- package/src/Command/Dev.ts +79 -107
- package/src/Command/Exec.ts +11 -2
- package/src/Command/Memo.ts +27 -3
- package/src/Command/Redaction.ts +181 -0
- package/src/Destroy.ts +1 -10
- package/src/Docker/Container.ts +55 -15
- package/src/Docker/Context.ts +236 -0
- package/src/Docker/Docker.ts +393 -43
- package/src/Docker/Image.ts +28 -7
- package/src/Docker/Network.ts +38 -14
- package/src/Docker/Providers.ts +16 -1
- package/src/Docker/RemoteImage.ts +23 -7
- package/src/Docker/Service.ts +1119 -0
- package/src/Docker/ServiceImage.ts +331 -0
- package/src/Docker/Swarm.ts +226 -0
- package/src/Docker/Volume.ts +25 -6
- package/src/Docker/index.ts +3 -0
- package/src/Http.ts +15 -2
- package/src/Local/LocalProvider.ts +518 -0
- package/src/Local/ProviderLayer.ts +113 -11
- package/src/Local/RpcProvider.ts +10 -5
- package/src/Local/RpcProviderProxy.ts +4 -1
- package/src/Local/RpcServer.ts +20 -2
- package/src/Plan.ts +182 -54
- package/src/Planetscale/AuthProvider.ts +15 -2
- package/src/Planetscale/Branch.ts +39 -6
- package/src/Planetscale/MySQL/MySQLDatabase.ts +34 -6
- package/src/Planetscale/OAuthClient.ts +59 -3
- package/src/Planetscale/Postgres/PostgresDatabase.ts +33 -5
- package/src/Platform.ts +29 -17
- package/src/Prisma/App.ts +433 -0
- package/src/Prisma/AuthProvider.ts +260 -0
- package/src/Prisma/Branch.ts +417 -0
- package/src/Prisma/Client.ts +1337 -0
- package/src/Prisma/Compute.ts +2878 -0
- package/src/Prisma/ComputeArchive.ts +432 -0
- package/src/Prisma/ComputeBuild.ts +1652 -0
- package/src/Prisma/ComputeLifecycle.ts +391 -0
- package/src/Prisma/Connect.ts +433 -0
- package/src/Prisma/Connection.ts +643 -0
- package/src/Prisma/CustomDomain.ts +373 -0
- package/src/Prisma/Database.ts +850 -0
- package/src/Prisma/Deployment.ts +661 -0
- package/src/Prisma/EnvironmentVariable.ts +417 -0
- package/src/Prisma/Internal/AppIdentity.ts +19 -0
- package/src/Prisma/Internal/AppPromotion.ts +172 -0
- package/src/Prisma/Internal/ArchivePlatform.ts +320 -0
- package/src/Prisma/Internal/ArtifactFile.ts +242 -0
- package/src/Prisma/Internal/ArtifactUpload.ts +86 -0
- package/src/Prisma/Internal/BundlePaths.ts +28 -0
- package/src/Prisma/Internal/CleanupFailure.ts +17 -0
- package/src/Prisma/Internal/DatabaseSecrets.ts +175 -0
- package/src/Prisma/Internal/DeploymentActions.ts +59 -0
- package/src/Prisma/Internal/DeploymentIdentity.ts +25 -0
- package/src/Prisma/Internal/DeploymentObserve.ts +6 -0
- package/src/Prisma/Internal/EnvName.ts +24 -0
- package/src/Prisma/Internal/HttpClient.ts +30 -0
- package/src/Prisma/Operations.ts +259 -0
- package/src/Prisma/Postgres.ts +25 -0
- package/src/Prisma/PostgresOrigin.ts +52 -0
- package/src/Prisma/PrismaDevDatabase.ts +395 -0
- package/src/Prisma/PrismaEnvironment.ts +89 -0
- package/src/Prisma/PrismaLogs.ts +434 -0
- package/src/Prisma/Project.ts +687 -0
- package/src/Prisma/Providers.ts +471 -0
- package/src/Prisma/Refs.ts +69 -0
- package/src/Prisma/SourceRepository.ts +455 -0
- package/src/Prisma/Types.ts +611 -0
- package/src/Prisma/index.ts +24 -0
- package/src/Provider.ts +155 -39
- package/src/ProviderMode.ts +123 -0
- package/src/Resource.ts +46 -0
- package/src/RuntimeContext.ts +7 -0
- package/src/Server/Process.ts +33 -0
- package/src/State/InMemoryState.ts +2 -0
- package/src/State/ResourceState.ts +18 -0
- package/src/Sync.ts +14 -2
- package/src/Telemetry.ts +736 -0
- package/src/Test/Alchemy.ts +3 -1
- package/src/Test/Core.ts +1 -8
- package/src/Util/Clank.ts +37 -11
- package/src/Util/zip.ts +39 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1,1545 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Duration from "effect/Duration";
|
|
3
|
+
import * as Exit from "effect/Exit";
|
|
4
|
+
import * as FileSystem from "effect/FileSystem";
|
|
5
|
+
import * as Option from "effect/Option";
|
|
6
|
+
import * as Path from "effect/Path";
|
|
7
|
+
import * as Redacted from "effect/Redacted";
|
|
8
|
+
import * as Result from "effect/Result";
|
|
9
|
+
import * as Schedule from "effect/Schedule";
|
|
10
|
+
import * as Stream from "effect/Stream";
|
|
11
|
+
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
12
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
13
|
+
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
|
|
14
|
+
import * as ChildProcess from "effect/unstable/process/ChildProcess";
|
|
15
|
+
import { AlchemyContext } from "../AlchemyContext.js";
|
|
16
|
+
import { Unowned } from "../AdoptPolicy.js";
|
|
17
|
+
import * as Bundle from "../Bundle/Bundle.js";
|
|
18
|
+
import { findCwdForBundle } from "../Bundle/TempRoot.js";
|
|
19
|
+
import { createPhysicalName } from "../PhysicalName.js";
|
|
20
|
+
import { isResolved } from "../Diff.js";
|
|
21
|
+
import { HttpServer } from "../Http.js";
|
|
22
|
+
import * as Output from "../Output.js";
|
|
23
|
+
import { Platform } from "../Platform.js";
|
|
24
|
+
import * as Provider from "../Provider.js";
|
|
25
|
+
import { Resource } from "../Resource.js";
|
|
26
|
+
import { RuntimeContext } from "../RuntimeContext.js";
|
|
27
|
+
import { Self } from "../Self.js";
|
|
28
|
+
import { Stack } from "../Stack.js";
|
|
29
|
+
import { sha256Object } from "../Util/sha256.js";
|
|
30
|
+
import { PrismaApiError, PrismaClient, isNotFound, } from "./Client.js";
|
|
31
|
+
import { runBuildCommand, runComputeAutoBuild, } from "./ComputeBuild.js";
|
|
32
|
+
import { createComputeArchive, normalizeEntrypoint } from "./ComputeArchive.js";
|
|
33
|
+
import { destroyApp, destroyDeployment, isConflict, toDeploymentUrl, waitForDeploymentStatus, } from "./ComputeLifecycle.js";
|
|
34
|
+
import { startDeploymentIdempotent, stopDeploymentIdempotent, } from "./Internal/DeploymentActions.js";
|
|
35
|
+
import { ensureAppImmutableIdentity } from "./Internal/AppIdentity.js";
|
|
36
|
+
import { promoteAppObserved, waitForAppDeploymentTarget, } from "./Internal/AppPromotion.js";
|
|
37
|
+
import { normalizeBundleFilePath } from "./Internal/BundlePaths.js";
|
|
38
|
+
import { aggregateCleanupFailure } from "./Internal/CleanupFailure.js";
|
|
39
|
+
import { ensureDeploymentMembership } from "./Internal/DeploymentIdentity.js";
|
|
40
|
+
import { observeDeployment } from "./Internal/DeploymentObserve.js";
|
|
41
|
+
import { tailDeploymentLogs } from "./PrismaLogs.js";
|
|
42
|
+
import { concreteIdsChanged, isInputObject, isPrismaDevId, resolveProjectId, unresolvedProjectIdOf, } from "./Refs.js";
|
|
43
|
+
import { readUploadArtifact, uploadArtifact } from "./Deployment.js";
|
|
44
|
+
const ComputeTypeId = "Prisma.Compute";
|
|
45
|
+
export const isCompute = (value) => typeof value === "object" &&
|
|
46
|
+
value !== null &&
|
|
47
|
+
"Type" in value &&
|
|
48
|
+
value.Type === ComputeTypeId;
|
|
49
|
+
const hasEffectNativeComputeInput = (props) => props.isExternal !== true &&
|
|
50
|
+
(props.main !== undefined || props.exports !== undefined);
|
|
51
|
+
const isEffectNativeCompute = (props) => hasEffectNativeComputeInput(props);
|
|
52
|
+
/**
|
|
53
|
+
* Build and deploy an application to Prisma Compute.
|
|
54
|
+
*
|
|
55
|
+
* Prisma's create-deployment API exposes neither an idempotency key nor a
|
|
56
|
+
* caller-defined recovery key. If the API commits a deployment but its create
|
|
57
|
+
* response is lost before Alchemy persists the returned ID, that deployment
|
|
58
|
+
* can remain orphaned and a later deploy may create another one. Alchemy does
|
|
59
|
+
* not guess that the App's latest deployment is owned, because it could belong
|
|
60
|
+
* to another actor. Use a durable, locked state backend and inspect the App's
|
|
61
|
+
* deployment history after an interrupted create.
|
|
62
|
+
*
|
|
63
|
+
* @section Deploying an App
|
|
64
|
+
* @example Deploy a directory with an entrypoint
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const app = yield* Prisma.Compute("api", {
|
|
67
|
+
* project: project.projectId,
|
|
68
|
+
* path: "./apps/api",
|
|
69
|
+
* entrypoint: "server.ts",
|
|
70
|
+
* port: 3000,
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @example Deploy an Effect-native HTTP app
|
|
75
|
+
* ```typescript
|
|
76
|
+
* export default Prisma.Compute(
|
|
77
|
+
* "api",
|
|
78
|
+
* {
|
|
79
|
+
* project,
|
|
80
|
+
* appName: "api",
|
|
81
|
+
* main: import.meta.filename,
|
|
82
|
+
* port: 8080,
|
|
83
|
+
* },
|
|
84
|
+
* Effect.gen(function* () {
|
|
85
|
+
* return {
|
|
86
|
+
* fetch: Effect.succeed(HttpServerResponse.text("ok")),
|
|
87
|
+
* };
|
|
88
|
+
* }),
|
|
89
|
+
* );
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @section Runtime Bindings
|
|
93
|
+
* @example Bind a Prisma Connection
|
|
94
|
+
* ```typescript
|
|
95
|
+
* export default Prisma.Compute(
|
|
96
|
+
* "api",
|
|
97
|
+
* {
|
|
98
|
+
* project,
|
|
99
|
+
* appName: "api",
|
|
100
|
+
* main: import.meta.filename,
|
|
101
|
+
* },
|
|
102
|
+
* Effect.gen(function* () {
|
|
103
|
+
* const db = yield* Prisma.Connect(connection);
|
|
104
|
+
* const sql = yield* SQL.Postgres({ url: db.databaseUrl });
|
|
105
|
+
*
|
|
106
|
+
* return {
|
|
107
|
+
* fetch: Effect.gen(function* () {
|
|
108
|
+
* const users = yield* sql`SELECT * FROM users`;
|
|
109
|
+
* return yield* HttpServerResponse.json(users);
|
|
110
|
+
* }),
|
|
111
|
+
* };
|
|
112
|
+
* }).pipe(Effect.provide(Prisma.ConnectBinding)),
|
|
113
|
+
* );
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* @example Build before upload and replace old versions
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const app = yield* Prisma.Compute("api", {
|
|
119
|
+
* project: project.projectId,
|
|
120
|
+
* path: "./apps/api",
|
|
121
|
+
* build: {
|
|
122
|
+
* command: "bun build src/server.ts --target bun --outdir dist",
|
|
123
|
+
* outdir: "dist",
|
|
124
|
+
* entrypoint: "server.js",
|
|
125
|
+
* },
|
|
126
|
+
* port: 8080,
|
|
127
|
+
* env: {
|
|
128
|
+
* // Use this for a standalone Connection. A project's default database
|
|
129
|
+
* // is injected by Prisma without an explicit DATABASE_URL entry.
|
|
130
|
+
* DATABASE_URL: connection.databaseUrl,
|
|
131
|
+
* },
|
|
132
|
+
* destroyOldDeployment: true,
|
|
133
|
+
* });
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @example Auto-build a framework app
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const app = yield* Prisma.Compute("api", {
|
|
139
|
+
* project: project.projectId,
|
|
140
|
+
* path: "./apps/web",
|
|
141
|
+
* build: "auto",
|
|
142
|
+
* destroyOldDeployment: true,
|
|
143
|
+
* });
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example Deploy a prebuilt tar.gz artifact
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const app = yield* Prisma.Compute("api", {
|
|
149
|
+
* project: project.projectId,
|
|
150
|
+
* artifactPath: "./dist/app.tar.gz",
|
|
151
|
+
* port: 8080,
|
|
152
|
+
* });
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* @section Deployment Health
|
|
156
|
+
* @example Require application readiness before promotion
|
|
157
|
+
* ```typescript
|
|
158
|
+
* const app = yield* Prisma.Compute("api", {
|
|
159
|
+
* project,
|
|
160
|
+
* path: "./apps/api",
|
|
161
|
+
* entrypoint: "server.ts",
|
|
162
|
+
* healthCheck: {
|
|
163
|
+
* path: "/api/health",
|
|
164
|
+
* // Defaults to any 2xx response when omitted.
|
|
165
|
+
* statusCodes: [200, 204],
|
|
166
|
+
* },
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @section Local Development
|
|
171
|
+
* @example Run locally during alchemy dev
|
|
172
|
+
* ```typescript
|
|
173
|
+
* const app = yield* Prisma.Compute("api", {
|
|
174
|
+
* project: project.projectId,
|
|
175
|
+
* path: "./apps/api",
|
|
176
|
+
* entrypoint: "server.ts",
|
|
177
|
+
* dev: {
|
|
178
|
+
* command: "bun run dev",
|
|
179
|
+
* port: 3000,
|
|
180
|
+
* },
|
|
181
|
+
* });
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @resource
|
|
185
|
+
*/
|
|
186
|
+
export const Compute = Platform(ComputeTypeId, {
|
|
187
|
+
createRuntimeContext: (id) => {
|
|
188
|
+
const runners = [];
|
|
189
|
+
const env = {};
|
|
190
|
+
let runtimeContext;
|
|
191
|
+
const run = (effect) => Effect.sync(() => {
|
|
192
|
+
runners.push(effect);
|
|
193
|
+
});
|
|
194
|
+
const serve = (handler) => Effect.sync(() => {
|
|
195
|
+
runners.push(Effect.gen(function* () {
|
|
196
|
+
const httpServer = yield* Effect.serviceOption(HttpServer).pipe(Effect.map(Option.getOrUndefined));
|
|
197
|
+
if (httpServer) {
|
|
198
|
+
yield* httpServer.serve(handler.pipe(Effect.provideService(RuntimeContext, runtimeContext)));
|
|
199
|
+
yield* Effect.never;
|
|
200
|
+
}
|
|
201
|
+
}).pipe(Effect.catch((error) => Effect.die(error))));
|
|
202
|
+
});
|
|
203
|
+
runtimeContext = {
|
|
204
|
+
Type: ComputeTypeId,
|
|
205
|
+
id,
|
|
206
|
+
env,
|
|
207
|
+
set: (bindingId, output) => Effect.sync(() => {
|
|
208
|
+
const key = bindingId.replaceAll(/[^a-zA-Z0-9]/g, "_");
|
|
209
|
+
env[key] = output.pipe(Output.map((value) => Redacted.isRedacted(value)
|
|
210
|
+
? Redacted.make(JSON.stringify({
|
|
211
|
+
_tag: "Redacted",
|
|
212
|
+
value: Redacted.value(value),
|
|
213
|
+
}))
|
|
214
|
+
: JSON.stringify(value)));
|
|
215
|
+
return key;
|
|
216
|
+
}),
|
|
217
|
+
get: (key) =>
|
|
218
|
+
// Runtime ConfigProvider lookups call back into RuntimeContext.get.
|
|
219
|
+
// Read the process env directly here to avoid re-entering that path.
|
|
220
|
+
Effect.sync(() => {
|
|
221
|
+
const value = process.env[key];
|
|
222
|
+
if (value === undefined) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const parsed = JSON.parse(value);
|
|
227
|
+
if (parsed !== null &&
|
|
228
|
+
typeof parsed === "object" &&
|
|
229
|
+
parsed._tag === "Redacted" &&
|
|
230
|
+
"value" in parsed) {
|
|
231
|
+
return Redacted.make(parsed.value);
|
|
232
|
+
}
|
|
233
|
+
return parsed;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
}),
|
|
239
|
+
run,
|
|
240
|
+
serve,
|
|
241
|
+
exports: Effect.sync(() => ({
|
|
242
|
+
default: Effect.all(runners.map((effect) => Effect.forever(effect.pipe(Effect.tapError((error) => Effect.logError(error)), Effect.ignore))), { concurrency: "unbounded" }),
|
|
243
|
+
})),
|
|
244
|
+
};
|
|
245
|
+
return runtimeContext;
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const devProcesses = new Map();
|
|
249
|
+
const stopTrackedDevProcess = Effect.fn(function* (processKey) {
|
|
250
|
+
const existing = devProcesses.get(processKey);
|
|
251
|
+
if (!existing)
|
|
252
|
+
return;
|
|
253
|
+
const running = yield* existing.isRunning;
|
|
254
|
+
if (running) {
|
|
255
|
+
// Keep the handle tracked when termination fails so a later reconcile or
|
|
256
|
+
// destroy can retry instead of losing the only reference to the process.
|
|
257
|
+
yield* existing.kill();
|
|
258
|
+
}
|
|
259
|
+
devProcesses.delete(processKey);
|
|
260
|
+
});
|
|
261
|
+
const projectConsistencySchedule = Schedule.max([
|
|
262
|
+
Schedule.exponential(Duration.millis(500)),
|
|
263
|
+
Schedule.recurs(6),
|
|
264
|
+
]);
|
|
265
|
+
const isAppProvisioningNotFound = (error) => error instanceof PrismaApiError &&
|
|
266
|
+
error.status === 404 &&
|
|
267
|
+
(error.path.startsWith("/v1/projects/") ||
|
|
268
|
+
error.path === "/v1/apps" ||
|
|
269
|
+
error.path.startsWith("/v1/apps/"));
|
|
270
|
+
const desiredComputeBranchId = Effect.fn(function* (client, projectId, props) {
|
|
271
|
+
if (props.branchId !== undefined && !isPrismaDevId(props.branchId)) {
|
|
272
|
+
return { resolved: true, id: props.branchId };
|
|
273
|
+
}
|
|
274
|
+
const branches = yield* client.listBranches(projectId, props.branchGitName === undefined
|
|
275
|
+
? { limit: 100 }
|
|
276
|
+
: { gitName: props.branchGitName, limit: 100 });
|
|
277
|
+
const matchingBranches = props.branchGitName === undefined
|
|
278
|
+
? branches.filter((branch) => branch.isDefault)
|
|
279
|
+
: branches;
|
|
280
|
+
if (matchingBranches.length > 1) {
|
|
281
|
+
return yield* Effect.fail(new Error(props.branchGitName === undefined
|
|
282
|
+
? `Prisma returned multiple default branches for project '${projectId}'; refusing an ambiguous Compute App match.`
|
|
283
|
+
: `Prisma returned multiple branches named '${props.branchGitName}' in project '${projectId}'; refusing an ambiguous Compute App match.`));
|
|
284
|
+
}
|
|
285
|
+
const branch = matchingBranches[0];
|
|
286
|
+
return branch
|
|
287
|
+
? { resolved: true, id: branch.id }
|
|
288
|
+
: { resolved: false };
|
|
289
|
+
});
|
|
290
|
+
const createAppName = (id, appName) => appName === undefined ? createPhysicalName({ id }) : Effect.succeed(appName);
|
|
291
|
+
const findApp = Effect.fn(function* (client, projectId, appName, props) {
|
|
292
|
+
const candidates = (yield* client.listApps({
|
|
293
|
+
projectId,
|
|
294
|
+
limit: 100,
|
|
295
|
+
})).filter((app) => app.name === appName);
|
|
296
|
+
if (candidates.length === 0)
|
|
297
|
+
return undefined;
|
|
298
|
+
const branch = yield* desiredComputeBranchId(client, projectId, props);
|
|
299
|
+
if (!branch.resolved)
|
|
300
|
+
return undefined;
|
|
301
|
+
const matches = candidates.filter((app) => app.branchId === branch.id);
|
|
302
|
+
if (matches.length > 1) {
|
|
303
|
+
return yield* Effect.fail(new Error(`Prisma returned multiple Apps named '${appName}' on branch '${branch.id}' in project '${projectId}'; refusing an ambiguous ownership match.`));
|
|
304
|
+
}
|
|
305
|
+
return matches[0];
|
|
306
|
+
});
|
|
307
|
+
const createApp = (client, projectId, props, branchId) => client.createApp({
|
|
308
|
+
projectId,
|
|
309
|
+
displayName: props.appName,
|
|
310
|
+
regionId: props.regionId,
|
|
311
|
+
branchId,
|
|
312
|
+
branchGitName: undefined,
|
|
313
|
+
});
|
|
314
|
+
const plainEnv = (env = {}) => Object.fromEntries(Object.entries(env).flatMap(([key, value]) => value === undefined
|
|
315
|
+
? []
|
|
316
|
+
: [[key, Redacted.isRedacted(value) ? Redacted.value(value) : value]]));
|
|
317
|
+
const persistedArtifactHashValue = (value) => (Redacted.isRedacted(value) ? Redacted.value(value) : value);
|
|
318
|
+
const managedEnvKeys = (env = {}) => Object.entries(plainEnv(env))
|
|
319
|
+
.flatMap(([key, value]) => (value === null ? [] : [key]))
|
|
320
|
+
.sort();
|
|
321
|
+
const ENV_KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
322
|
+
const ENV_VALUE_MAX_BYTES = 8 * 1024;
|
|
323
|
+
const EXPORT_IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
324
|
+
const computeEnvValue = (value) => Redacted.isRedacted(value) ? Redacted.value(value) : value;
|
|
325
|
+
const validateComputeEnvironmentKey = (key) => Effect.gen(function* () {
|
|
326
|
+
if (key.length < 1 || key.length > 256 || !ENV_KEY_PATTERN.test(key)) {
|
|
327
|
+
return yield* Effect.fail(new Error(`Prisma environment variable key '${key}' must match POSIX env-var key shape: [A-Z_][A-Z0-9_]* and be at most 256 characters.`));
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
const validateComputeEnvironmentWrite = (key, value) => Effect.gen(function* () {
|
|
331
|
+
yield* validateComputeEnvironmentKey(key);
|
|
332
|
+
const raw = computeEnvValue(value);
|
|
333
|
+
if (raw.length === 0) {
|
|
334
|
+
return yield* Effect.fail(new Error(`Prisma environment variable '${key}' value must be non-empty.`));
|
|
335
|
+
}
|
|
336
|
+
const byteLength = yield* Effect.sync(() => new TextEncoder().encode(raw).byteLength);
|
|
337
|
+
if (byteLength > ENV_VALUE_MAX_BYTES) {
|
|
338
|
+
return yield* Effect.fail(new Error(`Prisma environment variable '${key}' value exceeds ${ENV_VALUE_MAX_BYTES} bytes.`));
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
const validateComputeHealthCheck = (healthCheck) => Effect.gen(function* () {
|
|
342
|
+
if (healthCheck === undefined)
|
|
343
|
+
return;
|
|
344
|
+
if (!healthCheck.path.startsWith("/") ||
|
|
345
|
+
healthCheck.path.startsWith("//") ||
|
|
346
|
+
healthCheck.path.includes("\\") ||
|
|
347
|
+
/\s/.test(healthCheck.path)) {
|
|
348
|
+
return yield* Effect.fail(new Error("healthCheck.path must be an absolute application path beginning with one '/'."));
|
|
349
|
+
}
|
|
350
|
+
if (healthCheck.statusCodes !== undefined &&
|
|
351
|
+
healthCheck.statusCodes.length === 0) {
|
|
352
|
+
return yield* Effect.fail(new Error("healthCheck.statusCodes must contain at least one status."));
|
|
353
|
+
}
|
|
354
|
+
for (const status of healthCheck.statusCodes ?? []) {
|
|
355
|
+
if (!Number.isInteger(status) || status < 100 || status > 599) {
|
|
356
|
+
return yield* Effect.fail(new Error("healthCheck.statusCodes must contain HTTP status integers from 100 through 599."));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
const validateComputeProps = (props) => Effect.gen(function* () {
|
|
361
|
+
yield* validateComputeHealthCheck(props.healthCheck);
|
|
362
|
+
if (props.healthCheck !== undefined && props.verifyUrl === false) {
|
|
363
|
+
return yield* Effect.fail(new Error("healthCheck cannot be combined with verifyUrl: false."));
|
|
364
|
+
}
|
|
365
|
+
if (props.healthCheck !== undefined && props.start === false) {
|
|
366
|
+
return yield* Effect.fail(new Error("healthCheck requires start to be enabled."));
|
|
367
|
+
}
|
|
368
|
+
for (const [name, value] of [
|
|
369
|
+
["timeoutSeconds", props.timeoutSeconds],
|
|
370
|
+
["pollIntervalMs", props.pollIntervalMs],
|
|
371
|
+
["urlReadinessTimeoutSeconds", props.urlReadinessTimeoutSeconds],
|
|
372
|
+
]) {
|
|
373
|
+
if (value !== undefined && (!Number.isFinite(value) || value <= 0)) {
|
|
374
|
+
return yield* Effect.fail(new Error(`${name} must be a positive finite number.`));
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
for (const [name, value] of [
|
|
378
|
+
["port", props.port],
|
|
379
|
+
["dev.port", props.dev?.port],
|
|
380
|
+
]) {
|
|
381
|
+
if (value !== undefined &&
|
|
382
|
+
(!Number.isInteger(value) || value < 1 || value > 65_535)) {
|
|
383
|
+
return yield* Effect.fail(new Error(`${name} must be an integer between 1 and 65535.`));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
for (const [key, value] of Object.entries(props.env ?? {})) {
|
|
387
|
+
if (value === undefined)
|
|
388
|
+
continue;
|
|
389
|
+
if (value === null) {
|
|
390
|
+
yield* validateComputeEnvironmentKey(key);
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
yield* validateComputeEnvironmentWrite(key, value);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if ((props.skipPromote ?? false) && (props.destroyOldDeployment ?? false)) {
|
|
397
|
+
return yield* Effect.fail(new Error("destroyOldDeployment cannot be combined with skipPromote because the previous deployment stays active when promotion is skipped."));
|
|
398
|
+
}
|
|
399
|
+
if (props.start === false && !(props.skipPromote ?? false)) {
|
|
400
|
+
return yield* Effect.fail(new Error("start: false requires skipPromote: true because Prisma Compute promotion requires a running deployment."));
|
|
401
|
+
}
|
|
402
|
+
if (props.branchId !== undefined && props.branchGitName !== undefined) {
|
|
403
|
+
return yield* Effect.fail(new Error("branchId and branchGitName are mutually exclusive."));
|
|
404
|
+
}
|
|
405
|
+
if (props.branchId === null || props.branchGitName === null) {
|
|
406
|
+
return yield* Effect.fail(new Error("Prisma.Compute requires an attached branch because deployment creation resolves environment variables from the App branch. Omit branchGitName to use the project's default branch, or set branchId/branchGitName."));
|
|
407
|
+
}
|
|
408
|
+
if ((props.skipCodeUpload ?? false) && props.artifactPath !== undefined) {
|
|
409
|
+
return yield* Effect.fail(new Error("skipCodeUpload cannot be combined with artifactPath."));
|
|
410
|
+
}
|
|
411
|
+
if ((props.skipCodeUpload ?? false) && props.build !== undefined) {
|
|
412
|
+
return yield* Effect.fail(new Error("skipCodeUpload cannot be combined with build."));
|
|
413
|
+
}
|
|
414
|
+
if (hasEffectNativeComputeInput(props)) {
|
|
415
|
+
const handler = props.handler ?? "default";
|
|
416
|
+
if (handler !== "default" && !EXPORT_IDENTIFIER_PATTERN.test(handler)) {
|
|
417
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute handler must be `default` or a valid JavaScript export identifier."));
|
|
418
|
+
}
|
|
419
|
+
if (props.main === undefined) {
|
|
420
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps require `main`. Set `main: import.meta.filename`."));
|
|
421
|
+
}
|
|
422
|
+
if (props.artifactPath !== undefined) {
|
|
423
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps cannot use artifactPath."));
|
|
424
|
+
}
|
|
425
|
+
if (props.build !== undefined) {
|
|
426
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps cannot use build."));
|
|
427
|
+
}
|
|
428
|
+
if (props.skipCodeUpload) {
|
|
429
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps cannot skip code upload."));
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
const processEnv = (env = {}) => Object.fromEntries(Object.entries(env).flatMap(([key, value]) => value === undefined || value === null
|
|
434
|
+
? []
|
|
435
|
+
: [[key, Redacted.isRedacted(value) ? Redacted.value(value) : value]]));
|
|
436
|
+
const isPrismaEdgeServiceNotFound = (status, body) => status === 404 &&
|
|
437
|
+
(body.includes("There is no service on this URL") ||
|
|
438
|
+
body.includes("<title>Service not found</title>"));
|
|
439
|
+
const URL_READINESS_BODY_PREFIX_BYTES = 64 * 1024;
|
|
440
|
+
const readResponseBodyPrefix = (response) => Effect.gen(function* () {
|
|
441
|
+
const chunks = [];
|
|
442
|
+
let bytes = 0;
|
|
443
|
+
yield* Stream.runForEachWhile(response.stream, (chunk) => Effect.sync(() => {
|
|
444
|
+
const remaining = URL_READINESS_BODY_PREFIX_BYTES - bytes;
|
|
445
|
+
if (remaining <= 0)
|
|
446
|
+
return false;
|
|
447
|
+
const kept = chunk.byteLength > remaining ? chunk.slice(0, remaining) : chunk;
|
|
448
|
+
chunks.push(kept);
|
|
449
|
+
bytes += kept.byteLength;
|
|
450
|
+
return bytes < URL_READINESS_BODY_PREFIX_BYTES;
|
|
451
|
+
}));
|
|
452
|
+
const prefix = new Uint8Array(bytes);
|
|
453
|
+
let offset = 0;
|
|
454
|
+
for (const chunk of chunks) {
|
|
455
|
+
prefix.set(chunk, offset);
|
|
456
|
+
offset += chunk.byteLength;
|
|
457
|
+
}
|
|
458
|
+
return new TextDecoder().decode(prefix);
|
|
459
|
+
});
|
|
460
|
+
export const waitForDeploymentUrl = Effect.fn(function* (url, props) {
|
|
461
|
+
yield* validateComputeHealthCheck(props.healthCheck);
|
|
462
|
+
if (props.healthCheck !== undefined && props.verifyUrl === false) {
|
|
463
|
+
return yield* Effect.fail(new Error("healthCheck cannot be combined with verifyUrl: false."));
|
|
464
|
+
}
|
|
465
|
+
if (props.verifyUrl === false)
|
|
466
|
+
return;
|
|
467
|
+
if (!url) {
|
|
468
|
+
return yield* Effect.fail(new Error(props.healthCheck === undefined
|
|
469
|
+
? "Prisma Compute did not return a public URL for readiness verification."
|
|
470
|
+
: "Prisma Compute did not return a public URL for the configured healthCheck."));
|
|
471
|
+
}
|
|
472
|
+
const httpOption = yield* Effect.serviceOption(HttpClient.HttpClient);
|
|
473
|
+
if (Option.isNone(httpOption)) {
|
|
474
|
+
return props.healthCheck === undefined
|
|
475
|
+
? undefined
|
|
476
|
+
: yield* Effect.fail(new Error("Prisma Compute healthCheck requires an HTTP client service."));
|
|
477
|
+
}
|
|
478
|
+
const http = httpOption.value;
|
|
479
|
+
const probeUrl = props.healthCheck === undefined
|
|
480
|
+
? url
|
|
481
|
+
: new URL(props.healthCheck.path, url).toString();
|
|
482
|
+
const acceptsStatus = (status) => props.healthCheck === undefined ||
|
|
483
|
+
(props.healthCheck.statusCodes === undefined
|
|
484
|
+
? status >= 200 && status <= 299
|
|
485
|
+
: props.healthCheck.statusCodes.includes(status));
|
|
486
|
+
const timeoutSeconds = props.urlReadinessTimeoutSeconds ?? 60;
|
|
487
|
+
const intervalMs = props.pollIntervalMs ?? 1_000;
|
|
488
|
+
if (!Number.isFinite(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
489
|
+
return yield* Effect.fail(new Error("urlReadinessTimeoutSeconds must be a positive finite number."));
|
|
490
|
+
}
|
|
491
|
+
if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
|
|
492
|
+
return yield* Effect.fail(new Error("pollIntervalMs must be a positive finite number."));
|
|
493
|
+
}
|
|
494
|
+
const timeoutMs = timeoutSeconds * 1_000;
|
|
495
|
+
const startedAt = yield* Effect.sync(() => Date.now());
|
|
496
|
+
let lastStatus;
|
|
497
|
+
let lastBody = "";
|
|
498
|
+
while (true) {
|
|
499
|
+
const beforeRequest = yield* Effect.sync(() => Date.now());
|
|
500
|
+
const remainingBeforeRequest = timeoutMs - (beforeRequest - startedAt);
|
|
501
|
+
if (remainingBeforeRequest <= 0) {
|
|
502
|
+
return yield* Effect.fail(deploymentUrlTimeoutError(probeUrl, lastStatus, lastBody));
|
|
503
|
+
}
|
|
504
|
+
const requestTimeoutMs = Math.min(5_000, remainingBeforeRequest);
|
|
505
|
+
const response = yield* http.execute(HttpClientRequest.get(probeUrl)).pipe(Effect.provideService(FetchHttpClient.RequestInit, {
|
|
506
|
+
redirect: "manual",
|
|
507
|
+
}), Effect.timeoutOption(Duration.millis(requestTimeoutMs)), Effect.map(Option.getOrUndefined), Effect.catch(() => Effect.succeed(undefined)));
|
|
508
|
+
if (response) {
|
|
509
|
+
lastStatus = response.status;
|
|
510
|
+
// Without an application health check, any non-404 response proves that
|
|
511
|
+
// edge routing is live. A configured health check must also match its
|
|
512
|
+
// status contract. Do not consume non-404 bodies: application responses
|
|
513
|
+
// may intentionally stream.
|
|
514
|
+
if (response.status !== 404 && acceptsStatus(response.status)) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const beforeBody = yield* Effect.sync(() => Date.now());
|
|
518
|
+
const remainingBeforeBody = timeoutMs - (beforeBody - startedAt);
|
|
519
|
+
if (remainingBeforeBody > 0) {
|
|
520
|
+
const bodyPrefix = yield* readResponseBodyPrefix(response).pipe(Effect.timeoutOption(Duration.millis(Math.min(2_000, remainingBeforeBody))), Effect.catch(() => Effect.succeed(Option.none())));
|
|
521
|
+
if (Option.isSome(bodyPrefix)) {
|
|
522
|
+
lastBody = bodyPrefix.value;
|
|
523
|
+
if (!isPrismaEdgeServiceNotFound(response.status, lastBody) &&
|
|
524
|
+
acceptsStatus(response.status)) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const elapsed = yield* Effect.sync(() => Date.now() - startedAt);
|
|
531
|
+
if (elapsed >= timeoutMs) {
|
|
532
|
+
return yield* Effect.fail(deploymentUrlTimeoutError(probeUrl, lastStatus, lastBody));
|
|
533
|
+
}
|
|
534
|
+
yield* Effect.sleep(Duration.millis(Math.min(intervalMs, timeoutMs - elapsed)));
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
const deploymentUrlTimeoutError = (url, lastStatus, lastBody) => new Error([
|
|
538
|
+
`Timed out waiting for Prisma Compute URL '${url}' to become reachable.`,
|
|
539
|
+
lastStatus
|
|
540
|
+
? `Last response: HTTP ${lastStatus}.`
|
|
541
|
+
: "No HTTP response was received.",
|
|
542
|
+
lastBody.includes("There is no service on this URL")
|
|
543
|
+
? "The Prisma edge returned: There is no service on this URL."
|
|
544
|
+
: undefined,
|
|
545
|
+
]
|
|
546
|
+
.filter((line) => line !== undefined)
|
|
547
|
+
.join(" "));
|
|
548
|
+
const isAutoBuild = (build) => build === "auto" ||
|
|
549
|
+
(typeof build === "object" &&
|
|
550
|
+
build !== null &&
|
|
551
|
+
"type" in build &&
|
|
552
|
+
build.type === "auto");
|
|
553
|
+
const readPackageMain = Effect.fn(function* (directory) {
|
|
554
|
+
const fs = yield* FileSystem.FileSystem;
|
|
555
|
+
const path = yield* Path.Path;
|
|
556
|
+
const text = yield* fs
|
|
557
|
+
.readFileString(path.join(directory, "package.json"))
|
|
558
|
+
.pipe(Effect.catchIf((error) => error._tag === "PlatformError" && error.reason._tag === "NotFound", () => Effect.succeed(undefined)));
|
|
559
|
+
if (!text)
|
|
560
|
+
return undefined;
|
|
561
|
+
return yield* Effect.try({
|
|
562
|
+
try: () => {
|
|
563
|
+
const parsed = JSON.parse(text);
|
|
564
|
+
return typeof parsed.main === "string" ? parsed.main : undefined;
|
|
565
|
+
},
|
|
566
|
+
catch: (cause) => new Error(`Failed to parse package.json in ${directory}: ${cause}`),
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
const writeBundleDirectory = Effect.fn(function* (bundle) {
|
|
570
|
+
const fs = yield* FileSystem.FileSystem;
|
|
571
|
+
const path = yield* Path.Path;
|
|
572
|
+
if (bundle.files.length === 0) {
|
|
573
|
+
return yield* Effect.fail(new Error("Effect-native Compute bundler produced no output files."));
|
|
574
|
+
}
|
|
575
|
+
const normalizedFiles = yield* Effect.forEach(bundle.files, (file) => normalizeBundleFilePath(file.path).pipe(Effect.map((normalizedPath) => ({ file, normalizedPath }))));
|
|
576
|
+
const seen = new Set();
|
|
577
|
+
for (const { normalizedPath } of normalizedFiles) {
|
|
578
|
+
if (seen.has(normalizedPath)) {
|
|
579
|
+
return yield* Effect.fail(new Error(`Effect-native Compute bundler produced duplicate output path '${normalizedPath}'.`));
|
|
580
|
+
}
|
|
581
|
+
seen.add(normalizedPath);
|
|
582
|
+
}
|
|
583
|
+
const directory = yield* fs.makeTempDirectory({
|
|
584
|
+
prefix: "alchemy-prisma-compute-",
|
|
585
|
+
});
|
|
586
|
+
return yield* Effect.gen(function* () {
|
|
587
|
+
for (const { file, normalizedPath } of normalizedFiles) {
|
|
588
|
+
const target = path.join(directory, normalizedPath);
|
|
589
|
+
yield* fs.makeDirectory(path.dirname(target), { recursive: true });
|
|
590
|
+
if (typeof file.content === "string") {
|
|
591
|
+
yield* fs.writeFileString(target, file.content);
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
yield* fs.writeFile(target, file.content);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
directory,
|
|
599
|
+
entrypoint: normalizedFiles[0].normalizedPath,
|
|
600
|
+
cleanup: fs
|
|
601
|
+
.remove(directory, { recursive: true })
|
|
602
|
+
.pipe(Effect.catch(() => Effect.void)),
|
|
603
|
+
};
|
|
604
|
+
}).pipe(Effect.onError(() => fs.remove(directory, { recursive: true }).pipe(Effect.ignore)));
|
|
605
|
+
});
|
|
606
|
+
const bundleEffectCompute = Effect.fn(function* (props) {
|
|
607
|
+
if (!props.main) {
|
|
608
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps require `main`. Set `main: import.meta.filename`."));
|
|
609
|
+
}
|
|
610
|
+
const fs = yield* FileSystem.FileSystem;
|
|
611
|
+
const stack = yield* Effect.serviceOption(Stack).pipe(Effect.map(Option.getOrElse(() => ({
|
|
612
|
+
name: "alchemy",
|
|
613
|
+
stage: "dev",
|
|
614
|
+
bindings: {},
|
|
615
|
+
resources: {},
|
|
616
|
+
}))));
|
|
617
|
+
const virtualEntryPlugin = yield* Bundle.virtualEntryPlugin;
|
|
618
|
+
const realMain = yield* fs.realPath(props.main);
|
|
619
|
+
const cwd = yield* findCwdForBundle(realMain);
|
|
620
|
+
const handler = props.handler ?? "default";
|
|
621
|
+
const defaultPort = props.port ?? 8080;
|
|
622
|
+
const importEntrypoint = handler === "default"
|
|
623
|
+
? "import entrypoint"
|
|
624
|
+
: `import { ${handler} as entrypoint }`;
|
|
625
|
+
const bundle = yield* Bundle.build({
|
|
626
|
+
...props.bundle?.input,
|
|
627
|
+
input: realMain,
|
|
628
|
+
cwd,
|
|
629
|
+
platform: "node",
|
|
630
|
+
plugins: [
|
|
631
|
+
props.bundle?.input?.plugins,
|
|
632
|
+
virtualEntryPlugin((importPath) => `
|
|
633
|
+
import { BunServices } from "@effect/platform-bun";
|
|
634
|
+
import { BunHttpServer } from "alchemy/Http";
|
|
635
|
+
import { Stack } from "alchemy/Stack";
|
|
636
|
+
import { Stage } from "alchemy/Stage";
|
|
637
|
+
import { makeEntrypointLayer } from "alchemy/Runtime";
|
|
638
|
+
import * as ConfigProvider from "effect/ConfigProvider";
|
|
639
|
+
import * as Context from "effect/Context";
|
|
640
|
+
import * as Effect from "effect/Effect";
|
|
641
|
+
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
642
|
+
import * as Layer from "effect/Layer";
|
|
643
|
+
import * as Logger from "effect/Logger";
|
|
644
|
+
import { MinimumLogLevel } from "effect/References";
|
|
645
|
+
|
|
646
|
+
${importEntrypoint} from ${JSON.stringify(importPath)};
|
|
647
|
+
|
|
648
|
+
process.env.PORT ??= ${JSON.stringify(String(defaultPort))};
|
|
649
|
+
|
|
650
|
+
const tag = Context.Service("${Self.key}");
|
|
651
|
+
const layer = makeEntrypointLayer(tag, entrypoint);
|
|
652
|
+
|
|
653
|
+
const platform = Layer.mergeAll(
|
|
654
|
+
BunServices.layer,
|
|
655
|
+
FetchHttpClient.layer,
|
|
656
|
+
Logger.layer([Logger.consolePretty()]),
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
const stack = Layer.mergeAll(
|
|
660
|
+
Layer.succeed(Stack, {
|
|
661
|
+
name: ${JSON.stringify(stack.name)},
|
|
662
|
+
stage: ${JSON.stringify(stack.stage)},
|
|
663
|
+
bindings: {},
|
|
664
|
+
resources: {},
|
|
665
|
+
}),
|
|
666
|
+
Layer.succeed(Stage, ${JSON.stringify(stack.stage)}),
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
const program = tag.pipe(
|
|
670
|
+
Effect.flatMap((app) => app.RuntimeContext.exports),
|
|
671
|
+
Effect.flatMap((exports) => exports.default),
|
|
672
|
+
Effect.provide(
|
|
673
|
+
layer.pipe(
|
|
674
|
+
Layer.provideMerge(stack),
|
|
675
|
+
Layer.provideMerge(BunHttpServer({ hostname: "0.0.0.0" })),
|
|
676
|
+
Layer.provideMerge(platform),
|
|
677
|
+
Layer.provideMerge(
|
|
678
|
+
Layer.succeed(
|
|
679
|
+
ConfigProvider.ConfigProvider,
|
|
680
|
+
ConfigProvider.orElse(
|
|
681
|
+
ConfigProvider.fromUnknown({ ALCHEMY_PHASE: "runtime" }),
|
|
682
|
+
ConfigProvider.fromEnv(),
|
|
683
|
+
),
|
|
684
|
+
),
|
|
685
|
+
),
|
|
686
|
+
Layer.provideMerge(
|
|
687
|
+
Layer.succeed(
|
|
688
|
+
MinimumLogLevel,
|
|
689
|
+
process.env.DEBUG ? "Debug" : "Info",
|
|
690
|
+
),
|
|
691
|
+
),
|
|
692
|
+
),
|
|
693
|
+
),
|
|
694
|
+
Effect.scoped,
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
console.log("Prisma Compute bootstrap starting...");
|
|
698
|
+
await Effect.runPromise(program).catch((error) => {
|
|
699
|
+
console.error("Prisma Compute bootstrap failed:", error);
|
|
700
|
+
process.exit(1);
|
|
701
|
+
});
|
|
702
|
+
`),
|
|
703
|
+
],
|
|
704
|
+
checks: {
|
|
705
|
+
unresolvedImport: false,
|
|
706
|
+
ineffectiveDynamicImport: false,
|
|
707
|
+
},
|
|
708
|
+
}, {
|
|
709
|
+
...props.bundle?.output,
|
|
710
|
+
format: "esm",
|
|
711
|
+
sourcemap: props.bundle?.output?.sourcemap ?? "hidden",
|
|
712
|
+
minify: props.bundle?.output?.minify ?? true,
|
|
713
|
+
entryFileNames: "index.js",
|
|
714
|
+
}, props.bundle?.extra);
|
|
715
|
+
const artifact = yield* writeBundleDirectory(bundle);
|
|
716
|
+
const file = yield* createComputeArchive({
|
|
717
|
+
directory: artifact.directory,
|
|
718
|
+
entrypoint: artifact.entrypoint,
|
|
719
|
+
ignore: props.archiveIgnore,
|
|
720
|
+
output: "file",
|
|
721
|
+
}).pipe(Effect.ensuring(artifact.cleanup));
|
|
722
|
+
return {
|
|
723
|
+
file,
|
|
724
|
+
bundleHash: bundle.hash,
|
|
725
|
+
};
|
|
726
|
+
});
|
|
727
|
+
const resolveArtifact = Effect.fn(function* (props) {
|
|
728
|
+
const env = plainEnv(props.env);
|
|
729
|
+
const envClass = props.envClass ?? "production";
|
|
730
|
+
const defaultPort = props.port ?? 8080;
|
|
731
|
+
if (isEffectNativeCompute(props)) {
|
|
732
|
+
if (props.artifactPath !== undefined) {
|
|
733
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps cannot use artifactPath."));
|
|
734
|
+
}
|
|
735
|
+
if (props.skipCodeUpload) {
|
|
736
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps cannot skip code upload."));
|
|
737
|
+
}
|
|
738
|
+
if (props.build !== undefined) {
|
|
739
|
+
return yield* Effect.fail(new Error("Effect-native Prisma Compute apps cannot use build."));
|
|
740
|
+
}
|
|
741
|
+
const artifact = yield* bundleEffectCompute(props);
|
|
742
|
+
return {
|
|
743
|
+
file: artifact.file,
|
|
744
|
+
hash: yield* sha256Object({
|
|
745
|
+
bundle: artifact.bundleHash,
|
|
746
|
+
env,
|
|
747
|
+
envClass,
|
|
748
|
+
port: defaultPort,
|
|
749
|
+
}),
|
|
750
|
+
port: defaultPort,
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
if (props.skipCodeUpload) {
|
|
754
|
+
return {
|
|
755
|
+
file: undefined,
|
|
756
|
+
hash: yield* sha256Object({
|
|
757
|
+
skipCodeUpload: true,
|
|
758
|
+
env,
|
|
759
|
+
envClass,
|
|
760
|
+
port: defaultPort,
|
|
761
|
+
}),
|
|
762
|
+
port: defaultPort,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
if (props.artifactPath !== undefined) {
|
|
766
|
+
const file = yield* readUploadArtifact({
|
|
767
|
+
artifactPath: props.artifactPath,
|
|
768
|
+
output: "file",
|
|
769
|
+
});
|
|
770
|
+
return {
|
|
771
|
+
file: file,
|
|
772
|
+
hash: yield* sha256Object({
|
|
773
|
+
artifact: file.sha256,
|
|
774
|
+
env,
|
|
775
|
+
envClass,
|
|
776
|
+
port: defaultPort,
|
|
777
|
+
}),
|
|
778
|
+
port: defaultPort,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
const path = yield* Path.Path;
|
|
782
|
+
const appPath = path.resolve(props.path ?? ".");
|
|
783
|
+
let directory = appPath;
|
|
784
|
+
let entrypoint = props.entrypoint;
|
|
785
|
+
let port = defaultPort;
|
|
786
|
+
if (isAutoBuild(props.build)) {
|
|
787
|
+
const auto = props.build === "auto" ? undefined : props.build;
|
|
788
|
+
const artifact = yield* runComputeAutoBuild({
|
|
789
|
+
appPath,
|
|
790
|
+
entrypoint,
|
|
791
|
+
framework: auto?.framework,
|
|
792
|
+
env: auto?.env,
|
|
793
|
+
outputLimitBytes: auto?.outputLimitBytes,
|
|
794
|
+
timeoutSeconds: auto?.timeoutSeconds,
|
|
795
|
+
});
|
|
796
|
+
const file = yield* createComputeArchive({
|
|
797
|
+
directory: artifact.directory,
|
|
798
|
+
entrypoint: artifact.entrypoint,
|
|
799
|
+
ignore: props.archiveIgnore,
|
|
800
|
+
output: "file",
|
|
801
|
+
}).pipe(Effect.ensuring(artifact.cleanup));
|
|
802
|
+
port = props.port ?? artifact.defaultPort ?? 8080;
|
|
803
|
+
return {
|
|
804
|
+
file,
|
|
805
|
+
hash: yield* sha256Object({
|
|
806
|
+
artifact: file.sha256,
|
|
807
|
+
env,
|
|
808
|
+
envClass,
|
|
809
|
+
port,
|
|
810
|
+
}),
|
|
811
|
+
port,
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
if (props.build) {
|
|
815
|
+
const cwd = props.build.cwd ? path.resolve(props.build.cwd) : appPath;
|
|
816
|
+
yield* runBuildCommand({
|
|
817
|
+
command: props.build.command,
|
|
818
|
+
cwd,
|
|
819
|
+
env: processEnv(props.build.env),
|
|
820
|
+
outputLimitBytes: props.build.outputLimitBytes,
|
|
821
|
+
timeoutSeconds: props.build.timeoutSeconds,
|
|
822
|
+
});
|
|
823
|
+
directory = path.resolve(cwd, props.build.outdir);
|
|
824
|
+
entrypoint = props.build.entrypoint ?? entrypoint;
|
|
825
|
+
}
|
|
826
|
+
entrypoint ??= yield* readPackageMain(directory);
|
|
827
|
+
if (!entrypoint) {
|
|
828
|
+
return yield* Effect.fail(new Error("Prisma Compute app entrypoint is required. Set `entrypoint` or package.json `main`."));
|
|
829
|
+
}
|
|
830
|
+
const normalizedEntrypoint = yield* normalizeEntrypoint(entrypoint);
|
|
831
|
+
const file = yield* createComputeArchive({
|
|
832
|
+
directory,
|
|
833
|
+
entrypoint: normalizedEntrypoint,
|
|
834
|
+
ignore: props.archiveIgnore,
|
|
835
|
+
output: "file",
|
|
836
|
+
});
|
|
837
|
+
return {
|
|
838
|
+
file,
|
|
839
|
+
hash: yield* sha256Object({
|
|
840
|
+
artifact: file.sha256,
|
|
841
|
+
env,
|
|
842
|
+
envClass,
|
|
843
|
+
port,
|
|
844
|
+
}),
|
|
845
|
+
port,
|
|
846
|
+
};
|
|
847
|
+
});
|
|
848
|
+
const findExistingApp = Effect.fn(function* (client, output) {
|
|
849
|
+
const appId = output?.appId && !isPrismaDevId(output.appId) ? output.appId : undefined;
|
|
850
|
+
return appId
|
|
851
|
+
? yield* client
|
|
852
|
+
.getApp(appId)
|
|
853
|
+
.pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)))
|
|
854
|
+
: undefined;
|
|
855
|
+
});
|
|
856
|
+
const ensureApp = Effect.fn(function* (client, projectId, props, output, observedApp) {
|
|
857
|
+
let app = observedApp ?? (yield* findExistingApp(client, output));
|
|
858
|
+
const branch = yield* desiredComputeBranchId(client, projectId, props);
|
|
859
|
+
if (!branch.resolved) {
|
|
860
|
+
return yield* Effect.fail(new Error(props.branchGitName === undefined
|
|
861
|
+
? `Prisma project '${projectId}' has no default branch to attach Compute App '${props.appName}'. Create or promote a default branch, or specify branchId/branchGitName.`
|
|
862
|
+
: `Prisma project '${projectId}' has no branch named '${props.branchGitName}' to attach Compute App '${props.appName}'.`));
|
|
863
|
+
}
|
|
864
|
+
let createdApp = false;
|
|
865
|
+
if (!app) {
|
|
866
|
+
const result = yield* createApp(client, projectId, props, branch.id).pipe(Effect.map((app) => ({ app, created: true })), Effect.catchIf(isConflict, (conflict) => findApp(client, projectId, props.appName, props).pipe(Effect.flatMap((app) => app && output?.appId !== undefined && app.id === output.appId
|
|
867
|
+
? Effect.succeed({ app, created: false })
|
|
868
|
+
: Effect.fail(new Error(`Prisma App '${props.appName}' already exists on the requested branch but is not owned by this Compute resource. Import it with explicit adoption or choose a different App name.`, { cause: conflict }))))));
|
|
869
|
+
app = result.app;
|
|
870
|
+
createdApp = result.created;
|
|
871
|
+
}
|
|
872
|
+
yield* ensureAppImmutableIdentity(app, projectId, props.regionId ?? output?.regionId ?? app.region.id);
|
|
873
|
+
if (app.name !== props.appName || app.branchId !== branch.id) {
|
|
874
|
+
app = yield* client.updateApp(app.id, {
|
|
875
|
+
displayName: props.appName,
|
|
876
|
+
branchId: branch.id,
|
|
877
|
+
branchGitName: undefined,
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
return { app, created: createdApp };
|
|
881
|
+
});
|
|
882
|
+
const ensureSkipCodeUploadCanFork = (props, app) => Effect.gen(function* () {
|
|
883
|
+
if (!(props.skipCodeUpload ?? false))
|
|
884
|
+
return;
|
|
885
|
+
if (app?.latestDeploymentId)
|
|
886
|
+
return;
|
|
887
|
+
return yield* Effect.fail(new Error("skipCodeUpload requires an existing Prisma deployment to fork from. Upload and start a deployment first, or remove skipCodeUpload."));
|
|
888
|
+
});
|
|
889
|
+
const findEnvironmentVariable = (client, projectId, cls, key, branchId) => client
|
|
890
|
+
.listEnvironmentVariables({
|
|
891
|
+
projectId,
|
|
892
|
+
class: cls,
|
|
893
|
+
key,
|
|
894
|
+
...(branchId ? { branchId } : {}),
|
|
895
|
+
limit: 100,
|
|
896
|
+
})
|
|
897
|
+
.pipe(Effect.map((variables) => variables.find((variable) => variable.branchId === (branchId ?? null))));
|
|
898
|
+
const systemManagedEnvironmentVariableError = (key) => new Error(`Prisma environment variable '${key}' is managed by Prisma and cannot be managed by Alchemy.`);
|
|
899
|
+
const ensureUserManagedEnvironmentVariable = (variable) => Effect.gen(function* () {
|
|
900
|
+
if (variable.isManagedBySystem) {
|
|
901
|
+
return yield* Effect.fail(systemManagedEnvironmentVariableError(variable.key));
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
const environmentVariableOwnershipError = (key, variableId) => new Error(`Prisma environment variable '${key}' (${variableId}) already exists in this branch/class scope but is not owned by this Compute resource. It may be foreign or left by an interrupted prior Compute deploy; the Management API exposes no ownership marker or plaintext value that would make takeover safe. Use one standalone Prisma.EnvironmentVariable resource as the independently manageable owner, choose a different key, explicitly adopt that resource, or remove the existing variable before deploying.`);
|
|
905
|
+
const environmentScope = (cls, branchId) => ({
|
|
906
|
+
class: cls,
|
|
907
|
+
branchId: branchId ?? null,
|
|
908
|
+
});
|
|
909
|
+
const sameEnvironmentScope = (left, right) => left.class === right.class && left.branchId === right.branchId;
|
|
910
|
+
const resolveComputeEnvironmentScope = Effect.fn(function* (client, app, props) {
|
|
911
|
+
if (!app.branchId) {
|
|
912
|
+
return yield* Effect.fail(new Error("Prisma.Compute requires an attached branch because deployment creation resolves environment variables from the App branch."));
|
|
913
|
+
}
|
|
914
|
+
const branch = yield* client.getBranch(app.branchId);
|
|
915
|
+
const inferredClass = branch.role;
|
|
916
|
+
if (props.envClass !== undefined && props.envClass !== inferredClass) {
|
|
917
|
+
return yield* Effect.fail(new Error(`Prisma.Compute envClass '${props.envClass}' does not match attached branch role '${inferredClass}'. Omit envClass to let Alchemy infer the correct environment variable scope.`));
|
|
918
|
+
}
|
|
919
|
+
return environmentScope(inferredClass, inferredClass === "preview" ? app.branchId : null);
|
|
920
|
+
});
|
|
921
|
+
const rollbackCreatedEnvironmentVariables = Effect.fn(function* (client, createdIds, originalError) {
|
|
922
|
+
if (createdIds.length === 0) {
|
|
923
|
+
return yield* Effect.fail(originalError);
|
|
924
|
+
}
|
|
925
|
+
const cleanupErrors = [];
|
|
926
|
+
for (const created of [...createdIds].reverse()) {
|
|
927
|
+
const result = yield* Effect.result(client
|
|
928
|
+
.deleteEnvironmentVariable(created.id)
|
|
929
|
+
.pipe(Effect.catchIf(isNotFound, () => Effect.void)));
|
|
930
|
+
if (Result.isFailure(result)) {
|
|
931
|
+
cleanupErrors.push(result.failure);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
if (cleanupErrors.length > 0) {
|
|
935
|
+
return yield* Effect.fail(new AggregateError([originalError, ...cleanupErrors], `Failed to roll back newly created Prisma environment variables after reconcile failed. Manual cleanup: ${createdIds.map(({ id }) => `DELETE /v1/environment-variables/${id}`).join(", ")}.`));
|
|
936
|
+
}
|
|
937
|
+
return yield* Effect.fail(originalError);
|
|
938
|
+
});
|
|
939
|
+
const syncComputeEnvironmentInternal = Effect.fn(function* (client, projectId, cls, env = {}, branchId, ownedIds = {}) {
|
|
940
|
+
const synced = [];
|
|
941
|
+
const deleted = [];
|
|
942
|
+
const nextOwnedIds = {};
|
|
943
|
+
const createdIds = [];
|
|
944
|
+
const plans = [];
|
|
945
|
+
// Observe and validate the entire scope before the first write. In
|
|
946
|
+
// particular, a foreign/system-owned key discovered late in the input must
|
|
947
|
+
// not leave earlier keys partially created.
|
|
948
|
+
for (const [key, value] of Object.entries(plainEnv(env))) {
|
|
949
|
+
if (value === null) {
|
|
950
|
+
yield* validateComputeEnvironmentKey(key);
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
yield* validateComputeEnvironmentWrite(key, value);
|
|
954
|
+
}
|
|
955
|
+
const variable = yield* findEnvironmentVariable(client, projectId, cls, key, branchId);
|
|
956
|
+
if (variable) {
|
|
957
|
+
yield* ensureUserManagedEnvironmentVariable(variable);
|
|
958
|
+
if (ownedIds[key] !== variable.id) {
|
|
959
|
+
return yield* Effect.fail(environmentVariableOwnershipError(key, variable.id));
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
plans.push({ key, value, variable });
|
|
963
|
+
}
|
|
964
|
+
const apply = Effect.gen(function* () {
|
|
965
|
+
for (const { key, value, variable } of plans) {
|
|
966
|
+
if (value === null)
|
|
967
|
+
continue;
|
|
968
|
+
if (variable) {
|
|
969
|
+
yield* client.updateEnvironmentVariable(variable.id, { value });
|
|
970
|
+
nextOwnedIds[key] = variable.id;
|
|
971
|
+
}
|
|
972
|
+
else {
|
|
973
|
+
const created = yield* client.createEnvironmentVariable({
|
|
974
|
+
projectId,
|
|
975
|
+
...(branchId ? { branchId } : {}),
|
|
976
|
+
class: cls,
|
|
977
|
+
key,
|
|
978
|
+
value,
|
|
979
|
+
});
|
|
980
|
+
createdIds.push({ key, id: created.id });
|
|
981
|
+
nextOwnedIds[key] = created.id;
|
|
982
|
+
}
|
|
983
|
+
synced.push(key);
|
|
984
|
+
}
|
|
985
|
+
// Apply explicit deletions only after all ownership checks and upserts.
|
|
986
|
+
for (const { key, value, variable } of plans) {
|
|
987
|
+
if (value !== null || !variable)
|
|
988
|
+
continue;
|
|
989
|
+
yield* client
|
|
990
|
+
.deleteEnvironmentVariable(variable.id)
|
|
991
|
+
.pipe(Effect.catchIf(isNotFound, () => Effect.void));
|
|
992
|
+
deleted.push(key);
|
|
993
|
+
}
|
|
994
|
+
return { synced, deleted, ownedIds: nextOwnedIds, createdIds };
|
|
995
|
+
});
|
|
996
|
+
return yield* apply.pipe(Effect.catch((error) => rollbackCreatedEnvironmentVariables(client, createdIds, error)));
|
|
997
|
+
});
|
|
998
|
+
export const syncComputeEnvironment = Effect.fn(function* (client, projectId, cls, env = {}, branchId, ownedIds = {}) {
|
|
999
|
+
const result = yield* syncComputeEnvironmentInternal(client, projectId, cls, env, branchId, ownedIds);
|
|
1000
|
+
return {
|
|
1001
|
+
synced: result.synced,
|
|
1002
|
+
deleted: result.deleted,
|
|
1003
|
+
ownedIds: result.ownedIds,
|
|
1004
|
+
};
|
|
1005
|
+
});
|
|
1006
|
+
const destroyComputeEnvironment = Effect.fn(function* (client, projectId, scope, ownedIds = {}) {
|
|
1007
|
+
const deleted = [];
|
|
1008
|
+
for (const [key, ownedId] of Object.entries(ownedIds)) {
|
|
1009
|
+
const variable = yield* findEnvironmentVariable(client, projectId, scope.class, key, scope.branchId).pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)));
|
|
1010
|
+
if (!variable)
|
|
1011
|
+
continue;
|
|
1012
|
+
if (variable.id !== ownedId || variable.isManagedBySystem)
|
|
1013
|
+
continue;
|
|
1014
|
+
yield* client
|
|
1015
|
+
.deleteEnvironmentVariable(variable.id)
|
|
1016
|
+
.pipe(Effect.catchIf(isNotFound, () => Effect.void));
|
|
1017
|
+
deleted.push(key);
|
|
1018
|
+
}
|
|
1019
|
+
return { deleted };
|
|
1020
|
+
});
|
|
1021
|
+
const cleanupRemovedComputeEnvironment = Effect.fn(function* (client, projectId, oldScope, oldOwnedIds, newScope, newEnv) {
|
|
1022
|
+
const newValues = plainEnv(newEnv);
|
|
1023
|
+
const deleted = [];
|
|
1024
|
+
for (const [key, ownedId] of Object.entries(oldOwnedIds)) {
|
|
1025
|
+
if (sameEnvironmentScope(oldScope, newScope) && key in newValues)
|
|
1026
|
+
continue;
|
|
1027
|
+
const variable = yield* findEnvironmentVariable(client, projectId, oldScope.class, key, oldScope.branchId);
|
|
1028
|
+
if (!variable)
|
|
1029
|
+
continue;
|
|
1030
|
+
if (variable.id !== ownedId || variable.isManagedBySystem)
|
|
1031
|
+
continue;
|
|
1032
|
+
yield* client
|
|
1033
|
+
.deleteEnvironmentVariable(variable.id)
|
|
1034
|
+
.pipe(Effect.catchIf(isNotFound, () => Effect.void));
|
|
1035
|
+
deleted.push(key);
|
|
1036
|
+
}
|
|
1037
|
+
return { deleted };
|
|
1038
|
+
});
|
|
1039
|
+
const startDev = Effect.fn(function* (id, props) {
|
|
1040
|
+
const path = yield* Path.Path;
|
|
1041
|
+
const dev = props.dev;
|
|
1042
|
+
const processKey = `dev:${id}`;
|
|
1043
|
+
const localUrl = dev?.url ??
|
|
1044
|
+
((dev?.port ?? props.port)
|
|
1045
|
+
? `http://localhost:${dev?.port ?? props.port}`
|
|
1046
|
+
: undefined);
|
|
1047
|
+
if (!dev?.command) {
|
|
1048
|
+
return localUrl;
|
|
1049
|
+
}
|
|
1050
|
+
yield* stopTrackedDevProcess(processKey);
|
|
1051
|
+
const cwd = dev.cwd ? path.resolve(dev.cwd) : path.resolve(props.path ?? ".");
|
|
1052
|
+
const env = {
|
|
1053
|
+
...processEnv(props.env),
|
|
1054
|
+
...processEnv(dev.env),
|
|
1055
|
+
...((dev.port ?? props.port)
|
|
1056
|
+
? { PORT: String(dev.port ?? props.port) }
|
|
1057
|
+
: {}),
|
|
1058
|
+
};
|
|
1059
|
+
const handle = yield* ChildProcess.make(dev.command, [], {
|
|
1060
|
+
shell: true,
|
|
1061
|
+
cwd,
|
|
1062
|
+
env,
|
|
1063
|
+
extendEnv: true,
|
|
1064
|
+
stdin: "inherit",
|
|
1065
|
+
stdout: "inherit",
|
|
1066
|
+
stderr: "inherit",
|
|
1067
|
+
detached: false,
|
|
1068
|
+
});
|
|
1069
|
+
devProcesses.set(processKey, handle);
|
|
1070
|
+
return localUrl;
|
|
1071
|
+
});
|
|
1072
|
+
const activeBindingEnv = (bindings) => bindings
|
|
1073
|
+
.filter((binding) => binding.action !== "delete")
|
|
1074
|
+
.map((binding) => binding.data?.env)
|
|
1075
|
+
.reduce((acc, env) => (env ? { ...acc, ...env } : acc), {});
|
|
1076
|
+
export const ComputeProvider = () => Provider.effect(Compute, Effect.gen(function* () {
|
|
1077
|
+
const client = yield* PrismaClient;
|
|
1078
|
+
return {
|
|
1079
|
+
stables: ["appId"],
|
|
1080
|
+
// Compute is a composite over App + Deployment. AppProvider owns nuke
|
|
1081
|
+
// enumeration to avoid deleting the same canonical App twice.
|
|
1082
|
+
list: () => Effect.succeed([]),
|
|
1083
|
+
diff: Effect.fn(function* ({ olds, news, output }) {
|
|
1084
|
+
if (!isInputObject(news))
|
|
1085
|
+
return undefined;
|
|
1086
|
+
if (output?.local || isPrismaDevId(output?.appId)) {
|
|
1087
|
+
return { action: "update" };
|
|
1088
|
+
}
|
|
1089
|
+
const oldProjectId = output?.projectId ?? unresolvedProjectIdOf(olds.project);
|
|
1090
|
+
const newProjectId = isResolved(news.project)
|
|
1091
|
+
? unresolvedProjectIdOf(news.project)
|
|
1092
|
+
: undefined;
|
|
1093
|
+
if (concreteIdsChanged(oldProjectId, newProjectId)) {
|
|
1094
|
+
// A different project is a distinct API uniqueness scope, so the
|
|
1095
|
+
// old and replacement Apps can safely coexist.
|
|
1096
|
+
return { action: "replace" };
|
|
1097
|
+
}
|
|
1098
|
+
if (isResolved(news.regionId) && news.regionId !== undefined) {
|
|
1099
|
+
const currentRegionId = output?.regionId ?? olds.regionId;
|
|
1100
|
+
if (currentRegionId !== undefined &&
|
|
1101
|
+
news.regionId !== currentRegionId) {
|
|
1102
|
+
return yield* Effect.fail(new Error(`Prisma Compute App region is immutable and cannot be changed atomically without deleting the live App first. Deploy a second Compute App under a different appName in the target region, cut traffic over, then remove the original.`));
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
// Source files/build output can change with no prop change, so
|
|
1106
|
+
// reconcile must rerun and decide from the computed artifact hash.
|
|
1107
|
+
return { action: "update" };
|
|
1108
|
+
}),
|
|
1109
|
+
read: Effect.fn(function* ({ id, output, olds }) {
|
|
1110
|
+
if (output?.local)
|
|
1111
|
+
return output;
|
|
1112
|
+
const appId = output?.appId && !isPrismaDevId(output.appId)
|
|
1113
|
+
? output.appId
|
|
1114
|
+
: undefined;
|
|
1115
|
+
const app = appId
|
|
1116
|
+
? yield* client
|
|
1117
|
+
.getApp(appId)
|
|
1118
|
+
.pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)))
|
|
1119
|
+
: yield* Effect.gen(function* () {
|
|
1120
|
+
const projectId = unresolvedProjectIdOf(olds.project);
|
|
1121
|
+
return projectId
|
|
1122
|
+
? yield* findApp(client, projectId, yield* createAppName(id, olds.appName), olds)
|
|
1123
|
+
: undefined;
|
|
1124
|
+
});
|
|
1125
|
+
if (!app)
|
|
1126
|
+
return undefined;
|
|
1127
|
+
const readDeployment = (id) => observeDeployment(client, id).pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)));
|
|
1128
|
+
const outputDeployment = output?.deploymentId
|
|
1129
|
+
? yield* readDeployment(output.deploymentId)
|
|
1130
|
+
: undefined;
|
|
1131
|
+
if (outputDeployment) {
|
|
1132
|
+
yield* ensureDeploymentMembership(client, app.id, outputDeployment, app.latestDeploymentId);
|
|
1133
|
+
}
|
|
1134
|
+
const latestDeployment = !outputDeployment && app.latestDeploymentId
|
|
1135
|
+
? yield* readDeployment(app.latestDeploymentId)
|
|
1136
|
+
: undefined;
|
|
1137
|
+
const deployment = outputDeployment ?? latestDeployment;
|
|
1138
|
+
const deploymentUrl = toDeploymentUrl(deployment?.previewDomain ?? undefined);
|
|
1139
|
+
const appUrl = toDeploymentUrl(app.appEndpointDomain);
|
|
1140
|
+
const promoted = app.latestDeploymentId !== null &&
|
|
1141
|
+
deployment?.id === app.latestDeploymentId;
|
|
1142
|
+
const attrs = {
|
|
1143
|
+
appId: app.id,
|
|
1144
|
+
deploymentId: deployment?.id,
|
|
1145
|
+
projectId: app.projectId ?? output?.projectId,
|
|
1146
|
+
appName: app.name,
|
|
1147
|
+
regionId: app.region.id,
|
|
1148
|
+
deploymentEndpointDomain: deployment?.previewDomain ?? undefined,
|
|
1149
|
+
deploymentUrl,
|
|
1150
|
+
appEndpointDomain: app.appEndpointDomain ?? output?.appEndpointDomain,
|
|
1151
|
+
url: promoted ? (appUrl ?? deploymentUrl) : deploymentUrl,
|
|
1152
|
+
promoted,
|
|
1153
|
+
previousDeploymentId: output?.previousDeploymentId,
|
|
1154
|
+
previousDeploymentAction: output?.previousDeploymentAction,
|
|
1155
|
+
readinessStatus: output?.readinessStatus,
|
|
1156
|
+
pendingDeploymentCleanup: output?.pendingDeploymentCleanup,
|
|
1157
|
+
environmentKeys: output?.environmentKeys,
|
|
1158
|
+
environmentVariableIds: output?.environmentVariableIds,
|
|
1159
|
+
environmentClass: output?.environmentClass ?? olds.envClass,
|
|
1160
|
+
environmentBranchId: output?.environmentBranchId,
|
|
1161
|
+
// A latest-deployment fallback is unrelated to a missing saved
|
|
1162
|
+
// deployment. Never transfer its artifact identity to other code.
|
|
1163
|
+
artifactHash: outputDeployment ? output?.artifactHash : undefined,
|
|
1164
|
+
local: false,
|
|
1165
|
+
};
|
|
1166
|
+
return appId ? attrs : Unowned(attrs);
|
|
1167
|
+
}),
|
|
1168
|
+
reconcile: Effect.fn(function* ({ id, news, olds, output, bindings }) {
|
|
1169
|
+
const bindingEnv = activeBindingEnv(bindings);
|
|
1170
|
+
const effectiveNews = {
|
|
1171
|
+
...news,
|
|
1172
|
+
appName: yield* createAppName(id, news.appName),
|
|
1173
|
+
env: {
|
|
1174
|
+
...bindingEnv,
|
|
1175
|
+
...news.env,
|
|
1176
|
+
},
|
|
1177
|
+
};
|
|
1178
|
+
yield* validateComputeProps(effectiveNews);
|
|
1179
|
+
const projectId = yield* resolveProjectId(effectiveNews.project);
|
|
1180
|
+
const artifact = yield* resolveArtifact(effectiveNews);
|
|
1181
|
+
const cleanupArtifact = artifact.file?.cleanup ?? Effect.void;
|
|
1182
|
+
const releaseArtifactOnFailure = (effect) => effect.pipe(Effect.onExit((exit) => Exit.isSuccess(exit) ? Effect.void : cleanupArtifact));
|
|
1183
|
+
const observedApp = effectiveNews.skipCodeUpload
|
|
1184
|
+
? yield* releaseArtifactOnFailure(findExistingApp(client, output).pipe(Effect.retry({
|
|
1185
|
+
while: isAppProvisioningNotFound,
|
|
1186
|
+
schedule: projectConsistencySchedule,
|
|
1187
|
+
})))
|
|
1188
|
+
: undefined;
|
|
1189
|
+
yield* releaseArtifactOnFailure(ensureSkipCodeUploadCanFork(effectiveNews, observedApp));
|
|
1190
|
+
const ensuredApp = yield* releaseArtifactOnFailure(ensureApp(client, projectId, effectiveNews, output, observedApp).pipe(Effect.retry({
|
|
1191
|
+
while: isAppProvisioningNotFound,
|
|
1192
|
+
schedule: projectConsistencySchedule,
|
|
1193
|
+
})));
|
|
1194
|
+
let app = ensuredApp.app;
|
|
1195
|
+
let preserveCreatedAppOnFailure = false;
|
|
1196
|
+
const cleanupCreatedAppOnFailure = (error) => ensuredApp.created && !preserveCreatedAppOnFailure
|
|
1197
|
+
? destroyApp(client, app.id).pipe(Effect.catch((cleanupError) => Effect.fail(aggregateCleanupFailure("App", app.id, `/v1/apps/${app.id}`, error, cleanupError))), Effect.andThen(() => Effect.fail(error)))
|
|
1198
|
+
: Effect.fail(error);
|
|
1199
|
+
let createdEnvironmentVariableIds = [];
|
|
1200
|
+
let deploymentConverged = false;
|
|
1201
|
+
return yield* Effect.gen(function* () {
|
|
1202
|
+
const currentEnvironmentScope = yield* resolveComputeEnvironmentScope(client, app, effectiveNews);
|
|
1203
|
+
const deploymentHash = yield* sha256Object({
|
|
1204
|
+
artifact: artifact.hash,
|
|
1205
|
+
branchId: app.branchId,
|
|
1206
|
+
environmentClass: currentEnvironmentScope.class,
|
|
1207
|
+
environmentBranchId: currentEnvironmentScope.branchId,
|
|
1208
|
+
});
|
|
1209
|
+
const outputArtifactHash = persistedArtifactHashValue(output?.artifactHash);
|
|
1210
|
+
const persistedDeployment = output?.deploymentId
|
|
1211
|
+
? yield* observeDeployment(client, output.deploymentId).pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)))
|
|
1212
|
+
: undefined;
|
|
1213
|
+
const terminalFailedDeploymentId = persistedDeployment?.status === "failed"
|
|
1214
|
+
? persistedDeployment.id
|
|
1215
|
+
: undefined;
|
|
1216
|
+
const promotionRequested = !(effectiveNews.skipPromote ?? false);
|
|
1217
|
+
let persistedPendingCleanup = output?.pendingDeploymentCleanup;
|
|
1218
|
+
const cleanupPreviousDeployment = Effect.fn(function* (deploymentId, action) {
|
|
1219
|
+
const observed = yield* observeDeployment(client, deploymentId).pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)));
|
|
1220
|
+
if (!observed) {
|
|
1221
|
+
return (action === "destroy" ? "destroyed" : "stopped");
|
|
1222
|
+
}
|
|
1223
|
+
yield* ensureDeploymentMembership(client, app.id, observed, app.latestDeploymentId);
|
|
1224
|
+
if (action === "destroy") {
|
|
1225
|
+
yield* destroyDeployment(client, deploymentId, effectiveNews);
|
|
1226
|
+
return "destroyed";
|
|
1227
|
+
}
|
|
1228
|
+
yield* stopDeploymentIdempotent(client, deploymentId).pipe(Effect.catchIf(isNotFound, () => Effect.void));
|
|
1229
|
+
yield* waitForDeploymentStatus(client, deploymentId, "stopped", effectiveNews).pipe(Effect.catchIf(isNotFound, () => Effect.succeed(undefined)));
|
|
1230
|
+
return "stopped";
|
|
1231
|
+
});
|
|
1232
|
+
if (terminalFailedDeploymentId !== undefined &&
|
|
1233
|
+
promotionRequested &&
|
|
1234
|
+
output?.promoted === true &&
|
|
1235
|
+
app.latestDeploymentId !== null &&
|
|
1236
|
+
app.latestDeploymentId !== terminalFailedDeploymentId) {
|
|
1237
|
+
return yield* Effect.fail(new AggregateError([], `Prisma Compute state preserves terminal failed deployment '${terminalFailedDeploymentId}', but App '${app.id}' reports deployment '${app.latestDeploymentId}' as latest. Alchemy cannot prove that the live deployment is the interrupted replacement, and the persisted failed deployment is not a safe rollback target. No new deployment was created and neither deployment was deleted.`));
|
|
1238
|
+
}
|
|
1239
|
+
// Apply persists the previous stable Attributes before reconcile.
|
|
1240
|
+
// If a prior attempt promoted a new generation, failed its stable
|
|
1241
|
+
// health check, and could not roll back, that durable output still
|
|
1242
|
+
// identifies the deployment we must restore while the App points
|
|
1243
|
+
// at the displaced unhealthy generation. Recover that transition
|
|
1244
|
+
// before changing env or creating another deployment, otherwise a
|
|
1245
|
+
// retry would use the unhealthy generation as its rollback target.
|
|
1246
|
+
if (promotionRequested &&
|
|
1247
|
+
output?.promoted === true &&
|
|
1248
|
+
output.deploymentId !== undefined &&
|
|
1249
|
+
terminalFailedDeploymentId === undefined &&
|
|
1250
|
+
outputArtifactHash !== deploymentHash &&
|
|
1251
|
+
app.latestDeploymentId !== null &&
|
|
1252
|
+
app.latestDeploymentId !== output.deploymentId) {
|
|
1253
|
+
const persistedDeploymentId = output.deploymentId;
|
|
1254
|
+
const displacedDeploymentId = app.latestDeploymentId;
|
|
1255
|
+
const rollback = yield* client
|
|
1256
|
+
.rollbackApp(app.id, {
|
|
1257
|
+
deploymentId: persistedDeploymentId,
|
|
1258
|
+
})
|
|
1259
|
+
.pipe(Effect.result);
|
|
1260
|
+
const observedAfterRollback = yield* waitForAppDeploymentTarget(client, app.id, persistedDeploymentId, effectiveNews).pipe(Effect.result);
|
|
1261
|
+
if (Result.isFailure(observedAfterRollback)) {
|
|
1262
|
+
return yield* Effect.fail(new AggregateError([
|
|
1263
|
+
...(Result.isFailure(rollback) ? [rollback.failure] : []),
|
|
1264
|
+
...(Result.isFailure(observedAfterRollback)
|
|
1265
|
+
? [observedAfterRollback.failure]
|
|
1266
|
+
: []),
|
|
1267
|
+
], `Prisma App '${app.id}' has live deployment '${displacedDeploymentId}', while Alchemy state preserves deployment '${persistedDeploymentId}' as the prior promoted generation. Recovery via POST /v1/apps/${app.id}/rollback did not converge, so no environment variables or new deployment were changed and neither deployment was deleted.`));
|
|
1268
|
+
}
|
|
1269
|
+
app = observedAfterRollback.success;
|
|
1270
|
+
yield* destroyDeployment(client, displacedDeploymentId, effectiveNews).pipe(Effect.catch((cleanupError) => Effect.fail(new AggregateError([
|
|
1271
|
+
...(Result.isFailure(rollback)
|
|
1272
|
+
? [rollback.failure]
|
|
1273
|
+
: []),
|
|
1274
|
+
cleanupError,
|
|
1275
|
+
], `Prisma App '${app.id}' was restored to deployment '${persistedDeploymentId}', but displaced deployment '${displacedDeploymentId}' could not be deleted. No new deployment was created; retry cleanup with DELETE /v1/deployments/${displacedDeploymentId}.`))));
|
|
1276
|
+
}
|
|
1277
|
+
if (output?.readinessStatus === "pending" &&
|
|
1278
|
+
outputArtifactHash !== deploymentHash) {
|
|
1279
|
+
return yield* Effect.fail(new Error(`Prisma Compute deployment '${output.deploymentId ?? "unknown"}' still has pending stable-endpoint readiness. Reconcile the existing generation before changing code or environment inputs.`));
|
|
1280
|
+
}
|
|
1281
|
+
// Keep one cleanup candidate. A non-live older candidate is
|
|
1282
|
+
// drained before any env/deploy mutation; a candidate that is
|
|
1283
|
+
// still live is derived from app.latestDeploymentId below.
|
|
1284
|
+
if (persistedPendingCleanup !== undefined &&
|
|
1285
|
+
output?.readinessStatus !== "pending" &&
|
|
1286
|
+
persistedPendingCleanup.deploymentId !== app.latestDeploymentId) {
|
|
1287
|
+
yield* cleanupPreviousDeployment(persistedPendingCleanup.deploymentId, persistedPendingCleanup.action);
|
|
1288
|
+
persistedPendingCleanup = undefined;
|
|
1289
|
+
}
|
|
1290
|
+
else if (persistedPendingCleanup?.deploymentId === app.latestDeploymentId) {
|
|
1291
|
+
persistedPendingCleanup = undefined;
|
|
1292
|
+
}
|
|
1293
|
+
const previousEnvironmentScope = environmentScope(olds?.envClass ?? output?.environmentClass ?? "production", output?.environmentBranchId);
|
|
1294
|
+
const previousEnvironmentVariableIds = output?.environmentVariableIds ?? {};
|
|
1295
|
+
const environmentResult = yield* syncComputeEnvironmentInternal(client, projectId, currentEnvironmentScope.class, effectiveNews.env, currentEnvironmentScope.branchId, sameEnvironmentScope(previousEnvironmentScope, currentEnvironmentScope)
|
|
1296
|
+
? previousEnvironmentVariableIds
|
|
1297
|
+
: {});
|
|
1298
|
+
createdEnvironmentVariableIds = environmentResult.createdIds;
|
|
1299
|
+
// Deployment creation snapshots the App branch environment. Remove
|
|
1300
|
+
// formerly-owned keys before creating it so deleted keys cannot be
|
|
1301
|
+
// captured into the new runtime. Any failure here happens before
|
|
1302
|
+
// deployment creation and rolls back newly-created variables.
|
|
1303
|
+
yield* cleanupRemovedComputeEnvironment(client, projectId, previousEnvironmentScope, previousEnvironmentVariableIds, currentEnvironmentScope, effectiveNews.env);
|
|
1304
|
+
let deployment = outputArtifactHash === deploymentHash
|
|
1305
|
+
? persistedDeployment
|
|
1306
|
+
: undefined;
|
|
1307
|
+
// A failed deployment is terminal and cannot be repaired by
|
|
1308
|
+
// replaying start/promotion. Preserve it as the cleanup target,
|
|
1309
|
+
// but create a fresh generation and do not delete the failed one
|
|
1310
|
+
// until the replacement has passed preview + stable readiness and
|
|
1311
|
+
// promotion is observed.
|
|
1312
|
+
if (persistedDeployment !== undefined &&
|
|
1313
|
+
(deployment !== undefined ||
|
|
1314
|
+
terminalFailedDeploymentId !== undefined)) {
|
|
1315
|
+
yield* ensureDeploymentMembership(client, app.id, persistedDeployment, app.latestDeploymentId);
|
|
1316
|
+
}
|
|
1317
|
+
if (terminalFailedDeploymentId !== undefined) {
|
|
1318
|
+
deployment = undefined;
|
|
1319
|
+
}
|
|
1320
|
+
let createdDeploymentId;
|
|
1321
|
+
const cleanupCreatedDeploymentOnFailure = (failedDeploymentId, error) => createdDeploymentId === failedDeploymentId
|
|
1322
|
+
? destroyDeployment(client, failedDeploymentId, effectiveNews).pipe(Effect.catch((cleanupError) => Effect.fail(aggregateCleanupFailure("deployment", failedDeploymentId, `/v1/deployments/${failedDeploymentId}`, error, cleanupError))), Effect.andThen(() => Effect.fail(error)))
|
|
1323
|
+
: Effect.fail(error);
|
|
1324
|
+
if (!deployment) {
|
|
1325
|
+
const created = yield* client.createAppDeployment(app.id, {
|
|
1326
|
+
portMapping: { http: artifact.port },
|
|
1327
|
+
skipCodeUpload: effectiveNews.skipCodeUpload,
|
|
1328
|
+
});
|
|
1329
|
+
createdDeploymentId = created.id;
|
|
1330
|
+
if (artifact.file !== undefined && !created.uploadUrl) {
|
|
1331
|
+
return yield* cleanupCreatedDeploymentOnFailure(created.id, new Error("Prisma deployment creation did not return an upload URL."));
|
|
1332
|
+
}
|
|
1333
|
+
if (created.uploadUrl && artifact.file !== undefined) {
|
|
1334
|
+
yield* uploadArtifact(created.uploadUrl, artifact.file, "application/gzip").pipe(Effect.catch((error) => cleanupCreatedDeploymentOnFailure(created.id, error)));
|
|
1335
|
+
}
|
|
1336
|
+
deployment = yield* observeDeployment(client, created.id).pipe(Effect.catchIf(isNotFound, () => Effect.succeed({
|
|
1337
|
+
id: created.id,
|
|
1338
|
+
type: "deployment",
|
|
1339
|
+
url: created.url,
|
|
1340
|
+
foundryVersionId: created.foundryVersionId,
|
|
1341
|
+
status: "new",
|
|
1342
|
+
previewDomain: null,
|
|
1343
|
+
createdAt: undefined,
|
|
1344
|
+
})), Effect.catch((error) => cleanupCreatedDeploymentOnFailure(created.id, error)));
|
|
1345
|
+
}
|
|
1346
|
+
if (!deployment) {
|
|
1347
|
+
return yield* Effect.fail(new Error("Prisma deployment could not be resolved after creation."));
|
|
1348
|
+
}
|
|
1349
|
+
const previousDeploymentId = terminalFailedDeploymentId ??
|
|
1350
|
+
persistedPendingCleanup?.deploymentId ??
|
|
1351
|
+
(app.latestDeploymentId !== null &&
|
|
1352
|
+
app.latestDeploymentId !== deployment.id
|
|
1353
|
+
? app.latestDeploymentId
|
|
1354
|
+
: null);
|
|
1355
|
+
const rollbackDeploymentId = previousDeploymentId === terminalFailedDeploymentId
|
|
1356
|
+
? null
|
|
1357
|
+
: previousDeploymentId;
|
|
1358
|
+
if (effectiveNews.start ?? true) {
|
|
1359
|
+
const currentDeployment = deployment;
|
|
1360
|
+
const currentDeploymentId = currentDeployment.id;
|
|
1361
|
+
deployment = yield* Effect.gen(function* () {
|
|
1362
|
+
if (currentDeployment.status !== "running" &&
|
|
1363
|
+
currentDeployment.status !== "provisioning") {
|
|
1364
|
+
yield* startDeploymentIdempotent(client, currentDeployment.id);
|
|
1365
|
+
}
|
|
1366
|
+
const running = yield* waitForDeploymentStatus(client, currentDeployment.id, "running", effectiveNews);
|
|
1367
|
+
yield* waitForDeploymentUrl(toDeploymentUrl(running.previewDomain), effectiveNews);
|
|
1368
|
+
return running;
|
|
1369
|
+
}).pipe(Effect.catch((error) => cleanupCreatedDeploymentOnFailure(currentDeploymentId, error)));
|
|
1370
|
+
}
|
|
1371
|
+
let appEndpointDomain = app.appEndpointDomain;
|
|
1372
|
+
let previousDeploymentAction = previousDeploymentId ? "still-active" : null;
|
|
1373
|
+
let promoted = app.latestDeploymentId === deployment.id;
|
|
1374
|
+
if (promotionRequested) {
|
|
1375
|
+
// Replay promotion even when latestDeploymentId already matches.
|
|
1376
|
+
// Promotion also repairs endpoint/custom-domain routing drift.
|
|
1377
|
+
preserveCreatedAppOnFailure = true;
|
|
1378
|
+
const promotedApp = yield* promoteAppObserved(client, app.id, deployment.id, effectiveNews);
|
|
1379
|
+
appEndpointDomain = promotedApp.appEndpointDomain;
|
|
1380
|
+
promoted = true;
|
|
1381
|
+
}
|
|
1382
|
+
const deploymentUrl = toDeploymentUrl(deployment.previewDomain);
|
|
1383
|
+
const appUrl = toDeploymentUrl(appEndpointDomain) ??
|
|
1384
|
+
toDeploymentUrl(deployment.previewDomain);
|
|
1385
|
+
let readinessStatus = "skipped";
|
|
1386
|
+
if (promoted && effectiveNews.verifyUrl !== false) {
|
|
1387
|
+
const readiness = yield* waitForDeploymentUrl(appUrl, effectiveNews).pipe(Effect.result);
|
|
1388
|
+
if (Result.isSuccess(readiness)) {
|
|
1389
|
+
readinessStatus = "ready";
|
|
1390
|
+
}
|
|
1391
|
+
else if (rollbackDeploymentId) {
|
|
1392
|
+
const rollback = yield* client
|
|
1393
|
+
.rollbackApp(app.id, {
|
|
1394
|
+
deploymentId: rollbackDeploymentId,
|
|
1395
|
+
})
|
|
1396
|
+
.pipe(Effect.result);
|
|
1397
|
+
const observedAfterRollback = yield* waitForAppDeploymentTarget(client, app.id, rollbackDeploymentId, effectiveNews).pipe(Effect.result);
|
|
1398
|
+
if (Result.isSuccess(observedAfterRollback)) {
|
|
1399
|
+
return yield* cleanupCreatedDeploymentOnFailure(deployment.id, Result.isSuccess(rollback)
|
|
1400
|
+
? readiness.failure
|
|
1401
|
+
: new AggregateError([readiness.failure, rollback.failure], `Prisma App '${app.id}' endpoint was restored to deployment '${rollbackDeploymentId}', but the rollback response was lost.`));
|
|
1402
|
+
}
|
|
1403
|
+
return yield* Effect.fail(new AggregateError([
|
|
1404
|
+
readiness.failure,
|
|
1405
|
+
...(Result.isFailure(rollback) ? [rollback.failure] : []),
|
|
1406
|
+
observedAfterRollback.failure,
|
|
1407
|
+
], `Prisma App '${app.id}' promoted deployment '${deployment.id}', but its stable endpoint failed readiness and rollback to deployment '${rollbackDeploymentId}' did not converge. Alchemy preserved the prior deployment in state and deleted neither deployment; the next reconcile will retry recovery via POST /v1/apps/${app.id}/rollback before making any new cloud changes.`));
|
|
1408
|
+
}
|
|
1409
|
+
else {
|
|
1410
|
+
// A first deployment has no safe rollback target. Never report
|
|
1411
|
+
// a successful stack deployment while the production endpoint
|
|
1412
|
+
// is unreachable. A newly created App can be fully cleaned up;
|
|
1413
|
+
// a pre-existing App is preserved for observed-state recovery.
|
|
1414
|
+
if (ensuredApp.created) {
|
|
1415
|
+
preserveCreatedAppOnFailure = false;
|
|
1416
|
+
}
|
|
1417
|
+
else {
|
|
1418
|
+
deploymentConverged = true;
|
|
1419
|
+
}
|
|
1420
|
+
if (terminalFailedDeploymentId !== undefined) {
|
|
1421
|
+
return yield* Effect.fail(new AggregateError([readiness.failure], `Prisma App '${app.id}' promoted replacement deployment '${deployment.id}', but stable readiness failed and persisted deployment '${terminalFailedDeploymentId}' is terminal failed, so no safe rollback target exists. Neither deployment was deleted; a retry will refuse to create another generation while the live target differs from persisted state.`));
|
|
1422
|
+
}
|
|
1423
|
+
return yield* Effect.fail(readiness.failure);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
deploymentConverged = true;
|
|
1427
|
+
let pendingDeploymentCleanup = promoted &&
|
|
1428
|
+
previousDeploymentId &&
|
|
1429
|
+
previousDeploymentId !== deployment.id
|
|
1430
|
+
? {
|
|
1431
|
+
deploymentId: previousDeploymentId,
|
|
1432
|
+
action: persistedPendingCleanup?.deploymentId ===
|
|
1433
|
+
previousDeploymentId
|
|
1434
|
+
? persistedPendingCleanup.action
|
|
1435
|
+
: previousDeploymentId === terminalFailedDeploymentId
|
|
1436
|
+
? "destroy"
|
|
1437
|
+
: effectiveNews.destroyOldDeployment
|
|
1438
|
+
? "destroy"
|
|
1439
|
+
: "stop",
|
|
1440
|
+
}
|
|
1441
|
+
: undefined;
|
|
1442
|
+
if (promoted && pendingDeploymentCleanup) {
|
|
1443
|
+
const cleanup = yield* cleanupPreviousDeployment(pendingDeploymentCleanup.deploymentId, pendingDeploymentCleanup.action).pipe(Effect.result);
|
|
1444
|
+
if (Result.isSuccess(cleanup)) {
|
|
1445
|
+
previousDeploymentAction = cleanup.success;
|
|
1446
|
+
pendingDeploymentCleanup = undefined;
|
|
1447
|
+
}
|
|
1448
|
+
else {
|
|
1449
|
+
yield* Effect.logWarning(`Prisma deployment '${pendingDeploymentCleanup.deploymentId}' cleanup is pending and will be retried before another Compute generation is created.`);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
return {
|
|
1453
|
+
appId: app.id,
|
|
1454
|
+
deploymentId: deployment.id,
|
|
1455
|
+
projectId,
|
|
1456
|
+
appName: app.name,
|
|
1457
|
+
regionId: app.region.id,
|
|
1458
|
+
deploymentEndpointDomain: deployment.previewDomain ?? undefined,
|
|
1459
|
+
deploymentUrl,
|
|
1460
|
+
appEndpointDomain,
|
|
1461
|
+
url: promoted ? appUrl : deploymentUrl,
|
|
1462
|
+
promoted,
|
|
1463
|
+
previousDeploymentId,
|
|
1464
|
+
previousDeploymentAction,
|
|
1465
|
+
readinessStatus,
|
|
1466
|
+
pendingDeploymentCleanup,
|
|
1467
|
+
environmentKeys: managedEnvKeys(effectiveNews.env),
|
|
1468
|
+
environmentVariableIds: environmentResult.ownedIds,
|
|
1469
|
+
environmentClass: currentEnvironmentScope.class,
|
|
1470
|
+
environmentBranchId: currentEnvironmentScope.branchId,
|
|
1471
|
+
artifactHash: Redacted.make(deploymentHash),
|
|
1472
|
+
local: false,
|
|
1473
|
+
};
|
|
1474
|
+
}).pipe(Effect.catch((error) => deploymentConverged
|
|
1475
|
+
? Effect.fail(error)
|
|
1476
|
+
: rollbackCreatedEnvironmentVariables(client, createdEnvironmentVariableIds, error)), Effect.catch(cleanupCreatedAppOnFailure), Effect.ensuring(cleanupArtifact));
|
|
1477
|
+
}),
|
|
1478
|
+
delete: Effect.fn(function* ({ olds, output }) {
|
|
1479
|
+
if (output.local || isPrismaDevId(output.appId)) {
|
|
1480
|
+
yield* stopTrackedDevProcess(output.appId);
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
yield* destroyComputeEnvironment(client, output.projectId, environmentScope(olds?.envClass ?? output.environmentClass ?? "production", output.environmentBranchId), output.environmentVariableIds);
|
|
1484
|
+
yield* destroyApp(client, output.appId);
|
|
1485
|
+
}),
|
|
1486
|
+
tail: ({ output }) => output.deploymentId
|
|
1487
|
+
? tailDeploymentLogs(client, output.deploymentId)
|
|
1488
|
+
: Stream.empty,
|
|
1489
|
+
};
|
|
1490
|
+
}));
|
|
1491
|
+
export const ComputeDevProvider = () => Provider.effect(Compute, Effect.gen(function* () {
|
|
1492
|
+
const ctx = yield* AlchemyContext;
|
|
1493
|
+
return {
|
|
1494
|
+
stables: ["appId"],
|
|
1495
|
+
list: () => Effect.succeed([]),
|
|
1496
|
+
diff: Effect.fn(function* () {
|
|
1497
|
+
return { action: "update" };
|
|
1498
|
+
}),
|
|
1499
|
+
read: Effect.fn(function* ({ output }) {
|
|
1500
|
+
return output?.local ? output : undefined;
|
|
1501
|
+
}),
|
|
1502
|
+
reconcile: Effect.fn(function* ({ id, news, output, bindings }) {
|
|
1503
|
+
const bindingEnv = activeBindingEnv(bindings);
|
|
1504
|
+
const effectiveNews = {
|
|
1505
|
+
...news,
|
|
1506
|
+
env: {
|
|
1507
|
+
...bindingEnv,
|
|
1508
|
+
...news.env,
|
|
1509
|
+
},
|
|
1510
|
+
};
|
|
1511
|
+
yield* validateComputeProps(effectiveNews);
|
|
1512
|
+
const projectId = yield* resolveProjectId(effectiveNews.project);
|
|
1513
|
+
if (!ctx.dev) {
|
|
1514
|
+
return yield* Effect.fail(new Error("ComputeDevProvider requires Alchemy dev mode."));
|
|
1515
|
+
}
|
|
1516
|
+
const localUrl = yield* startDev(id, effectiveNews);
|
|
1517
|
+
return {
|
|
1518
|
+
appId: output?.appId ?? `dev:${id}`,
|
|
1519
|
+
deploymentId: undefined,
|
|
1520
|
+
projectId,
|
|
1521
|
+
appName: effectiveNews.appName ?? id,
|
|
1522
|
+
regionId: effectiveNews.regionId ?? "us-east-1",
|
|
1523
|
+
deploymentEndpointDomain: localUrl,
|
|
1524
|
+
deploymentUrl: localUrl,
|
|
1525
|
+
appEndpointDomain: localUrl,
|
|
1526
|
+
url: localUrl,
|
|
1527
|
+
promoted: false,
|
|
1528
|
+
previousDeploymentId: undefined,
|
|
1529
|
+
previousDeploymentAction: undefined,
|
|
1530
|
+
readinessStatus: "skipped",
|
|
1531
|
+
pendingDeploymentCleanup: undefined,
|
|
1532
|
+
environmentKeys: managedEnvKeys(effectiveNews.env),
|
|
1533
|
+
environmentVariableIds: {},
|
|
1534
|
+
environmentClass: effectiveNews.envClass ?? "production",
|
|
1535
|
+
environmentBranchId: null,
|
|
1536
|
+
artifactHash: undefined,
|
|
1537
|
+
local: true,
|
|
1538
|
+
};
|
|
1539
|
+
}),
|
|
1540
|
+
delete: Effect.fn(function* ({ output }) {
|
|
1541
|
+
yield* stopTrackedDevProcess(output.appId);
|
|
1542
|
+
}),
|
|
1543
|
+
};
|
|
1544
|
+
}));
|
|
1545
|
+
//# sourceMappingURL=Compute.js.map
|