@stacksjs/ts-cloud 0.5.16 → 0.5.17
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/dist/bin/cli.js +3 -3
- package/dist/index.js +1 -8
- package/package.json +3 -3
package/dist/bin/cli.js
CHANGED
|
@@ -3639,7 +3639,7 @@ export const queue = __handlers.queue
|
|
|
3639
3639
|
export const cli = __handlers.cli
|
|
3640
3640
|
`}function J3(){return S9(oD($3(import.meta.url)),"runtime","adapter.ts")}function $X($,J,Y){for(let Q of $??[])Y?.(`build: ${Q}`),mD(Q,{stdio:"inherit",cwd:J})}function J6($){return pD("sha256").update($).digest("hex")}function JW($,J,Y){return`deployments/${$}/${J}/${Y}.zip`}async function c9($){let J=eD($.projectRoot??process.cwd()),{app:Y}=$;if(!$.skipBuild)$X(Y.build,J,$.onStep);let Q=Y.entry;if(!Q)throw Error("serverless app: `entry` is required to package a Node/Bun application");let G=sD(Q)?Q:S9(J,Q),Z=nD(S9(aD(),"tscloud-pkg-"));try{rD(J3(),S9(Z,"adapter.ts"));let W=S9(Z,"bootstrap.ts");tD(W,eH({entryImport:G,adapterImport:"./adapter"})),$.onStep?.("bundling application");let U=await Bun.build({entrypoints:[W],target:Y.kind==="bun"?"bun":"node",format:"esm",minify:!1,sourcemap:"none"});if(!U.success){let F=U.logs.map((B)=>String(B)).join(`
|
|
3641
3641
|
`);throw Error(`serverless app bundle failed:
|
|
3642
|
-
${F}`)}let z=U.outputs[0],_=Buffer.from(await z.arrayBuffer()),H="index",X=C8([{name:`${H}.mjs`,data:_}]);return{zip:X,bundle:_,sha256:J6(X),handlerFile:H,handlers:{http:Y.handlers?.http??`${H}.http`,queue:Y.handlers?.queue??`${H}.queue`,cli:Y.handlers?.cli??`${H}.cli`},bundleBytes:_.length}}finally{iD(Z,{recursive:!0,force:!0})}}function Y3($){if(!$)return"22";let J=String($).match(/(\d+)/);return J?J[1]:"22"}function Y6($){let J=$.kind??"node";if(J==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:$.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(J==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:$.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let Y=Y3($.runtimeVersion);if($.runtime!=="provided.al2023"&&JX.includes(Y))return{lambdaRuntime:$.runtime&&$.runtime.startsWith("nodejs")?$.runtime:`nodejs${Y}.x`,kind:"node",version:Y,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:Y,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function l9($,J,Y){if($.queues===!1)return[];if($.queues===void 0||$.queues===!0)return[{name:`${J}-${Y}-default`}];return $.queues.map((Q)=>{if(typeof Q==="string")return{name:`${J}-${Y}-${Q}`};let[G,Z]=Object.entries(Q)[0];return{name:`${J}-${Y}-${G}`,concurrency:Z}})}function YW($,J,Y){return l9($,J,Y).map((Q)=>Q.name)}function QW($){let{app:J,environment:Y,handlers:Q}=$,G=$.config.project.slug,Z=Y6(J).lambdaRuntime,W=J.architecture??"x86_64",U=$.config.project.region,z={http:`${G}-${Y}-http`,queue:`${G}-${Y}-queue`,cli:`${G}-${Y}-cli`};if(J.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let _=l9(J,G,Y),H=_.map((O0)=>O0.name),X=H.length>0,F=J.logRetention??14,B=J.packaging==="image",V=(J.scheduler??"on")!=="off",K=(J.cache?.driver??"dynamodb")==="dynamodb",L=Boolean(J.assets),E=aY(G,Y),A=J.tmpStorage??512,j={},q={},M=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:w.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:w.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${G}-${Y}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[w.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${G}/${Y}/*`),w.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${G}/${Y}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[w.sub(`arn:aws:s3:::${E}`),w.sub(`arn:aws:s3:::${E}/*`),...J.storage?.bucket?[w.sub(`arn:aws:s3:::${J.storage.bucket}`),w.sub(`arn:aws:s3:::${J.storage.bucket}/*`)]:[]]}]}}];if(X)M[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:w.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${G}-${Y}-*`)});if(K)M[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:w.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${G}-${Y}-cache*`)});let T=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(J.vpc?.subnets?.length)T.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");j.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${G}-${Y}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:T,Policies:M}};let R=(O0)=>({TSCLOUD_LAMBDA_MODE:O0,TSCLOUD_ENV:Y,...J.octane?{TSCLOUD_OCTANE:"1"}:{},...J.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...K?{TSCLOUD_CACHE_TABLE:`${G}-${Y}-cache`}:{},...X?{TSCLOUD_QUEUE:H[0]}:{},...J.env??{}}),S=Boolean(J.efs),N=typeof J.efs==="object"?J.efs:{},C=N.mountPath??"/mnt/local",x=S&&!N.accessPointArn,k=N.accessPointArn??(x?w.getAtt("EfsAccessPoint","Arn"):void 0),b=J.vpc?.subnets??[],m=b.length>0,y=J.cache?.driver==="elasticache"||J.database?.connection==="aurora-serverless"||Boolean(J.rdsProxy)||S;if(y&&!m)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let u=m?{VpcConfig:{SubnetIds:b,SecurityGroupIds:[...J.vpc?.securityGroups??[],...y?[w.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},J0=x?b.map((O0,h0)=>`EfsMountTarget${h0}`):[],Y0=S?{FileSystemConfigs:[{Arn:k,LocalMountPath:C}]}:{};if(S)M[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function a(O0,h0,o0,d0,P$,Y5,z9,g2=A){j[`${O0}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${h0}`,RetentionInDays:F}};let dJ=B?{PackageType:"Image",Code:{ImageUri:w.ref("ImageUri")},...J.kind==="php"?{}:{ImageConfig:{Command:[o0]}}}:{Runtime:Z,Handler:o0,Code:{S3Bucket:w.ref("ArtifactBucket"),S3Key:w.ref("ArtifactKey")},...$.runtimeLayers?.length?{Layers:$.runtimeLayers}:{}};j[O0]={Type:"AWS::Lambda::Function",DependsOn:[`${O0}LogGroup`,...J0],Properties:{FunctionName:h0,Architectures:[W],MemorySize:P$,Timeout:Y5,Role:w.getAtt("AppRole","Arn"),Environment:{Variables:R(d0)},EphemeralStorage:{Size:g2},...dJ,...z9!==void 0?{ReservedConcurrentExecutions:z9}:{},...u,...Y0}}}if(a("HttpFunction",z.http,Q.http,"http",J.memory??1024,J.timeout??28,J.concurrency,A),a("CliFunction",z.cli,Q.cli,"cli",J.cliMemory??1024,J.cliTimeout??900,void 0,J.cliTmpStorage??A),X)a("QueueFunction",z.queue,Q.queue,"queue",J.queueMemory??1024,J.queueTimeout??120,void 0,J.queueTmpStorage??A);let s=(J.provisionedConcurrency??0)>0?J.provisionedConcurrency:0,$0=["HttpFunction","CliFunction",...X?["QueueFunction"]:[]];if(s)for(let O0 of $0)j[`${O0}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:w.ref(O0)}},j[`${O0}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:w.ref(O0),Name:"live",FunctionVersion:w.getAtt(`${O0}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:s}}};let w0=(O0)=>s?w.ref(`${O0}Alias`):w.getAtt(O0,"Arn"),b0=(O0)=>s?w.ref(`${O0}Alias`):w.ref(O0);j.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${G}-${Y}`,ProtocolType:"HTTP"}},j.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:w.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:w0("HttpFunction"),PayloadFormatVersion:"2.0"}},j.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:w.ref("HttpApi"),RouteKey:"$default",Target:w.join("/",["integrations",w.ref("HttpIntegration")])}},j.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:w.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},j.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:b0("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:w.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},q.HttpApiEndpoint={Description:"HTTP API endpoint",Value:w.getAtt("HttpApi","ApiEndpoint")},q.HttpApiId={Description:"HTTP API id",Value:w.ref("HttpApi")};let S0=(Array.isArray(J.domain)?J.domain:J.domain?[J.domain]:[]).filter(Boolean);if(S0.length){if(!J.certificateArn&&!J.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let O0=J.certificateArn;if(!O0)j.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:S0[0],...S0.length>1?{SubjectAlternativeNames:S0.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:S0.map((h0)=>({DomainName:h0,HostedZoneId:J.hostedZoneId}))}},O0=w.ref("HttpCertificate");S0.forEach((h0,o0)=>{let d0=`HttpDomain${o0}`;if(j[d0]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:h0,DomainNameConfigurations:[{CertificateArn:O0,EndpointType:"REGIONAL"}]}},j[`HttpApiMapping${o0}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:w.ref("HttpApi"),DomainName:w.ref(d0),Stage:"$default"}},J.hostedZoneId)j[`HttpDomainRecord${o0}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:J.hostedZoneId,Name:h0,Type:"A",AliasTarget:{DNSName:w.getAtt(d0,"RegionalDomainName"),HostedZoneId:w.getAtt(d0,"RegionalHostedZoneId")}}};q[`CustomDomain${o0}`]={Description:`Custom domain ${h0}`,Value:h0},q[`CustomDomainTarget${o0}`]={Description:`Point ${h0} (CNAME/alias) at this APIGW regional domain`,Value:w.getAtt(d0,"RegionalDomainName")}})}if(X)j.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${G}-${Y}-dlq`,MessageRetentionPeriod:1209600}},_.forEach((O0,h0)=>{let o0=`AppQueue${h0}`,d0=J.queueTimeout??120;j[o0]={Type:"AWS::SQS::Queue",Properties:{QueueName:O0.name,VisibilityTimeout:Math.min(43200,d0*6),RedrivePolicy:{deadLetterTargetArn:w.getAtt("AppQueueDlq","Arn"),maxReceiveCount:J.queueTries??3}}};let P$=O0.concurrency??J.queueConcurrency;j[`${o0}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:w.getAtt(o0,"Arn"),FunctionName:b0("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...P$?{ScalingConfig:{MaximumConcurrency:Math.max(2,P$)}}:{}}},q[`QueueUrl${h0}`]={Description:`Queue URL: ${O0.name}`,Value:w.ref(o0)}});if(V)j.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${G}-${Y}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:w0("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},j.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:b0("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:w.getAtt("SchedulerRule","Arn")}};if(J.warm&&J.warm>0){let h0={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},o0=(J.warmFunctions??["http"]).filter((d0)=>d0!=="queue"||X);for(let d0 of o0){let P$=d0.charAt(0).toUpperCase()+d0.slice(1),Y5=Math.ceil(J.warm/5),z9=0;for(let g2=0;g2<Y5;g2++){let dJ=Math.min(5,J.warm-z9);j[`Warmer${P$}Rule${g2}`]={Type:"AWS::Events::Rule",Properties:{Name:`${G}-${Y}-warmer-${d0}-${g2}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:dJ},(Xy,QA)=>({Id:`warm-${d0}-${g2}-${QA}`,Arn:w.getAtt(h0[d0],"Arn"),Input:JSON.stringify({warmer:!0})}))}},z9+=dJ}j[`Warmer${P$}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:w.ref(h0[d0]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:w.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${G}-${Y}-warmer-${d0}-*`)}}}}if(K)j.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${G}-${Y}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},q.CacheTableName={Description:"DynamoDB cache table",Value:w.ref("CacheTable")};if(L){if(j.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:E,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},j.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${G}-${Y}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},j.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:w.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:w.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...J.assetDomain?{Aliases:[J.assetDomain],ViewerCertificate:{AcmCertificateArn:J.assetCertificateArn??w.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},J.assetDomain){if(!J.assetCertificateArn){if(!J.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(U!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${U}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);j.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:J.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:J.assetDomain,HostedZoneId:J.hostedZoneId}]}}}if(J.hostedZoneId)j.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:J.hostedZoneId,Name:J.assetDomain,Type:"A",AliasTarget:{DNSName:w.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};q.AssetDomain={Description:"Custom asset CDN host",Value:J.assetDomain}}j.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:w.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:w.sub(`arn:aws:s3:::${E}/*`),Condition:{StringEquals:{"AWS:SourceArn":w.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},q.AssetsBucketName={Description:"Assets bucket",Value:w.ref("AssetsBucket")},q.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:w.getAtt("AssetsDistribution","DomainName")}}if(J.firewall?.enabled){let O0=[],h0=0;if(J.firewall.rateLimit)O0.push({Name:"rate-limit",Priority:h0++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:J.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${G}-${Y}-rate`}});let o0={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let d0 of J.firewall.rules??[]){let P$=o0[d0];if(!P$)continue;O0.push({Name:`managed-${d0}`,Priority:h0++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:P$}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${G}-${Y}-${d0}`}})}j.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${G}-${Y}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:O0,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${G}-${Y}-waf`}}},j.WebAclAssociation={Type:"AWS::WAFv2::WebACLAssociation",DependsOn:["HttpStage"],Properties:{ResourceArn:w.sub("arn:aws:apigateway:${AWS::Region}::/apis/${HttpApi}/stages/$default"),WebACLArn:w.getAtt("WebAcl","Arn")}}}if(m&&y){if(!J.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");j.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:J.vpc.id,GroupDescription:`${G}-${Y} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(x)j.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${G}-${Y}-efs`}]}},b.forEach((O0,h0)=>{j[`EfsMountTarget${h0}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:w.ref("EfsFileSystem"),SubnetId:O0,SecurityGroups:[w.getAtt("DataSecurityGroup","GroupId")]}}}),j.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:w.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},q.EfsFileSystemId={Description:"EFS file system id",Value:w.ref("EfsFileSystem")};if(J.cache?.driver==="elasticache")j.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${G}-${Y} cache subnets`,SubnetIds:b}},j.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${G}-${Y}-cache`,ReplicationGroupDescription:`${G}-${Y} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:w.ref("CacheSubnetGroup"),SecurityGroupIds:[w.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},q.CacheEndpoint={Description:"Redis primary endpoint",Value:w.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(J.database?.connection==="aurora-serverless")j.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${G}-${Y} db subnets`,SubnetIds:b}},j.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${G}/${Y}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},j.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${G}-${Y}-db`,DatabaseName:"app",MasterUsername:w.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:w.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:J.database?.minCapacity??0.5,MaxCapacity:J.database?.maxCapacity??4},DBSubnetGroupName:w.ref("DbSubnetGroup"),VpcSecurityGroupIds:[w.getAtt("DataSecurityGroup","GroupId")]}},j.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:w.ref("DbCluster")}},q.DbEndpoint={Description:"Aurora cluster endpoint",Value:w.getAtt("DbCluster","Endpoint.Address")};if(J.rdsProxy&&J.database?.connection==="aurora-serverless")j.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:w.ref("DbSecret")}]}}]}},j.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof J.rdsProxy==="object"&&J.rdsProxy.name?J.rdsProxy.name:`${G}-${Y}-proxy`,EngineFamily:"MYSQL",RoleArn:w.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:w.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:b,VpcSecurityGroupIds:[w.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},j.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:w.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[w.ref("DbCluster")]}},q.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:w.getAtt("DbProxy","Endpoint")};if(q.HttpFunctionName={Description:"HTTP function name",Value:w.ref("HttpFunction")},q.CliFunctionName={Description:"CLI function name",Value:w.ref("CliFunction")},X)q.QueueFunctionName={Description:"Queue function name",Value:w.ref("QueueFunction")};let F$={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${$.config.project.name} (${G}-${Y})`,Parameters:B?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:j,Outputs:q},g$={};for(let O0 of Object.values(j))g$[O0.Type]=(g$[O0.Type]??0)+1;return{template:F$,functionNames:z,queueNames:H,resourceSummary:g$}}function QX($){let J=`php${$.replace(".","")}`;return YX.map((Y)=>`${J}-php-${Y}`)}function GW($,J){let Y=`php${$.replace(".","")}`,Q=QX($).join(" \\\n "),G=`/opt/remi/${Y}/root`,Z=`/etc/opt/remi/${Y}`;return`${J?`FROM almalinux:9 AS ${J}`:"FROM almalinux:9"}
|
|
3642
|
+
${F}`)}let z=U.outputs[0],_=Buffer.from(await z.arrayBuffer()),H="index",X=C8([{name:`${H}.mjs`,data:_}]);return{zip:X,bundle:_,sha256:J6(X),handlerFile:H,handlers:{http:Y.handlers?.http??`${H}.http`,queue:Y.handlers?.queue??`${H}.queue`,cli:Y.handlers?.cli??`${H}.cli`},bundleBytes:_.length}}finally{iD(Z,{recursive:!0,force:!0})}}function Y3($){if(!$)return"22";let J=String($).match(/(\d+)/);return J?J[1]:"22"}function Y6($){let J=$.kind??"node";if(J==="php")return{lambdaRuntime:"provided.al2023",kind:"php",version:$.phpVersion??"8.3",usesLayer:!0,layerKind:"php",layerEnvVar:"TSCLOUD_PHP_LAYER_ARN"};if(J==="bun")return{lambdaRuntime:"provided.al2023",kind:"bun",version:$.runtimeVersion??"latest",usesLayer:!0,layerKind:"bun",layerEnvVar:"TSCLOUD_BUN_LAYER_ARN"};let Y=Y3($.runtimeVersion);if($.runtime!=="provided.al2023"&&JX.includes(Y))return{lambdaRuntime:$.runtime&&$.runtime.startsWith("nodejs")?$.runtime:`nodejs${Y}.x`,kind:"node",version:Y,usesLayer:!1};return{lambdaRuntime:"provided.al2023",kind:"node",version:Y,usesLayer:!0,layerKind:"node",layerEnvVar:"TSCLOUD_NODE_LAYER_ARN"}}function l9($,J,Y){if($.queues===!1)return[];if($.queues===void 0||$.queues===!0)return[{name:`${J}-${Y}-default`}];return $.queues.map((Q)=>{if(typeof Q==="string")return{name:`${J}-${Y}-${Q}`};let[G,Z]=Object.entries(Q)[0];return{name:`${J}-${Y}-${G}`,concurrency:Z}})}function YW($,J,Y){return l9($,J,Y).map((Q)=>Q.name)}function QW($){let{app:J,environment:Y,handlers:Q}=$,G=$.config.project.slug,Z=Y6(J).lambdaRuntime,W=J.architecture??"x86_64",U=$.config.project.region,z={http:`${G}-${Y}-http`,queue:`${G}-${Y}-queue`,cli:`${G}-${Y}-cli`};if(J.gatewayVersion===1)throw Error("serverless app: `gatewayVersion: 1` (REST API) is not supported — ts-cloud uses API Gateway HTTP API (v2). Remove `gatewayVersion` or set it to 2.");let _=l9(J,G,Y),H=_.map((O0)=>O0.name),X=H.length>0,F=J.logRetention??14,B=J.packaging==="image",V=(J.scheduler??"on")!=="off",K=(J.cache?.driver??"dynamodb")==="dynamodb",L=Boolean(J.assets),E=aY(G,Y),A=J.tmpStorage??512,j={},q={},M=[{PolicyName:"tscloud-serverless-app",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],Resource:w.sub("arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*")},{Effect:"Allow",Action:["lambda:InvokeFunction"],Resource:w.sub(`arn:aws:lambda:\${AWS::Region}:\${AWS::AccountId}:function:${G}-${Y}-*`)},{Effect:"Allow",Action:["secretsmanager:GetSecretValue","ssm:GetParameter","ssm:GetParameters","ssm:GetParametersByPath"],Resource:[w.sub(`arn:aws:secretsmanager:\${AWS::Region}:\${AWS::AccountId}:secret:${G}/${Y}/*`),w.sub(`arn:aws:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/${G}/${Y}/*`)]},{Effect:"Allow",Action:["s3:GetObject","s3:PutObject","s3:DeleteObject","s3:ListBucket"],Resource:[w.sub(`arn:aws:s3:::${E}`),w.sub(`arn:aws:s3:::${E}/*`),...J.storage?.bucket?[w.sub(`arn:aws:s3:::${J.storage.bucket}`),w.sub(`arn:aws:s3:::${J.storage.bucket}/*`)]:[]]}]}}];if(X)M[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["sqs:SendMessage","sqs:ReceiveMessage","sqs:DeleteMessage","sqs:GetQueueAttributes","sqs:GetQueueUrl"],Resource:w.sub(`arn:aws:sqs:\${AWS::Region}:\${AWS::AccountId}:${G}-${Y}-*`)});if(K)M[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["dynamodb:GetItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem","dynamodb:Query","dynamodb:Scan","dynamodb:BatchGetItem","dynamodb:BatchWriteItem"],Resource:w.sub(`arn:aws:dynamodb:\${AWS::Region}:\${AWS::AccountId}:table/${G}-${Y}-cache*`)});let T=["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"];if(J.vpc?.subnets?.length)T.push("arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole");j.AppRole={Type:"AWS::IAM::Role",Properties:{RoleName:`${G}-${Y}-app-role`,AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"lambda.amazonaws.com"},Action:"sts:AssumeRole"}]},ManagedPolicyArns:T,Policies:M}};let R=(O0)=>({TSCLOUD_LAMBDA_MODE:O0,TSCLOUD_ENV:Y,...J.octane?{TSCLOUD_OCTANE:"1"}:{},...J.scheduler==="sub-minute"?{TSCLOUD_SCHEDULER:"sub-minute"}:{},...K?{TSCLOUD_CACHE_TABLE:`${G}-${Y}-cache`}:{},...X?{TSCLOUD_QUEUE:H[0]}:{},...J.env??{}}),S=Boolean(J.efs),N=typeof J.efs==="object"?J.efs:{},C=N.mountPath??"/mnt/local",x=S&&!N.accessPointArn,k=N.accessPointArn??(x?w.getAtt("EfsAccessPoint","Arn"):void 0),b=J.vpc?.subnets??[],m=b.length>0,y=J.cache?.driver==="elasticache"||J.database?.connection==="aurora-serverless"||Boolean(J.rdsProxy)||S;if(y&&!m)throw Error("serverless app: elasticache / aurora-serverless / rdsProxy / efs require app.vpc.subnets (private subnets) to be set.");let u=m?{VpcConfig:{SubnetIds:b,SecurityGroupIds:[...J.vpc?.securityGroups??[],...y?[w.getAtt("DataSecurityGroup","GroupId")]:[]]}}:{},J0=x?b.map((O0,h0)=>`EfsMountTarget${h0}`):[],Y0=S?{FileSystemConfigs:[{Arn:k,LocalMountPath:C}]}:{};if(S)M[0].PolicyDocument.Statement.push({Effect:"Allow",Action:["elasticfilesystem:ClientMount","elasticfilesystem:ClientWrite","elasticfilesystem:ClientRootAccess","elasticfilesystem:DescribeMountTargets"],Resource:"*"});function a(O0,h0,o0,d0,P$,Y5,z9,g2=A){j[`${O0}LogGroup`]={Type:"AWS::Logs::LogGroup",Properties:{LogGroupName:`/aws/lambda/${h0}`,RetentionInDays:F}};let dJ=B?{PackageType:"Image",Code:{ImageUri:w.ref("ImageUri")},...J.kind==="php"?{}:{ImageConfig:{Command:[o0]}}}:{Runtime:Z,Handler:o0,Code:{S3Bucket:w.ref("ArtifactBucket"),S3Key:w.ref("ArtifactKey")},...$.runtimeLayers?.length?{Layers:$.runtimeLayers}:{}};j[O0]={Type:"AWS::Lambda::Function",DependsOn:[`${O0}LogGroup`,...J0],Properties:{FunctionName:h0,Architectures:[W],MemorySize:P$,Timeout:Y5,Role:w.getAtt("AppRole","Arn"),Environment:{Variables:R(d0)},EphemeralStorage:{Size:g2},...dJ,...z9!==void 0?{ReservedConcurrentExecutions:z9}:{},...u,...Y0}}}if(a("HttpFunction",z.http,Q.http,"http",J.memory??1024,J.timeout??28,J.concurrency,A),a("CliFunction",z.cli,Q.cli,"cli",J.cliMemory??1024,J.cliTimeout??900,void 0,J.cliTmpStorage??A),X)a("QueueFunction",z.queue,Q.queue,"queue",J.queueMemory??1024,J.queueTimeout??120,void 0,J.queueTmpStorage??A);let s=(J.provisionedConcurrency??0)>0?J.provisionedConcurrency:0,$0=["HttpFunction","CliFunction",...X?["QueueFunction"]:[]];if(s)for(let O0 of $0)j[`${O0}Version`]={Type:"AWS::Lambda::Version",DeletionPolicy:"Retain",Properties:{FunctionName:w.ref(O0)}},j[`${O0}Alias`]={Type:"AWS::Lambda::Alias",Properties:{FunctionName:w.ref(O0),Name:"live",FunctionVersion:w.getAtt(`${O0}Version`,"Version"),ProvisionedConcurrencyConfig:{ProvisionedConcurrentExecutions:s}}};let w0=(O0)=>s?w.ref(`${O0}Alias`):w.getAtt(O0,"Arn"),b0=(O0)=>s?w.ref(`${O0}Alias`):w.ref(O0);j.HttpApi={Type:"AWS::ApiGatewayV2::Api",Properties:{Name:`${G}-${Y}`,ProtocolType:"HTTP"}},j.HttpIntegration={Type:"AWS::ApiGatewayV2::Integration",Properties:{ApiId:w.ref("HttpApi"),IntegrationType:"AWS_PROXY",IntegrationUri:w0("HttpFunction"),PayloadFormatVersion:"2.0"}},j.HttpRoute={Type:"AWS::ApiGatewayV2::Route",Properties:{ApiId:w.ref("HttpApi"),RouteKey:"$default",Target:w.join("/",["integrations",w.ref("HttpIntegration")])}},j.HttpStage={Type:"AWS::ApiGatewayV2::Stage",Properties:{ApiId:w.ref("HttpApi"),StageName:"$default",AutoDeploy:!0}},j.HttpPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:b0("HttpFunction"),Action:"lambda:InvokeFunction",Principal:"apigateway.amazonaws.com",SourceArn:w.sub("arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HttpApi}/*/*")}},q.HttpApiEndpoint={Description:"HTTP API endpoint",Value:w.getAtt("HttpApi","ApiEndpoint")},q.HttpApiId={Description:"HTTP API id",Value:w.ref("HttpApi")};let S0=(Array.isArray(J.domain)?J.domain:J.domain?[J.domain]:[]).filter(Boolean);if(S0.length){if(!J.certificateArn&&!J.hostedZoneId)throw Error("serverless app: a custom `domain` needs either `certificateArn` (pre-issued, regional) or `hostedZoneId` (to auto-issue + validate an ACM cert).");let O0=J.certificateArn;if(!O0)j.HttpCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:S0[0],...S0.length>1?{SubjectAlternativeNames:S0.slice(1)}:{},ValidationMethod:"DNS",DomainValidationOptions:S0.map((h0)=>({DomainName:h0,HostedZoneId:J.hostedZoneId}))}},O0=w.ref("HttpCertificate");S0.forEach((h0,o0)=>{let d0=`HttpDomain${o0}`;if(j[d0]={Type:"AWS::ApiGatewayV2::DomainName",Properties:{DomainName:h0,DomainNameConfigurations:[{CertificateArn:O0,EndpointType:"REGIONAL"}]}},j[`HttpApiMapping${o0}`]={Type:"AWS::ApiGatewayV2::ApiMapping",DependsOn:["HttpStage"],Properties:{ApiId:w.ref("HttpApi"),DomainName:w.ref(d0),Stage:"$default"}},J.hostedZoneId)j[`HttpDomainRecord${o0}`]={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:J.hostedZoneId,Name:h0,Type:"A",AliasTarget:{DNSName:w.getAtt(d0,"RegionalDomainName"),HostedZoneId:w.getAtt(d0,"RegionalHostedZoneId")}}};q[`CustomDomain${o0}`]={Description:`Custom domain ${h0}`,Value:h0},q[`CustomDomainTarget${o0}`]={Description:`Point ${h0} (CNAME/alias) at this APIGW regional domain`,Value:w.getAtt(d0,"RegionalDomainName")}})}if(X)j.AppQueueDlq={Type:"AWS::SQS::Queue",Properties:{QueueName:`${G}-${Y}-dlq`,MessageRetentionPeriod:1209600}},_.forEach((O0,h0)=>{let o0=`AppQueue${h0}`,d0=J.queueTimeout??120;j[o0]={Type:"AWS::SQS::Queue",Properties:{QueueName:O0.name,VisibilityTimeout:Math.min(43200,d0*6),RedrivePolicy:{deadLetterTargetArn:w.getAtt("AppQueueDlq","Arn"),maxReceiveCount:J.queueTries??3}}};let P$=O0.concurrency??J.queueConcurrency;j[`${o0}Mapping`]={Type:"AWS::Lambda::EventSourceMapping",Properties:{EventSourceArn:w.getAtt(o0,"Arn"),FunctionName:b0("QueueFunction"),BatchSize:1,FunctionResponseTypes:["ReportBatchItemFailures"],...P$?{ScalingConfig:{MaximumConcurrency:Math.max(2,P$)}}:{}}},q[`QueueUrl${h0}`]={Description:`Queue URL: ${O0.name}`,Value:w.ref(o0)}});if(V)j.SchedulerRule={Type:"AWS::Events::Rule",Properties:{Name:`${G}-${Y}-scheduler`,ScheduleExpression:"rate(1 minute)",State:"ENABLED",Targets:[{Id:"cli",Arn:w0("CliFunction"),Input:JSON.stringify({command:"schedule:run"})}]}},j.SchedulerPermission={Type:"AWS::Lambda::Permission",Properties:{FunctionName:b0("CliFunction"),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:w.getAtt("SchedulerRule","Arn")}};if(J.warm&&J.warm>0){let h0={http:"HttpFunction",queue:"QueueFunction",cli:"CliFunction"},o0=(J.warmFunctions??["http"]).filter((d0)=>d0!=="queue"||X);for(let d0 of o0){let P$=d0.charAt(0).toUpperCase()+d0.slice(1),Y5=Math.ceil(J.warm/5),z9=0;for(let g2=0;g2<Y5;g2++){let dJ=Math.min(5,J.warm-z9);j[`Warmer${P$}Rule${g2}`]={Type:"AWS::Events::Rule",Properties:{Name:`${G}-${Y}-warmer-${d0}-${g2}`,ScheduleExpression:"rate(5 minutes)",State:"ENABLED",Targets:Array.from({length:dJ},(Xy,QA)=>({Id:`warm-${d0}-${g2}-${QA}`,Arn:w.getAtt(h0[d0],"Arn"),Input:JSON.stringify({warmer:!0})}))}},z9+=dJ}j[`Warmer${P$}Permission`]={Type:"AWS::Lambda::Permission",Properties:{FunctionName:w.ref(h0[d0]),Action:"lambda:InvokeFunction",Principal:"events.amazonaws.com",SourceArn:w.sub(`arn:aws:events:\${AWS::Region}:\${AWS::AccountId}:rule/${G}-${Y}-warmer-${d0}-*`)}}}}if(K)j.CacheTable={Type:"AWS::DynamoDB::Table",Properties:{TableName:`${G}-${Y}-cache`,BillingMode:"PAY_PER_REQUEST",AttributeDefinitions:[{AttributeName:"key",AttributeType:"S"}],KeySchema:[{AttributeName:"key",KeyType:"HASH"}],TimeToLiveSpecification:{AttributeName:"expires_at",Enabled:!0}}},q.CacheTableName={Description:"DynamoDB cache table",Value:w.ref("CacheTable")};if(L){if(j.AssetsBucket={Type:"AWS::S3::Bucket",Properties:{BucketName:E,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!0,IgnorePublicAcls:!0,RestrictPublicBuckets:!0}}},j.AssetsOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`${G}-${Y}-assets-oac`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},j.AssetsDistribution={Type:"AWS::CloudFront::Distribution",Properties:{DistributionConfig:{Enabled:!0,DefaultCacheBehavior:{TargetOriginId:"assets",ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"658327ea-f89d-4fab-a63d-7e88639e58f6"},Origins:[{Id:"assets",DomainName:w.getAtt("AssetsBucket","RegionalDomainName"),OriginAccessControlId:w.ref("AssetsOAC"),S3OriginConfig:{OriginAccessIdentity:""}}],...J.assetDomain?{Aliases:[J.assetDomain],ViewerCertificate:{AcmCertificateArn:J.assetCertificateArn??w.ref("AssetsCertificate"),SslSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021"}}:{}}}},J.assetDomain){if(!J.assetCertificateArn){if(!J.hostedZoneId)throw Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");if(U!=="us-east-1")throw Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${U}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);j.AssetsCertificate={Type:"AWS::CertificateManager::Certificate",Properties:{DomainName:J.assetDomain,ValidationMethod:"DNS",DomainValidationOptions:[{DomainName:J.assetDomain,HostedZoneId:J.hostedZoneId}]}}}if(J.hostedZoneId)j.AssetsDomainRecord={Type:"AWS::Route53::RecordSet",Properties:{HostedZoneId:J.hostedZoneId,Name:J.assetDomain,Type:"A",AliasTarget:{DNSName:w.getAtt("AssetsDistribution","DomainName"),HostedZoneId:"Z2FDTNDATAQYW2"}}};q.AssetDomain={Description:"Custom asset CDN host",Value:J.assetDomain}}j.AssetsBucketPolicy={Type:"AWS::S3::BucketPolicy",Properties:{Bucket:w.ref("AssetsBucket"),PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:w.sub(`arn:aws:s3:::${E}/*`),Condition:{StringEquals:{"AWS:SourceArn":w.sub("arn:aws:cloudfront::${AWS::AccountId}:distribution/${AssetsDistribution}")}}}]}}},q.AssetsBucketName={Description:"Assets bucket",Value:w.ref("AssetsBucket")},q.AssetsCdnDomain={Description:"Assets CloudFront domain",Value:w.getAtt("AssetsDistribution","DomainName")}}if(J.firewall?.enabled){let O0=[],h0=0;if(J.firewall.rateLimit)O0.push({Name:"rate-limit",Priority:h0++,Action:{Block:{}},Statement:{RateBasedStatement:{Limit:J.firewall.rateLimit,AggregateKeyType:"IP"}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${G}-${Y}-rate`}});let o0={sqlInjection:"AWSManagedRulesSQLiRuleSet",xss:"AWSManagedRulesCommonRuleSet",common:"AWSManagedRulesCommonRuleSet",botControl:"AWSManagedRulesBotControlRuleSet",ipReputation:"AWSManagedRulesAmazonIpReputationList"};for(let d0 of J.firewall.rules??[]){let P$=o0[d0];if(!P$)continue;O0.push({Name:`managed-${d0}`,Priority:h0++,OverrideAction:{None:{}},Statement:{ManagedRuleGroupStatement:{VendorName:"AWS",Name:P$}},VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${G}-${Y}-${d0}`}})}j.WebAcl={Type:"AWS::WAFv2::WebACL",Properties:{Name:`${G}-${Y}-waf`,Scope:"REGIONAL",DefaultAction:{Allow:{}},Rules:O0,VisibilityConfig:{SampledRequestsEnabled:!0,CloudWatchMetricsEnabled:!0,MetricName:`${G}-${Y}-waf`}}},q.WafAclArn={Description:"WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).",Value:w.getAtt("WebAcl","Arn")}}if(m&&y){if(!J.vpc?.id)throw Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");j.DataSecurityGroup={Type:"AWS::EC2::SecurityGroup",Properties:{VpcId:J.vpc.id,GroupDescription:`${G}-${Y} serverless data access`,SecurityGroupIngress:[{IpProtocol:"-1",CidrIp:"10.0.0.0/8"}]}}}if(x)j.EfsFileSystem={Type:"AWS::EFS::FileSystem",Properties:{Encrypted:!0,FileSystemTags:[{Key:"Name",Value:`${G}-${Y}-efs`}]}},b.forEach((O0,h0)=>{j[`EfsMountTarget${h0}`]={Type:"AWS::EFS::MountTarget",Properties:{FileSystemId:w.ref("EfsFileSystem"),SubnetId:O0,SecurityGroups:[w.getAtt("DataSecurityGroup","GroupId")]}}}),j.EfsAccessPoint={Type:"AWS::EFS::AccessPoint",Properties:{FileSystemId:w.ref("EfsFileSystem"),PosixUser:{Uid:1001,Gid:1001},RootDirectory:{Path:"/lambda",CreationInfo:{OwnerUid:1001,OwnerGid:1001,Permissions:"0755"}}}},q.EfsFileSystemId={Description:"EFS file system id",Value:w.ref("EfsFileSystem")};if(J.cache?.driver==="elasticache")j.CacheSubnetGroup={Type:"AWS::ElastiCache::SubnetGroup",Properties:{Description:`${G}-${Y} cache subnets`,SubnetIds:b}},j.CacheCluster={Type:"AWS::ElastiCache::ReplicationGroup",Properties:{ReplicationGroupId:`${G}-${Y}-cache`,ReplicationGroupDescription:`${G}-${Y} redis`,Engine:"redis",CacheNodeType:"cache.t4g.micro",NumCacheClusters:1,AutomaticFailoverEnabled:!1,CacheSubnetGroupName:w.ref("CacheSubnetGroup"),SecurityGroupIds:[w.getAtt("DataSecurityGroup","GroupId")],TransitEncryptionEnabled:!1}},q.CacheEndpoint={Description:"Redis primary endpoint",Value:w.getAtt("CacheCluster","PrimaryEndPoint.Address")};if(J.database?.connection==="aurora-serverless")j.DbSubnetGroup={Type:"AWS::RDS::DBSubnetGroup",Properties:{DBSubnetGroupDescription:`${G}-${Y} db subnets`,SubnetIds:b}},j.DbSecret={Type:"AWS::SecretsManager::Secret",Properties:{Name:`${G}/${Y}/db`,GenerateSecretString:{SecretStringTemplate:JSON.stringify({username:"app"}),GenerateStringKey:"password",PasswordLength:32,ExcludePunctuation:!0}}},j.DbCluster={Type:"AWS::RDS::DBCluster",Properties:{Engine:"aurora-mysql",EngineMode:"provisioned",DBClusterIdentifier:`${G}-${Y}-db`,DatabaseName:"app",MasterUsername:w.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),MasterUserPassword:w.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),ServerlessV2ScalingConfiguration:{MinCapacity:J.database?.minCapacity??0.5,MaxCapacity:J.database?.maxCapacity??4},DBSubnetGroupName:w.ref("DbSubnetGroup"),VpcSecurityGroupIds:[w.getAtt("DataSecurityGroup","GroupId")]}},j.DbInstance={Type:"AWS::RDS::DBInstance",Properties:{Engine:"aurora-mysql",DBInstanceClass:"db.serverless",DBClusterIdentifier:w.ref("DbCluster")}},q.DbEndpoint={Description:"Aurora cluster endpoint",Value:w.getAtt("DbCluster","Endpoint.Address")};if(J.rdsProxy&&J.database?.connection==="aurora-serverless")j.DbProxyRole={Type:"AWS::IAM::Role",Properties:{AssumeRolePolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Principal:{Service:"rds.amazonaws.com"},Action:"sts:AssumeRole"}]},Policies:[{PolicyName:"read-db-secret",PolicyDocument:{Version:"2012-10-17",Statement:[{Effect:"Allow",Action:["secretsmanager:GetSecretValue"],Resource:w.ref("DbSecret")}]}}]}},j.DbProxy={Type:"AWS::RDS::DBProxy",Properties:{DBProxyName:typeof J.rdsProxy==="object"&&J.rdsProxy.name?J.rdsProxy.name:`${G}-${Y}-proxy`,EngineFamily:"MYSQL",RoleArn:w.getAtt("DbProxyRole","Arn"),Auth:[{AuthScheme:"SECRETS",SecretArn:w.ref("DbSecret"),IAMAuth:"DISABLED"}],VpcSubnetIds:b,VpcSecurityGroupIds:[w.getAtt("DataSecurityGroup","GroupId")],RequireTLS:!1}},j.DbProxyTargetGroup={Type:"AWS::RDS::DBProxyTargetGroup",DependsOn:["DbInstance"],Properties:{DBProxyName:w.ref("DbProxy"),TargetGroupName:"default",DBClusterIdentifiers:[w.ref("DbCluster")]}},q.DbProxyEndpoint={Description:"RDS Proxy endpoint",Value:w.getAtt("DbProxy","Endpoint")};if(q.HttpFunctionName={Description:"HTTP function name",Value:w.ref("HttpFunction")},q.CliFunctionName={Description:"CLI function name",Value:w.ref("CliFunction")},X)q.QueueFunctionName={Description:"Queue function name",Value:w.ref("QueueFunction")};let F$={AWSTemplateFormatVersion:"2010-09-09",Description:`Serverless application for ${$.config.project.name} (${G}-${Y})`,Parameters:B?{ImageUri:{Type:"String",Description:"ECR image URI of the deployment artifact"}}:{ArtifactBucket:{Type:"String",Description:"S3 bucket holding the deployment artifact"},ArtifactKey:{Type:"String",Description:"S3 key of the deployment artifact (zip)"}},Resources:j,Outputs:q},g$={};for(let O0 of Object.values(j))g$[O0.Type]=(g$[O0.Type]??0)+1;return{template:F$,functionNames:z,queueNames:H,resourceSummary:g$}}function QX($){let J=`php${$.replace(".","")}`;return YX.map((Y)=>`${J}-php-${Y}`)}function GW($,J){let Y=`php${$.replace(".","")}`,Q=QX($).join(" \\\n "),G=`/opt/remi/${Y}/root`,Z=`/etc/opt/remi/${Y}`;return`${J?`FROM almalinux:9 AS ${J}`:"FROM almalinux:9"}
|
|
3643
3643
|
|
|
3644
3644
|
# Build PHP on AlmaLinux 9 (where Remi's version-isolated SCL packages install
|
|
3645
3645
|
# cleanly — Remi's release RPM rejects Amazon Linux 2023). AlmaLinux 9 shares
|
|
@@ -13638,7 +13638,7 @@ async function sendFallbackSms(to, message) {
|
|
|
13638
13638
|
</ChangeResourceRecordSetsRequest>`;let G=await this.client.request({service:"route53",region:this.region,method:"POST",path:`/2013-04-01/hostedzone/${Y}/rrset`,headers:{"content-type":"application/xml"},body:Q});return this.parseChangeResourceRecordSetsResponse(G)}escapeXml(J){return J.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}parseCreateHostedZoneResponse(J){let Y=J.CreateHostedZoneResponse||J;return{HostedZone:this.parseHostedZone(Y.HostedZone),ChangeInfo:{Id:Y.ChangeInfo?.Id||"",Status:Y.ChangeInfo?.Status||"",SubmittedAt:Y.ChangeInfo?.SubmittedAt||""},DelegationSet:this.parseDelegationSet(Y.DelegationSet),Location:Y.Location||""}}parseListHostedZonesResponse(J){let Y=J.ListHostedZonesResponse||J.ListHostedZonesByNameResponse||J,Q=Y.HostedZones?.HostedZone||Y.HostedZones||[];if(!Array.isArray(Q))Q=Q?[Q]:[];return{HostedZones:Q.map((G)=>this.parseHostedZone(G)),IsTruncated:Y.IsTruncated==="true"||Y.IsTruncated===!0,MaxItems:Y.MaxItems||"100",Marker:Y.Marker,NextMarker:Y.NextMarker}}parseGetHostedZoneResponse(J){let Y=J.GetHostedZoneResponse||J;return{HostedZone:this.parseHostedZone(Y.HostedZone),DelegationSet:this.parseDelegationSet(Y.DelegationSet),VPCs:Y.VPCs?.VPC?Array.isArray(Y.VPCs.VPC)?Y.VPCs.VPC:[Y.VPCs.VPC]:void 0}}parseListResourceRecordSetsResponse(J){let Y=J.ListResourceRecordSetsResponse||J,Q=Y.ResourceRecordSets?.ResourceRecordSet||Y.ResourceRecordSets||[];if(!Array.isArray(Q))Q=Q?[Q]:[];return{ResourceRecordSets:Q.map((G)=>this.parseResourceRecordSet(G)),IsTruncated:Y.IsTruncated==="true"||Y.IsTruncated===!0,MaxItems:Y.MaxItems||"100",NextRecordName:Y.NextRecordName,NextRecordType:Y.NextRecordType,NextRecordIdentifier:Y.NextRecordIdentifier}}parseChangeResourceRecordSetsResponse(J){let Y=J.ChangeResourceRecordSetsResponse||J;return{ChangeInfo:{Id:Y.ChangeInfo?.Id||"",Status:Y.ChangeInfo?.Status||"",SubmittedAt:Y.ChangeInfo?.SubmittedAt||"",Comment:Y.ChangeInfo?.Comment}}}parseHostedZone(J){if(!J)return{Id:"",Name:""};return{Id:J.Id||"",Name:J.Name||"",CallerReference:J.CallerReference,Config:J.Config?{Comment:J.Config.Comment,PrivateZone:J.Config.PrivateZone==="true"||J.Config.PrivateZone===!0}:void 0,ResourceRecordSetCount:J.ResourceRecordSetCount?Number(J.ResourceRecordSetCount):void 0}}parseDelegationSet(J){if(!J)return{NameServers:[]};let Y=J.NameServers?.NameServer||J.NameServers||[];if(!Array.isArray(Y))Y=Y?[Y]:[];return{Id:J.Id,CallerReference:J.CallerReference,NameServers:Y}}parseResourceRecordSet(J){if(!J)return{Name:"",Type:""};let Y=J.ResourceRecords?.ResourceRecord||J.ResourceRecords||[];if(!Array.isArray(Y))Y=Y?[Y]:[];return{Name:J.Name||"",Type:J.Type||"",TTL:J.TTL?Number(J.TTL):void 0,ResourceRecords:Y.map((Q)=>({Value:Q.Value||Q})),AliasTarget:J.AliasTarget?{HostedZoneId:J.AliasTarget.HostedZoneId,DNSName:J.AliasTarget.DNSName,EvaluateTargetHealth:J.AliasTarget.EvaluateTargetHealth==="true"||J.AliasTarget.EvaluateTargetHealth===!0}:void 0,SetIdentifier:J.SetIdentifier,Weight:J.Weight?Number(J.Weight):void 0,Region:J.Region,GeoLocation:J.GeoLocation,Failover:J.Failover,HealthCheckId:J.HealthCheckId}}async findHostedZoneByName(J){let Y=J.endsWith(".")?J:`${J}.`;return(await this.listHostedZonesByName({DNSName:Y})).HostedZones.find((Z)=>Z.Name===Y)||null}async createARecord(J){let Y=Array.isArray(J.Value)?J.Value:[J.Value];return this.changeResourceRecordSets({HostedZoneId:J.HostedZoneId,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:J.Name,Type:"A",TTL:J.TTL||300,ResourceRecords:Y.map((Q)=>({Value:Q}))}}]}})}async createCnameRecord(J){return this.changeResourceRecordSets({HostedZoneId:J.HostedZoneId,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:J.Name,Type:"CNAME",TTL:J.TTL||300,ResourceRecords:[{Value:J.Value}]}}]}})}async createAliasRecord(J){return this.changeResourceRecordSets({HostedZoneId:J.HostedZoneId,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:J.Name,Type:J.Type||"A",AliasTarget:{HostedZoneId:J.TargetHostedZoneId,DNSName:J.TargetDNSName,EvaluateTargetHealth:J.EvaluateTargetHealth??!1}}}]}})}async createTxtRecord(J){let Q=(Array.isArray(J.Value)?J.Value:[J.Value]).map((G)=>{if(!G.startsWith('"'))return`"${G}"`;return G});return this.changeResourceRecordSets({HostedZoneId:J.HostedZoneId,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:J.Name,Type:"TXT",TTL:J.TTL||300,ResourceRecords:Q.map((G)=>({Value:G}))}}]}})}async createMxRecord(J){return this.changeResourceRecordSets({HostedZoneId:J.HostedZoneId,ChangeBatch:{Changes:[{Action:"UPSERT",ResourceRecordSet:{Name:J.Name,Type:"MX",TTL:J.TTL||300,ResourceRecords:J.Values.map((Y)=>({Value:`${Y.priority} ${Y.mailServer}`}))}}]}})}async deleteRecord(J){return this.changeResourceRecordSets({HostedZoneId:J.HostedZoneId,ChangeBatch:{Changes:[{Action:"DELETE",ResourceRecordSet:J.RecordSet}]}})}async waitForChange(J,Y=60,Q=5000){let G=J.replace("/change/","");for(let Z=0;Z<Y;Z++){let W=await this.client.request({service:"route53",region:this.region,method:"GET",path:`/2013-04-01/change/${G}`});if((W.GetChangeResponse?.ChangeInfo?.Status||W.ChangeInfo?.Status)==="INSYNC")return!0;await new Promise((z)=>setTimeout(z,Q))}return!1}async findOrCreateHostedZone(J){let Y=J.domainName.endsWith(".")?J.domainName:`${J.domainName}.`,Q=await this.findHostedZoneByName(Y);if(Q){let Z=await this.getHostedZone({Id:Q.Id});return{hostedZone:Q,nameServers:Z.DelegationSet.NameServers,isNew:!1}}let G=await this.createHostedZone({Name:Y,HostedZoneConfig:{Comment:J.comment||`Hosted zone for ${J.domainName}`,PrivateZone:J.privateZone},VPC:J.vpc});return{hostedZone:G.HostedZone,nameServers:G.DelegationSet.NameServers,isNew:!0}}static getRootDomain(J){let Y=J.replace(/\.$/,"").split(".");if(Y.length<=2)return J;return Y.slice(-2).join(".")}async findHostedZoneForDomain(J){let Q=J.replace(/\.$/,"").split(".");for(let G=0;G<Q.length-1;G++){let Z=Q.slice(G).join("."),W=await this.findHostedZoneByName(Z);if(W)return W}return null}async ensureHostedZone(J){let Y=await this.findOrCreateHostedZone({domainName:J.domainName,comment:J.comment});return{hostedZoneId:Y.hostedZone.Id.replace("/hostedzone/",""),nameServers:Y.nameServers,isNew:Y.isNew,action:Y.isNew?"created":"found"}}async setupDomainDns(J){let{domain:Y,createIfNotExists:Q=!0}=J,G=await this.findHostedZoneByName(Y);if(G){let W=await this.getHostedZone({Id:G.Id});return{success:!0,hostedZoneId:G.Id.replace("/hostedzone/",""),nameServers:W.DelegationSet.NameServers,isNew:!1,message:`Found existing hosted zone for ${Y}`}}if(!Q)return{success:!1,hostedZoneId:null,nameServers:[],isNew:!1,message:`No hosted zone found for ${Y} and createIfNotExists is false`};let Z=await this.createHostedZone({Name:Y,HostedZoneConfig:{Comment:`Created automatically by ts-cloud for ${Y}`}});return{success:!0,hostedZoneId:Z.HostedZone.Id.replace("/hostedzone/",""),nameServers:Z.DelegationSet.NameServers,isNew:!0,message:`Created new hosted zone for ${Y}. Please update your domain registrar with these name servers: ${Z.DelegationSet.NameServers.join(", ")}`}}static CloudFrontHostedZoneId="Z2FDTNDATAQYW2";static S3WebsiteHostedZoneIds={"us-east-1":"Z3AQBSTGFYJSTF","us-east-2":"Z2O1EMRO9K5GLX","us-west-1":"Z2F56UZL2M1ACD","us-west-2":"Z3BJ6K6RIION7M","ap-east-1":"ZNB98KWMFR0R6","ap-south-1":"Z11RGJOFQNVJUP","ap-northeast-1":"Z2M4EHUR26P7ZW","ap-northeast-2":"Z3W03O7B5YMIYP","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"Z3O0J2DXBE1FTB","ap-southeast-2":"Z1WCIGYICN2BYD","ca-central-1":"Z1QDHH18159H29","eu-central-1":"Z21DNDUVLTQW6Q","eu-west-1":"Z1BKCTXD74EZPE","eu-west-2":"Z3GKZC51ZF0DB4","eu-west-3":"Z3R1K369G5AVDG","eu-north-1":"Z3BAZG2TWCNX0D","sa-east-1":"Z7KQH4QJS55SO"};static ALBHostedZoneIds={"us-east-1":"Z35SXDOTRQ7X7K","us-east-2":"Z3AADJGX6KTTL2","us-west-1":"Z368ELLRRE2KJ0","us-west-2":"Z1H1FL5HABSF5","ap-east-1":"Z3DQVH9N71FHZ0","ap-south-1":"ZP97RAFLXTNZK","ap-northeast-1":"Z14GRHDCWA56QT","ap-northeast-2":"ZWKZPGTI48KDX","ap-northeast-3":"Z5LXEBD8Y73MNV","ap-southeast-1":"Z1LMS91P8CMLE5","ap-southeast-2":"Z1GM3OXH4ZPM65","ca-central-1":"ZQSVJUPU6J1EY","eu-central-1":"Z215JYRZR1TBD5","eu-west-1":"Z32O12XQLNTSW2","eu-west-2":"ZHURV8PSTC4K8","eu-west-3":"Z3Q77PNBQS71R4","eu-north-1":"Z23TAZ6LKFMNIO","sa-east-1":"Z2P70J7HTTTPLU"};static APIGatewayHostedZoneIds={"us-east-1":"Z1UJRXOUMOOFQ8","us-east-2":"ZOJJZC49E0EPZ","us-west-1":"Z2MUQ32089INYE","us-west-2":"Z2OJLYMUO9EFXC","ap-east-1":"Z3FD1VL90ND7K5","ap-south-1":"Z3VO1THU9YC4UR","ap-northeast-1":"Z1YSHQZHG15GKL","ap-northeast-2":"Z20JF4UZKIW1U8","ap-northeast-3":"Z2YQB5RD63NC85","ap-southeast-1":"ZL327KTPIQFUL","ap-southeast-2":"Z2RPCDW04V8134","ca-central-1":"Z19DQILCV0OWEC","eu-central-1":"Z1U9ULNL0V5AJ3","eu-west-1":"ZLY8HYME6SFDD","eu-west-2":"ZJ5UAJN8Y3Z2Q","eu-west-3":"Z3KY65QIEKYHQQ","eu-north-1":"Z3UWIKFBOOGXPP","sa-east-1":"ZCMLWB8V5SYIT"}}});Hz=a0(()=>{Z9()});RV=a0(()=>{pQ(),W9()});W9=a0(()=>{Hz(),RV(),Hz(),_x=new DV});pQ=a0(()=>{F0(),Z9(),W9()});PV=a0(()=>{F0()});pz=a0(()=>{F0()});xV=a0(()=>{F0()}),Xx={};cQ(Xx,{email:()=>kV,EmailClient:()=>rz});Fx=a0(()=>{pz(),i1(),xV(),Z9(),kV=new rz}),Ox=a0(()=>{F0()});nz=a0(()=>{G9(),i1(),lz(),pQ(),W9(),Hz(),RV()}),Vx={};cQ(Vx,{uploadStaticFiles:()=>yV,invalidateCache:()=>vV,generateStaticSiteTemplate:()=>bV,deployStaticSiteFull:()=>Ax,deployStaticSite:()=>hV,deleteStaticSite:()=>Lx});Ex=a0(()=>{G9(),i1(),lz(),Z9(),pQ(),nz()});fV=a0(()=>{Xz={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m"},qx=!!(process.env.CI||process.env.GITHUB_ACTIONS||process.env.BUILDKITE||process.env.CIRCLECI||process.env.GITLAB_CI)}),Mx={};cQ(Mx,{buildAndPushServerlessImage:()=>Nx});Sx=a0(async()=>{PV(),fV(),await X2()});CQ=new dV,iz=new cV,Vk=Object.defineProperty;lV={};Ek(lV,{withErrorRecovery:()=>rV,tryLoadConfig:()=>lk,loadConfigWithResult:()=>dk,loadConfig:()=>oV,isRetryableError:()=>hk,isConfigNotFoundError:()=>bk,isBunfigError:()=>nV,globalPerformanceMonitor:()=>yJ,globalCache:()=>Y9,getEnvOrDefault:()=>yk,generateConfigTypes:()=>mk,defaultGeneratedDir:()=>ZL,defaultConfigDir:()=>GL,deepMergeWithArrayStrategy:()=>ez,deepMerge:()=>iV,createLibraryConfig:()=>pk,config:()=>ck,bunfigPlugin:()=>rk,applyEnvVarsToConfig:()=>SJ,TypeGenerationError:()=>qz,SchemaValidationError:()=>kJ,PluginError:()=>wz,PerformanceMonitor:()=>az,FileSystemError:()=>jz,ErrorFactory:()=>y2,EnvVarError:()=>yQ,EnvProcessor:()=>nQ,ConfigValidator:()=>$4,ConfigValidationError:()=>Az,ConfigNotFoundError:()=>hQ,ConfigMergeError:()=>Ez,ConfigLoader:()=>J4,ConfigLoadError:()=>xJ,ConfigFileLoader:()=>iQ,ConfigCache:()=>tz,CacheUtils:()=>eV,BunfigError:()=>n1,BrowserConfigError:()=>Mz,ArrayMergeStrategies:()=>YL});jb=jk(async()=>{sV=import.meta.require,Y9=new tz,yJ=new az,eV={createKey:qk,isEquivalent:Mk,estimateMemoryUsage:wk},nk=SQ(Bz.cwd(),"config"),ik=SQ(Bz.cwd(),"src/generated"),KB=NQ.env.CLARITY_LOG_DIR||yx(Dk(),"logs"),VQ={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:KB,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1},Vz=await Nk(),E1={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,reset:"\x1B[0m"},v0=E1,tk=E1.red,VB=E1.green,ak=E1.yellow,LB=E1.blue,ok=E1.magenta,sk=E1.cyan,tU=E1.white,ek=E1.gray,AB=E1.bgRed,EB=E1.bgYellow,aU=E1.bold,$b=E1.dim,Jb=E1.italic,Yb=E1.underline,Qb=E1.reset,LQ={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},$L={debug:"\uD83D\uDD0D",info:LB("ℹ"),success:VB("✓"),warning:EB(tU(aU(" WARN "))),error:AB(tU(aU(" ERROR ")))},Gb=new xQ("stacks"),j1=new xQ("bunfig",{showTags:!0}),Zb=S1(IJ.cwd(),"config"),Wb=S1(IJ.cwd(),"src/generated"),jB=DQ.env.CLARITY_LOG_DIR||bx(Ik(),"logs"),AQ={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:jB,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},Lz=await xk(),Z1={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bgGray:($)=>`\x1B[100m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,strikethrough:($)=>`\x1B[9m${$}\x1B[0m`,reset:"\x1B[0m"},R0=Z1,Ub=Z1.red,qB=Z1.green,zb=Z1.yellow,MB=Z1.blue,_b=Z1.magenta,Hb=Z1.cyan,oU=Z1.white,Xb=Z1.gray,wB=Z1.bgRed,TB=Z1.bgYellow,Fb=Z1.bgGray,sU=Z1.bold,Ob=Z1.dim,Bb=Z1.italic,Kb=Z1.underline,Vb=Z1.strikethrough,Lb=Z1.reset,EQ={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},JL={debug:"\uD83D\uDD0D",info:MB("ℹ"),success:qB("✓"),warning:TB(oU(sU(" WARN "))),error:wB(oU(sU(" ERROR ")))},Ab=new bQ("stacks"),n1=class extends Error{timestamp;context;constructor(J,Y={}){super(J);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=Y,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let J=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([Y,Q])=>`${Y}: ${Q}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${J}`}},hQ=class extends n1{code="CONFIG_NOT_FOUND";constructor(J,Y,Q){let G=Q?` or alias "${Q}"`:"";super(`Configuration "${J}"${G} not found`,{configName:J,alias:Q,searchPaths:Y,searchPathCount:Y.length})}},xJ=class extends n1{code="CONFIG_LOAD_ERROR";constructor(J,Y,Q){super(`Failed to load configuration from "${J}": ${Y.message}`,{configPath:J,configName:Q,originalError:Y.name,originalMessage:Y.message});this.cause=Y}},Az=class extends n1{code="CONFIG_VALIDATION_ERROR";constructor(J,Y,Q){super(`Configuration validation failed for "${J}"`,{configPath:J,configName:Q,validationErrors:Y,errorCount:Y.length})}},Ez=class extends n1{code="CONFIG_MERGE_ERROR";constructor(J,Y,Q,G){super(`Failed to merge configuration from "${J}" with "${Y}": ${Q.message}`,{sourcePath:J,targetPath:Y,configName:G,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},yQ=class extends n1{code="ENV_VAR_ERROR";constructor(J,Y,Q,G){super(`Failed to parse environment variable "${J}" with value "${Y}" as ${Q}`,{envKey:J,envValue:Y,expectedType:Q,configName:G})}},jz=class extends n1{code="FILE_SYSTEM_ERROR";constructor(J,Y,Q){super(`File system ${J} failed for "${Y}": ${Q.message}`,{operation:J,path:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},qz=class extends n1{code="TYPE_GENERATION_ERROR";constructor(J,Y,Q){super(`Failed to generate types from "${J}" to "${Y}": ${Q.message}`,{configDir:J,outputPath:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},kJ=class extends n1{code="SCHEMA_VALIDATION_ERROR";constructor(J,Y,Q){super(`Schema validation failed${Q?` for config "${Q}"`:""}`,{schemaPath:J,configName:Q,validationErrors:Y,errorCount:Y.length})}},Mz=class extends n1{code="BROWSER_CONFIG_ERROR";constructor(J,Y,Q,G){super(`Failed to fetch configuration from "${J}": ${Y} ${Q}`,{endpoint:J,status:Y,statusText:Q,configName:G})}},wz=class extends n1{code="PLUGIN_ERROR";constructor(J,Y,Q){super(`Plugin "${J}" failed during ${Y}: ${Q.message}`,{pluginName:J,operation:Y,originalError:Q.name,originalMessage:Q.message});this.cause=Q}},y2={configNotFound($,J,Y){return new hQ($,J,Y)},configLoad($,J,Y){return new xJ($,J,Y)},configValidation($,J,Y){return new Az($,J,Y)},configMerge($,J,Y,Q){return new Ez($,J,Y,Q)},envVar($,J,Y,Q){return new yQ($,J,Y,Q)},fileSystem($,J,Y){return new jz($,J,Y)},typeGeneration($,J,Y){return new qz($,J,Y)},schemaValidation($,J,Y){return new kJ($,J,Y)},browserConfig($,J,Y,Q){return new Mz($,J,Y,Q)},plugin($,J,Y){return new wz($,J,Y)}},YL={replace:"replace",concat:"concat",smart:"smart"},QL=/^https?:\/\//,w$=new bQ("bunfig",{showTags:!0}),_2=new J4,GL=P1(_8.cwd(),"config"),ZL=P1(_8.cwd(),"src/generated")});Mb=PQ.env.CLARITY_LOG_DIR||Gk(qb(),"logs"),WL={level:"info",defaultName:"clarity",timestamp:!0,colors:!0,format:"text",maxLogSize:10485760,logDatePattern:"YYYY-MM-DD",logDirectory:Mb,rotation:{frequency:"daily",maxSize:10485760,maxFiles:5,compress:!1,rotateHour:0,rotateMinute:0,rotateDayOfWeek:0,rotateDayOfMonth:1,encrypt:!1},verbose:!1,writeToFile:!1},vQ={...WL},pr=(async()=>{try{let{loadConfig:$}=await jb().then(()=>lV),J=await $({name:"clarity",alias:"logging",defaultConfig:WL,cwd:PQ.cwd()});if(J)Object.assign(vQ,J)}catch{}return vQ})();_1={red:($)=>`\x1B[31m${$}\x1B[0m`,green:($)=>`\x1B[32m${$}\x1B[0m`,yellow:($)=>`\x1B[33m${$}\x1B[0m`,blue:($)=>`\x1B[34m${$}\x1B[0m`,magenta:($)=>`\x1B[35m${$}\x1B[0m`,cyan:($)=>`\x1B[36m${$}\x1B[0m`,white:($)=>`\x1B[37m${$}\x1B[0m`,gray:($)=>`\x1B[90m${$}\x1B[0m`,bgRed:($)=>`\x1B[41m${$}\x1B[0m`,bgYellow:($)=>`\x1B[43m${$}\x1B[0m`,bgGray:($)=>`\x1B[100m${$}\x1B[0m`,bold:($)=>`\x1B[1m${$}\x1B[0m`,dim:($)=>`\x1B[2m${$}\x1B[0m`,italic:($)=>`\x1B[3m${$}\x1B[0m`,underline:($)=>`\x1B[4m${$}\x1B[0m`,strikethrough:($)=>`\x1B[9m${$}\x1B[0m`,reset:"\x1B[0m"},N0=_1,rr=_1.red,Tb=_1.green,nr=_1.yellow,Rb=_1.blue,ir=_1.magenta,tr=_1.cyan,RB=_1.white,ar=_1.gray,Db=_1.bgRed,Nb=_1.bgYellow,or=_1.bgGray,DB=_1.bold,sr=_1.dim,er=_1.italic,$n=_1.underline,Jn=_1.strikethrough,Yn=_1.reset,eU={activationLevel:"error",bufferSize:50,flushOnDeactivation:!0,stopBuffering:!1},Sb={debug:"\uD83D\uDD0D",info:Rb("ℹ"),success:Tb("✓"),warning:Nb(RB(DB(" WARN "))),error:Db(RB(DB(" ERROR ")))};Qn=new tQ("stacks");R$=class R$ extends Error{timestamp;context;constructor($,J={}){super($);if(this.name=this.constructor.name,this.timestamp=new Date,this.context=J,Error.captureStackTrace)Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,code:this.code,message:this.message,timestamp:this.timestamp.toISOString(),context:this.context,stack:this.stack}}toString(){let $=Object.keys(this.context).length>0?` (${Object.entries(this.context).map(([J,Y])=>`${J}: ${Y}`).join(", ")})`:"";return`${this.name} [${this.code}]: ${this.message}${$}`}};zL=class zL extends R${code="CONFIG_NOT_FOUND";constructor($,J,Y){let Q=Y===void 0?[]:Array.isArray(Y)?Y.filter(Boolean):[Y],G="";if(Q.length===1)G=` or alias "${Q[0]}"`;else if(Q.length>1)G=` or aliases ${Q.map((Z)=>`"${Z}"`).join(", ")}`;super(`Configuration "${$}"${G} not found`,{configName:$,alias:Y,searchPaths:J,searchPathCount:J.length})}};fQ=class fQ extends R${code="CONFIG_LOAD_ERROR";constructor($,J,Y){super(`Failed to load configuration from "${$}": ${J.message}`,{configPath:$,configName:Y,originalError:J.name,originalMessage:J.message});this.cause=J}};_L=class _L extends R${code="CONFIG_VALIDATION_ERROR";constructor($,J,Y){super(`Configuration validation failed for "${$}"`,{configPath:$,configName:Y,validationErrors:J,errorCount:J.length})}};HL=class HL extends R${code="CONFIG_MERGE_ERROR";constructor($,J,Y,Q){super(`Failed to merge configuration from "${$}" with "${J}": ${Y.message}`,{sourcePath:$,targetPath:J,configName:Q,originalError:Y.name,originalMessage:Y.message});this.cause=Y}};Y4=class Y4 extends R${code="ENV_VAR_ERROR";constructor($,J,Y,Q){super(`Failed to parse environment variable "${$}" with value "${J}" as ${Y}`,{envKey:$,envValue:J,expectedType:Y,configName:Q})}};XL=class XL extends R${code="FILE_SYSTEM_ERROR";constructor($,J,Y){super(`File system ${$} failed for "${J}": ${Y.message}`,{operation:$,path:J,originalError:Y.name,originalMessage:Y.message});this.cause=Y}};FL=class FL extends R${code="TYPE_GENERATION_ERROR";constructor($,J,Y){super(`Failed to generate types from "${$}" to "${J}": ${Y.message}`,{configDir:$,outputPath:J,originalError:Y.name,originalMessage:Y.message});this.cause=Y}};gQ=class gQ extends R${code="SCHEMA_VALIDATION_ERROR";constructor($,J,Y){super(`Schema validation failed${Y?` for config "${Y}"`:""}`,{schemaPath:$,configName:Y,validationErrors:J,errorCount:J.length})}};OL=class OL extends R${code="BROWSER_CONFIG_ERROR";constructor($,J,Y,Q){super(`Failed to fetch configuration from "${$}": ${J} ${Y}`,{endpoint:$,status:J,statusText:Y,configName:Q})}};BL=class BL extends R${code="PLUGIN_ERROR";constructor($,J,Y){super(`Plugin "${$}" failed during ${J}: ${Y.message}`,{pluginName:$,operation:J,originalError:Y.name,originalMessage:Y.message});this.cause=Y}};Q9={configNotFound($,J,Y){return new zL($,J,Y)},configLoad($,J,Y){return new fQ($,J,Y)},configValidation($,J,Y){return new _L($,J,Y)},configMerge($,J,Y,Q){return new HL($,J,Y,Q)},envVar($,J,Y,Q){return new Y4($,J,Y,Q)},fileSystem($,J,Y){return new XL($,J,Y)},typeGeneration($,J,Y){return new FL($,J,Y)},schemaValidation($,J,Y){return new gQ($,J,Y)},browserConfig($,J,Y,Q){return new OL($,J,Y,Q)},plugin($,J,Y){return new BL($,J,Y)}};hb=/^https?:\/\//;G2=new tQ("bunfig",{showTags:!0});Gn=new jL;Zn=U$(rQ.cwd(),"config"),Wn=U$(rQ.cwd(),"src/generated");await X2();F0();i1();G9();F0();fb=24*vb,Un=30*fb;F0();i1();lz();Z9();F0();pQ();PV();F0();F0();F0();F0();pz();Fx();F0();F0();F0();F0();F0();F0();Ox();F0();F0();F0();F0();F0();F0();F0();F0();F0();F0();F0();F0();F0();F0();xV();F0();i1();pz();i1();i1();i1();F0();i1();F0();F0();W9();W9();Z9();gb=new Set(["laravel","php","statamic","wordpress"]);Ex();nz();nz();G9();await X2();i1();fV();await Sx();G9();await X2();F0();i1();F0();await X2();G9();await X2();i1();lb={php:"php.net",nginx:"nginx.org",composer:"getcomposer.org",mysql:"mysql.com",mariadb:"mariadb.com/server",postgres:"postgresql.org",redis:"redis.io",memcached:"memcached.org",meilisearch:"meilisearch.com",git:"git-scm.com",certbot:"certbot.eff.org",bun:"bun.sh",node:"nodejs.org",deno:"deno.land"};rb={"opcache.enable":"1","opcache.enable_cli":"1","opcache.memory_consumption":"256","opcache.interned_strings_buffer":"16","opcache.max_accelerated_files":"20000","opcache.validate_timestamps":"0","opcache.revalidate_freq":"0","opcache.save_comments":"1","opcache.fast_shutdown":"1",realpath_cache_size:"4096K",realpath_cache_ttl:"600"};ob=[80,443];await X2();Gz={micro:"cpx11",small:"cx23",medium:"cx33",large:"cx43",xlarge:"cx53","2xlarge":"ccx33"};dQ=class dQ{name="hetzner";usesCloudFormation=!1;client;sshPrivateKeyPath;sshPublicKeyPath;sshUser;location;waitForBoot;bootWait;constructor($={}){this.client=$.client??new IL({apiToken:Kh($.apiToken)}),this.sshPrivateKeyPath=yB($.sshPrivateKeyPath||process.env.HCLOUD_SSH_KEY||"~/.ssh/id_ed25519"),this.sshPublicKeyPath=yB($.sshPublicKeyPath||process.env.HCLOUD_SSH_PUBLIC_KEY||`${this.sshPrivateKeyPath}.pub`),this.sshUser=$.sshUser||process.env.HCLOUD_SSH_USER||"root",this.location=$.location||process.env.HCLOUD_LOCATION||"fsn1",this.waitForBoot=$.waitForBoot??!0,this.bootWait={sshIntervalMs:$.bootWait?.sshIntervalMs??5000,sshTimeoutMs:$.bootWait?.sshTimeoutMs??300000,cloudInitIntervalMs:$.bootWait?.cloudInitIntervalMs??5000,cloudInitTimeoutMs:$.bootWait?.cloudInitTimeoutMs??600000}}async provisionComputeInfrastructure($){let{config:J,environment:Y}=$,Q=J.project.slug,G=J.infrastructure?.compute;if(!G)throw Error("infrastructure.compute is required to provision Hetzner compute");let Z=NJ(J,Y),W=`${Q}-${Y}-app`,U=wh(G);if(U.dedicatedServices||U.appServers>1)return this.provisionFleet($,U);let z=await XQ(Z);if(z?.serverId){let k=await this.tryGetServer(z.serverId);if(k&&k.status!=="off")return this.outputsFromState(z,k)}let _=I2(Q,Y,"app"),H=await this.findExistingServer(Q,Y,W);if(H&&H.status!=="off"){let k={provider:"hetzner",stackName:Z,serverId:H.id,serverName:H.name,publicIp:H.public_net.ipv4?.ip,deployStoragePath:"/var/ts-cloud/staging",sshUser:this.sshUser};return await FQ(Z,k),this.outputsFromState(k,H)}let X=J.sites||{},F=this.collectUpstreamPorts(X),B=G.proxy?.engine==="rpx"?Mh({proxy:G.proxy,config:Eh(X,{proxy:G.proxy}),bunBin:G.runtime==="node"||G.runtime==="deno"?void 0:"/usr/local/bin/bun"}):void 0,V=PL(J),K=G.bakedImage===!0,L=qQ({runtime:V.runtime,runtimeVersion:V.runtimeVersion,systemPackages:G.systemPackages,database:J.infrastructure?.database,phpProvision:V.phpProvision,servicesProvision:V.servicesProvision,rpxProvision:B,baked:K}),E=Yz(L),A=Zz(G.size),j=G.image||J.hetzner?.image||"ubuntu-24.04",q=`${Q}-${Y}-app-fw`,{firewall:M}=await this.ensureFirewall(q,_,hB({allowSsh:G.allowSsh!==!1,sitePorts:F})),T=await this.ensureSshKey(Q,Y,_),{server:R,action:S}=await this.client.createServer({name:W,serverType:A,image:j,location:J.hetzner?.location||this.location,userData:E,labels:_,sshKeys:T?[T]:void 0,firewalls:[{firewall:M.id}]});await this.client.waitForAction(S.id);let N=await this.client.waitForServerRunning(R.id),C={provider:"hetzner",stackName:Z,serverId:N.id,serverName:N.name,firewallId:M.id,publicIp:N.public_net.ipv4?.ip,deployStoragePath:"/var/ts-cloud/staging",sshUser:this.sshUser};await FQ(Z,C);let x=N.public_net.ipv4?.ip;if(x&&this.waitForBoot)await this.waitForSshReady(x),await this.waitForCloudInit(x);return this.outputsFromState(C,N)}async provisionFleet($,J){let{config:Y,environment:Q}=$,G=Y.project.slug,Z=Y.infrastructure.compute,W=NJ(Y,Q),U=Zz(Z.size),z=Z.image||Y.hetzner?.image||"ubuntu-24.04",_=Y.hetzner?.location||this.location,H=Z.bakedImage===!0,X=await XQ(W);if(X?.loadBalancerId){let s=(await this.client.listLoadBalancers().catch(()=>[])).find(($0)=>$0.id===X.loadBalancerId);if(s)return{appPublicIp:s.public_net?.ipv4?.ip,loadBalancerIp:s.public_net?.ipv4?.ip,servicesPrivateIp:X.servicesPrivateIp,deployStoragePath:"/var/ts-cloud/staging",sshUser:this.sshUser}}let F=await this.ensureSshKey(G,Q,I2(G,Q,"app")),B=`${G}-${Q}-net`,K=(await this.client.listNetworks().catch(()=>[])).find((a)=>a.name===B)??await this.client.createNetwork({name:B,labels:I2(G,Q,"app")}),{firewall:L}=await this.ensureFirewall(`${G}-${Q}-app-fw`,I2(G,Q,"app"),hB({allowSsh:!0,sitePorts:[]})),{firewall:E}=await this.ensureFirewall(`${G}-${Q}-services-fw`,I2(G,Q,"services"),[{direction:"in",protocol:"tcp",port:"22",source_ips:["0.0.0.0/0","::/0"]},{direction:"in",protocol:"tcp",port:"3306",source_ips:[K.ip_range]},{direction:"in",protocol:"tcp",port:"5432",source_ips:[K.ip_range]},{direction:"in",protocol:"tcp",port:"6379",source_ips:[K.ip_range]},{direction:"in",protocol:"tcp",port:"7700",source_ips:[K.ip_range]}]),A=[...TL(Z.managedServices??{mysql:!0,redis:!0},{bindPrivate:!0}),...RL(Y.infrastructure?.appDatabase,Z.managedServices??{mysql:!0}),...Nz(!0),...Sz(!0),...Pz(Z.sshKeys)],j=Yz(qQ({runtime:"php",servicesProvision:A,baked:H})),q=await this.client.listServers().catch(()=>[]),M=[],T=q.find((a)=>e8(a.labels,G,Q,"services"));if(!T){let{server:a,action:s}=await this.client.createServer({name:`${G}-${Q}-services`,serverType:Zz(typeof Z.servicesServer==="object"?Z.servicesServer.size:Z.size),image:z,location:_,userData:j,labels:I2(G,Q,"services"),sshKeys:F?[F]:void 0,firewalls:[{firewall:E.id}],networks:[K.id]});await this.client.waitForAction(s.id),T=await this.client.waitForServerRunning(a.id),M.push(a.id)}let R=T.id,S=T.private_net?.[0]?.ip??(await this.client.getServer(R)).private_net?.[0]?.ip,N=[...Nz(!0),...Sz(!0),...Pz(Z.sshKeys),...NL(Y.notifications)],C=DL({versions:Z.php?.versions,default:Z.php?.default,extensions:Z.php?.extensions,installNginx:Z.webServer!=="rpx",optimizeForProduction:Z.php?.optimizeForProduction,ini:Z.php?.ini}),x=Yz(qQ({runtime:"php",phpProvision:C,servicesProvision:N,baked:H})),k=q.filter((a)=>e8(a.labels,G,Q,"app")),b=k.map((a)=>a.id);if(k.length>J.appServers)for(let a of k.slice(J.appServers))await this.client.deleteServer(a.id).catch(()=>{}),b.splice(b.indexOf(a.id),1);for(let a=k.length;a<J.appServers;a++){let{server:s,action:$0}=await this.client.createServer({name:`${G}-${Q}-app-${a+1}`,serverType:U,image:z,location:_,userData:x,labels:I2(G,Q,"app"),sshKeys:F?[F]:void 0,firewalls:[{firewall:L.id}],networks:[K.id]});await this.client.waitForAction($0.id),b.push(s.id),M.push(s.id)}if(this.waitForBoot&&M.length>0)await Promise.all(M.map(async(a)=>{let $0=(await this.client.waitForServerRunning(a)).public_net.ipv4?.ip;if($0)await this.waitForSshReady($0),await this.waitForCloudInit($0)}));let m=`${G}-${Q}-lb`,y,u;if(J.loadBalancer){let s=(await this.client.listLoadBalancers().catch(()=>[])).find(($0)=>$0.name===m)??await this.client.createLoadBalancer({name:m,location:_,network:K.id,labels:I2(G,Q,"lb"),labelSelector:`ts-cloud/project=${G},ts-cloud/environment=${Q},ts-cloud/role=app`,services:[{listenPort:80,destinationPort:80},{listenPort:443,destinationPort:443}]});u=s.id,y=s.public_net?.ipv4?.ip}let J0=y??(await this.client.getServer(b[0]).catch(()=>{return}))?.public_net.ipv4?.ip,Y0={provider:"hetzner",stackName:W,networkId:K.id,loadBalancerId:u,servicesServerId:R,servicesPrivateIp:S,publicIp:J0,deployStoragePath:"/var/ts-cloud/staging",sshUser:this.sshUser};return await FQ(W,Y0),{appPublicIp:J0,loadBalancerIp:y,servicesPrivateIp:S,deployStoragePath:"/var/ts-cloud/staging",sshUser:this.sshUser}}async destroyCompute($){let{config:J,environment:Y}=$,Q=J.project.slug,G=NJ(J,Y),Z=await XQ(G),W=[],U=`${Q}-${Y}-lb`,_=(await this.client.listLoadBalancers().catch(()=>[])).find((L)=>L.name===U);if(_)try{await this.client.deleteLoadBalancer(_.id),W.push(`load balancer ${U}`)}catch{}let H=await this.client.listServers().catch(()=>[]),X=new Set;for(let L of H)if(e8(L.labels,Q,Y,"app")||e8(L.labels,Q,Y,"services"))X.add(L.id);if(Z?.serverId)X.add(Z.serverId);if(Z?.servicesServerId)X.add(Z.servicesServerId);for(let L of X)try{await this.client.deleteServer(L),W.push(`server ${L}`)}catch{}let F=await this.client.listFirewalls().catch(()=>[]);for(let L of[`${Q}-${Y}-app-fw`,`${Q}-${Y}-services-fw`]){let E=F.find((A)=>A.name===L);if(!E)continue;for(let A=0;A<12;A++)try{await this.client.deleteFirewall(E.id),W.push(`firewall ${L}`);break}catch{await this.sleep(3000)}}let B=`${Q}-${Y}-net`,K=(await this.client.listNetworks().catch(()=>[])).find((L)=>L.name===B);if(K)for(let L=0;L<12;L++)try{await this.client.deleteNetwork(K.id),W.push(`network ${B}`);break}catch{await this.sleep(3000)}return await FQ(G,{provider:"hetzner",stackName:G}).catch(()=>{}),{destroyed:W}}async getComputeOutputs($){let J=NJ($.config,$.environment),Y=await XQ(J);if(Y?.serverId){let Z=await this.client.getServer(Y.serverId);return this.outputsFromState(Y,Z)}if(Y?.loadBalancerId||Y?.servicesPrivateIp)return this.outputsFromState(Y);let G=(await this.findComputeTargets({slug:$.config.project.slug,environment:$.environment,role:"app"}))[0];return{deployStoragePath:"/var/ts-cloud/staging",appInstanceId:G?.id,appPublicIp:G?.publicIp,sshUser:this.sshUser}}async uploadRelease($){let J=$.targets?.length?$.targets:await this.findComputeTargets({slug:$.config.project.slug,environment:$.environment,role:"app"});if(J.length===0)throw Error("No Hetzner compute targets found for release upload");let Y=`/var/ts-cloud/staging/${$.remoteKey.split("/").pop()}`;for(let Q of J){if(!Q.publicIp)throw Error(`Target ${Q.id} has no public IP for SCP upload`);this.scpToHost(Q.publicIp,$.localPath,Y)}return{artifactRef:Y}}async findComputeTargets($){return(await this.client.listServers()).filter((Y)=>e8(Y.labels,$.slug,$.environment,$.role||"app")).map((Y)=>({id:String(Y.id),name:Y.name,publicIp:Y.public_net.ipv4?.ip,privateIp:Y.private_net?.[0]?.ip,status:Y.status}))}async runRemoteDeploy($){if($.targets.length===0)return{success:!1,instanceCount:0,perInstance:[],error:"No targets provided"};let J=$.commands.join(`
|
|
13639
13639
|
`),Y=[];for(let G of $.targets){if(!G.publicIp){Y.push({instanceId:G.id,status:"Failed",error:"Missing public IP"});continue}try{let Z=this.sshExec(G.publicIp,J);Y.push({instanceId:G.id,status:"Success",output:Z})}catch(Z){Y.push({instanceId:G.id,status:"Failed",error:Z.message})}}let Q=Y.every((G)=>G.status==="Success");return{success:Q,instanceCount:$.targets.length,perInstance:Y,error:Q?void 0:"One or more SSH deploy commands failed"}}async ensureSshKey($,J,Y){if(!Hh(this.sshPublicKeyPath))throw Error(`SSH public key not found at ${this.sshPublicKeyPath}. ts-cloud deploys to Hetzner over SSH and needs a public key to authorize on the server. Generate one (\`ssh-keygen -t ed25519\`) or set hetzner.sshPrivateKeyPath / HCLOUD_SSH_PUBLIC_KEY.`);let Q=Xh(this.sshPublicKeyPath,"utf8").trim(),G=xB(Q),W=(await this.client.listSshKeys()).find((z)=>xB(z.public_key)===G);if(W)return W.id;return(await this.client.createSshKey({name:`${$}-${J}-deploy`,publicKey:Q,labels:Y})).id}async tryGetServer($){try{return await this.client.getServer($)}catch{return null}}async findExistingServer($,J,Y){return(await this.client.listServers()).find((G)=>e8(G.labels,$,J,"app")||G.name===Y)}async ensureFirewall($,J,Y){let G=(await this.client.listFirewalls()).find((W)=>W.name===$);if(G)return await this.client.setFirewallRules(G.id,Y),{firewall:G};let{firewall:Z}=await this.client.createFirewall({name:$,labels:J,rules:Y});return{firewall:Z}}collectUpstreamPorts($){let J=new Set;for(let Y of Object.values($))if(typeof Y.port==="number")J.add(Y.port);return[...J].filter((Y)=>![80,443].includes(Y))}async sleep($){await new Promise((J)=>setTimeout(J,$))}async waitForSshReady($){let{sshIntervalMs:J,sshTimeoutMs:Y}=this.bootWait,Q=Date.now(),G;while(Date.now()-Q<Y)try{Jz(`ssh ${this.sshBaseArgs($,["-o","ConnectTimeout=5"]).map((Z)=>`"${Z.replace(/"/g,"\\\"")}"`).join(" ")} true`,{stdio:"pipe",maxBuffer:Wz});return}catch(Z){G=Z,await this.sleep(J)}throw Error(`Timed out waiting for SSH on ${$} after ${Y}ms: ${G?.message??"unknown error"}`)}async waitForCloudInit($){let{cloudInitIntervalMs:J,cloudInitTimeoutMs:Y}=this.bootWait,Q=Date.now();while(Date.now()-Q<Y){try{let G=this.sshExec($,"cloud-init status --long 2>/dev/null || cloud-init status 2>/dev/null || echo status:\\ done");if(/status:\s*done/.test(G))return;if(/status:\s*error/.test(G))throw Error(`cloud-init reported an error on ${$}:
|
|
13640
13640
|
${G}`)}catch(G){if(G instanceof Error&&/cloud-init reported an error/.test(G.message))throw G}await this.sleep(J)}throw Error(`Timed out waiting for cloud-init to finish on ${$} after ${Y}ms`)}outputsFromState($,J){return{deployStoragePath:$.deployStoragePath||"/var/ts-cloud/staging",appInstanceId:$.serverId?String($.serverId):void 0,appPublicIp:J?.public_net.ipv4?.ip||$.publicIp,sshUser:$.sshUser||this.sshUser,servicesPrivateIp:$.servicesPrivateIp}}static SSH_HOST_KEY_OPTS=["-o","StrictHostKeyChecking=no","-o","UserKnownHostsFile=/dev/null","-o","LogLevel=ERROR"];sshBaseArgs($,J=[]){return["-i",this.sshPrivateKeyPath,...dQ.SSH_HOST_KEY_OPTS,"-o","BatchMode=yes",...J,`${this.sshUser}@${$}`]}scpToHost($,J,Y){Jz(["scp","-i",this.sshPrivateKeyPath,...dQ.SSH_HOST_KEY_OPTS,"-o","BatchMode=yes",J,`${this.sshUser}@${$}:${Y}`].map((Q)=>`"${Q.replace(/"/g,"\\\"")}"`).join(" "),{stdio:"pipe",maxBuffer:Wz})}sshExec($,J){let Y=J.replace(/'/g,"'\\''");return Jz(`ssh ${this.sshBaseArgs($).map((Q)=>`"${Q.replace(/"/g,"\\\"")}"`).join(" ")} '${Y}'`,{encoding:"utf8",stdio:["pipe","pipe","pipe"],maxBuffer:Wz})}};Kn=new hL;await X2();Vn=`eval "$(cd ${H8} && pantry env 2>/dev/null)"`;W9();X2()});var fL={};t0(fL,{resolveUiSource:()=>vL,ensureManagementDashboard:()=>xh});import{existsSync as aQ}from"node:fs";import{dirname as Sh,join as v2}from"node:path";import{fileURLToPath as Ph}from"node:url";function Ih($){return $!=null&&$!==""&&$!=="0"&&$.toLowerCase()!=="false"}function vL($){if(aQ(v2($,"ui","pages"))||aQ(v2($,"ui","package.json")))return{uiRoot:"ui/dist",build:"cd ui && bun install && bun run build"};let J=Sh(Ph(import.meta.url)),Y=[v2(J,"ui"),v2(J,"..","ui"),v2(J,"..","..","ui"),v2(J,"..","dist","ui")];for(let Q of Y)if(aQ(v2(Q,"index.html"))||aQ(v2(Q,"serverless.html")))return{uiRoot:Q,build:!1};return null}function xh($,J={}){let Y=J.logger??Ch,Q=J.cwd??process.cwd();if(Ih(process.env.TS_CLOUD_UI_DISABLE))return Y.info("Management dashboard: skipped (TS_CLOUD_UI_DISABLE set)."),$;if(kz($))return $;let G=vL(Q);if(!G)return Y.info("Management dashboard: UI not found (no local ui/ or packaged dist/ui) — skipping auto-deploy."),$;let Z=process.env.TS_CLOUD_UI_PASSWORD?.trim()||void 0,W=$.environments&&Object.keys($.environments)[0],U=tB($,W??"production",{uiRoot:G.uiRoot,build:G.build,domain:process.env.TS_CLOUD_UI_DOMAIN?.trim()||void 0,username:process.env.TS_CLOUD_UI_USERNAME?.trim()||void 0,password:Z,realm:process.env.TS_CLOUD_UI_REALM?.trim()||void 0});if(!U)return Y.info("Management dashboard: no domain resolved (set TS_CLOUD_UI_DOMAIN or configure a site domain) — skipping."),$;return $.sites={...$.sites??{},[U.name]:U.site},Y.info(`Management dashboard → https://${U.site.domain} (${Z?"htpasswd-protected":"NO AUTH — set TS_CLOUD_UI_PASSWORD"})`),$}var Ch;var gL=Z0(async()=>{await yL();Ch={info:()=>{},warn:()=>{}}});function kh($){return`'${$.split("'").join("'\\''")}'`}function uL($){let J=$.user||"root",Y=$.script.join(`
|
|
13641
|
-
`),Q=J==="root"?'bash -l "$TS_CLOUD_RECIPE"':`runuser -l ${kh(J)} -c "bash $TS_CLOUD_RECIPE"`;return["set -uo pipefail",`echo "__TS_CLOUD_RECIPE_BEGIN__ ${$.name} (user=${J})"`,"TS_CLOUD_RECIPE=$(mktemp)",`cat > "$TS_CLOUD_RECIPE" <<'TS_CLOUD_RECIPE_EOF'`,Y,"TS_CLOUD_RECIPE_EOF",'chmod +r "$TS_CLOUD_RECIPE"',Q,"TS_CLOUD_RC=$?",'rm -f "$TS_CLOUD_RECIPE"',`echo "__TS_CLOUD_RECIPE_END__ ${$.name} exit=$TS_CLOUD_RC"`,"exit $TS_CLOUD_RC"]}var oQ={};t0(oQ,{runComputeRecipe:()=>yh,rollbackComputeSite:()=>bh,getComputeDeployHistory:()=>hh});async function G4($){return await $.driver.findComputeTargets({slug:$.slug,environment:$.environment,role:$.role||"app"})}async function bh($,J){let Y=$.logger||dL,Q=await G4($);if(Q.length===0)return{success:!1,error:`No '${$.role||"app"}' servers found for ${$.slug}/${$.environment}.`};let G=`/var/www/${J.siteName}`,Z=p6(G,J.to||"unused"),W=["set -uo pipefail",...lF(Z,J.to?{to:J.to}:{}),`(cd ${s$} && pantry restart php-fpm) 2>/dev/null || true`,`(cd ${Z.current} && eval "$(cd ${s$} && pantry env 2>/dev/null)" && php artisan queue:restart) 2>/dev/null || true`];Y.step(`Rolling back ${J.siteName}${J.to?` to ${J.to}`:" to the previous release"} on ${Q.length} server(s)...`);let U=await $.driver.runRemoteDeploy({targets:Q,commands:W,comment:`ts-cloud rollback ${$.slug}/${J.siteName}`,tags:{Project:$.slug,Environment:$.environment,Role:$.role||"app"}});if(!U.success)Y.error(`Rollback failed: ${U.error||"unknown error"}`);else Y.success(`Rolled back ${J.siteName}.`);return{success:U.success,error:U.error,perInstance:U.perInstance}}async function hh($,J){let Y=await G4($);if(Y.length===0)return{success:!1,error:`No '${$.role||"app"}' servers found for ${$.slug}/${$.environment}.`};let Q=RU(`/var/www/${J.siteName}`),G=Math.max(1,J.limit??20),Z=[`[ -f ${Q} ] && tail -n ${G} ${Q} || echo "no deploy history for ${J.siteName}"`],W=await $.driver.runRemoteDeploy({targets:Y,commands:Z,comment:`ts-cloud deploy:history ${$.slug}/${J.siteName}`,tags:{Project:$.slug,Environment:$.environment,Role:$.role||"app"}});return{success:W.success,error:W.error,perInstance:W.perInstance}}async function yh($,J){let Y=$.logger||dL,Q=await G4($);if(Q.length===0)return{success:!1,error:`No '${$.role||"app"}' servers found for ${$.slug}/${$.environment}.`};Y.step(`Running recipe '${J.name}' as ${J.user||"root"} on ${Q.length} server(s)...`);let G=await $.driver.runRemoteDeploy({targets:Q,commands:uL({name:J.name,script:J.script,user:J.user}),comment:`ts-cloud recipe ${J.name}`,tags:{Project:$.slug,Environment:$.environment,Role:$.role||"app"}});if(!G.success)Y.error(`Recipe '${J.name}' failed: ${G.error||"unknown error"}`);else Y.success(`Recipe '${J.name}' completed.`);return{success:G.success,error:G.error,perInstance:G.perInstance}}var dL;var sQ=Z0(()=>{Y8();DU();dL={info:()=>{},warn:()=>{},error:()=>{},step:()=>{},success:()=>{}}});class eQ{client;region;constructor($="us-east-1"){this.region=$,this.client=new Q0}async describeFileSystems($){let J=[];if($?.FileSystemId)J.push(`FileSystemId=${encodeURIComponent($.FileSystemId)}`);if($?.CreationToken)J.push(`CreationToken=${encodeURIComponent($.CreationToken)}`);let Y=`/2015-02-01/file-systems${J.length>0?`?${J.join("&")}`:""}`;return{FileSystems:((await this.client.request({service:"elasticfilesystem",region:this.region,method:"GET",path:Y,headers:{"Content-Type":"application/json"}})).FileSystems||[]).map((G)=>({FileSystemId:G.FileSystemId,Name:G.Name,CreationTime:G.CreationTime,LifeCycleState:G.LifeCycleState,NumberOfMountTargets:G.NumberOfMountTargets,SizeInBytes:G.SizeInBytes?{Value:G.SizeInBytes.Value,Timestamp:G.SizeInBytes.Timestamp}:void 0,PerformanceMode:G.PerformanceMode,Encrypted:G.Encrypted,ThroughputMode:G.ThroughputMode,Tags:G.Tags}))}}}var Z4=Z0(()=>{z0()});var cL={};t0(cL,{SQSClient:()=>t1});class t1{client;region;constructor($="us-east-1",J){this.region=$,this.client=new Q0}async createQueue($){let Y={Action:"CreateQueue",QueueName:$.fifo&&!$.queueName.endsWith(".fifo")?`${$.queueName}.fifo`:$.queueName,Version:"2012-11-05"},Q=1;if($.visibilityTimeout!==void 0)Y[`Attribute.${Q}.Name`]="VisibilityTimeout",Y[`Attribute.${Q}.Value`]=$.visibilityTimeout.toString(),Q++;if($.messageRetentionPeriod!==void 0)Y[`Attribute.${Q}.Name`]="MessageRetentionPeriod",Y[`Attribute.${Q}.Value`]=$.messageRetentionPeriod.toString(),Q++;if($.delaySeconds!==void 0)Y[`Attribute.${Q}.Name`]="DelaySeconds",Y[`Attribute.${Q}.Value`]=$.delaySeconds.toString(),Q++;if($.maxMessageSize!==void 0)Y[`Attribute.${Q}.Name`]="MaximumMessageSize",Y[`Attribute.${Q}.Value`]=$.maxMessageSize.toString(),Q++;if($.receiveMessageWaitTime!==void 0)Y[`Attribute.${Q}.Name`]="ReceiveMessageWaitTimeSeconds",Y[`Attribute.${Q}.Value`]=$.receiveMessageWaitTime.toString(),Q++;if($.fifo){if(Y[`Attribute.${Q}.Name`]="FifoQueue",Y[`Attribute.${Q}.Value`]="true",Q++,$.contentBasedDeduplication)Y[`Attribute.${Q}.Name`]="ContentBasedDeduplication",Y[`Attribute.${Q}.Value`]="true",Q++}if($.deadLetterTargetArn&&$.maxReceiveCount)Y[`Attribute.${Q}.Name`]="RedrivePolicy",Y[`Attribute.${Q}.Value`]=JSON.stringify({deadLetterTargetArn:$.deadLetterTargetArn,maxReceiveCount:$.maxReceiveCount}),Q++;if($.tags&&Object.keys($.tags).length>0){let Z=1;for(let[W,U]of Object.entries($.tags))Y[`Tag.${Z}.Key`]=W,Y[`Tag.${Z}.Value`]=U,Z++}let G=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(Y).toString()});return{QueueUrl:G.QueueUrl||G.CreateQueueResult?.QueueUrl}}async listQueues($){let J={Action:"ListQueues",Version:"2012-11-05"};if($)J.QueueNamePrefix=$;let Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()}),Q=[];if(Y.QueueUrl)Q.push(Y.QueueUrl);else if(Y.ListQueuesResult?.QueueUrl)if(Array.isArray(Y.ListQueuesResult.QueueUrl))Q.push(...Y.ListQueuesResult.QueueUrl);else Q.push(Y.ListQueuesResult.QueueUrl);return{QueueUrls:Q}}async getQueueAttributes($){let J={Action:"GetQueueAttributes",QueueUrl:$,Version:"2012-11-05","AttributeName.1":"All"},Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()});return{Attributes:Y.Attributes||Y.GetQueueAttributesResult?.Attributes||{}}}async getQueueUrl($){let J={Action:"GetQueueUrl",QueueName:$,Version:"2012-11-05"},Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()});return{QueueUrl:Y.QueueUrl||Y.GetQueueUrlResult?.QueueUrl}}async deleteQueue($){let J={Action:"DeleteQueue",QueueUrl:$,Version:"2012-11-05"};await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()})}async purgeQueue($){let J={Action:"PurgeQueue",QueueUrl:$,Version:"2012-11-05"};await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()})}async sendMessage($){let J={Action:"SendMessage",QueueUrl:$.queueUrl,MessageBody:$.messageBody,Version:"2012-11-05"};if($.delaySeconds!==void 0)J.DelaySeconds=$.delaySeconds;if($.messageGroupId)J.MessageGroupId=$.messageGroupId;if($.messageDeduplicationId)J.MessageDeduplicationId=$.messageDeduplicationId;let Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()});return{MessageId:Y.MessageId||Y.SendMessageResult?.MessageId}}async receiveMessages($){let J={Action:"ReceiveMessage",QueueUrl:$.queueUrl,Version:"2012-11-05"};if($.maxMessages!==void 0)J.MaxNumberOfMessages=$.maxMessages;if($.visibilityTimeout!==void 0)J.VisibilityTimeout=$.visibilityTimeout;if($.waitTimeSeconds!==void 0)J.WaitTimeSeconds=$.waitTimeSeconds;let Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()}),Q=[],G=Y.Message||Y.ReceiveMessageResult?.Message;if(G)if(Array.isArray(G))Q.push(...G.map((Z)=>({MessageId:Z.MessageId,ReceiptHandle:Z.ReceiptHandle,Body:Z.Body})));else Q.push({MessageId:G.MessageId,ReceiptHandle:G.ReceiptHandle,Body:G.Body});return{Messages:Q}}async deleteMessage($,J){let Y={Action:"DeleteMessage",QueueUrl:$,ReceiptHandle:J,Version:"2012-11-05"};await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(Y).toString()})}}var vJ=Z0(()=>{z0()});class W4{client;region;constructor($="us-east-1"){this.region=$,this.client=new Q0}async call($,J){return this.client.request({service:"wafv2",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`AWSWAF_20190729.${$}`},body:JSON.stringify(J)})}async listWebACLs($="REGIONAL"){return(await this.call("ListWebACLs",{Scope:$,Limit:100}))?.WebACLs??[]}async getWebACLRules($,J,Y="REGIONAL"){return((await this.call("GetWebACL",{Name:$,Id:J,Scope:Y}))?.WebACL?.Rules??[]).map((Z)=>({Name:Z.Name,Priority:Z.Priority,Action:Z.Action?Object.keys(Z.Action)[0]:Z.OverrideAction?Object.keys(Z.OverrideAction)[0]:"count"}))}}var lL=Z0(()=>{z0()});var rL={};t0(rL,{resolveDashboardData:()=>pL});function mL($){return String($).padStart(2,"0")}function U9($){return`${$.getUTCFullYear()}-${mL($.getUTCMonth()+1)}-${mL($.getUTCDate())}`}async function fJ($,J,Y,Q,G,Z){let W=await $.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:Y,Dimensions:[{Name:"FunctionName",Value:J}],StartTime:G,EndTime:Z,Period:86400,Statistics:[Q]}).catch(()=>[]);if(!W.length)return 0;if(Q==="Sum")return W.reduce((U,z)=>U+(z.Sum??0),0);if(Q==="Maximum")return Math.max(...W.map((U)=>U.Maximum??0));return W.reduce((U,z)=>U+(z.Average??0),0)/W.length}async function gJ($,J,Y,Q,G,Z,W){let U=await $.getMetricStatistics({Namespace:J,MetricName:Y,Dimensions:Q,StartTime:Z,EndTime:W,Period:86400,Statistics:[G]}).catch(()=>[]);if(!U.length)return 0;if(G==="Sum")return U.reduce((z,_)=>z+(_.Sum??0),0);if(G==="Maximum")return Math.max(...U.map((z)=>z.Maximum??0));return U.reduce((z,_)=>z+(_.Average??0),0)/U.length}async function U4($,J,Y,Q,G){let Z=await $.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Duration",Dimensions:[{Name:"FunctionName",Value:J}],StartTime:Q,EndTime:G,Period:86400,ExtendedStatistics:[Y]}).catch(()=>[]);return Math.round(Z.reduce((W,U)=>W+(U.Percentiles?.[Y]??0),0))}async function pL($,J){let Y=await kW($,J),Q=Y.region,G=new e2(Q),Z=new Q1(Q),W=new N2(Q),U=new Date,z=new Date(U.getTime()-86400000),_=$.environments?.[J]?.app,H={};H.app={name:Y.slug,env:J,region:Q,runtime:_?.kind==="php"?`php-${_?.phpVersion??"8.3"} (fpm)`:_?.kind??"node",url:Y.endpoint??"",build:Y.lastRelease?.sha?.slice(0,7)??"—",deployedAt:Y.lastRelease?.timestamp??"—"},H.maintenance={enabled:!1},H.scheduler={enabled:Y.scheduler!=="off",expression:Y.scheduler==="sub-minute"?"rate(1 minute) · sub-minute":"rate(1 minute)",lastRun:"—"};let X=0,F=0,B=0,V=[],K=[];for(let A of Y.functions){let[j,q,M,T,R,S,N,C,x]=await Promise.all([fJ(G,A.name,"Invocations","Sum",z,U),fJ(G,A.name,"Errors","Sum",z,U),fJ(G,A.name,"Throttles","Sum",z,U),fJ(G,A.name,"Duration","Average",z,U),Z.getFunction(A.name).catch(()=>null),U4(G,A.name,"p50",z,U),U4(G,A.name,"p95",z,U),U4(G,A.name,"p99",z,U),G.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:A.name}],StartTime:new Date(U.getTime()-43200000),EndTime:U,Period:3600,Stat:"Sum"}).catch(()=>[])]);X+=j,F+=q,B=Math.max(B,T);let k=R?.Configuration?.MemorySize??0,b=Object.keys(R?.Configuration?.Environment?.Variables??{}),m=[],y=0;try{let{events:J0=[]}=await W.filterLogEvents({logGroupName:`/aws/lambda/${A.name}`,startTime:z.getTime(),limit:40});for(let Y0 of J0){let a=(Y0.message??"").trim(),s=/Max Memory Used:\s*(\d+)\s*MB/.exec(a);if(s)y=Math.max(y,Number(s[1]))}m=J0.filter((Y0)=>!/^(?:START|END|REPORT|INIT_START)/.test((Y0.message??"").trim())).slice(-6).map((Y0)=>({ts:new Date(Y0.timestamp??0).toISOString().slice(11,19),msg:(Y0.message??"").trim().slice(0,120),err:/error|exception|fatal/i.test(Y0.message??"")}))}catch{}let u=Math.max(1,...x);V.push({key:A.mode,name:A.name,version:A.version,memory:k,timeout:R?.Configuration?.Timeout??0,runtime:R?.Configuration?.Runtime??"provided.al2023",invocations:Math.round(j),errors:Math.round(q),p95:N||Math.round(T),status:"active",provisioned:A.provisioned?`${A.provisioned.allocated}/${A.provisioned.requested}`:void 0}),K.push({key:A.mode,name:A.name,runtime:R?.Configuration?.Runtime??"provided.al2023",arch:R?.Configuration?.Architectures?.[0]??"x86_64",memory:k,timeout:R?.Configuration?.Timeout??0,ephemeral:R?.Configuration?.EphemeralStorage?.Size??512,version:A.version,concurrency:_?.concurrency??"—",invocations:Math.round(j),errors:Math.round(q),throttles:Math.round(M),p50:S||Math.round(T),p95:N||Math.round(T),p99:C||Math.round(T),maxMem:y,spark:x.length?x.map((J0)=>Math.round(J0/u*100)):[0],env:b.length?b:["(none)"],recent:m.length?m:[{ts:"—",msg:"no recent events",err:!1}]})}H.functions=V,H.functionsDetail=K;let L=X?Number((F/X*100).toFixed(2)):0,E=Math.round(await fJ(G,Y.functions[0]?.name??"","ConcurrentExecutions","Maximum",z,U));H.metrics={invocations:Math.round(X),errorRatePct:L,p95Ms:Math.round(B),coldStartPct:0,concurrency:E,estCostUsd:0};try{let A=new t1(Q),j=[],q=[],M=0;try{let{QueueUrl:R}=await A.getQueueUrl(`${Y.slug}-${J}-dlq`),{Attributes:S}=await A.getQueueAttributes(R);M=Number(S.ApproximateNumberOfMessages??0)}catch{}let T=_?l9(_,Y.slug,J):[];for(let R of T){let S=R.name.replace(`${Y.slug}-${J}-`,""),N=0,C=0;try{let{QueueUrl:k}=await A.getQueueUrl(R.name),{Attributes:b}=await A.getQueueAttributes(k);N=Number(b.ApproximateNumberOfMessages??0),C=Number(b.ApproximateNumberOfMessagesNotVisible??0)}catch{}let x=Math.round(await gJ(G,"AWS/SQS","NumberOfMessagesDeleted",[{Name:"QueueName",Value:R.name}],"Sum",z,U));j.push({name:S,visible:N,inFlight:C,processed:x,dlq:M}),q.push({name:R.name,short:S,visible:N,inFlight:C,delayed:0,processed:x,oldestSec:0,concurrency:R.concurrency??_?.queueConcurrency??"—",tries:_?.queueTries??3,visTimeout:(_?.queueTimeout??120)*6,dlq:M})}if(j.length)H.queues=j;if(q.length)H.queuesDetail=q;H.dlqItems=[]}catch{}try{let A=new A0(Q),{Stacks:j}=await A.describeStacks({stackName:o2($,J)}),q={};for(let M of j?.[0]?.Outputs??[])if(M.OutputKey)q[M.OutputKey]=M.OutputValue??"";if(_?.database?.connection==="aurora-serverless"){let M=`${Y.slug}-${J}-db`,T=[{Name:"DBClusterIdentifier",Value:M}],[R,S]=await Promise.all([gJ(G,"AWS/RDS","ServerlessDatabaseCapacity",T,"Average",z,U),gJ(G,"AWS/RDS","DatabaseConnections",T,"Maximum",z,U)]);if(H.aurora={id:M,engine:"aurora-mysql",minAcu:_?.database?.minCapacity??0.5,maxAcu:_?.database?.maxCapacity??4,currentAcu:R?Number(R.toFixed(1)):_?.database?.minCapacity??0.5,database:"app",connections:Math.round(S),status:q.DbEndpoint?"available":"creating"},_?.rdsProxy)H.proxy={name:`${Y.slug}-${J}-proxy`,endpoint:q.DbProxyEndpoint??"—",pooledConns:Math.round(S),status:"available"}}if(_?.cache?.driver==="elasticache"){let M=`${Y.slug}-${J}-redis`,T=[{Name:"CacheClusterId",Value:`${M}-001`}],[R,S]=await Promise.all([gJ(G,"AWS/ElastiCache","CacheHits",T,"Sum",z,U),gJ(G,"AWS/ElastiCache","CacheMisses",T,"Sum",z,U)]),N=R+S>0?Number((R/(R+S)*100).toFixed(1)):0;H.redis={id:M,node:"cache.t4g.micro",engine:"redis",hitRate:N,status:q.CacheEndpoint?"available":"creating"}}if(_?.efs){let M=0;try{if(q.EfsId){let T=new eQ(Q),{FileSystems:R}=await T.describeFileSystems({FileSystemId:q.EfsId});M=Number(((R?.[0]?.SizeInBytes?.Value??0)/1048576).toFixed(1))}}catch{}H.efs={id:q.EfsId??"efs",mount:"/mnt/local",sizeMb:M,status:"available"}}H.assetsInfo=q.AssetsCdnDomain?{bucket:q.AssetsBucketName??`${Y.slug}-${J}-assets`,cdn:q.AssetsCdnDomain,customDomain:_?.assetDomain??"—",assetUrl:Y.assetUrl??"—",files:0,sizeMb:0,cacheHitPct:0,build:H.app.build}:void 0}catch{}if(H.assetsInfo)try{let j=await new H0(Q).list({bucket:H.assetsInfo.bucket,maxKeys:1000});H.assetsInfo.files=j.length,H.assetsInfo.sizeMb=Number((j.reduce((q,M)=>q+(M.Size??0),0)/1048576).toFixed(1)),H.assetsRecent=j.slice(0,8).map((q)=>({path:`/${q.Key}`,size:`${Math.max(1,Math.round((q.Size??0)/1024))} KB`,type:q.Key.split(".").pop()??""}))}catch{}try{if(_?.secrets){let A=Array.isArray(_.secrets)?_.secrets.map((j)=>({key:j.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),source:j})):Object.entries(_.secrets).map(([j,q])=>({key:j,source:String(q)}));H.secretsList=A.map((j)=>({...j,updated:"—"}))}}catch{}try{let A=new H0(Q),j=`${Y.slug}-${J}-deployments`,q=await A.getObjectJson(j,`deployments/${Y.slug}/${J}/history.json`).catch(()=>null);if(q?.records?.length)H.deploymentsDetail=q.records.slice(-12).reverse().map((M)=>({sha:(M.sha??"").slice(0,7),status:M.status??"success",when:M.timestamp??"—",took:M.took??"—",by:M.by??"—",version:M.version??"—",hooks:M.hooks??[]}))}catch{}H.metricsTotals={invocations:H.metrics.invocations,errors:Math.round(F),errorRatePct:L,p95Ms:H.metrics.p95Ms,throttles:K.reduce((A,j)=>A+j.throttles,0),coldStartPct:0,estCostUsd:0,concurrency:E},H.metricsPerFn=K.map((A)=>({key:A.key,invocations:A.invocations,errors:A.errors,throttles:A.throttles,avgMs:A.p50,maxMs:A.p99,costUsd:0}));try{H.invSpark=await G.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:Y.functions.find((A)=>A.mode==="http")?.name??""}],StartTime:new Date(U.getTime()-86400000),EndTime:U,Period:3600,Stat:"Sum"})}catch{}try{let A=new s9(Q),j=U,q=new Date(Date.UTC(j.getUTCFullYear(),j.getUTCMonth(),1)),M=new Date(Date.UTC(j.getUTCFullYear(),j.getUTCMonth()-1,1)),[T,R]=await Promise.all([A.getCostByService({start:U9(q),end:U9(j),granularity:"MONTHLY"}).catch(()=>[]),A.getCostByService({start:U9(M),end:U9(q),granularity:"MONTHLY"}).catch(()=>[])]);if(T.length){let S=T.reduce((y,u)=>y+u.amount,0),N=R.reduce((y,u)=>y+u.amount,0),C=j.getUTCDate(),x=new Date(Date.UTC(j.getUTCFullYear(),j.getUTCMonth()+1,0)).getUTCDate();H.costSummary={monthToDateUsd:Number(S.toFixed(2)),projectedUsd:Number((S/C*x).toFixed(2)),lastMonthUsd:Number(N.toFixed(2)),dailyAvgUsd:Number((S/C).toFixed(2))},H.costServices=T.filter((y)=>y.amount>0).sort((y,u)=>u.amount-y.amount).slice(0,12).map((y)=>({name:y.service,usd:Number(y.amount.toFixed(2)),note:""})),H.metrics.estCostUsd=Number((S/C).toFixed(2)),H.metricsTotals.estCostUsd=H.metrics.estCostUsd,H.costTrend=await A.getDailyTotals({start:U9(q),end:U9(j)}).catch(()=>[]);let k=T.find((y)=>/lambda/i.test(y.service))?.amount??0,b=(y)=>y.invocations*(y.p50/1000)*(y.memory/1024),m=K.reduce((y,u)=>y+b(u),0)||1;H.costPerFn=K.map((y)=>({key:y.key,requests:y.invocations,gbSec:Math.round(b(y)),usd:Number((k*(b(y)/m)).toFixed(2))}))}}catch{}if(_?.firewall)try{let A=await G.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"BlockedRequests",StartTime:z,EndTime:U,Period:86400,Statistics:["Sum"]}).catch(()=>[]),j=await G.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"AllowedRequests",StartTime:z,EndTime:U,Period:86400,Statistics:["Sum"]}).catch(()=>[]);H.waf={enabled:!0,scope:"REGIONAL",acl:`${Y.slug}-${J}-waf`,allowed24h:Math.round(j.reduce((q,M)=>q+(M.Sum??0),0)),blocked24h:Math.round(A.reduce((q,M)=>q+(M.Sum??0),0))};try{let q=new W4(Q),M=await q.listWebACLs("REGIONAL"),T=M.find((R)=>R.Name?.includes(`${Y.slug}-${J}`))??M[0];if(T?.Name&&T.Id){H.waf.acl=T.Name;let R=await q.getWebACLRules(T.Name,T.Id,"REGIONAL");if(R.length)H.wafRules=R.map((S)=>({name:S.Name??"—",detail:`priority ${S.Priority??0}`,action:S.Action??"count",blocked24h:0}))}}catch{}}catch{}if(Y.scheduler!=="off"&&_?.kind==="php")try{let A=await y8($,J,"schedule:list"),j=[];for(let q of(A||"").split(`
|
|
13641
|
+
`),Q=J==="root"?'bash -l "$TS_CLOUD_RECIPE"':`runuser -l ${kh(J)} -c "bash $TS_CLOUD_RECIPE"`;return["set -uo pipefail",`echo "__TS_CLOUD_RECIPE_BEGIN__ ${$.name} (user=${J})"`,"TS_CLOUD_RECIPE=$(mktemp)",`cat > "$TS_CLOUD_RECIPE" <<'TS_CLOUD_RECIPE_EOF'`,Y,"TS_CLOUD_RECIPE_EOF",'chmod +r "$TS_CLOUD_RECIPE"',Q,"TS_CLOUD_RC=$?",'rm -f "$TS_CLOUD_RECIPE"',`echo "__TS_CLOUD_RECIPE_END__ ${$.name} exit=$TS_CLOUD_RC"`,"exit $TS_CLOUD_RC"]}var oQ={};t0(oQ,{runComputeRecipe:()=>yh,rollbackComputeSite:()=>bh,getComputeDeployHistory:()=>hh});async function G4($){return await $.driver.findComputeTargets({slug:$.slug,environment:$.environment,role:$.role||"app"})}async function bh($,J){let Y=$.logger||dL,Q=await G4($);if(Q.length===0)return{success:!1,error:`No '${$.role||"app"}' servers found for ${$.slug}/${$.environment}.`};let G=`/var/www/${J.siteName}`,Z=p6(G,J.to||"unused"),W=["set -uo pipefail",...lF(Z,J.to?{to:J.to}:{}),`(cd ${s$} && pantry restart php-fpm) 2>/dev/null || true`,`(cd ${Z.current} && eval "$(cd ${s$} && pantry env 2>/dev/null)" && php artisan queue:restart) 2>/dev/null || true`];Y.step(`Rolling back ${J.siteName}${J.to?` to ${J.to}`:" to the previous release"} on ${Q.length} server(s)...`);let U=await $.driver.runRemoteDeploy({targets:Q,commands:W,comment:`ts-cloud rollback ${$.slug}/${J.siteName}`,tags:{Project:$.slug,Environment:$.environment,Role:$.role||"app"}});if(!U.success)Y.error(`Rollback failed: ${U.error||"unknown error"}`);else Y.success(`Rolled back ${J.siteName}.`);return{success:U.success,error:U.error,perInstance:U.perInstance}}async function hh($,J){let Y=await G4($);if(Y.length===0)return{success:!1,error:`No '${$.role||"app"}' servers found for ${$.slug}/${$.environment}.`};let Q=RU(`/var/www/${J.siteName}`),G=Math.max(1,J.limit??20),Z=[`[ -f ${Q} ] && tail -n ${G} ${Q} || echo "no deploy history for ${J.siteName}"`],W=await $.driver.runRemoteDeploy({targets:Y,commands:Z,comment:`ts-cloud deploy:history ${$.slug}/${J.siteName}`,tags:{Project:$.slug,Environment:$.environment,Role:$.role||"app"}});return{success:W.success,error:W.error,perInstance:W.perInstance}}async function yh($,J){let Y=$.logger||dL,Q=await G4($);if(Q.length===0)return{success:!1,error:`No '${$.role||"app"}' servers found for ${$.slug}/${$.environment}.`};Y.step(`Running recipe '${J.name}' as ${J.user||"root"} on ${Q.length} server(s)...`);let G=await $.driver.runRemoteDeploy({targets:Q,commands:uL({name:J.name,script:J.script,user:J.user}),comment:`ts-cloud recipe ${J.name}`,tags:{Project:$.slug,Environment:$.environment,Role:$.role||"app"}});if(!G.success)Y.error(`Recipe '${J.name}' failed: ${G.error||"unknown error"}`);else Y.success(`Recipe '${J.name}' completed.`);return{success:G.success,error:G.error,perInstance:G.perInstance}}var dL;var sQ=Z0(()=>{Y8();DU();dL={info:()=>{},warn:()=>{},error:()=>{},step:()=>{},success:()=>{}}});class eQ{client;region;constructor($="us-east-1"){this.region=$,this.client=new Q0}async describeFileSystems($){let J=[];if($?.FileSystemId)J.push(`FileSystemId=${encodeURIComponent($.FileSystemId)}`);if($?.CreationToken)J.push(`CreationToken=${encodeURIComponent($.CreationToken)}`);let Y=`/2015-02-01/file-systems${J.length>0?`?${J.join("&")}`:""}`;return{FileSystems:((await this.client.request({service:"elasticfilesystem",region:this.region,method:"GET",path:Y,headers:{"Content-Type":"application/json"}})).FileSystems||[]).map((G)=>({FileSystemId:G.FileSystemId,Name:G.Name,CreationTime:G.CreationTime,LifeCycleState:G.LifeCycleState,NumberOfMountTargets:G.NumberOfMountTargets,SizeInBytes:G.SizeInBytes?{Value:G.SizeInBytes.Value,Timestamp:G.SizeInBytes.Timestamp}:void 0,PerformanceMode:G.PerformanceMode,Encrypted:G.Encrypted,ThroughputMode:G.ThroughputMode,Tags:G.Tags}))}}}var Z4=Z0(()=>{z0()});var cL={};t0(cL,{SQSClient:()=>t1});class t1{client;region;constructor($="us-east-1",J){this.region=$,this.client=new Q0}async createQueue($){let Y={Action:"CreateQueue",QueueName:$.fifo&&!$.queueName.endsWith(".fifo")?`${$.queueName}.fifo`:$.queueName,Version:"2012-11-05"},Q=1;if($.visibilityTimeout!==void 0)Y[`Attribute.${Q}.Name`]="VisibilityTimeout",Y[`Attribute.${Q}.Value`]=$.visibilityTimeout.toString(),Q++;if($.messageRetentionPeriod!==void 0)Y[`Attribute.${Q}.Name`]="MessageRetentionPeriod",Y[`Attribute.${Q}.Value`]=$.messageRetentionPeriod.toString(),Q++;if($.delaySeconds!==void 0)Y[`Attribute.${Q}.Name`]="DelaySeconds",Y[`Attribute.${Q}.Value`]=$.delaySeconds.toString(),Q++;if($.maxMessageSize!==void 0)Y[`Attribute.${Q}.Name`]="MaximumMessageSize",Y[`Attribute.${Q}.Value`]=$.maxMessageSize.toString(),Q++;if($.receiveMessageWaitTime!==void 0)Y[`Attribute.${Q}.Name`]="ReceiveMessageWaitTimeSeconds",Y[`Attribute.${Q}.Value`]=$.receiveMessageWaitTime.toString(),Q++;if($.fifo){if(Y[`Attribute.${Q}.Name`]="FifoQueue",Y[`Attribute.${Q}.Value`]="true",Q++,$.contentBasedDeduplication)Y[`Attribute.${Q}.Name`]="ContentBasedDeduplication",Y[`Attribute.${Q}.Value`]="true",Q++}if($.deadLetterTargetArn&&$.maxReceiveCount)Y[`Attribute.${Q}.Name`]="RedrivePolicy",Y[`Attribute.${Q}.Value`]=JSON.stringify({deadLetterTargetArn:$.deadLetterTargetArn,maxReceiveCount:$.maxReceiveCount}),Q++;if($.tags&&Object.keys($.tags).length>0){let Z=1;for(let[W,U]of Object.entries($.tags))Y[`Tag.${Z}.Key`]=W,Y[`Tag.${Z}.Value`]=U,Z++}let G=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(Y).toString()});return{QueueUrl:G.QueueUrl||G.CreateQueueResult?.QueueUrl}}async listQueues($){let J={Action:"ListQueues",Version:"2012-11-05"};if($)J.QueueNamePrefix=$;let Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()}),Q=[];if(Y.QueueUrl)Q.push(Y.QueueUrl);else if(Y.ListQueuesResult?.QueueUrl)if(Array.isArray(Y.ListQueuesResult.QueueUrl))Q.push(...Y.ListQueuesResult.QueueUrl);else Q.push(Y.ListQueuesResult.QueueUrl);return{QueueUrls:Q}}async getQueueAttributes($){let J={Action:"GetQueueAttributes",QueueUrl:$,Version:"2012-11-05","AttributeName.1":"All"},Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()});return{Attributes:Y.Attributes||Y.GetQueueAttributesResult?.Attributes||{}}}async getQueueUrl($){let J={Action:"GetQueueUrl",QueueName:$,Version:"2012-11-05"},Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()});return{QueueUrl:Y.QueueUrl||Y.GetQueueUrlResult?.QueueUrl}}async deleteQueue($){let J={Action:"DeleteQueue",QueueUrl:$,Version:"2012-11-05"};await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()})}async purgeQueue($){let J={Action:"PurgeQueue",QueueUrl:$,Version:"2012-11-05"};await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()})}async sendMessage($){let J={Action:"SendMessage",QueueUrl:$.queueUrl,MessageBody:$.messageBody,Version:"2012-11-05"};if($.delaySeconds!==void 0)J.DelaySeconds=$.delaySeconds;if($.messageGroupId)J.MessageGroupId=$.messageGroupId;if($.messageDeduplicationId)J.MessageDeduplicationId=$.messageDeduplicationId;let Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()});return{MessageId:Y.MessageId||Y.SendMessageResult?.MessageId}}async receiveMessages($){let J={Action:"ReceiveMessage",QueueUrl:$.queueUrl,Version:"2012-11-05"};if($.maxMessages!==void 0)J.MaxNumberOfMessages=$.maxMessages;if($.visibilityTimeout!==void 0)J.VisibilityTimeout=$.visibilityTimeout;if($.waitTimeSeconds!==void 0)J.WaitTimeSeconds=$.waitTimeSeconds;let Y=await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(J).toString()}),Q=[],G=Y.Message||Y.ReceiveMessageResult?.Message;if(G)if(Array.isArray(G))Q.push(...G.map((Z)=>({MessageId:Z.MessageId,ReceiptHandle:Z.ReceiptHandle,Body:Z.Body})));else Q.push({MessageId:G.MessageId,ReceiptHandle:G.ReceiptHandle,Body:G.Body});return{Messages:Q}}async deleteMessage($,J){let Y={Action:"DeleteMessage",QueueUrl:$,ReceiptHandle:J,Version:"2012-11-05"};await this.client.request({service:"sqs",region:this.region,method:"POST",path:"/",body:new URLSearchParams(Y).toString()})}}var vJ=Z0(()=>{z0()});class W4{client;region;constructor($="us-east-1"){this.region=$,this.client=new Q0}async call($,J){return this.client.request({service:"wafv2",region:this.region,method:"POST",path:"/",headers:{"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":`AWSWAF_20190729.${$}`},body:JSON.stringify(J)})}async listWebACLs($="REGIONAL"){return(await this.call("ListWebACLs",{Scope:$,Limit:100}))?.WebACLs??[]}async getWebACLRules($,J,Y="REGIONAL"){return((await this.call("GetWebACL",{Name:$,Id:J,Scope:Y}))?.WebACL?.Rules??[]).map((Z)=>({Name:Z.Name,Priority:Z.Priority,Action:Z.Action?Object.keys(Z.Action)[0]:Z.OverrideAction?Object.keys(Z.OverrideAction)[0]:"count"}))}}var lL=Z0(()=>{z0()});var rL={};t0(rL,{resolveDashboardData:()=>pL});function mL($){return String($).padStart(2,"0")}function U9($){return`${$.getUTCFullYear()}-${mL($.getUTCMonth()+1)}-${mL($.getUTCDate())}`}async function fJ($,J,Y,Q,G,Z){let W=await $.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:Y,Dimensions:[{Name:"FunctionName",Value:J}],StartTime:G,EndTime:Z,Period:86400,Statistics:[Q]}).catch(()=>[]);if(!W.length)return 0;if(Q==="Sum")return W.reduce((U,z)=>U+(z.Sum??0),0);if(Q==="Maximum")return Math.max(...W.map((U)=>U.Maximum??0));return W.reduce((U,z)=>U+(z.Average??0),0)/W.length}async function gJ($,J,Y,Q,G,Z,W){let U=await $.getMetricStatistics({Namespace:J,MetricName:Y,Dimensions:Q,StartTime:Z,EndTime:W,Period:86400,Statistics:[G]}).catch(()=>[]);if(!U.length)return 0;if(G==="Sum")return U.reduce((z,_)=>z+(_.Sum??0),0);if(G==="Maximum")return Math.max(...U.map((z)=>z.Maximum??0));return U.reduce((z,_)=>z+(_.Average??0),0)/U.length}async function U4($,J,Y,Q,G){let Z=await $.getMetricStatistics({Namespace:"AWS/Lambda",MetricName:"Duration",Dimensions:[{Name:"FunctionName",Value:J}],StartTime:Q,EndTime:G,Period:86400,ExtendedStatistics:[Y]}).catch(()=>[]);return Math.round(Z.reduce((W,U)=>W+(U.Percentiles?.[Y]??0),0))}async function pL($,J){let Y=await kW($,J),Q=Y.region,G=new e2(Q),Z=new Q1(Q),W=new N2(Q),U=new Date,z=new Date(U.getTime()-86400000),_=$.environments?.[J]?.app,H={};H.app={name:Y.slug,env:J,region:Q,runtime:_?.kind==="php"?`php-${_?.phpVersion??"8.3"} (fpm)`:_?.kind??"node",url:Y.endpoint??"",build:Y.lastRelease?.sha?.slice(0,7)??"—",deployedAt:Y.lastRelease?.timestamp??"—"},H.maintenance={enabled:!1},H.scheduler={enabled:Y.scheduler!=="off",expression:Y.scheduler==="sub-minute"?"rate(1 minute) · sub-minute":"rate(1 minute)",lastRun:"—"};let X=0,F=0,B=0,V=[],K=[];for(let A of Y.functions){let[j,q,M,T,R,S,N,C,x]=await Promise.all([fJ(G,A.name,"Invocations","Sum",z,U),fJ(G,A.name,"Errors","Sum",z,U),fJ(G,A.name,"Throttles","Sum",z,U),fJ(G,A.name,"Duration","Average",z,U),Z.getFunction(A.name).catch(()=>null),U4(G,A.name,"p50",z,U),U4(G,A.name,"p95",z,U),U4(G,A.name,"p99",z,U),G.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:A.name}],StartTime:new Date(U.getTime()-43200000),EndTime:U,Period:3600,Stat:"Sum"}).catch(()=>[])]);X+=j,F+=q,B=Math.max(B,T);let k=R?.Configuration?.MemorySize??0,b=Object.keys(R?.Configuration?.Environment?.Variables??{}),m=[],y=0;try{let{events:J0=[]}=await W.filterLogEvents({logGroupName:`/aws/lambda/${A.name}`,startTime:z.getTime(),limit:40});for(let Y0 of J0){let a=(Y0.message??"").trim(),s=/Max Memory Used:\s*(\d+)\s*MB/.exec(a);if(s)y=Math.max(y,Number(s[1]))}m=J0.filter((Y0)=>!/^(?:START|END|REPORT|INIT_START)/.test((Y0.message??"").trim())).slice(-6).map((Y0)=>({ts:new Date(Y0.timestamp??0).toISOString().slice(11,19),msg:(Y0.message??"").trim().slice(0,120),err:/error|exception|fatal/i.test(Y0.message??"")}))}catch{}let u=Math.max(1,...x);V.push({key:A.mode,name:A.name,version:A.version,memory:k,timeout:R?.Configuration?.Timeout??0,runtime:R?.Configuration?.Runtime??"provided.al2023",invocations:Math.round(j),errors:Math.round(q),p95:N||Math.round(T),status:"active",provisioned:A.provisioned?`${A.provisioned.allocated}/${A.provisioned.requested}`:void 0}),K.push({key:A.mode,name:A.name,runtime:R?.Configuration?.Runtime??"provided.al2023",arch:R?.Configuration?.Architectures?.[0]??"x86_64",memory:k,timeout:R?.Configuration?.Timeout??0,ephemeral:R?.Configuration?.EphemeralStorage?.Size??512,version:A.version,concurrency:_?.concurrency??"—",invocations:Math.round(j),errors:Math.round(q),throttles:Math.round(M),p50:S||Math.round(T),p95:N||Math.round(T),p99:C||Math.round(T),maxMem:y,spark:x.length?x.map((J0)=>Math.round(J0/u*100)):[0],env:b.length?b:["(none)"],recent:m.length?m:[{ts:"—",msg:"no recent events",err:!1}]})}H.functions=V,H.functionsDetail=K;let L=X?Number((F/X*100).toFixed(2)):0,E=Math.round(await fJ(G,Y.functions[0]?.name??"","ConcurrentExecutions","Maximum",z,U));H.metrics={invocations:Math.round(X),errorRatePct:L,p95Ms:Math.round(B),coldStartPct:0,concurrency:E,estCostUsd:0};try{let A=new t1(Q),j=[],q=[],M=0;try{let{QueueUrl:R}=await A.getQueueUrl(`${Y.slug}-${J}-dlq`),{Attributes:S}=await A.getQueueAttributes(R);M=Number(S.ApproximateNumberOfMessages??0)}catch{}let T=_?l9(_,Y.slug,J):[];for(let R of T){let S=R.name.replace(`${Y.slug}-${J}-`,""),N=0,C=0;try{let{QueueUrl:k}=await A.getQueueUrl(R.name),{Attributes:b}=await A.getQueueAttributes(k);N=Number(b.ApproximateNumberOfMessages??0),C=Number(b.ApproximateNumberOfMessagesNotVisible??0)}catch{}let x=Math.round(await gJ(G,"AWS/SQS","NumberOfMessagesDeleted",[{Name:"QueueName",Value:R.name}],"Sum",z,U));j.push({name:S,visible:N,inFlight:C,processed:x,dlq:M}),q.push({name:R.name,short:S,visible:N,inFlight:C,delayed:0,processed:x,oldestSec:0,concurrency:R.concurrency??_?.queueConcurrency??"—",tries:_?.queueTries??3,visTimeout:(_?.queueTimeout??120)*6,dlq:M})}if(j.length)H.queues=j;if(q.length)H.queuesDetail=q;H.dlqItems=[]}catch{}try{let A=new A0(Q),{Stacks:j}=await A.describeStacks({stackName:o2($,J)}),q={};for(let M of j?.[0]?.Outputs??[])if(M.OutputKey)q[M.OutputKey]=M.OutputValue??"";if(_?.database?.connection==="aurora-serverless"){let M=`${Y.slug}-${J}-db`,T=[{Name:"DBClusterIdentifier",Value:M}],[R,S]=await Promise.all([gJ(G,"AWS/RDS","ServerlessDatabaseCapacity",T,"Average",z,U),gJ(G,"AWS/RDS","DatabaseConnections",T,"Maximum",z,U)]);if(H.aurora={id:M,engine:"aurora-mysql",minAcu:_?.database?.minCapacity??0.5,maxAcu:_?.database?.maxCapacity??4,currentAcu:R?Number(R.toFixed(1)):_?.database?.minCapacity??0.5,database:"app",connections:Math.round(S),status:q.DbEndpoint?"available":"creating"},_?.rdsProxy)H.proxy={name:`${Y.slug}-${J}-proxy`,endpoint:q.DbProxyEndpoint??"—",pooledConns:Math.round(S),status:"available"}}if(_?.cache?.driver==="elasticache"){let M=`${Y.slug}-${J}-cache`,T=[{Name:"CacheClusterId",Value:`${M}-001`}],[R,S]=await Promise.all([gJ(G,"AWS/ElastiCache","CacheHits",T,"Sum",z,U),gJ(G,"AWS/ElastiCache","CacheMisses",T,"Sum",z,U)]),N=R+S>0?Number((R/(R+S)*100).toFixed(1)):0;H.redis={id:M,node:"cache.t4g.micro",engine:"redis",hitRate:N,status:q.CacheEndpoint?"available":"creating"}}if(_?.efs){let M=0;try{if(q.EfsFileSystemId){let T=new eQ(Q),{FileSystems:R}=await T.describeFileSystems({FileSystemId:q.EfsFileSystemId});M=Number(((R?.[0]?.SizeInBytes?.Value??0)/1048576).toFixed(1))}}catch{}H.efs={id:q.EfsFileSystemId??"efs",mount:"/mnt/local",sizeMb:M,status:"available"}}H.assetsInfo=q.AssetsCdnDomain?{bucket:q.AssetsBucketName??`${Y.slug}-${J}-assets`,cdn:q.AssetsCdnDomain,customDomain:_?.assetDomain??"—",assetUrl:Y.assetUrl??"—",files:0,sizeMb:0,cacheHitPct:0,build:H.app.build}:void 0}catch{}if(H.assetsInfo)try{let j=await new H0(Q).list({bucket:H.assetsInfo.bucket,maxKeys:1000});H.assetsInfo.files=j.length,H.assetsInfo.sizeMb=Number((j.reduce((q,M)=>q+(M.Size??0),0)/1048576).toFixed(1)),H.assetsRecent=j.slice(0,8).map((q)=>({path:`/${q.Key}`,size:`${Math.max(1,Math.round((q.Size??0)/1024))} KB`,type:q.Key.split(".").pop()??""}))}catch{}try{if(_?.secrets){let A=Array.isArray(_.secrets)?_.secrets.map((j)=>({key:j.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),source:j})):Object.entries(_.secrets).map(([j,q])=>({key:j,source:String(q)}));H.secretsList=A.map((j)=>({...j,updated:"—"}))}}catch{}try{let A=new H0(Q),j=`${Y.slug}-${J}-deployments`,q=await A.getObjectJson(j,`deployments/${Y.slug}/${J}/history.json`).catch(()=>null);if(q?.records?.length)H.deploymentsDetail=q.records.slice(-12).reverse().map((M)=>({sha:(M.sha??"").slice(0,7),status:M.status??"success",when:M.timestamp??"—",took:M.took??"—",by:M.by??"—",version:M.version??"—",hooks:M.hooks??[]}))}catch{}H.metricsTotals={invocations:H.metrics.invocations,errors:Math.round(F),errorRatePct:L,p95Ms:H.metrics.p95Ms,throttles:K.reduce((A,j)=>A+j.throttles,0),coldStartPct:0,estCostUsd:0,concurrency:E},H.metricsPerFn=K.map((A)=>({key:A.key,invocations:A.invocations,errors:A.errors,throttles:A.throttles,avgMs:A.p50,maxMs:A.p99,costUsd:0}));try{H.invSpark=await G.getMetricSeries({Namespace:"AWS/Lambda",MetricName:"Invocations",Dimensions:[{Name:"FunctionName",Value:Y.functions.find((A)=>A.mode==="http")?.name??""}],StartTime:new Date(U.getTime()-86400000),EndTime:U,Period:3600,Stat:"Sum"})}catch{}try{let A=new s9,j=U,q=new Date(Date.UTC(j.getUTCFullYear(),j.getUTCMonth(),1)),M=new Date(Date.UTC(j.getUTCFullYear(),j.getUTCMonth()-1,1)),[T,R]=await Promise.all([A.getCostByService({start:U9(q),end:U9(j),granularity:"MONTHLY"}).catch(()=>[]),A.getCostByService({start:U9(M),end:U9(q),granularity:"MONTHLY"}).catch(()=>[])]);if(T.length){let S=T.reduce((y,u)=>y+u.amount,0),N=R.reduce((y,u)=>y+u.amount,0),C=j.getUTCDate(),x=new Date(Date.UTC(j.getUTCFullYear(),j.getUTCMonth()+1,0)).getUTCDate();H.costSummary={monthToDateUsd:Number(S.toFixed(2)),projectedUsd:Number((S/C*x).toFixed(2)),lastMonthUsd:Number(N.toFixed(2)),dailyAvgUsd:Number((S/C).toFixed(2))},H.costServices=T.filter((y)=>y.amount>0).sort((y,u)=>u.amount-y.amount).slice(0,12).map((y)=>({name:y.service,usd:Number(y.amount.toFixed(2)),note:""})),H.metrics.estCostUsd=Number((S/C).toFixed(2)),H.metricsTotals.estCostUsd=H.metrics.estCostUsd,H.costTrend=await A.getDailyTotals({start:U9(q),end:U9(j)}).catch(()=>[]);let k=T.find((y)=>/lambda/i.test(y.service))?.amount??0,b=(y)=>y.invocations*(y.p50/1000)*(y.memory/1024),m=K.reduce((y,u)=>y+b(u),0)||1;H.costPerFn=K.map((y)=>({key:y.key,requests:y.invocations,gbSec:Math.round(b(y)),usd:Number((k*(b(y)/m)).toFixed(2))}))}}catch{}if(_?.firewall)try{let A=await G.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"BlockedRequests",StartTime:z,EndTime:U,Period:86400,Statistics:["Sum"]}).catch(()=>[]),j=await G.getMetricStatistics({Namespace:"AWS/WAFV2",MetricName:"AllowedRequests",StartTime:z,EndTime:U,Period:86400,Statistics:["Sum"]}).catch(()=>[]);H.waf={enabled:!0,scope:"REGIONAL",acl:`${Y.slug}-${J}-waf`,allowed24h:Math.round(j.reduce((q,M)=>q+(M.Sum??0),0)),blocked24h:Math.round(A.reduce((q,M)=>q+(M.Sum??0),0))};try{let q=new W4(Q),M=await q.listWebACLs("REGIONAL"),T=M.find((R)=>R.Name?.includes(`${Y.slug}-${J}`))??M[0];if(T?.Name&&T.Id){H.waf.acl=T.Name;let R=await q.getWebACLRules(T.Name,T.Id,"REGIONAL");if(R.length)H.wafRules=R.map((S)=>({name:S.Name??"—",detail:`priority ${S.Priority??0}`,action:S.Action??"count",blocked24h:0}))}}catch{}}catch{}if(Y.scheduler!=="off"&&_?.kind==="php")try{let A=await y8($,J,"schedule:list"),j=[];for(let q of(A||"").split(`
|
|
13642
13642
|
`)){let M=/^\s*([\d*/,\-\s]+?)\s{2,}(.+?)(?:\s{2,}Next Due.*)?$/.exec(q);if(M&&/[*\d]/.test(M[1])&&M[1].trim().split(/\s+/).length===5)j.push({command:M[2].trim().replace(/^php artisan /,""),cron:M[1].trim(),desc:"",lastRun:"—",lastStatus:"ok"})}if(j.length)H.schedulerTasks=j}catch{}return H}var z4=Z0(async()=>{f1();TW();i9();L6();Z4();j$();m0();vJ();lL();await cJ([L1(),M1()])});var iL={};t0(iL,{resolveServerDashboardData:()=>gh,parseBlock:()=>nL});function fh(){return["set +e",'echo "CPUS=$(nproc 2>/dev/null || echo 1)"',`echo "LOAD=$(cut -d' ' -f1 /proc/loadavg 2>/dev/null || echo 0)"`,`echo "MEMTOTAL=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}')"`,`echo "MEMUSED=$(free -m 2>/dev/null | awk '/^Mem:/{print $3}')"`,`echo "DISKPCT=$(df -P / 2>/dev/null | awk 'NR==2{gsub("%","",$5);print $5}')"`,`echo "DISKUSEDG=$(df -BG / 2>/dev/null | awk 'NR==2{gsub("G","",$3);print $3}')"`,`echo "DISKTOTG=$(df -BG / 2>/dev/null | awk 'NR==2{gsub("G","",$2);print $2}')"`,`echo "UPTIME=$(uptime -p 2>/dev/null | sed 's/^up //' || echo unknown)"`,'echo "OS=$(. /etc/os-release 2>/dev/null; echo "$PRETTY_NAME")"',`for s in ${vh.join(" ")}; do st=$(systemctl is-active "$s" 2>/dev/null); [ -n "$st" ] && [ "$st" != "inactive" ] && [ "$st" != "unknown" ] && echo "SVC=$s=$st"; done`]}function nL($){let J={services:[]};for(let Y of $.split(`
|
|
13643
13643
|
`)){let Q=Y.trim();if(Q.startsWith("SVC=")){let[,G,Z]=/^SVC=([^=]+)=(.+)$/.exec(Q)??[];if(G)J.services.push({name:G,status:Z})}else{let G=Q.indexOf("=");if(G>0)J[Q.slice(0,G)]=Q.slice(G+1)}}return J}async function gh($,J){if(!$.infrastructure?.compute)return null;let Y;try{Y=Z$({config:$})}catch{return null}let Q=null,G=0;try{let z=await Y.findComputeTargets({slug:$.project.slug,environment:J,role:"app"});if(G=z.length,z.length){let H=(await Y.runRemoteDeploy({targets:[z[0]],commands:fh(),comment:`ts-cloud dashboard:build ${$.project.slug}`,tags:{Project:$.project.slug,Environment:J,Role:"app"}})).perInstance?.[0]?.output;if(H)Q=nL(H)}}catch{}let Z={},W=(z,_=0)=>{let H=Number(z);return Number.isFinite(H)?H:_};if(Z.server={name:`${$.project.slug}-${J}-app`,provider:$.infrastructure?.compute?.provider??"aws",region:$.project.region??"us-east-1",ip:"—",os:Q?.OS||"Linux",uptime:Q?.UPTIME||"—"},Q){if(Z.systemMetrics={load:W(Q.LOAD),cpus:W(Q.CPUS,1),memUsedMb:W(Q.MEMUSED),memTotalMb:W(Q.MEMTOTAL,1),diskUsedPct:W(Q.DISKPCT),diskUsedGb:W(Q.DISKUSEDG),diskTotalGb:W(Q.DISKTOTG,1)},Q.services.length)Z.services=Q.services.map((z)=>({name:z.name,status:z.status==="active"?"running":z.status})),Z.servicesDetail=Q.services.map((z)=>({name:z.name,status:z.status==="active"?"running":z.status,since:Z.server.uptime,memMb:0,auto:!0}))}if($.sites){let z=Object.entries($.sites).map(([_,H])=>({name:_,domain:H.domain??"—",type:H.type??(H.static?"static":"laravel"),php:H.php??H.phpVersion??"8.3",ssl:H.ssl!==!1,status:"live",lastDeploy:"—"}));if(z.length)Z.sites=z,Z.sitesDetail=z.map((_)=>({..._,root:`/var/www/${_.name}/current`,branch:"main"}))}let U=$.infrastructure?.ssh?.keys??$.infrastructure?.sshKeys;if(Array.isArray(U)&&U.length)Z.sshKeys=U.map((z,_)=>({name:z.name??`key-${_+1}`,fingerprint:"—",type:"ssh",added:"—"}));return Z._serverReachable=G>0&&!!Q,Z}var vh;var tL=Z0(async()=>{await AJ();vh=["nginx","php8.3-fpm","php8.2-fpm","mysql","mariadb","postgresql","redis","redis-server","meilisearch"]});import{existsSync as zA}from"node:fs";import Q5 from"node:fs/promises";import v4 from"node:os";import G5 from"node:path";import u2 from"node:process";import{EventEmitter as _A}from"node:events";import O2 from"node:process";import f4 from"node:process";import z5 from"node:process";import pJ from"node:process";import X9 from"node:process";import d4 from"node:tty";import aA,{stdin as Iy,stdout as xy}from"node:process";import l4,{stdin as eA,stdout as $E}from"node:process";import JE from"node:readline";class p4{configPath;config=null;events=[];retryCount=0;maxRetries=3;retryDelayMs=1000;constructor(){let $=v4.homedir(),J=G5.join($,".config","clapp");this.configPath=G5.join(J,"telemetry.json")}async isEnabled(){if(u2.env.DO_NOT_TRACK==="1"||u2.env.DO_NOT_TRACK==="true")return!1;if(u2.env.NO_TELEMETRY==="1"||u2.env.NO_TELEMETRY==="true")return!1;return(await this.loadConfig()).enabled}async enable(){let $=await this.loadConfig();if($.enabled=!0,!$.userId)$.userId=this.generateUserId();await this.saveConfig($)}async disable(){let $=await this.loadConfig();$.enabled=!1,await this.saveConfig($)}async track($,J){if(!await this.isEnabled())return;let Q={event:$,...J,timestamp:Date.now(),platform:v4.platform(),nodeVersion:u2.version};if(this.events.push(Q),this.events.length>=10)await this.send()}async trackCommand($,J){await this.track("command",{command:$,duration:J})}async trackError($,J){await this.track("error",{error:$,command:J})}async send(){if(!await this.isEnabled()||this.events.length===0)return!0;try{this.events=[],this.retryCount=0;let J=await this.loadConfig();return J.lastSent=Date.now(),await this.saveConfig(J),!0}catch{if(this.retryCount<this.maxRetries){this.retryCount++;let J=this.retryDelayMs*2**(this.retryCount-1);return await this.sleep(J),this.send()}return this.events=[],this.retryCount=0,!1}}async flush(){if(this.events.length===0)return!0;return this.send()}sleep($){return new Promise((J)=>setTimeout(J,$))}async status(){let $=await this.loadConfig();return{enabled:$.enabled,doNotTrack:u2.env.DO_NOT_TRACK==="1"||u2.env.DO_NOT_TRACK==="true",eventsQueued:this.events.length,lastSent:$.lastSent}}async loadConfig(){if(this.config)return this.config;try{if(zA(this.configPath)){let $=await Q5.readFile(this.configPath,"utf-8");return this.config=JSON.parse($),this.config}}catch{}return this.config={enabled:!1},this.config}async saveConfig($){this.config=$;try{let J=G5.dirname(this.configPath);await Q5.mkdir(J,{recursive:!0}),await Q5.writeFile(this.configPath,JSON.stringify($,null,2),"utf-8")}catch{}}generateUserId(){let $=Math.random().toString(36).substring(2,15),J=Date.now().toString(36);return`${$}-${J}`}}var Ey=new p4;function HA($,J={}){let Y={_:[]},Q=J.alias||{},G=new Set(J.boolean||[]),Z={};for(let U of Object.keys(Q))for(let z of Q[U])Z[z]=U;for(let U of G)if(Q[U])for(let z of Q[U])G.add(z);function W(U,z){let _=Z[U]||U;if(Y[_]=z,Q[_])for(let H of Q[_])Y[H]=z;if(Z[U]&&Q[Z[U]])for(let H of Q[Z[U]])Y[H]=z;Y[U]=z}for(let U=0;U<$.length;U++){let z=$[U];if(z==="--"){Y._.push(...$.slice(U+1));break}if(z.startsWith("--")){let _=z.indexOf("=");if(_!==-1){let H=z.slice(2,_),X=z.slice(_+1);W(H,X)}else{let H=z.slice(2);if(H.startsWith("no-")){let F=H.slice(3);W(F,!1);continue}let X=Z[H]||H;if(G.has(X)||G.has(H))W(H,!0);else{let F=$[U+1];if(F!==void 0&&!F.startsWith("-"))W(H,F),U++;else W(H,!0)}}}else if(z.startsWith("-")&&z.length>1){let _=z.slice(1);for(let H=0;H<_.length;H++){let X=_[H],F=Z[X]||X;if(H===_.length-1&&!G.has(F)&&!G.has(X)){let B=$[U+1];if(B!==void 0&&!B.startsWith("-"))W(X,B),U++;else W(X,!0)}else W(X,!0)}}else Y._.push(z)}return Y}function U5($){return $.replace(/[<[].+/,"").trim()}function XA($){let J=/<([^>]+)>/g,Y=/\[([^\]]+)\]/g,Q=[],G=(U)=>{let z=!1,_=U[1];if(_.startsWith("..."))_=_.slice(3),z=!0;return{required:U[0].startsWith("<"),value:_,variadic:z}},Z;while(Z=J.exec($))Q.push(G(Z));let W;while(W=Y.exec($))Q.push(G(W));return Q}function FA($){let J={alias:{},boolean:[]};for(let[Y,Q]of $.entries()){if(Q.names.length>1)J.alias[Q.names[0]]=Q.names.slice(1);if(Q.isBoolean)if(Q.negated){if(!$.some((Z,W)=>{return W!==Y&&Z.names.some((U)=>Q.names.includes(U))&&typeof Z.required==="boolean"}))J.boolean.push(Q.names[0])}else J.boolean.push(Q.names[0])}return J}function g4($){return $.reduce((J,Y)=>J.length>=Y.length?J:Y,"")}function Z5($,J){return $.length>=J?$:`${$}${" ".repeat(J-$.length)}`}function OA($){return $.replace(/([a-z])-([a-z])/g,(J,Y,Q)=>{return Y+Q.toUpperCase()})}function BA($,J,Y){let Q=0,G=J.length,Z=$,W;for(;Q<G;++Q)W=Z[J[Q]],Z=Z[J[Q]]=Q===G-1?Y:W!=null?W:!!~J[Q+1].indexOf(".")||!(+J[Q+1]>-1)?{}:[]}function KA($,J){for(let Y of Object.keys(J)){let Q=J[Y];if(Q.shouldTransform){if($[Y]=Array.prototype.concat.call([],$[Y]),typeof Q.transformFunction==="function")$[Y]=$[Y].map(Q.transformFunction)}}}function VA($){let J=/([^\\/]+)$/.exec($);return J?J[1]:""}function r4($){return $.split(".").map((J,Y)=>{return Y===0?OA(J):J}).join(".")}class mJ extends Error{exitCode=2;isUsageError=!0;constructor($){super($);if(this.name=this.constructor.name,typeof Error.captureStackTrace==="function")Error.captureStackTrace(this,this.constructor);else this.stack=Error($).stack}format($=!1){if($&&this.stack)return`${this.message}
|
|
13644
13644
|
|
|
@@ -13678,7 +13678,7 @@ Run \`${this.name??"cli"} --help\` for usage.`;O2.stderr.write(`${Z}${G}${W}
|
|
|
13678
13678
|
`).length-1;this.output.write(u$.move(-999,$*-1))}render(){let $=m4(this._render(this)??"",l4.stdout.columns,{hard:!0,trim:!1});if($===this._prevFrame)return;if(this.state==="initial")this.output.write(u$.hide);else{let J=sA(this._prevFrame,$);if(this.restoreCursor(),J&&J?.length===1){let Y=J[0];this.output.write(u$.move(0,Y)),this.output.write(W5.lines(1));let Q=$.split(`
|
|
13679
13679
|
`);this.output.write(Q[Y]),this._prevFrame=$,this.output.write(u$.move(0,Q.length-Y-1));return}if(J&&J?.length>1){let Y=J[0];this.output.write(u$.move(0,Y)),this.output.write(W5.down());let G=$.split(`
|
|
13680
13680
|
`).slice(Y);this.output.write(G.join(`
|
|
13681
|
-
`)),this._prevFrame=$;return}this.output.write(W5.down())}if(this.output.write($),this.state==="initial")this.state="active";this._prevFrame=$}}function GE($,J){if($===void 0)return 0;if(J.length===0)return 0;let Q=J.findIndex((G)=>G.value===$);return Q!==-1?Q:0}function ZE($,J){return(J.label??String(J.value)).toLowerCase().includes($.toLowerCase())}function WE($,J){if(!J)return;if($)return J;return J[0]}class UE extends F5{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#$=0;#Y="";#Q;#J;get cursor(){return this.#$}get userInputWithCursor(){if(!this.userInput)return rJ.inverse(rJ.hidden("_"));if(this._cursor>=this.userInput.length)return`${this.userInput}█`;let $=this.userInput.slice(0,this._cursor),[J,...Y]=this.userInput.slice(this._cursor);return`${$}${rJ.inverse(J)}${Y.join("")}`}get options(){if(typeof this.#J==="function")return this.#J();return this.#J}constructor($){super($);this.#J=$.options;let J=this.options;this.filteredOptions=[...J],this.multiple=$.multiple===!0,this.#Q=$.filter??ZE;let Y;if($.initialValue&&Array.isArray($.initialValue))if(this.multiple)Y=$.initialValue;else Y=$.initialValue.slice(0,1);else if(!this.multiple&&this.options.length>0)Y=[this.options[0].value];if(Y)for(let Q of Y){let G=J.findIndex((Z)=>Z.value===Q);if(G!==-1)this.toggleSelected(Q),this.#$=G}this.focusedValue=this.options[this.#$]?.value,this.on("key",(Q,G)=>this.#G(Q,G)),this.on("userInput",(Q)=>this.#Z(Q))}_isActionKey($,J){return $==="\t"||this.multiple&&this.isNavigating&&J.name==="space"&&$!==void 0&&$!==""}#G($,J){let Y=J.name==="up",Q=J.name==="down",G=J.name==="return";if(Y||Q){if(this.#$=Math.max(0,Math.min(this.#$+(Y?-1:1),this.filteredOptions.length-1)),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)this.selectedValues=[this.focusedValue];this.isNavigating=!0}else if(G)this.value=WE(this.multiple,this.selectedValues);else if(this.multiple)if(this.focusedValue!==void 0&&(J.name==="tab"||this.isNavigating&&J.name==="space"))this.toggleSelected(this.focusedValue);else this.isNavigating=!1;else{if(this.focusedValue)this.selectedValues=[this.focusedValue];this.isNavigating=!1}}deselectAll(){this.selectedValues=[]}toggleSelected($){if(this.filteredOptions.length===0)return;if(this.multiple)if(this.selectedValues.includes($))this.selectedValues=this.selectedValues.filter((J)=>J!==$);else this.selectedValues=[...this.selectedValues,$];else this.selectedValues=[$]}#Z($){if($!==this.#Y){this.#Y=$;let J=this.options;if($)this.filteredOptions=J.filter((Y)=>this.#Q($,Y));else this.filteredOptions=[...J];if(this.#$=GE(this.focusedValue,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)if(this.focusedValue!==void 0)this.toggleSelected(this.focusedValue);else this.deselectAll()}}}class zE extends F5{options;cursor=0;#$;getGroupItems($){return this.options.filter((J)=>J.group===$)}isGroupSelected($){let J=this.getGroupItems($),Y=this.value;if(Y===void 0)return!1;return J.every((Q)=>Y.includes(Q.value))}toggleValue(){let $=this.options[this.cursor];if(this.value===void 0)this.value=[];if($.group===!0){let J=$.value,Y=this.getGroupItems(J);if(this.isGroupSelected(J))this.value=this.value.filter((Q)=>Y.findIndex((G)=>G.value===Q)===-1);else this.value=[...this.value,...Y.map((Q)=>Q.value)];this.value=Array.from(new Set(this.value))}else{let J=this.value.includes($.value);this.value=J?this.value.filter((Y)=>Y!==$.value):[...this.value,$.value]}}constructor($){super($,!1);let{options:J}=$;this.#$=$.selectableGroups!==!1,this.options=Object.entries(J).flatMap(([Y,Q])=>[{value:Y,group:!0,label:Y},...Q.map((G)=>({...G,group:Y}))]),this.value=[...$.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:Y})=>Y===$.cursorAt),this.#$?0:1),this.on("cursor",(Y)=>{switch(Y){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}case"space":this.toggleValue();break}})}}var _E=LA();var f0=($,J)=>_E?$:J,yy=f0("◆","*"),vy=f0("■","x"),fy=f0("▲","x"),gy=f0("◇","o"),uy=f0("┌","T"),HE=f0("│","|"),dy=f0("└","—"),cy=f0("●",">"),ly=f0("○"," "),my=f0("◻","[•]"),py=f0("◼","[+]"),ry=f0("◻","[ ]"),ny=f0("▪","•"),iy=f0("─","-"),ty=f0("╮","+"),ay=f0("├","+"),oy=f0("╯","+"),sy=f0("●","•"),ey=f0("◆","*"),$v=f0("▲","!"),Jv=f0("■","x");var Yv={light:f0("─","-"),heavy:f0("━","="),block:f0("█","#")};function XE(){return`${rJ.gray(HE)} `}var Qv=XE();var O5="0.5.
|
|
13681
|
+
`)),this._prevFrame=$;return}this.output.write(W5.down())}if(this.output.write($),this.state==="initial")this.state="active";this._prevFrame=$}}function GE($,J){if($===void 0)return 0;if(J.length===0)return 0;let Q=J.findIndex((G)=>G.value===$);return Q!==-1?Q:0}function ZE($,J){return(J.label??String(J.value)).toLowerCase().includes($.toLowerCase())}function WE($,J){if(!J)return;if($)return J;return J[0]}class UE extends F5{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#$=0;#Y="";#Q;#J;get cursor(){return this.#$}get userInputWithCursor(){if(!this.userInput)return rJ.inverse(rJ.hidden("_"));if(this._cursor>=this.userInput.length)return`${this.userInput}█`;let $=this.userInput.slice(0,this._cursor),[J,...Y]=this.userInput.slice(this._cursor);return`${$}${rJ.inverse(J)}${Y.join("")}`}get options(){if(typeof this.#J==="function")return this.#J();return this.#J}constructor($){super($);this.#J=$.options;let J=this.options;this.filteredOptions=[...J],this.multiple=$.multiple===!0,this.#Q=$.filter??ZE;let Y;if($.initialValue&&Array.isArray($.initialValue))if(this.multiple)Y=$.initialValue;else Y=$.initialValue.slice(0,1);else if(!this.multiple&&this.options.length>0)Y=[this.options[0].value];if(Y)for(let Q of Y){let G=J.findIndex((Z)=>Z.value===Q);if(G!==-1)this.toggleSelected(Q),this.#$=G}this.focusedValue=this.options[this.#$]?.value,this.on("key",(Q,G)=>this.#G(Q,G)),this.on("userInput",(Q)=>this.#Z(Q))}_isActionKey($,J){return $==="\t"||this.multiple&&this.isNavigating&&J.name==="space"&&$!==void 0&&$!==""}#G($,J){let Y=J.name==="up",Q=J.name==="down",G=J.name==="return";if(Y||Q){if(this.#$=Math.max(0,Math.min(this.#$+(Y?-1:1),this.filteredOptions.length-1)),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)this.selectedValues=[this.focusedValue];this.isNavigating=!0}else if(G)this.value=WE(this.multiple,this.selectedValues);else if(this.multiple)if(this.focusedValue!==void 0&&(J.name==="tab"||this.isNavigating&&J.name==="space"))this.toggleSelected(this.focusedValue);else this.isNavigating=!1;else{if(this.focusedValue)this.selectedValues=[this.focusedValue];this.isNavigating=!1}}deselectAll(){this.selectedValues=[]}toggleSelected($){if(this.filteredOptions.length===0)return;if(this.multiple)if(this.selectedValues.includes($))this.selectedValues=this.selectedValues.filter((J)=>J!==$);else this.selectedValues=[...this.selectedValues,$];else this.selectedValues=[$]}#Z($){if($!==this.#Y){this.#Y=$;let J=this.options;if($)this.filteredOptions=J.filter((Y)=>this.#Q($,Y));else this.filteredOptions=[...J];if(this.#$=GE(this.focusedValue,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#$]?.value,!this.multiple)if(this.focusedValue!==void 0)this.toggleSelected(this.focusedValue);else this.deselectAll()}}}class zE extends F5{options;cursor=0;#$;getGroupItems($){return this.options.filter((J)=>J.group===$)}isGroupSelected($){let J=this.getGroupItems($),Y=this.value;if(Y===void 0)return!1;return J.every((Q)=>Y.includes(Q.value))}toggleValue(){let $=this.options[this.cursor];if(this.value===void 0)this.value=[];if($.group===!0){let J=$.value,Y=this.getGroupItems(J);if(this.isGroupSelected(J))this.value=this.value.filter((Q)=>Y.findIndex((G)=>G.value===Q)===-1);else this.value=[...this.value,...Y.map((Q)=>Q.value)];this.value=Array.from(new Set(this.value))}else{let J=this.value.includes($.value);this.value=J?this.value.filter((Y)=>Y!==$.value):[...this.value,$.value]}}constructor($){super($,!1);let{options:J}=$;this.#$=$.selectableGroups!==!1,this.options=Object.entries(J).flatMap(([Y,Q])=>[{value:Y,group:!0,label:Y},...Q.map((G)=>({...G,group:Y}))]),this.value=[...$.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:Y})=>Y===$.cursorAt),this.#$?0:1),this.on("cursor",(Y)=>{switch(Y){case"left":case"up":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break}case"down":case"right":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;let Q=this.options[this.cursor]?.group===!0;if(!this.#$&&Q)this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}case"space":this.toggleValue();break}})}}var _E=LA();var f0=($,J)=>_E?$:J,yy=f0("◆","*"),vy=f0("■","x"),fy=f0("▲","x"),gy=f0("◇","o"),uy=f0("┌","T"),HE=f0("│","|"),dy=f0("└","—"),cy=f0("●",">"),ly=f0("○"," "),my=f0("◻","[•]"),py=f0("◼","[+]"),ry=f0("◻","[ ]"),ny=f0("▪","•"),iy=f0("─","-"),ty=f0("╮","+"),ay=f0("├","+"),oy=f0("╯","+"),sy=f0("●","•"),ey=f0("◆","*"),$v=f0("▲","!"),Jv=f0("■","x");var Yv={light:f0("─","-"),heavy:f0("━","="),block:f0("█","#")};function XE(){return`${rJ.gray(HE)} `}var Qv=XE();var O5="0.5.17";B0();import{existsSync as w5}from"node:fs";import{mkdir as ME,writeFile as z7}from"node:fs/promises";function T5($){$.command("init","Initialize a new ts-cloud project").option("--mode <mode>","Deployment mode: server, serverless, or hybrid").option("--name <name>","Project name").option("--region <region>","AWS Region").action(async(J)=>{if(P("Initializing ts-cloud Project"),w5("cloud.config.ts")){if(!await p("cloud.config.ts already exists. Overwrite?",!1)){O("Initialization cancelled");return}}let Y=J?.name||await x0("Project name","my-app"),Q=J?.mode||await tJ("Select deployment mode",["serverless","server","hybrid"]),G=J?.region||await tJ("Select AWS region",["us-east-1","us-west-2","eu-west-1","eu-central-1","ap-southeast-1"]),Z=new I("Creating configuration file...");Z.start();let W=`import { defineConfig } from '@ts-cloud/core'
|
|
13682
13682
|
|
|
13683
13683
|
export default defineConfig({
|
|
13684
13684
|
project: {
|
package/dist/index.js
CHANGED
|
@@ -26399,14 +26399,7 @@ function composeServerlessAppTemplate(opts) {
|
|
|
26399
26399
|
VisibilityConfig: { SampledRequestsEnabled: true, CloudWatchMetricsEnabled: true, MetricName: `${slug}-${environment}-waf` }
|
|
26400
26400
|
}
|
|
26401
26401
|
};
|
|
26402
|
-
|
|
26403
|
-
Type: "AWS::WAFv2::WebACLAssociation",
|
|
26404
|
-
DependsOn: ["HttpStage"],
|
|
26405
|
-
Properties: {
|
|
26406
|
-
ResourceArn: Fn2.sub("arn:aws:apigateway:${AWS::Region}::/apis/${HttpApi}/stages/$default"),
|
|
26407
|
-
WebACLArn: Fn2.getAtt("WebAcl", "Arn")
|
|
26408
|
-
}
|
|
26409
|
-
};
|
|
26402
|
+
outputs.WafAclArn = { Description: "WAF web ACL ARN. Attach to a CloudFront distribution fronting the API to enforce (HTTP API v2 stages do not support direct WAF association).", Value: Fn2.getAtt("WebAcl", "Arn") };
|
|
26410
26403
|
}
|
|
26411
26404
|
if (hasVpc && needsDataVpc) {
|
|
26412
26405
|
if (!app.vpc?.id)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/ts-cloud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.17",
|
|
5
5
|
"description": "A lightweight, performant infrastructure-as-code library and CLI for deploying both server-based (EC2) and serverless applications.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"test": "bun test"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@ts-cloud/aws-types": "0.5.
|
|
93
|
-
"@ts-cloud/core": "0.5.
|
|
92
|
+
"@ts-cloud/aws-types": "0.5.17",
|
|
93
|
+
"@ts-cloud/core": "0.5.17",
|
|
94
94
|
"@stacksjs/ts-xml": "^0.1.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|