@stacksjs/ts-cloud 0.16.67 → 0.16.68
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/aws/index.js +1 -1
- package/dist/bin/{chunk-vcs8wtay.js → chunk-17ewx21n.js} +11 -11
- package/dist/bin/{chunk-6rvejkny.js → chunk-1cb0r1j3.js} +1 -1
- package/dist/bin/{chunk-shxqbkrz.js → chunk-1tk64amh.js} +1 -1
- package/dist/bin/{chunk-jq4xyf7y.js → chunk-2247xk4n.js} +1 -1
- package/dist/bin/{chunk-yec39wzh.js → chunk-37xeqae4.js} +1 -1
- package/dist/bin/{chunk-bzjr9jwn.js → chunk-43a60zkj.js} +1 -1
- package/dist/bin/chunk-4vz5erjz.js +1 -0
- package/dist/bin/{chunk-f4v7nm9a.js → chunk-55j0x82p.js} +5 -5
- package/dist/bin/{chunk-7pxqdq44.js → chunk-5fde4d44.js} +1 -1
- package/dist/bin/{chunk-qjh516ah.js → chunk-5gf0je0v.js} +11 -11
- package/dist/bin/{chunk-245rppy4.js → chunk-5t1ky9re.js} +1 -1
- package/dist/bin/{chunk-pyxmdv8d.js → chunk-6cyr6gcg.js} +1 -1
- package/dist/bin/chunk-6rwewb7j.js +1 -0
- package/dist/bin/{chunk-xkcvfpd0.js → chunk-6tqzgm9z.js} +4 -4
- package/dist/bin/chunk-7d83f6sn.js +1 -0
- package/dist/bin/chunk-7v68hpgc.js +2 -0
- package/dist/bin/{chunk-djqrnrpx.js → chunk-7y56qyrj.js} +1 -1
- package/dist/bin/{chunk-jyfm20f3.js → chunk-8escxm7h.js} +1 -1
- package/dist/bin/{chunk-kwfbth5c.js → chunk-b0r8a5h5.js} +3 -3
- package/dist/bin/{chunk-6stcmq7g.js → chunk-bkvxzenb.js} +1 -1
- package/dist/bin/{chunk-0h1ae217.js → chunk-d28q9ath.js} +1 -1
- package/dist/bin/chunk-dmm1p4bs.js +1 -0
- package/dist/bin/chunk-dycx66c7.js +1 -0
- package/dist/bin/{chunk-9vjg754g.js → chunk-e4c7ba0g.js} +1 -1
- package/dist/bin/chunk-fjx816tt.js +1 -0
- package/dist/bin/{chunk-sb29jzvd.js → chunk-fx9zesgx.js} +113 -113
- package/dist/bin/{chunk-p801tzxz.js → chunk-gga18c4g.js} +1 -1
- package/dist/bin/{chunk-er5zfr54.js → chunk-gmy8p7nr.js} +1 -1
- package/dist/bin/chunk-h5ccvped.js +1 -0
- package/dist/bin/chunk-h9h9dn0r.js +1 -0
- package/dist/bin/chunk-ht6s2cwm.js +1 -0
- package/dist/bin/{chunk-vwgpwjwh.js → chunk-jrxb5sg4.js} +2 -2
- package/dist/bin/{chunk-g47h6fg3.js → chunk-krt80e8w.js} +2 -2
- package/dist/bin/{chunk-vf5w5aed.js → chunk-m60wwxz1.js} +6 -6
- package/dist/bin/{chunk-mn0rzykt.js → chunk-m92m9tx3.js} +34 -34
- package/dist/bin/{chunk-yc1n2h5w.js → chunk-mjbd4pbz.js} +2 -2
- package/dist/bin/chunk-ncr1dwdt.js +1 -0
- package/dist/bin/{chunk-5zp3s61y.js → chunk-nxsx69p4.js} +2 -2
- package/dist/bin/chunk-nzhpva7z.js +1 -0
- package/dist/bin/chunk-p40tvp17.js +1 -0
- package/dist/bin/{chunk-k20dxfrh.js → chunk-pgbtdsj2.js} +2 -2
- package/dist/bin/{chunk-a68bhc0s.js → chunk-pr96tp0s.js} +2 -2
- package/dist/bin/chunk-qe8zh9kn.js +1 -0
- package/dist/bin/{chunk-qascek4k.js → chunk-qjxd8f5m.js} +3 -3
- package/dist/bin/{chunk-pxm3w8a3.js → chunk-qka0e661.js} +5 -5
- package/dist/bin/{chunk-n80ewf4z.js → chunk-rgnmxfvp.js} +1 -1
- package/dist/bin/{chunk-sz45s7mw.js → chunk-sn1zde06.js} +1 -1
- package/dist/bin/{chunk-2mdh3syn.js → chunk-sv7n9ape.js} +2 -2
- package/dist/bin/chunk-t6zpvaqr.js +1 -0
- package/dist/bin/{chunk-34r2fwwn.js → chunk-tdv5rwjv.js} +1 -1
- package/dist/bin/chunk-v4ncs6q2.js +1 -0
- package/dist/bin/{chunk-dbtm1j98.js → chunk-v5js5pz6.js} +170 -170
- package/dist/bin/chunk-vrn0akcn.js +1 -0
- package/dist/bin/{chunk-nxsa7efz.js → chunk-w2eezm9z.js} +2 -2
- package/dist/bin/{chunk-h2f4f194.js → chunk-wjn2bpdb.js} +1 -1
- package/dist/bin/chunk-x00efaxm.js +1 -0
- package/dist/bin/{chunk-gvk2af4h.js → chunk-x40sd2m9.js} +2 -2
- package/dist/bin/chunk-zred4827.js +1 -0
- package/dist/bin/{chunk-jwby10he.js → chunk-zz9nj5kn.js} +3 -3
- package/dist/bin/cli.js +83 -83
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/{chunk-y9589qef.js → chunk-040rbk7k.js} +35 -35
- package/dist/{chunk-bkkwtcnf.js → chunk-192rthtb.js} +70 -70
- package/dist/{chunk-9w5ncn9s.js → chunk-1wc2zfct.js} +3 -3
- package/dist/{chunk-axcxfz8p.js → chunk-1yj07hbw.js} +2 -2
- package/dist/{chunk-0kemzwpg.js → chunk-41fwhvp7.js} +1 -1
- package/dist/chunk-426k7fgf.js +1 -0
- package/dist/chunk-4b0ynr9y.js +1 -0
- package/dist/{chunk-a92gvctb.js → chunk-a07kew2q.js} +6 -6
- package/dist/chunk-emkp3dsp.js +1 -0
- package/dist/{chunk-pymc2aad.js → chunk-h360gwrf.js} +2 -2
- package/dist/{chunk-7mpbjr6c.js → chunk-h5yx54ks.js} +3 -3
- package/dist/{chunk-q4408fwg.js → chunk-hvttzk9q.js} +2 -2
- package/dist/{chunk-q8vvwmka.js → chunk-je8tky8z.js} +1 -1
- package/dist/{chunk-03eny26f.js → chunk-kbr9nc8y.js} +2 -2
- package/dist/{chunk-3ca6cb1s.js → chunk-p21vbrgk.js} +1 -1
- package/dist/chunk-pcagajw1.js +1 -0
- package/dist/{chunk-83fy36fn.js → chunk-qb25wesa.js} +2 -2
- package/dist/{chunk-hk1frmnn.js → chunk-qrpy0h2n.js} +1 -1
- package/dist/{chunk-xd67tr7p.js → chunk-s4wz0csj.js} +1 -1
- package/dist/{chunk-0dfyn0bv.js → chunk-spr6akra.js} +49 -49
- package/dist/chunk-sybwn2y6.js +1 -0
- package/dist/{chunk-r49ynkag.js → chunk-t8fbwcdk.js} +1 -1
- package/dist/{chunk-qgtydqpj.js → chunk-tb8azghz.js} +23 -23
- package/dist/{chunk-pah2r8a0.js → chunk-tq7nsdnd.js} +4 -4
- package/dist/{chunk-0860mm00.js → chunk-v0s8vpa3.js} +1 -1
- package/dist/{chunk-tngsyawj.js → chunk-xyem7g21.js} +1 -1
- package/dist/{chunk-zgfzc46r.js → chunk-yh9tmx00.js} +3 -3
- package/dist/{chunk-1t3rjvf9.js → chunk-z585dfjz.js} +12 -12
- package/dist/deploy/index.js +1 -1
- package/dist/dns/index.js +1 -1
- package/dist/drivers/index.js +1 -1
- package/dist/index.js +8 -8
- package/dist/mail/index.js +2 -2
- package/dist/object-storage/index.d.ts +6 -4
- package/dist/object-storage/migrate.d.ts +3 -1
- package/dist/operations/index.js +1 -1
- package/dist/protection/index.js +1 -1
- package/dist/spend/index.js +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/accept-invitation.html +1 -1
- package/dist/ui/access-denied.html +1 -1
- package/dist/ui/account/automation.html +6 -6
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +6 -6
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +6 -6
- package/dist/ui/data/services.html +6 -6
- package/dist/ui/data/volumes.html +6 -6
- package/dist/ui/index.html +6 -6
- package/dist/ui/infrastructure/topology.html +5 -5
- package/dist/ui/integrations.html +1 -1
- package/dist/ui/operations/alerts.html +6 -6
- package/dist/ui/operations/configuration.html +6 -6
- package/dist/ui/operations/jobs.html +5 -5
- package/dist/ui/operations/maintenance.html +5 -5
- package/dist/ui/operations/observability.html +6 -6
- package/dist/ui/operations/previews.html +6 -6
- package/dist/ui/operations/queue.html +6 -6
- package/dist/ui/operations/regions.html +5 -5
- package/dist/ui/operations/releases.html +6 -6
- package/dist/ui/operations/spend.html +6 -6
- package/dist/ui/operations/workloads.html +6 -6
- package/dist/ui/security.html +1 -1
- package/dist/ui/server/actions.html +6 -6
- package/dist/ui/server/activity.html +1 -1
- package/dist/ui/server/capacity.html +6 -6
- package/dist/ui/server/database.html +6 -6
- package/dist/ui/server/deployments.html +5 -5
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +6 -6
- package/dist/ui/server/fleet.html +6 -6
- package/dist/ui/server/logs.html +6 -6
- package/dist/ui/server/metrics.html +5 -5
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +5 -5
- package/dist/ui/server/ssh-keys.html +6 -6
- package/dist/ui/server/team.html +6 -6
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +6 -6
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +6 -6
- package/dist/ui/serverless/deployments.html +2 -2
- package/dist/ui/serverless/firewall.html +1 -1
- package/dist/ui/serverless/functions.html +5 -5
- package/dist/ui/serverless/logs.html +5 -5
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +6 -6
- package/dist/ui/serverless/secrets.html +6 -6
- package/dist/ui/serverless/traces.html +6 -6
- package/dist/ui/serverless.html +5 -5
- package/package.json +3 -3
- package/dist/bin/chunk-2r9748kw.js +0 -1
- package/dist/bin/chunk-483ppsv0.js +0 -1
- package/dist/bin/chunk-9fn41ztz.js +0 -1
- package/dist/bin/chunk-af8511dv.js +0 -1
- package/dist/bin/chunk-asvxjh7p.js +0 -1
- package/dist/bin/chunk-bphzq12c.js +0 -1
- package/dist/bin/chunk-c6tt4fj9.js +0 -1
- package/dist/bin/chunk-c6yrhzw5.js +0 -1
- package/dist/bin/chunk-cf2teb1b.js +0 -1
- package/dist/bin/chunk-dhb1xs5a.js +0 -1
- package/dist/bin/chunk-dwahpsj4.js +0 -1
- package/dist/bin/chunk-evbh466n.js +0 -1
- package/dist/bin/chunk-j9yq3b4d.js +0 -2
- package/dist/bin/chunk-n54ssj0h.js +0 -1
- package/dist/bin/chunk-nj4eg5vt.js +0 -1
- package/dist/bin/chunk-p6c2d6em.js +0 -1
- package/dist/bin/chunk-va3yvvs0.js +0 -1
- package/dist/bin/chunk-vy27rc50.js +0 -1
- package/dist/bin/chunk-y815amx5.js +0 -1
- package/dist/chunk-0c48hvb8.js +0 -1
- package/dist/chunk-8crqfe8x.js +0 -1
- package/dist/chunk-949tycxj.js +0 -1
- package/dist/chunk-s3pe89wj.js +0 -1
- package/dist/chunk-wxjd9gyb.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{p}from"./chunk-
|
|
1
|
+
import{p}from"./chunk-b0r8a5h5.js";class F{client;region;constructor(e="us-east-1"){this.region=e,this.client=new p}async createHostedZone(e){let t=e.CallerReference||`${Date.now()}-${Math.random().toString(36).slice(2)}`,o=`<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<CreateHostedZoneRequest xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
|
|
3
3
|
<Name>${e.Name}</Name>
|
|
4
4
|
<CallerReference>${t}</CallerReference>`;if(e.HostedZoneConfig){if(o+=`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cc,Y,lc,as,kp,_t,Np,xp,
|
|
1
|
+
import{cc,Y,lc,as,kp,_t,Np,xp,Nn,_p,Op,$p,Lp,Mp}from"./chunk-mjbd4pbz.js";export{Op as clearSigningKeyCache,as as createPresignedUrl,kp as createPresignedUrlAsync,cc as detectServiceRegion,$p as getSigningKeyCacheSize,Lp as isNodeCryptoAvailable,Mp as isWebCryptoAvailable,_t as makeAWSRequest,xp as makeAWSRequestAsync,Np as makeAWSRequestOnce,_p as parseJSONResponse,Nn as parseXMLResponse,Y as signRequest,lc as signRequestAsync};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g}from"./chunk-17ewx21n.js";import"./chunk-b0r8a5h5.js";export{g as S3Client};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Gp,qp,Wp,Kp}from"./chunk-wjn2bpdb.js";import"./chunk-17ewx21n.js";import"./chunk-b0r8a5h5.js";import"./chunk-v5js5pz6.js";import"./chunk-mjbd4pbz.js";export{Kp as deleteFailoverReplicaBuckets,Gp as ensureFailoverReplicaBuckets,qp as grantFailoverReplicaAccess,Wp as seedFailoverReplicas};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{W,No}from"./chunk-w2eezm9z.js";import"./chunk-gga18c4g.js";import"./chunk-b0r8a5h5.js";export{W as ACMClient,No as ACMDnsValidator};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{p}from"./chunk-kwfbth5c.js";import{$e,ya,Ui,Ja,Pn,Wi,Xa,Qa,oc,sc}from"./chunk-dbtm1j98.js";import{n,r,a,e,u,i,Ee}from"./chunk-pxm3w8a3.js";import{v}from"./chunk-7pxqdq44.js";import{P}from"./chunk-9vjg754g.js";import{g}from"./chunk-vcs8wtay.js";class K{client;region;constructor(t="us-east-1",s){this.region=t,this.client=new p(void 0,{profile:s})}async createSecret(t){let s={Name:t.Name};if(t.Description)s.Description=t.Description;if(t.KmsKeyId)s.KmsKeyId=t.KmsKeyId;if(t.SecretBinary)s.SecretBinary=t.SecretBinary;if(t.SecretString)s.SecretString=t.SecretString;if(t.Tags&&t.Tags.length>0)s.Tags=t.Tags;if(t.AddReplicaRegions&&t.AddReplicaRegions.length>0)s.AddReplicaRegions=t.AddReplicaRegions;if(t.ForceOverwriteReplicaSecret!==void 0)s.ForceOverwriteReplicaSecret=t.ForceOverwriteReplicaSecret;s.ClientRequestToken=t.ClientRequestToken||crypto.randomUUID();let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.CreateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId,ReplicationStatus:o.ReplicationStatus}}async updateSecret(t){let s={SecretId:t.SecretId,ClientRequestToken:t.ClientRequestToken||crypto.randomUUID()};if(t.Description)s.Description=t.Description;if(t.KmsKeyId)s.KmsKeyId=t.KmsKeyId;if(t.SecretBinary)s.SecretBinary=t.SecretBinary;if(t.SecretString)s.SecretString=t.SecretString;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.UpdateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId}}async putSecretValue(t){let s={SecretId:t.SecretId};if(t.SecretBinary)s.SecretBinary=t.SecretBinary;if(t.SecretString)s.SecretString=t.SecretString;if(t.VersionStages&&t.VersionStages.length>0)s.VersionStages=t.VersionStages;s.ClientRequestToken=t.ClientRequestToken||crypto.randomUUID();let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.PutSecretValue","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId,VersionStages:o.VersionStages}}async getSecretValue(t){let s={SecretId:t.SecretId};if(t.VersionId)s.VersionId=t.VersionId;if(t.VersionStage)s.VersionStage=t.VersionStage;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.GetSecretValue","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId,SecretBinary:o.SecretBinary,SecretString:o.SecretString,VersionStages:o.VersionStages,CreatedDate:o.CreatedDate}}async describeSecret(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.DescribeSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return this.parseSecret(o)}async listSecrets(t){let s={};if(t?.MaxResults)s.MaxResults=t.MaxResults;if(t?.NextToken)s.NextToken=t.NextToken;if(t?.Filters&&t.Filters.length>0)s.Filters=t.Filters;if(t?.SortOrder)s.SortOrder=t.SortOrder;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.ListSecrets","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{SecretList:o.SecretList?.map((c)=>this.parseSecret(c)),NextToken:o.NextToken}}async deleteSecret(t){let s={SecretId:t.SecretId};if(t.RecoveryWindowInDays!==void 0)s.RecoveryWindowInDays=t.RecoveryWindowInDays;if(t.ForceDeleteWithoutRecovery!==void 0)s.ForceDeleteWithoutRecovery=t.ForceDeleteWithoutRecovery;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.DeleteSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,DeletionDate:o.DeletionDate}}async restoreSecret(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.RestoreSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async rotateSecret(t){let s={SecretId:t.SecretId};if(t.ClientRequestToken)s.ClientRequestToken=t.ClientRequestToken;if(t.RotationLambdaARN)s.RotationLambdaARN=t.RotationLambdaARN;if(t.RotationRules)s.RotationRules=t.RotationRules;if(t.RotateImmediately!==void 0)s.RotateImmediately=t.RotateImmediately;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.RotateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId}}async cancelRotateSecret(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.CancelRotateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async getResourcePolicy(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.GetResourcePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,ResourcePolicy:o.ResourcePolicy}}async putResourcePolicy(t){let s={SecretId:t.SecretId,ResourcePolicy:t.ResourcePolicy};if(t.BlockPublicPolicy!==void 0)s.BlockPublicPolicy=t.BlockPublicPolicy;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.PutResourcePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async deleteResourcePolicy(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.DeleteResourcePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async tagResource(t){let s={SecretId:t.SecretId,Tags:t.Tags};await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.TagResource","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)})}async untagResource(t){let s={SecretId:t.SecretId,TagKeys:t.TagKeys};await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.UntagResource","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)})}async setString(t,s,o){try{let c=await this.putSecretValue({SecretId:t,SecretString:s});return{ARN:c.ARN,VersionId:c.VersionId}}catch(c){if(c.code==="ResourceNotFoundException"){let l=await this.createSecret({Name:t,SecretString:s,Description:o?.description,KmsKeyId:o?.kmsKeyId,Tags:o?.tags});return{ARN:l.ARN,VersionId:l.VersionId}}throw c}}async setJson(t,s,o){return this.setString(t,JSON.stringify(s),o)}async getString(t){return(await this.getSecretValue({SecretId:t})).SecretString}async getJson(t){let s=await this.getString(t);if(s)return JSON.parse(s);return}async listAll(){let t=[],s;do{let o=await this.listSecrets({NextToken:s});if(o.SecretList)t.push(...o.SecretList);s=o.NextToken}while(s);return t}parseSecret(t){return{ARN:t.ARN,Name:t.Name,Description:t.Description,KmsKeyId:t.KmsKeyId,RotationEnabled:t.RotationEnabled,RotationLambdaARN:t.RotationLambdaARN,RotationRules:t.RotationRules,LastRotatedDate:t.LastRotatedDate,LastChangedDate:t.LastChangedDate,LastAccessedDate:t.LastAccessedDate,DeletedDate:t.DeletedDate,NextRotationDate:t.NextRotationDate,Tags:t.Tags,SecretVersionsToStages:t.SecretVersionsToStages,CreatedDate:t.CreatedDate,PrimaryRegion:t.PrimaryRegion}}}import{existsSync as de,readdirSync as me,readFileSync as pe,statSync as fe}from"node:fs";import{join as ne,relative as Se}from"node:path";function k(t,s){let o=t.environments?.[s]?.app;if(!o)throw Error(`No serverless app configured for environment '${s}'. Add environments.${s}.app to your config.`);let c=t.project.slug,l=t.environments?.[s]?.region||t.project.region||"us-east-1";return{app:o,slug:c,region:l,stackName:$e(t,s),artifactBucket:ya(c,s),assetsBucket:Ui(c,s)}}function Tt(t,s){let o=k(t,s),c=`${o.slug}-${s}`;return{region:o.region,slug:o.slug,stackName:o.stackName,functions:{http:`${c}-http`,queue:`${c}-queue`,cli:`${c}-cli`}}}async function q(t,s=8){let o;for(let c=0;c<s;c++)try{return await t()}catch(l){let d=l?.code||l?.name||"",m=String(l?.message||"");if(d==="ResourceConflictException"||/update is in progress|currently in the following state/i.test(m)){o=l,await new Promise((f)=>setTimeout(f,3000));continue}throw l}throw o}var ie=(t,s)=>`releases/${t}/${s}/current.json`;async function G(t,s,o,c){try{return await t.getObjectJson(s,ie(o,c))}catch{return null}}async function ae(t,s,o,c,l){await t.putObjectJson(s,ie(o,c),l)}async function ye(t,s){if(!t.secrets)return{};let o=new K(s),c={},l=Array.isArray(t.secrets)?t.secrets.map((d)=>({envName:d.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),secretId:d})):Object.entries(t.secrets).map(([d,m])=>({envName:d,secretId:m}));if(Array.isArray(t.secrets)){let d=new Map;for(let{envName:f,secretId:S}of l)d.set(f,[...d.get(f)??[],S]);let m=[...d.entries()].filter(([,f])=>f.length>1);if(m.length){let f=m.map(([S,R])=>`${S} ← ${R.join(", ")}`).join("; ");throw Error(`serverless secrets: multiple secrets map to the same env var (${f}). Use the map form { ENV_NAME: 'secret/id' } to disambiguate.`)}}for(let{envName:d,secretId:m}of l){let S=(await o.getSecretValue({SecretId:m})).SecretString??"";try{let R=JSON.parse(S);if(R&&typeof R==="object"&&!Array.isArray(R)){for(let[w,N]of Object.entries(R))c[w]=String(N);continue}}catch{}c[d]=S}return c}function Zd(t,s){let o={},c=s.DbProxyEndpoint||s.DbEndpoint;if(c)o.DB_CONNECTION="mysql",o.DB_HOST=c,o.DB_PORT="3306",o.DB_DATABASE=o.DB_DATABASE||"app";if(s.CacheEndpoint){if(o.REDIS_HOST=s.CacheEndpoint,o.REDIS_PORT="6379",t.cache?.driver==="elasticache")o.CACHE_STORE="redis",o.CACHE_DRIVER="redis",o.SESSION_DRIVER="redis"}return o}function Fs(t,s,o,c,l,d,m,f={}){let S=t.kind==="php"?oc({cacheDriver:t.cache?.driver==="elasticache"?"redis":"dynamodb"}):{};return{TSCLOUD_LAMBDA_MODE:c,TSCLOUD_ENV:o,MAINTENANCE_MODE:"0",...t.octane?{TSCLOUD_OCTANE:"1"}:{},...t.serveAssets?{TSCLOUD_SERVE_ASSETS:"1"}:{},...t.redirectRobotsTxt===!1?{TSCLOUD_REDIRECT_ROBOTS_TXT:"0"}:{},...S,...f,...s.app.cache?.driver!=="elasticache"?{TSCLOUD_CACHE_TABLE:`${s.slug}-${o}-cache`}:{},...m?{TSCLOUD_QUEUE:m,SQS_QUEUE:m}:{},...d?{ASSET_URL:d}:{},...t.env??{},...l}}function Re(t){let s=t.slice(t.lastIndexOf(".")).toLowerCase();return{".html":"text/html",".css":"text/css",".js":"text/javascript",".mjs":"text/javascript",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".txt":"text/plain",".map":"application/json"}[s]??"application/octet-stream"}function*oe(t){for(let s of me(t)){let o=ne(t,s);if(fe(o).isDirectory())yield*oe(o);else yield o}}async function he(t,s,o,c,l=!1){let d=0;for(let m of oe(o)){let f=Se(o,m).replace(/\\/g,"/");if(!l&&f.split("/").some((S)=>S.startsWith(".")))continue;await t.putObject({bucket:s,key:`${c}/${f}`,body:pe(m),contentType:Re(m),cacheControl:"public, max-age=31536000, immutable"}),d++}return d}function $o(t,s){let o=Object.entries(s).reduce((c,[l,d])=>c+Buffer.byteLength(`${l}=${d}`,"utf8"),0);if(o>4096){let c=Object.entries(s).map(([l,d])=>[l,Buffer.byteLength(`${l}=${d}`,"utf8")]).sort((l,d)=>d[1]-l[1]).slice(0,5).map(([l,d])=>`${l} (${d}B)`).join(", ");throw Error(`${t}: environment variables total ${o}B, over AWS's 4096B limit (${o-4096}B too large). Largest: ${c}. Move large/secret values out of env — store them in Secrets Manager and fetch at cold start.`)}}async function U(t,s,o,c){$o(s,o),await q(()=>t.updateFunctionConfiguration({FunctionName:s,Environment:{Variables:o}})),await t.waitForFunctionActive(s,120);let l=c.kind==="image"?{FunctionName:s,ImageUri:c.imageUri}:{FunctionName:s,S3Bucket:c.bucket,S3Key:c.key};await q(()=>t.updateFunctionCode(l)),await t.waitForFunctionActive(s,120)}async function X(t,s){let c=(await q(()=>t.publishVersion({FunctionName:s}))).Version;if(!c)throw Error(`publishVersion returned no version for ${s}`);return await q(()=>t.updateAlias({FunctionName:s,Name:"live",FunctionVersion:c})),c}async function um(t,s,o={}){let c=k(t,s),{app:l,slug:d,region:m,stackName:f,artifactBucket:S}=c,R=o.projectRoot??process.cwd();i(`Deploying serverless app: ${d} (${s})`),e(`Stack: ${f}`),e(`Region: ${m}`);let w=new g(m),N=new v(m),T=new P(m),D=l.kind==="php",O=l.packaging==="image",h=Wi(l),V,E,b,Y,M=[];if(O&&h.usesLayer&&h.layerKind!=="php")throw Error(`packaging: 'image' currently supports PHP and managed Node runtimes. ${h.kind}${h.kind==="node"?` ${h.version}`:""} uses a custom runtime — `+"use the default zip packaging (the runtime layer is built + attached automatically).");if(O){u("Building + pushing container image");let{buildAndPushServerlessImage:y}=await import("./chunk-af8511dv.js"),C=await y({app:l,projectRoot:R,region:m,repository:`${d}-${s}`,skipBuild:o.skipBuild,onStep:(I)=>e(` ${I}`)});V=C.handlers,E={kind:"image",imageUri:C.imageUri},b=C.tag,M.push({ParameterKey:"ImageUri",ParameterValue:C.imageUri})}else{u("Packaging application");let y=D?sc({projectRoot:R,app:l,skipBuild:o.skipBuild,onStep:(x)=>e(` ${x}`)}):await Pn({projectRoot:R,app:l,skipBuild:o.skipBuild,onStep:(x)=>e(` ${x}`)}),C=Ja(d,s,y.sha256);if(e(`Artifact: ${y.sha256.slice(0,12)} (${(y.zip.length/1024).toFixed(0)} KB)`),V=y.handlers,b=y.sha256,h.usesLayer){let x=h.layerEnvVar?process.env[h.layerEnvVar]:void 0;if(Y=l.layers??(x?[x]:void 0),!Y?.length){let ge=h.layerKind==="php"?"serverless:build-php-layer":h.layerKind==="bun"?"serverless:build-bun-layer":"serverless:build-node-layer";throw Error(`${h.kind} apps on provided.al2023 need a runtime layer. Set environments.<env>.app.layers or the ${h.layerEnvVar} env var (build one with \`cloud ${ge}\`)${h.kind==="node"?", or use a managed Node version (18/20/22)":""}.`)}}if(!await w.bucketExists(S))u(`Creating artifact bucket ${S}`),await w.createBucket(S);if(await w.headObject(S,C).then((x)=>x!==null).catch(()=>!1))e("Artifact already uploaded — reusing");else u("Uploading artifact"),await w.putObject({bucket:S,key:C,body:y.zip,contentType:"application/zip"});E={kind:"zip",bucket:S,key:C},M.push({ParameterKey:"ArtifactBucket",ParameterValue:S},{ParameterKey:"ArtifactKey",ParameterValue:C})}let A=Qa({config:t,environment:s,app:l,handlers:V,runtimeLayers:Y}),te=JSON.stringify(A.template),re=["CAPABILITY_NAMED_IAM"],L=await N.describeStacks({stackName:f}).then((y)=>y.Stacks[0]?.StackStatus).catch(()=>{return}),J=L!==void 0;if(L&&/DELETE_IN_PROGRESS/.test(L))u("Waiting for an in-progress stack delete to finish"),await N.waitForStack(f,"stack-delete-complete").catch(()=>{}),J=!1;else if(L&&/(?:ROLLBACK_COMPLETE|REVIEW_IN_PROGRESS|CREATE_FAILED)/.test(L))u(`Deleting unusable stack (status ${L}) before recreate`),await N.deleteStack(f),await N.waitForStack(f,"stack-delete-complete").catch(()=>{}),J=!1;u(J?"Updating infrastructure stack":"Creating infrastructure stack");try{if(J)await N.updateStack({stackName:f,templateBody:te,parameters:M,capabilities:re}),await N.waitForStack(f,"stack-update-complete");else await N.createStack({stackName:f,templateBody:te,parameters:M,capabilities:re,onFailure:"DELETE"}),await N.waitForStack(f,"stack-create-complete")}catch(y){if(/No updates are to be performed/i.test(String(y?.message)))e("No infrastructure changes");else throw y}let Q=await N.getStackOutputs(f).catch(()=>({})),B;if(l.assets){let y=ne(R,l.assets);if(de(y)){let C=l.assetDomain||Q.AssetsCdnDomain;B=C?`https://${C}/${b}`:void 0,u(`Syncing assets from ${l.assets}`);let I=await he(w,c.assetsBucket,y,b,l.dotFilesAsAssets);e(`Uploaded ${I} asset(s)${B?` → ${B}`:""}`)}else a(`Assets directory not found: ${y}`)}u("Resolving secrets");let _=await ye(l,m);if(l.database?.connection==="aurora-serverless")try{let C=await new K(m).getSecretValue({SecretId:`${d}/${s}/db`}),I=JSON.parse(C.SecretString??"{}");if(I.username)_.DB_USERNAME=I.username;if(I.password)_.DB_PASSWORD=I.password}catch(y){a(`Could not resolve Aurora DB credentials: ${y.message}`)}if(!await w.bucketExists(S))await w.createBucket(S);let H=await G(w,S,d,s),F={},Z=A.queueNames[0],ee=Zd(l,Q);if(u("Activating functions"),F.http=Fs(l,c,s,"http",_,B,Z,ee),await U(T,A.functionNames.http,F.http,E),F.cli=Fs(l,c,s,"cli",_,B,Z,ee),await U(T,A.functionNames.cli,F.cli,E),A.queueNames.length)F.queue=Fs(l,c,s,"queue",_,B,Z,ee),await U(T,A.functionNames.queue,F.queue,E);let se=(l.provisionedConcurrency??0)>0,W={};if(se){if(u("Publishing versions + flipping live alias"),W.http=await X(T,A.functionNames.http),W.cli=await X(T,A.functionNames.cli),A.queueNames.length)W.queue=await X(T,A.functionNames.queue)}if(await ae(w,S,d,s,{sha:b,code:E,previousSha:H?.sha,previousCode:H?.code,previousFunctionEnv:H?.functionEnv,...se?{functionVersions:W,previousFunctionVersions:H?.functionVersions}:{},functionEnv:F,functionNames:{http:A.functionNames.http,cli:A.functionNames.cli,...A.queueNames.length?{queue:A.functionNames.queue}:{}},assetUrl:B,timestamp:new Date().toISOString()}),!o.skipDeployHooks&&l.deploy?.length){u("Running deploy hooks");for(let y of l.deploy){e(` deploy: ${y}`);let C=await T.invoke({FunctionName:A.functionNames.cli,InvocationType:"RequestResponse",Payload:{command:y},LogType:"Tail"});if(C.FunctionError)throw r("Deploy hook failed — the new build is ALREADY LIVE."),e(` Roll back with: cloud serverless:rollback --env ${s}`),Error(`Deploy hook failed (${y}): ${C.Payload}`)}}let j=Q.HttpApiEndpoint;if(!o.skipHealthCheck&&j){u("Health check");try{let y=await fetch(j,{method:"GET"});e(`GET ${j} → ${y.status}`)}catch(y){a(`Health check could not reach ${j}: ${y.message}`)}}Ee(["Serverless deploy complete","",j?`URL: ${j}`:"",`Stack: ${f}`,`Build: ${b.slice(0,12)}`].filter(Boolean).join(`
|
|
2
|
-
`),"green")}async function Bs(t,s){let o=k(t,s),c=new g(o.region),l=new P(o.region),d=await G(c,o.artifactBucket,o.slug,s);if(!d)throw Error("No previous release to redeploy. Run a full deploy first.");i(`Redeploying ${o.slug} (${s}) — build ${d.sha.slice(0,12)}`);for(let[m,f]of Object.entries(d.functionNames)){if(!f)continue;u(`Re-activating ${m} (${f})`),await U(l,f,d.functionEnv[m]??{},d.code);let S=d.functionVersions?.[m];if(S)await q(()=>l.updateAlias({FunctionName:f,Name:"live",FunctionVersion:S}))}n("Redeploy complete")}async function js(t,s){let o=k(t,s),c=new g(o.region),l=new P(o.region),d=await G(c,o.artifactBucket,o.slug,s);if(!d?.previousCode)throw Error("No previous release to roll back to.");i(`Rolling back ${o.slug} (${s}) → ${d.previousSha?.slice(0,12)}`);for(let[m,f]of Object.entries(d.functionNames)){if(!f)continue;u(`Restoring ${m} (${f})`);let S=d.previousFunctionEnv?.[m]??d.functionEnv[m]??{};await U(l,f,S,d.previousCode);let R=d.previousFunctionVersions?.[m];if(R)await q(()=>l.updateAlias({FunctionName:f,Name:"live",FunctionVersion:R}))}await ae(c,o.artifactBucket,o.slug,s,{...d,sha:d.previousSha??d.sha,code:d.previousCode,functionEnv:d.previousFunctionEnv??d.functionEnv,functionVersions:d.previousFunctionVersions??d.functionVersions,previousSha:void 0,previousCode:void 0,previousFunctionEnv:void 0,previousFunctionVersions:void 0,timestamp:new Date().toISOString()}),n("Rollback complete")}async function Lo(t,s,o,c){let l=k(t,s),d=new P(l.region),m=`${l.slug}-${s}-http`,S={...(await d.getFunction(m)).Configuration?.Environment?.Variables??{}};if(S.MAINTENANCE_MODE=o?"1":"0",o&&c)S.MAINTENANCE_BYPASS_SECRET=c;if(!o)delete S.MAINTENANCE_BYPASS_SECRET;if(await q(()=>d.updateFunctionConfiguration({FunctionName:m,Environment:{Variables:S}})),(l.app.provisionedConcurrency??0)>0)await d.waitForFunctionActive(m,120),await X(d,m);n(o?"Application is now in maintenance mode (503)":"Application is live")}async function Gt(t,s,o){let c=k(t,s),l=new P(c.region),d=`${c.slug}-${s}-cli`,m=await l.invoke({FunctionName:d,InvocationType:"RequestResponse",Payload:{command:o},LogType:"Tail"});if(m.FunctionError)throw Error(`Command failed: ${m.Payload}`);return m.Payload??""}var ce=(t,s)=>`commands/${t}/${s}/history.json`,ve=50;async function le(t,s,o,c){try{return(await t.getObjectJson(s,ce(o,c)))?.records??[]}catch{return[]}}async function pm(t,s,o){let c=k(t,s),l=new P(c.region),d=`${c.slug}-${s}-cli`,m=await l.invoke({FunctionName:d,InvocationType:"RequestResponse",Payload:{command:o},LogType:"Tail"}),f=m.Payload??"",S=m.FunctionError?"error":"ok",R=-1;try{let w=new g(c.region);if(await w.bucketExists(c.artifactBucket)){let N=await le(w,c.artifactBucket,c.slug,s);R=N.reduce((T,D)=>Math.max(T,D.id),0)+1,N.push({id:R,command:o,timestamp:new Date().toISOString(),status:S,output:f.slice(0,4000)}),await w.putObjectJson(c.artifactBucket,ce(c.slug,s),{records:N.slice(-ve)})}}catch{}if(m.FunctionError)throw Error(`Command failed${R>0?` (#${R})`:""}: ${f}`);return{id:R,status:S,output:f}}async function eu(t,s){let o=k(t,s),c=new g(o.region);return le(c,o.artifactBucket,o.slug,s)}async function mm(t,s,o){let c=await eu(t,s);if(!c.length)return;return o==null?c[c.length-1]:c.find((l)=>l.id===o)}async function gm(t,s,o){let c=Buffer.from(o,"utf-8").toString("base64");return Gt(t,s,`tscloud:db-query --sql-base64=${c}`)}async function z(t,s){let o=k(t,s),c=new v(o.region),l=new P(o.region),d=new g(o.region),m="not deployed",f={};try{let{Stacks:O}=await c.describeStacks({stackName:o.stackName});m=O?.[0]?.StackStatus??m;for(let h of O?.[0]?.Outputs??[])if(h.OutputKey)f[h.OutputKey]=h.OutputValue??""}catch{}let S=Xa(o.app,o.slug,s),R=o.app.provisionedConcurrency??0,w=["http","cli",...S.length?["queue"]:[]],N=`${o.slug}-${s}`,T=[];for(let O of w){let h=`${N}-${O}`,V={mode:O,name:h,version:"$LATEST"};if(R>0){let E=await l.getAlias(h,"live").catch(()=>null);if(E?.FunctionVersion){V.version=E.FunctionVersion;let b=await l.getProvisionedConcurrencyConfig(h,"live").catch(()=>null);if(b)V.provisioned={status:b.Status??"-",allocated:b.AllocatedProvisionedConcurrentExecutions??0,requested:b.RequestedProvisionedConcurrentExecutions??0}}}T.push(V)}let D=await G(d,o.artifactBucket,o.slug,s).catch(()=>null);return{slug:o.slug,environment:s,region:o.region,stackStatus:m,endpoint:f.HttpApiEndpoint,assetUrl:D?.assetUrl,scheduler:o.app.scheduler??"on",queues:S,provisionedConcurrency:R,functions:T,lastRelease:D?{sha:D.sha,timestamp:D.timestamp}:void 0}}function ue(t,s){return`${t}-${s}-db`}async function Vs(t,s,o,c){let l=k(t,s);if(l.app.database?.connection!=="aurora-serverless")throw Error("No Aurora Serverless v2 database is configured for this environment.");let{RDSClient:d}=await import("./chunk-
|
|
1
|
+
import{p}from"./chunk-b0r8a5h5.js";import{$e,ya,Ui,Ja,Dn,Wi,Xa,Qa,oc,sc}from"./chunk-v5js5pz6.js";import{n,r,a,e,u,i,Ee}from"./chunk-qka0e661.js";import{v}from"./chunk-5fde4d44.js";import{P}from"./chunk-e4c7ba0g.js";import{g}from"./chunk-17ewx21n.js";class K{client;region;constructor(t="us-east-1",s){this.region=t,this.client=new p(void 0,{profile:s})}async createSecret(t){let s={Name:t.Name};if(t.Description)s.Description=t.Description;if(t.KmsKeyId)s.KmsKeyId=t.KmsKeyId;if(t.SecretBinary)s.SecretBinary=t.SecretBinary;if(t.SecretString)s.SecretString=t.SecretString;if(t.Tags&&t.Tags.length>0)s.Tags=t.Tags;if(t.AddReplicaRegions&&t.AddReplicaRegions.length>0)s.AddReplicaRegions=t.AddReplicaRegions;if(t.ForceOverwriteReplicaSecret!==void 0)s.ForceOverwriteReplicaSecret=t.ForceOverwriteReplicaSecret;s.ClientRequestToken=t.ClientRequestToken||crypto.randomUUID();let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.CreateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId,ReplicationStatus:o.ReplicationStatus}}async updateSecret(t){let s={SecretId:t.SecretId,ClientRequestToken:t.ClientRequestToken||crypto.randomUUID()};if(t.Description)s.Description=t.Description;if(t.KmsKeyId)s.KmsKeyId=t.KmsKeyId;if(t.SecretBinary)s.SecretBinary=t.SecretBinary;if(t.SecretString)s.SecretString=t.SecretString;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.UpdateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId}}async putSecretValue(t){let s={SecretId:t.SecretId};if(t.SecretBinary)s.SecretBinary=t.SecretBinary;if(t.SecretString)s.SecretString=t.SecretString;if(t.VersionStages&&t.VersionStages.length>0)s.VersionStages=t.VersionStages;s.ClientRequestToken=t.ClientRequestToken||crypto.randomUUID();let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.PutSecretValue","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId,VersionStages:o.VersionStages}}async getSecretValue(t){let s={SecretId:t.SecretId};if(t.VersionId)s.VersionId=t.VersionId;if(t.VersionStage)s.VersionStage=t.VersionStage;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.GetSecretValue","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId,SecretBinary:o.SecretBinary,SecretString:o.SecretString,VersionStages:o.VersionStages,CreatedDate:o.CreatedDate}}async describeSecret(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.DescribeSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return this.parseSecret(o)}async listSecrets(t){let s={};if(t?.MaxResults)s.MaxResults=t.MaxResults;if(t?.NextToken)s.NextToken=t.NextToken;if(t?.Filters&&t.Filters.length>0)s.Filters=t.Filters;if(t?.SortOrder)s.SortOrder=t.SortOrder;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.ListSecrets","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{SecretList:o.SecretList?.map((c)=>this.parseSecret(c)),NextToken:o.NextToken}}async deleteSecret(t){let s={SecretId:t.SecretId};if(t.RecoveryWindowInDays!==void 0)s.RecoveryWindowInDays=t.RecoveryWindowInDays;if(t.ForceDeleteWithoutRecovery!==void 0)s.ForceDeleteWithoutRecovery=t.ForceDeleteWithoutRecovery;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.DeleteSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,DeletionDate:o.DeletionDate}}async restoreSecret(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.RestoreSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async rotateSecret(t){let s={SecretId:t.SecretId};if(t.ClientRequestToken)s.ClientRequestToken=t.ClientRequestToken;if(t.RotationLambdaARN)s.RotationLambdaARN=t.RotationLambdaARN;if(t.RotationRules)s.RotationRules=t.RotationRules;if(t.RotateImmediately!==void 0)s.RotateImmediately=t.RotateImmediately;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.RotateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,VersionId:o.VersionId}}async cancelRotateSecret(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.CancelRotateSecret","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async getResourcePolicy(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.GetResourcePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name,ResourcePolicy:o.ResourcePolicy}}async putResourcePolicy(t){let s={SecretId:t.SecretId,ResourcePolicy:t.ResourcePolicy};if(t.BlockPublicPolicy!==void 0)s.BlockPublicPolicy=t.BlockPublicPolicy;let o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.PutResourcePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async deleteResourcePolicy(t){let s={SecretId:t},o=await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.DeleteResourcePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)});return{ARN:o.ARN,Name:o.Name}}async tagResource(t){let s={SecretId:t.SecretId,Tags:t.Tags};await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.TagResource","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)})}async untagResource(t){let s={SecretId:t.SecretId,TagKeys:t.TagKeys};await this.client.request({service:"secretsmanager",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"secretsmanager.UntagResource","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(s)})}async setString(t,s,o){try{let c=await this.putSecretValue({SecretId:t,SecretString:s});return{ARN:c.ARN,VersionId:c.VersionId}}catch(c){if(c.code==="ResourceNotFoundException"){let l=await this.createSecret({Name:t,SecretString:s,Description:o?.description,KmsKeyId:o?.kmsKeyId,Tags:o?.tags});return{ARN:l.ARN,VersionId:l.VersionId}}throw c}}async setJson(t,s,o){return this.setString(t,JSON.stringify(s),o)}async getString(t){return(await this.getSecretValue({SecretId:t})).SecretString}async getJson(t){let s=await this.getString(t);if(s)return JSON.parse(s);return}async listAll(){let t=[],s;do{let o=await this.listSecrets({NextToken:s});if(o.SecretList)t.push(...o.SecretList);s=o.NextToken}while(s);return t}parseSecret(t){return{ARN:t.ARN,Name:t.Name,Description:t.Description,KmsKeyId:t.KmsKeyId,RotationEnabled:t.RotationEnabled,RotationLambdaARN:t.RotationLambdaARN,RotationRules:t.RotationRules,LastRotatedDate:t.LastRotatedDate,LastChangedDate:t.LastChangedDate,LastAccessedDate:t.LastAccessedDate,DeletedDate:t.DeletedDate,NextRotationDate:t.NextRotationDate,Tags:t.Tags,SecretVersionsToStages:t.SecretVersionsToStages,CreatedDate:t.CreatedDate,PrimaryRegion:t.PrimaryRegion}}}import{existsSync as de,readdirSync as me,readFileSync as pe,statSync as fe}from"node:fs";import{join as ne,relative as Se}from"node:path";function k(t,s){let o=t.environments?.[s]?.app;if(!o)throw Error(`No serverless app configured for environment '${s}'. Add environments.${s}.app to your config.`);let c=t.project.slug,l=t.environments?.[s]?.region||t.project.region||"us-east-1";return{app:o,slug:c,region:l,stackName:$e(t,s),artifactBucket:ya(c,s),assetsBucket:Ui(c,s)}}function Tt(t,s){let o=k(t,s),c=`${o.slug}-${s}`;return{region:o.region,slug:o.slug,stackName:o.stackName,functions:{http:`${c}-http`,queue:`${c}-queue`,cli:`${c}-cli`}}}async function q(t,s=8){let o;for(let c=0;c<s;c++)try{return await t()}catch(l){let d=l?.code||l?.name||"",m=String(l?.message||"");if(d==="ResourceConflictException"||/update is in progress|currently in the following state/i.test(m)){o=l,await new Promise((f)=>setTimeout(f,3000));continue}throw l}throw o}var ie=(t,s)=>`releases/${t}/${s}/current.json`;async function G(t,s,o,c){try{return await t.getObjectJson(s,ie(o,c))}catch{return null}}async function ae(t,s,o,c,l){await t.putObjectJson(s,ie(o,c),l)}async function ye(t,s){if(!t.secrets)return{};let o=new K(s),c={},l=Array.isArray(t.secrets)?t.secrets.map((d)=>({envName:d.split("/").pop().toUpperCase().replace(/[^A-Z0-9_]/g,"_"),secretId:d})):Object.entries(t.secrets).map(([d,m])=>({envName:d,secretId:m}));if(Array.isArray(t.secrets)){let d=new Map;for(let{envName:f,secretId:S}of l)d.set(f,[...d.get(f)??[],S]);let m=[...d.entries()].filter(([,f])=>f.length>1);if(m.length){let f=m.map(([S,R])=>`${S} ← ${R.join(", ")}`).join("; ");throw Error(`serverless secrets: multiple secrets map to the same env var (${f}). Use the map form { ENV_NAME: 'secret/id' } to disambiguate.`)}}for(let{envName:d,secretId:m}of l){let S=(await o.getSecretValue({SecretId:m})).SecretString??"";try{let R=JSON.parse(S);if(R&&typeof R==="object"&&!Array.isArray(R)){for(let[w,N]of Object.entries(R))c[w]=String(N);continue}}catch{}c[d]=S}return c}function Zd(t,s){let o={},c=s.DbProxyEndpoint||s.DbEndpoint;if(c)o.DB_CONNECTION="mysql",o.DB_HOST=c,o.DB_PORT="3306",o.DB_DATABASE=o.DB_DATABASE||"app";if(s.CacheEndpoint){if(o.REDIS_HOST=s.CacheEndpoint,o.REDIS_PORT="6379",t.cache?.driver==="elasticache")o.CACHE_STORE="redis",o.CACHE_DRIVER="redis",o.SESSION_DRIVER="redis"}return o}function Fs(t,s,o,c,l,d,m,f={}){let S=t.kind==="php"?oc({cacheDriver:t.cache?.driver==="elasticache"?"redis":"dynamodb"}):{};return{TSCLOUD_LAMBDA_MODE:c,TSCLOUD_ENV:o,MAINTENANCE_MODE:"0",...t.octane?{TSCLOUD_OCTANE:"1"}:{},...t.serveAssets?{TSCLOUD_SERVE_ASSETS:"1"}:{},...t.redirectRobotsTxt===!1?{TSCLOUD_REDIRECT_ROBOTS_TXT:"0"}:{},...S,...f,...s.app.cache?.driver!=="elasticache"?{TSCLOUD_CACHE_TABLE:`${s.slug}-${o}-cache`}:{},...m?{TSCLOUD_QUEUE:m,SQS_QUEUE:m}:{},...d?{ASSET_URL:d}:{},...t.env??{},...l}}function Re(t){let s=t.slice(t.lastIndexOf(".")).toLowerCase();return{".html":"text/html",".css":"text/css",".js":"text/javascript",".mjs":"text/javascript",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".txt":"text/plain",".map":"application/json"}[s]??"application/octet-stream"}function*oe(t){for(let s of me(t)){let o=ne(t,s);if(fe(o).isDirectory())yield*oe(o);else yield o}}async function he(t,s,o,c,l=!1){let d=0;for(let m of oe(o)){let f=Se(o,m).replace(/\\/g,"/");if(!l&&f.split("/").some((S)=>S.startsWith(".")))continue;await t.putObject({bucket:s,key:`${c}/${f}`,body:pe(m),contentType:Re(m),cacheControl:"public, max-age=31536000, immutable"}),d++}return d}function $o(t,s){let o=Object.entries(s).reduce((c,[l,d])=>c+Buffer.byteLength(`${l}=${d}`,"utf8"),0);if(o>4096){let c=Object.entries(s).map(([l,d])=>[l,Buffer.byteLength(`${l}=${d}`,"utf8")]).sort((l,d)=>d[1]-l[1]).slice(0,5).map(([l,d])=>`${l} (${d}B)`).join(", ");throw Error(`${t}: environment variables total ${o}B, over AWS's 4096B limit (${o-4096}B too large). Largest: ${c}. Move large/secret values out of env — store them in Secrets Manager and fetch at cold start.`)}}async function U(t,s,o,c){$o(s,o),await q(()=>t.updateFunctionConfiguration({FunctionName:s,Environment:{Variables:o}})),await t.waitForFunctionActive(s,120);let l=c.kind==="image"?{FunctionName:s,ImageUri:c.imageUri}:{FunctionName:s,S3Bucket:c.bucket,S3Key:c.key};await q(()=>t.updateFunctionCode(l)),await t.waitForFunctionActive(s,120)}async function X(t,s){let c=(await q(()=>t.publishVersion({FunctionName:s}))).Version;if(!c)throw Error(`publishVersion returned no version for ${s}`);return await q(()=>t.updateAlias({FunctionName:s,Name:"live",FunctionVersion:c})),c}async function um(t,s,o={}){let c=k(t,s),{app:l,slug:d,region:m,stackName:f,artifactBucket:S}=c,R=o.projectRoot??process.cwd();i(`Deploying serverless app: ${d} (${s})`),e(`Stack: ${f}`),e(`Region: ${m}`);let w=new g(m),N=new v(m),T=new P(m),D=l.kind==="php",O=l.packaging==="image",h=Wi(l),V,E,b,Y,M=[];if(O&&h.usesLayer&&h.layerKind!=="php")throw Error(`packaging: 'image' currently supports PHP and managed Node runtimes. ${h.kind}${h.kind==="node"?` ${h.version}`:""} uses a custom runtime — `+"use the default zip packaging (the runtime layer is built + attached automatically).");if(O){u("Building + pushing container image");let{buildAndPushServerlessImage:y}=await import("./chunk-p40tvp17.js"),C=await y({app:l,projectRoot:R,region:m,repository:`${d}-${s}`,skipBuild:o.skipBuild,onStep:(I)=>e(` ${I}`)});V=C.handlers,E={kind:"image",imageUri:C.imageUri},b=C.tag,M.push({ParameterKey:"ImageUri",ParameterValue:C.imageUri})}else{u("Packaging application");let y=D?sc({projectRoot:R,app:l,skipBuild:o.skipBuild,onStep:(x)=>e(` ${x}`)}):await Dn({projectRoot:R,app:l,skipBuild:o.skipBuild,onStep:(x)=>e(` ${x}`)}),C=Ja(d,s,y.sha256);if(e(`Artifact: ${y.sha256.slice(0,12)} (${(y.zip.length/1024).toFixed(0)} KB)`),V=y.handlers,b=y.sha256,h.usesLayer){let x=h.layerEnvVar?process.env[h.layerEnvVar]:void 0;if(Y=l.layers??(x?[x]:void 0),!Y?.length){let ge=h.layerKind==="php"?"serverless:build-php-layer":h.layerKind==="bun"?"serverless:build-bun-layer":"serverless:build-node-layer";throw Error(`${h.kind} apps on provided.al2023 need a runtime layer. Set environments.<env>.app.layers or the ${h.layerEnvVar} env var (build one with \`cloud ${ge}\`)${h.kind==="node"?", or use a managed Node version (18/20/22)":""}.`)}}if(!await w.bucketExists(S))u(`Creating artifact bucket ${S}`),await w.createBucket(S);if(await w.headObject(S,C).then((x)=>x!==null).catch(()=>!1))e("Artifact already uploaded — reusing");else u("Uploading artifact"),await w.putObject({bucket:S,key:C,body:y.zip,contentType:"application/zip"});E={kind:"zip",bucket:S,key:C},M.push({ParameterKey:"ArtifactBucket",ParameterValue:S},{ParameterKey:"ArtifactKey",ParameterValue:C})}let A=Qa({config:t,environment:s,app:l,handlers:V,runtimeLayers:Y}),te=JSON.stringify(A.template),re=["CAPABILITY_NAMED_IAM"],L=await N.describeStacks({stackName:f}).then((y)=>y.Stacks[0]?.StackStatus).catch(()=>{return}),J=L!==void 0;if(L&&/DELETE_IN_PROGRESS/.test(L))u("Waiting for an in-progress stack delete to finish"),await N.waitForStack(f,"stack-delete-complete").catch(()=>{}),J=!1;else if(L&&/(?:ROLLBACK_COMPLETE|REVIEW_IN_PROGRESS|CREATE_FAILED)/.test(L))u(`Deleting unusable stack (status ${L}) before recreate`),await N.deleteStack(f),await N.waitForStack(f,"stack-delete-complete").catch(()=>{}),J=!1;u(J?"Updating infrastructure stack":"Creating infrastructure stack");try{if(J)await N.updateStack({stackName:f,templateBody:te,parameters:M,capabilities:re}),await N.waitForStack(f,"stack-update-complete");else await N.createStack({stackName:f,templateBody:te,parameters:M,capabilities:re,onFailure:"DELETE"}),await N.waitForStack(f,"stack-create-complete")}catch(y){if(/No updates are to be performed/i.test(String(y?.message)))e("No infrastructure changes");else throw y}let Q=await N.getStackOutputs(f).catch(()=>({})),B;if(l.assets){let y=ne(R,l.assets);if(de(y)){let C=l.assetDomain||Q.AssetsCdnDomain;B=C?`https://${C}/${b}`:void 0,u(`Syncing assets from ${l.assets}`);let I=await he(w,c.assetsBucket,y,b,l.dotFilesAsAssets);e(`Uploaded ${I} asset(s)${B?` → ${B}`:""}`)}else a(`Assets directory not found: ${y}`)}u("Resolving secrets");let _=await ye(l,m);if(l.database?.connection==="aurora-serverless")try{let C=await new K(m).getSecretValue({SecretId:`${d}/${s}/db`}),I=JSON.parse(C.SecretString??"{}");if(I.username)_.DB_USERNAME=I.username;if(I.password)_.DB_PASSWORD=I.password}catch(y){a(`Could not resolve Aurora DB credentials: ${y.message}`)}if(!await w.bucketExists(S))await w.createBucket(S);let H=await G(w,S,d,s),F={},Z=A.queueNames[0],ee=Zd(l,Q);if(u("Activating functions"),F.http=Fs(l,c,s,"http",_,B,Z,ee),await U(T,A.functionNames.http,F.http,E),F.cli=Fs(l,c,s,"cli",_,B,Z,ee),await U(T,A.functionNames.cli,F.cli,E),A.queueNames.length)F.queue=Fs(l,c,s,"queue",_,B,Z,ee),await U(T,A.functionNames.queue,F.queue,E);let se=(l.provisionedConcurrency??0)>0,W={};if(se){if(u("Publishing versions + flipping live alias"),W.http=await X(T,A.functionNames.http),W.cli=await X(T,A.functionNames.cli),A.queueNames.length)W.queue=await X(T,A.functionNames.queue)}if(await ae(w,S,d,s,{sha:b,code:E,previousSha:H?.sha,previousCode:H?.code,previousFunctionEnv:H?.functionEnv,...se?{functionVersions:W,previousFunctionVersions:H?.functionVersions}:{},functionEnv:F,functionNames:{http:A.functionNames.http,cli:A.functionNames.cli,...A.queueNames.length?{queue:A.functionNames.queue}:{}},assetUrl:B,timestamp:new Date().toISOString()}),!o.skipDeployHooks&&l.deploy?.length){u("Running deploy hooks");for(let y of l.deploy){e(` deploy: ${y}`);let C=await T.invoke({FunctionName:A.functionNames.cli,InvocationType:"RequestResponse",Payload:{command:y},LogType:"Tail"});if(C.FunctionError)throw r("Deploy hook failed — the new build is ALREADY LIVE."),e(` Roll back with: cloud serverless:rollback --env ${s}`),Error(`Deploy hook failed (${y}): ${C.Payload}`)}}let j=Q.HttpApiEndpoint;if(!o.skipHealthCheck&&j){u("Health check");try{let y=await fetch(j,{method:"GET"});e(`GET ${j} → ${y.status}`)}catch(y){a(`Health check could not reach ${j}: ${y.message}`)}}Ee(["Serverless deploy complete","",j?`URL: ${j}`:"",`Stack: ${f}`,`Build: ${b.slice(0,12)}`].filter(Boolean).join(`
|
|
2
|
+
`),"green")}async function Bs(t,s){let o=k(t,s),c=new g(o.region),l=new P(o.region),d=await G(c,o.artifactBucket,o.slug,s);if(!d)throw Error("No previous release to redeploy. Run a full deploy first.");i(`Redeploying ${o.slug} (${s}) — build ${d.sha.slice(0,12)}`);for(let[m,f]of Object.entries(d.functionNames)){if(!f)continue;u(`Re-activating ${m} (${f})`),await U(l,f,d.functionEnv[m]??{},d.code);let S=d.functionVersions?.[m];if(S)await q(()=>l.updateAlias({FunctionName:f,Name:"live",FunctionVersion:S}))}n("Redeploy complete")}async function js(t,s){let o=k(t,s),c=new g(o.region),l=new P(o.region),d=await G(c,o.artifactBucket,o.slug,s);if(!d?.previousCode)throw Error("No previous release to roll back to.");i(`Rolling back ${o.slug} (${s}) → ${d.previousSha?.slice(0,12)}`);for(let[m,f]of Object.entries(d.functionNames)){if(!f)continue;u(`Restoring ${m} (${f})`);let S=d.previousFunctionEnv?.[m]??d.functionEnv[m]??{};await U(l,f,S,d.previousCode);let R=d.previousFunctionVersions?.[m];if(R)await q(()=>l.updateAlias({FunctionName:f,Name:"live",FunctionVersion:R}))}await ae(c,o.artifactBucket,o.slug,s,{...d,sha:d.previousSha??d.sha,code:d.previousCode,functionEnv:d.previousFunctionEnv??d.functionEnv,functionVersions:d.previousFunctionVersions??d.functionVersions,previousSha:void 0,previousCode:void 0,previousFunctionEnv:void 0,previousFunctionVersions:void 0,timestamp:new Date().toISOString()}),n("Rollback complete")}async function Lo(t,s,o,c){let l=k(t,s),d=new P(l.region),m=`${l.slug}-${s}-http`,S={...(await d.getFunction(m)).Configuration?.Environment?.Variables??{}};if(S.MAINTENANCE_MODE=o?"1":"0",o&&c)S.MAINTENANCE_BYPASS_SECRET=c;if(!o)delete S.MAINTENANCE_BYPASS_SECRET;if(await q(()=>d.updateFunctionConfiguration({FunctionName:m,Environment:{Variables:S}})),(l.app.provisionedConcurrency??0)>0)await d.waitForFunctionActive(m,120),await X(d,m);n(o?"Application is now in maintenance mode (503)":"Application is live")}async function Gt(t,s,o){let c=k(t,s),l=new P(c.region),d=`${c.slug}-${s}-cli`,m=await l.invoke({FunctionName:d,InvocationType:"RequestResponse",Payload:{command:o},LogType:"Tail"});if(m.FunctionError)throw Error(`Command failed: ${m.Payload}`);return m.Payload??""}var ce=(t,s)=>`commands/${t}/${s}/history.json`,ve=50;async function le(t,s,o,c){try{return(await t.getObjectJson(s,ce(o,c)))?.records??[]}catch{return[]}}async function pm(t,s,o){let c=k(t,s),l=new P(c.region),d=`${c.slug}-${s}-cli`,m=await l.invoke({FunctionName:d,InvocationType:"RequestResponse",Payload:{command:o},LogType:"Tail"}),f=m.Payload??"",S=m.FunctionError?"error":"ok",R=-1;try{let w=new g(c.region);if(await w.bucketExists(c.artifactBucket)){let N=await le(w,c.artifactBucket,c.slug,s);R=N.reduce((T,D)=>Math.max(T,D.id),0)+1,N.push({id:R,command:o,timestamp:new Date().toISOString(),status:S,output:f.slice(0,4000)}),await w.putObjectJson(c.artifactBucket,ce(c.slug,s),{records:N.slice(-ve)})}}catch{}if(m.FunctionError)throw Error(`Command failed${R>0?` (#${R})`:""}: ${f}`);return{id:R,status:S,output:f}}async function eu(t,s){let o=k(t,s),c=new g(o.region);return le(c,o.artifactBucket,o.slug,s)}async function mm(t,s,o){let c=await eu(t,s);if(!c.length)return;return o==null?c[c.length-1]:c.find((l)=>l.id===o)}async function gm(t,s,o){let c=Buffer.from(o,"utf-8").toString("base64");return Gt(t,s,`tscloud:db-query --sql-base64=${c}`)}async function z(t,s){let o=k(t,s),c=new v(o.region),l=new P(o.region),d=new g(o.region),m="not deployed",f={};try{let{Stacks:O}=await c.describeStacks({stackName:o.stackName});m=O?.[0]?.StackStatus??m;for(let h of O?.[0]?.Outputs??[])if(h.OutputKey)f[h.OutputKey]=h.OutputValue??""}catch{}let S=Xa(o.app,o.slug,s),R=o.app.provisionedConcurrency??0,w=["http","cli",...S.length?["queue"]:[]],N=`${o.slug}-${s}`,T=[];for(let O of w){let h=`${N}-${O}`,V={mode:O,name:h,version:"$LATEST"};if(R>0){let E=await l.getAlias(h,"live").catch(()=>null);if(E?.FunctionVersion){V.version=E.FunctionVersion;let b=await l.getProvisionedConcurrencyConfig(h,"live").catch(()=>null);if(b)V.provisioned={status:b.Status??"-",allocated:b.AllocatedProvisionedConcurrentExecutions??0,requested:b.RequestedProvisionedConcurrentExecutions??0}}}T.push(V)}let D=await G(d,o.artifactBucket,o.slug,s).catch(()=>null);return{slug:o.slug,environment:s,region:o.region,stackStatus:m,endpoint:f.HttpApiEndpoint,assetUrl:D?.assetUrl,scheduler:o.app.scheduler??"on",queues:S,provisionedConcurrency:R,functions:T,lastRelease:D?{sha:D.sha,timestamp:D.timestamp}:void 0}}function ue(t,s){return`${t}-${s}-db`}async function Vs(t,s,o,c){let l=k(t,s);if(l.app.database?.connection!=="aurora-serverless")throw Error("No Aurora Serverless v2 database is configured for this environment.");let{RDSClient:d}=await import("./chunk-nzhpva7z.js"),m=new d(l.region),f=ue(l.slug,s);u(`Scaling ${f} → ${o}–${c} ACUs`),await m.modifyDBCluster({DBClusterIdentifier:f,ServerlessV2ScalingConfiguration:{MinCapacity:o,MaxCapacity:c},ApplyImmediately:!0}),n(`Scaling applied to ${f} (takes effect shortly).`)}async function fm(t,s,o){let c=k(t,s);if(c.app.database?.connection!=="aurora-serverless")throw Error("No Aurora Serverless v2 database is configured for this environment.");if(!o.toTime&&!o.latest)throw Error("Specify a restore point: --to <ISO timestamp> or --latest.");let{RDSClient:l}=await import("./chunk-nzhpva7z.js"),d=new l(c.region),m=ue(c.slug,s),f=o.latest?"latest":o.toTime.toISOString().replace(/[^0-9]/g,"").slice(0,14),S=o.target??`${m}-restore-${f}`;u(`Restoring ${m} → new cluster ${S} (${o.latest?"latest restorable time":o.toTime.toISOString()})`),await d.restoreDBClusterToPointInTime({DBClusterIdentifier:S,SourceDBClusterIdentifier:m,RestoreToTime:o.toTime,UseLatestRestorableTime:o.latest}),u("Waiting for the restored cluster to be ready");for(let R=0;R<120;R++){let{DBClusters:w}=await d.describeDBClusters({DBClusterIdentifier:S}),N=w?.[0]?.Status;if(N&&N!=="creating")break;await new Promise((T)=>setTimeout(T,15000))}return u("Adding a writer instance"),await d.createDBInstance({DBInstanceIdentifier:`${S}-1`,DBClusterIdentifier:S,Engine:"aurora-mysql",DBInstanceClass:"db.serverless"}),n(`Restore complete → cluster ${S} with writer ${S}-1. Point an env's database at it once available.`),S}
|
|
3
3
|
export{K,Tt,Zd,Fs,$o,um,Bs,js,Lo,Gt,pm,eu,mm,gm,z,Vs,fm};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var qd={newConnectionsPerSecond:50,concurrentPerSource:100,synPerSecond:2000,burst:100,icmpPerSecond:5,banSeconds:600};function h(e){return{...qd,...e.thresholds}}var _=/^(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,2})?$|^[0-9a-f:]+(?:\/\d{1,3})?$/i;function Eo(e){if(!_.test(e))return!1;let[t,n]=e.split("/");if(t.includes(":"))return n==null||Number(n)>=0&&Number(n)<=128;let s=t.split(".");if(s.length!==4||s.some((a)=>Number(a)>255||a===""))return!1;return n==null||Number(n)>=0&&Number(n)<=32}function f(e){return[...new Set((e??[]).map((t)=>t.trim()).filter(Eo))]}function y(e){let t=(e??[80,443]).filter((n)=>Number.isInteger(n)&&n>=1&&n<=65535);return[...new Set(t)].sort((n,s)=>n-s)}function Wd(e={}){let t=h(e);return{"net.ipv4.tcp_syncookies":"1","net.ipv4.tcp_max_syn_backlog":String(Math.max(4096,t.synPerSecond*4)),"net.ipv4.tcp_synack_retries":"2","net.ipv4.tcp_abort_on_overflow":"1","net.ipv4.tcp_fin_timeout":"15","net.ipv4.tcp_keepalive_time":"300","net.ipv4.tcp_keepalive_intvl":"30","net.ipv4.tcp_keepalive_probes":"3","net.core.somaxconn":"4096","net.core.netdev_max_backlog":"16384","net.ipv4.conf.all.rp_filter":"1","net.ipv4.conf.default.rp_filter":"1","net.ipv4.conf.all.accept_source_route":"0","net.ipv4.conf.all.accept_redirects":"0","net.ipv4.conf.all.send_redirects":"0","net.ipv6.conf.all.accept_redirects":"0","net.ipv6.conf.all.accept_source_route":"0","net.ipv4.icmp_echo_ignore_broadcasts":"1","net.ipv4.icmp_ignore_bogus_error_responses":"1","net.netfilter.nf_conntrack_max":"262144","net.netfilter.nf_conntrack_tcp_timeout_established":"3600"}}function Kd(e={}){let t=["# Managed by ts-cloud. Edits are overwritten on the next deploy.","# Network hardening against L3/L4 floods.",""];for(let[n,s]of Object.entries(Wd(e)))t.push(`${n} = ${s}`);return`${t.join(`
|
|
2
2
|
`)}
|
|
3
3
|
`}function Jd(e={}){let t=h(e),n=y(e.ports),s=f(e.allowlist),a=f(e.blocklist),l=e.monitorOnly?"counter":"counter drop",i=e.originProtection?.enabled?f(e.originProtection.cdnRanges):[],c=s.filter((r)=>!r.includes(":")),p=s.filter((r)=>r.includes(":")),u=a.filter((r)=>!r.includes(":")),o=["#!/usr/sbin/nft -f","# Managed by ts-cloud. Edits are overwritten on the next deploy.","","table inet ts_cloud_ddos","delete table inet ts_cloud_ddos","","table inet ts_cloud_ddos {"," # Sources that tripped a limit, with a timeout so a ban self-expires.",` set banned4 { type ipv4_addr; flags timeout; timeout ${t.banSeconds}s; }`,` set banned6 { type ipv6_addr; flags timeout; timeout ${t.banSeconds}s; }`];if(c.length>0)o.push(` set allow4 { type ipv4_addr; flags interval; elements = { ${c.join(", ")} } }`);if(p.length>0)o.push(` set allow6 { type ipv6_addr; flags interval; elements = { ${p.join(", ")} } }`);if(u.length>0)o.push(` set block4 { type ipv4_addr; flags interval; elements = { ${u.join(", ")} } }`);if(i.length>0)o.push(` set cdn4 { type ipv4_addr; flags interval; elements = { ${i.filter((r)=>!r.includes(":")).join(", ")} } }`);if(o.push(""," chain input {"," type filter hook input priority -150; policy accept;",""," # Established traffic is already paid for; never re-inspect it."," ct state established,related accept"," iif lo accept",""," # Invalid packets are never legitimate and are cheap to drop early."," ct state invalid counter drop"),c.length>0)o.push(" ip saddr @allow4 accept");if(p.length>0)o.push(" ip6 saddr @allow6 accept");if(u.length>0)o.push(" ip saddr @block4 counter drop");if(o.push(" ip saddr @banned4 counter drop"," ip6 saddr @banned6 counter drop",""),o.push(" # Nonsense TCP flag combinations: scanners and stack fingerprinting."," tcp flags & (fin|syn) == (fin|syn) counter drop"," tcp flags & (syn|rst) == (syn|rst) counter drop"," tcp flags & (fin|rst) == (fin|rst) counter drop"," tcp flags & (fin|ack) == fin counter drop"," tcp flags & (syn|fin|ack|rst|psh|urg) == 0x0 counter drop",""," # Ping stays usable, ping floods do not.",` ip protocol icmp icmp type echo-request limit rate ${t.icmpPerSecond}/second burst ${t.burst} packets accept`," ip protocol icmp icmp type echo-request counter drop",""),n.length>0){let r=n.join(", ");if(o.push(" # Platform-wide SYN ceiling. Above it the kernel falls back to cookies.",` tcp dport { ${r} } ct state new limit rate ${t.synPerSecond}/second burst ${t.burst} packets accept`,""," # Per-source new-connection rate. This is what stops one host hammering.",` tcp dport { ${r} } ct state new meter conn_rate4 { ip saddr limit rate over ${t.newConnectionsPerSecond}/second burst ${t.burst} packets } add @banned4 { ip saddr } ${l}`,` tcp dport { ${r} } ct state new meter conn_rate6 { ip6 saddr limit rate over ${t.newConnectionsPerSecond}/second burst ${t.burst} packets } add @banned6 { ip6 saddr } ${l}`,""," # Concurrency ceiling per source: the slow-loris defence.",` tcp dport { ${r} } ct state new meter conn_count4 { ip saddr ct count over ${t.concurrentPerSource} } ${l}`,` tcp dport { ${r} } ct state new meter conn_count6 { ip6 saddr ct count over ${t.concurrentPerSource} } ${l}`,""),i.length>0)o.push(" # Origin protection: reject traffic that skipped the CDN and came"," # straight to the box, which is how an attacker bypasses the edge.",` tcp dport { ${r} } ip saddr != @cdn4 counter drop`,"")}return o.push(" }","}",""),o.join(`
|
|
4
|
-
`)}function
|
|
4
|
+
`)}function Ir(e={}){return`#!/usr/bin/env bash
|
|
5
5
|
# Managed by ts-cloud. Installs L3/L4 flood mitigation.
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
@@ -41,4 +41,4 @@ fi
|
|
|
41
41
|
systemctl enable nftables >/dev/null 2>&1 || true
|
|
42
42
|
echo "ts-cloud: L3/L4 mitigation active"
|
|
43
43
|
`}var b=["off","monitor","rate_limit","challenge","lockdown"];function dm(e,t=[]){let n=[],s=Math.max(1,e.baselineRequestsPerSecond),a=e.requestsPerSecond/s,l=0,i=(g,v)=>{n.push(v),l=Math.max(l,b.indexOf(g))},c=a>=3;if(c)i("monitor",`Traffic is ${a.toFixed(1)}x the baseline.`);let p=e.topSourceShare>=0.25,u=e.errorRate>=0.25,o=(e.suspiciousAgentShare??0)>=0.5,r=e.uniqueSources>0&&e.requestsPerSecond/e.uniqueSources>=50;if(c&&p)i("rate_limit",`One source accounts for ${(e.topSourceShare*100).toFixed(0)}% of traffic.`);if(c&&r)i("rate_limit","Request rate per unique source is far above what a browser produces.");if(c&&u)i("challenge",`Error rate is ${(e.errorRate*100).toFixed(0)}% under load.`);if(c&&o)i("challenge","Most requests carry no recognisable browser agent.");if(a>=20&&(p||u||o||r))i("lockdown",`Traffic is ${a.toFixed(0)}x the baseline with attack-shaped characteristics.`);if(!c&&e.topSourceShare>=0.6&&e.requestsPerSecond>s)i("rate_limit","A single source dominates traffic without an overall surge.");let d=b[l],m={off:1,monitor:1,rate_limit:0.5,challenge:0.25,lockdown:0.1}[d];return{level:d,reasons:n,rateLimitFactor:m,challengeEnabled:d==="challenge"||d==="lockdown",staticOnly:d==="lockdown",banCandidates:d==="off"||d==="monitor"?[]:f(t)}}function wo(e,t){return Math.max(1,Math.floor(e*t.rateLimitFactor))}
|
|
44
|
-
export{qd,Eo,Wd,Kd,Jd,
|
|
44
|
+
export{qd,Eo,Wd,Kd,Jd,Ir,dm,wo};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{H,
|
|
2
|
-
`)}function he(e){let t=["# Generated by ts-cloud. See /etc/mail/config.toml for the rest.",`SMTP_DB_PATH=${re(e)}`,`SMTP_DELIVERY_METHOD=${e.delivery==="ses"?"ses":"direct"}`];if(e.delivery==="ses")t.push(`SMTP_SES_REGION=${e.sesRegion}`);if(e.ports.submission)t.push(`SUBMISSION_PORT=${e.ports.submission}`);if(e.ports.submissions)t.push(`SMTPS_PORT=${e.ports.submissions}`);if(e.ports.imap)t.push("IMAP_ENABLED=1",`IMAP_PORT=${e.ports.imap}`);if(e.webmail.enabled)t.push("SMTP_ENABLE_WEBMAIL=true",`SMTP_WEBMAIL_PORT=${e.webmail.port}`,`SMTP_WEBMAIL_TLS=${e.webmail.tls}`,`SMTP_WEBMAIL_SECURE_COOKIES=${e.webmail.secureCookies}`,`SMTP_WEBMAIL_ATTACHMENT_MAX_FILE=${e.webmail.attachmentMaxFileBytes}`,`SMTP_WEBMAIL_ATTACHMENT_MAX_TOTAL=${e.webmail.attachmentMaxTotalBytes}`,`SMTP_WEBMAIL_ATTACHMENT_MAX_COUNT=${e.webmail.attachmentMaxCount}`,`SMTP_WEBMAIL_UNDO_SEND_SECONDS=${e.webmail.undoSendSeconds}`);if(e.tls.requireForAuth)t.push("SMTP_REQUIRE_TLS_FOR_AUTH=true");if(e.dkim.enabled&&e.domains.length>0){let[r,...n]=e.domains;if(t.push(`DKIM_DOMAIN=${r}`,`DKIM_SELECTOR=${e.dkim.selector}`,`DKIM_PRIVATE_KEY_PATH=${Y(e,r)}`),n.length>0){let o=n.map((s)=>`${s}:${e.dkim.selector}:${Y(e,s)}`);t.push(`DKIM_EXTRA_KEYS=${o.join(",")}`)}}return t.push(""),t.join(`
|
|
1
|
+
import{H,Br}from"./chunk-v5js5pz6.js";function J(e,t){return`/var/www/${e}-${t}`}var me=new Set(["laravel","php","statamic","wordpress"]);function Ni(e){return e.type!=null&&me.has(e.type)}function Js(e){let t=e.proxyTo;if(t==null)return[];return(Array.isArray(t)?t:[t]).map((n)=>String(n).trim()).filter((n)=>n.length>0)}function fe(e){return Js(e).length>0}function te(e){if(e.deploy)return e.deploy;if(Ni(e))return"server";if(e.start)return"server";return"bucket"}function w(e){if(e.redirect)return"redirect";if(fe(e))return"proxy";if(Ni(e))return"server-php";if(te(e)==="bucket")return"bucket";return e.start?"server-app":"server-static"}function Uo(e){return e.infrastructure?.compute!=null||Boolean(e.cloud?.attachTo?.trim())}function Xs(e,t={}){let r=[],n=[],o=e.sites||{},s=Uo(e),c=Br(e);if(c)r.push(c);let p=new Map;for(let[l,i]of Object.entries(o)){if(!i)continue;let f=te(i),C=w(i);if(C==="redirect"){if(!i.domain)r.push(`Site '${l}' is a redirect site but has no \`domain\` to redirect from.`);if(!(typeof i.redirect==="string"?i.redirect:i.redirect?.to))r.push(`Site '${l}' is a redirect site but has no redirect target (\`redirect\` / \`redirect.to\`).`);if(!s)r.push(`Site '${l}' is a redirect site but no \`infrastructure.compute\` is configured to host the gateway that serves the redirect.`);let a=[];if(i.start)a.push("start");if(i.root)a.push("root");if(i.proxyTo)a.push("proxyTo");if(a.length>0)n.push(`Site '${l}' is a redirect site but also sets ${a.join(", ")}. These are ignored.`);continue}if(C==="proxy"){if(!i.domain)r.push(`Site '${l}' is a proxy site but has no \`domain\` to route from.`);if(!s)r.push(`Site '${l}' is a proxy site but no \`infrastructure.compute\` is configured to host the gateway that forwards it.`);let u=[];if(i.start)u.push("start");if(i.root)u.push("root");if(typeof i.port==="number")u.push("port");if(i.build)u.push("build");if(i.preStart&&i.preStart.length>0)u.push("preStart");if(u.length>0)n.push(`Site '${l}' sets \`proxyTo\`, so ts-cloud ships and supervises nothing for it. ${u.join(", ")} ${u.length===1?"is":"are"} ignored — remove ${u.length===1?"it":"them"}, or drop \`proxyTo\` to let ts-cloud own the service.`);continue}if(f==="server"&&!i.start&&!i.root){r.push(`Site '${l}' sets deploy:'server' but declares neither \`start\` (dynamic app) nor \`root\` (static site to serve). Add one.`);continue}if(C==="server-php"){if(!s)r.push(`Site '${l}' is a PHP site (type:'${i.type}') but no \`infrastructure.compute\` is configured. Add a server (infrastructure.compute) with PHP provisioning.`);if(!i.repository?.url)r.push(`Site '${l}' is a PHP site (type:'${i.type}') but has no \`repository.url\` to clone. PHP sites deploy via git.`)}else if(C==="server-app"){if(!s)r.push(`Site '${l}' deploys to a server (deploy:'server'${i.deploy?"":" inferred from `start`"}) but no \`infrastructure.compute\` is configured. Set deploy:'bucket' or add a server (infrastructure.compute).`);if(typeof i.port==="number"){let u=t.occupiedPorts?.get(i.port);if(u)r.push(`Site '${l}' wants port ${i.port}, which project '${u}' already serves on this box. Attached projects share one port namespace. Give '${l}' a free port, or let the attach allocate one.`);let a=p.get(i.port);if(a)r.push(`Sites '${a}' and '${l}' both use port ${i.port}. Server apps sharing a box must use distinct ports.`);else p.set(i.port,l)}}else if(C==="server-static"){if(!i.root)r.push(`Site '${l}' is a server static site (deploy:'server', no \`start\`) but has no \`root\` directory to serve.`);if(!s)r.push(`Site '${l}' deploys to a server (deploy:'server') but no \`infrastructure.compute\` is configured. Set deploy:'bucket' or add a server (infrastructure.compute).`)}else{if(!i.root)r.push(`Site '${l}' deploys to a bucket but has no \`root\` directory to upload.`);let u=[];if(i.start)u.push("start");if(typeof i.port==="number")u.push("port");if(i.preStart&&i.preStart.length>0)u.push("preStart");if(u.length>0)n.push(`Site '${l}' deploys to a bucket but sets server-only field(s): ${u.join(", ")}. These are ignored. Set deploy:'server' to use them.`)}}return{errors:r,warnings:n}}function Qs(e){let t=w(e);return t!=="bucket"&&t!=="redirect"&&t!=="proxy"}function Wc(e){return w(e)==="bucket"}function Kc(e,t){if(H(e)==="serverless")return!0;let r=Object.entries(e.sites??{}).filter(([,o])=>o!=null),n=t?r.filter(([o])=>o===t):r;if(n.length===0)return!0;return!n.every(([,o])=>{let s=w(o);return s==="redirect"||s==="proxy"})}var L={php:"php.net",nginx:"nginx.org",composer:"getcomposer.org",mysql:"mysql.com",mariadb:"mariadb.com/server",postgres:"postgresql.org",vitess:"vitess.io",etcd:"etcd.io",redis:"redis.io",memcached:"memcached.org",meilisearch:"meilisearch.com",mail:"github.com/mail-os/mail",git:"git-scm.com",certbot:"certbot.eff.org",bun:"bun.sh",node:"nodejs.org",deno:"deno.land"};var D="/opt/pantry";function M(e){return`'${e.split("'").join("'\\''")}'`}function Et(e={}){let t=e.installDir??"/usr/local/bin",r=e.version?`export PANTRY_VERSION=${M(e.version)}`:'export PANTRY_VERSION="${PANTRY_VERSION:-latest}"';return["export DEBIAN_FRONTEND=noninteractive","export PANTRY_SERVICE_SCOPE=system",`export PANTRY_INSTALL_DIR=${t}`,r,"command -v curl >/dev/null 2>&1 || (apt-get update -y && apt-get install -y curl ca-certificates)","command -v unzip >/dev/null 2>&1 || (apt-get update -y && apt-get install -y unzip)",`OS=$(uname -s | tr '[:upper:]' '[:lower:]'); ARCH=$(uname -m); case "$ARCH" in x86_64|amd64) ARCH=x64 ;; arm64|aarch64) ARCH=arm64 ;; esac; ZIP="pantry-\${OS}-\${ARCH}.zip"; if [ "\${PANTRY_VERSION:-latest}" = latest ]; then REL='latest/download'; else REL="download/v\${PANTRY_VERSION}"; fi; TMP=$(mktemp -d); curl -fsSL -o "\${TMP}/\${ZIP}" "https://github.com/pantry-pm/pantry/releases/\${REL}/\${ZIP}"; mkdir -p ${t}; unzip -o "\${TMP}/\${ZIP}" -d ${t}; chmod +x ${t}/pantry; rm -rf "\${TMP}"`,`export PATH="${t}:$PATH"`,"mkdir -p /opt/pantry"]}function wt(){return'eval "$(cd /opt/pantry && pantry env 2>/dev/null)" || true'}function it(e){if(e.length===0)return[];return[`(cd /opt/pantry && pantry install ${[...new Set(e)].map(M).join(" ")})`]}function Fo(e){return[...new Set(e)].flatMap((t)=>[`(cd /opt/pantry && pantry start ${M(t)})`,`(cd /opt/pantry && pantry enable ${M(t)})`])}var m="/etc/mail",T="mail-server",q="mail",F=`${D}/pantry/.bin`;function h(e){return`'${String(e).split("'").join("'\\''")}'`}function R(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function ge(e){return[e.version?`${L.mail}@${e.version}`:L.mail]}function Y(e,t){return`${m}/dkim/${t}.${e.dkim.selector}.pem`}function re(e){return`${e.storagePath}/smtp.db`}function Te(e){let t=["# Generated by ts-cloud. Edits are overwritten on the next deploy —","# change `services.mail` in the cloud config instead.","","[server]",`host = ${R(e.bindAddress)}`,`port = ${e.ports.smtp}`,`hostname = ${R(e.hostname)}`];if(e.domains.length>0)t.push(`local_domains = ${R(e.domains.join(", "))}`);if(e.mode==="catcher")t.push("catch_all = true");if(t.push(`max_message_size = ${e.maxMessageSize}`,"","[tls]",`enabled = ${e.tls.enabled}`),e.tls.certPath)t.push(`cert_path = ${R(e.tls.certPath)}`);if(e.tls.keyPath)t.push(`key_path = ${R(e.tls.keyPath)}`);if(t.push("","[auth]",`enabled = ${e.mode==="server"}`,"","[antispam]",`dnsbl = ${e.spam.dnsbl}`,`dnsbl_reject = ${e.spam.dnsblReject}`,`greylist = ${e.spam.greylist}`,`spam_filter = ${e.spam.enabled}`,`junk_score = ${e.spam.junkScore}`,`reject_score = ${e.spam.rejectScore}`,"","[dkim]",`rotation_enabled = ${e.dkim.enabled&&e.dkim.rotate}`,`rotation_interval_days = ${e.dkim.rotateIntervalDays}`,"","[acme]",`enabled = ${e.tls.acme}`),e.tls.acmeEmail)t.push(`email = ${R(e.tls.acmeEmail)}`);if(t.push("","[webhook]",`enabled = ${!!e.webhookUrl}`),e.webhookUrl)t.push(`url = ${R(e.webhookUrl)}`);return t.push(""),t.join(`
|
|
2
|
+
`)}function he(e){let t=["# Generated by ts-cloud. See /etc/mail/config.toml for the rest.",`SMTP_DB_PATH=${re(e)}`,`SMTP_DNSBL_REJECT=${e.spam.dnsblReject}`,`SMTP_DELIVERY_METHOD=${e.delivery==="ses"?"ses":"direct"}`];if(e.delivery==="ses")t.push(`SMTP_SES_REGION=${e.sesRegion}`);if(e.ports.submission)t.push(`SUBMISSION_PORT=${e.ports.submission}`);if(e.ports.submissions)t.push(`SMTPS_PORT=${e.ports.submissions}`);if(e.ports.imap)t.push("IMAP_ENABLED=1",`IMAP_PORT=${e.ports.imap}`);if(e.webmail.enabled)t.push("SMTP_ENABLE_WEBMAIL=true",`SMTP_WEBMAIL_PORT=${e.webmail.port}`,`SMTP_WEBMAIL_TLS=${e.webmail.tls}`,`SMTP_WEBMAIL_SECURE_COOKIES=${e.webmail.secureCookies}`,`SMTP_WEBMAIL_ATTACHMENT_MAX_FILE=${e.webmail.attachmentMaxFileBytes}`,`SMTP_WEBMAIL_ATTACHMENT_MAX_TOTAL=${e.webmail.attachmentMaxTotalBytes}`,`SMTP_WEBMAIL_ATTACHMENT_MAX_COUNT=${e.webmail.attachmentMaxCount}`,`SMTP_WEBMAIL_UNDO_SEND_SECONDS=${e.webmail.undoSendSeconds}`);if(e.tls.requireForAuth)t.push("SMTP_REQUIRE_TLS_FOR_AUTH=true");if(e.dkim.enabled&&e.domains.length>0){let[r,...n]=e.domains;if(t.push(`DKIM_DOMAIN=${r}`,`DKIM_SELECTOR=${e.dkim.selector}`,`DKIM_PRIVATE_KEY_PATH=${Y(e,r)}`),n.length>0){let o=n.map((s)=>`${s}:${e.dkim.selector}:${Y(e,s)}`);t.push(`DKIM_EXTRA_KEYS=${o.join(",")}`)}}return t.push(""),t.join(`
|
|
3
3
|
`)}function Ee(e){let t=[e.ports.smtp,e.ports.submission,e.ports.submissions,e.ports.imap,e.ports.imaps].some((r)=>typeof r==="number"&&r<1024);return["[Unit]","Description=Mail server (SMTP/IMAP + webmail)","After=network-online.target","Wants=network-online.target","","[Service]","Type=simple",`User=${T}`,`Group=${T}`,`WorkingDirectory=${e.storagePath}`,`EnvironmentFile=${m}/mail.env`,`Environment="PATH=${F}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"`,`ExecStart=${F}/mail serve --config ${m}/config.toml`,"Restart=always","RestartSec=5","LimitNOFILE=65536",...t?["AmbientCapabilities=CAP_NET_BIND_SERVICE","CapabilityBoundingSet=CAP_NET_BIND_SERVICE"]:[],"NoNewPrivileges=true","PrivateTmp=true","ProtectSystem=strict","ProtectHome=true","ProtectKernelTunables=true","ProtectKernelModules=true","ProtectControlGroups=true",`ReadWritePaths=${e.storagePath} ${m}`,"","[Install]","WantedBy=multi-user.target",""].join(`
|
|
4
|
-
`)}function ye(e){if(!e.dkim.enabled||e.domains.length===0)return[];let t=[`mkdir -p ${m}/dkim`];for(let r of e.domains){let n=Y(e,r);t.push(`if [ ! -f ${h(n)} ]; then openssl genrsa -out ${h(n)} 2048; fi`,`chmod 0600 ${h(n)}`,`echo "DKIM ${e.dkim.selector}._domainkey.${r} IN TXT v=DKIM1; k=rsa; p=$(openssl rsa -in ${h(n)} -pubout -outform PEM 2>/dev/null | grep -v '^-----' | tr -d '\\n')"`)}return t.push(`chown -R ${T}:${T} ${m}/dkim`),t}function ve(e){if(e.accounts.length===0)return[];let t=(r)=>`runuser -u ${T} -- env SMTP_DB_PATH="$TS_CLOUD_MAIL_DB" ${F}/mail user:local ${r}`;return e.accounts.flatMap((r)=>[t(`create ${h(r.address)} ${h(r.password)} ${h(r.address)}`),...r.passwordPolicy==="managed"?[t(`change-password ${h(r.address)} ${h(r.password)}`)]:[]])}function ne(e){if(!e.enabled)return[];return[...it(ge(e)),`id -u ${T} >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin ${T}`,`mkdir -p ${e.storagePath} ${m}`,`chown -R ${T}:${T} ${e.storagePath}`,`TS_CLOUD_MAIL_DB="$(grep -sE '^SMTP_DB_PATH=' ${m}/mail.env | head -1 | cut -d= -f2- || true)"`,`[ -n "$TS_CLOUD_MAIL_DB" ] || TS_CLOUD_MAIL_DB=${h(re(e))}`,`cat > ${m}/config.toml <<'TS_CLOUD_MAIL_CONF_EOF'`,Te(e),"TS_CLOUD_MAIL_CONF_EOF",`cat > ${m}/mail.env <<'TS_CLOUD_MAIL_ENV_EOF'`,he(e),"TS_CLOUD_MAIL_ENV_EOF",`sed -i "s|^SMTP_DB_PATH=.*|SMTP_DB_PATH=$TS_CLOUD_MAIL_DB|" ${m}/mail.env`,`chmod 0640 ${m}/mail.env`,`chown root:${T} ${m}/mail.env`,...ye(e),`cat > /etc/systemd/system/${q}.service <<'TS_CLOUD_MAIL_UNIT_EOF'`,Ee(e),"TS_CLOUD_MAIL_UNIT_EOF","systemctl daemon-reload",`systemctl enable ${q}`,`systemctl restart ${q}`,...ve(e)]}var g=`${D}/pantry/.bin`,W=15306,K=15991,N=15999,se=16101,B=2379,E="/var/lib/vitess",X=100;function
|
|
4
|
+
`)}function ye(e){if(!e.dkim.enabled||e.domains.length===0)return[];let t=[`mkdir -p ${m}/dkim`];for(let r of e.domains){let n=Y(e,r);t.push(`if [ ! -f ${h(n)} ]; then openssl genrsa -out ${h(n)} 2048; fi`,`chmod 0600 ${h(n)}`,`echo "DKIM ${e.dkim.selector}._domainkey.${r} IN TXT v=DKIM1; k=rsa; p=$(openssl rsa -in ${h(n)} -pubout -outform PEM 2>/dev/null | grep -v '^-----' | tr -d '\\n')"`)}return t.push(`chown -R ${T}:${T} ${m}/dkim`),t}function ve(e){if(e.accounts.length===0)return[];let t=(r)=>`runuser -u ${T} -- env SMTP_DB_PATH="$TS_CLOUD_MAIL_DB" ${F}/mail user:local ${r}`;return e.accounts.flatMap((r)=>[t(`create ${h(r.address)} ${h(r.password)} ${h(r.address)}`),...r.passwordPolicy==="managed"?[t(`change-password ${h(r.address)} ${h(r.password)}`)]:[]])}function ne(e){if(!e.enabled)return[];return[...it(ge(e)),`id -u ${T} >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin ${T}`,`mkdir -p ${e.storagePath} ${m}`,`chown -R ${T}:${T} ${e.storagePath}`,`TS_CLOUD_MAIL_DB="$(grep -sE '^SMTP_DB_PATH=' ${m}/mail.env | head -1 | cut -d= -f2- || true)"`,`[ -n "$TS_CLOUD_MAIL_DB" ] || TS_CLOUD_MAIL_DB=${h(re(e))}`,`cat > ${m}/config.toml <<'TS_CLOUD_MAIL_CONF_EOF'`,Te(e),"TS_CLOUD_MAIL_CONF_EOF",`cat > ${m}/mail.env <<'TS_CLOUD_MAIL_ENV_EOF'`,he(e),"TS_CLOUD_MAIL_ENV_EOF",`sed -i "s|^SMTP_DB_PATH=.*|SMTP_DB_PATH=$TS_CLOUD_MAIL_DB|" ${m}/mail.env`,`chmod 0640 ${m}/mail.env`,`chown root:${T} ${m}/mail.env`,...ye(e),`cat > /etc/systemd/system/${q}.service <<'TS_CLOUD_MAIL_UNIT_EOF'`,Ee(e),"TS_CLOUD_MAIL_UNIT_EOF","systemctl daemon-reload",`systemctl enable ${q}`,`systemctl restart ${q}`,...ve(e)]}var g=`${D}/pantry/.bin`,W=15306,K=15991,N=15999,se=16101,B=2379,E="/var/lib/vitess",X=100;function xi(e){return e===!0||typeof e==="object"&&e!==null}function Ce(e){return typeof e==="object"&&e!==null?e:{}}function _(e){return`'${String(e).split("'").join("'\\''")}'`}function Re(e){let r=[e.version?`vitess.io@${e.version}`:"vitess.io"];if(e.mode!=="combo"&&!e.etcdEndpoint)r.push("etcd.io");return r.push("mysql.com@8.0.43"),r}var S="vitess",Pe=`${g}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,ce="/usr/local/lib/vitess",z=new Map;function j(e){return`${ce}/${e}.sh`}function b(e,t){return z.set(e,be(t)),`/bin/sh ${j(e)}`}function oe(){let e=[`mkdir -p ${ce}`];for(let[t,r]of z)e.push(`cat > ${j(t)} <<'TS_CLOUD_VITESS_LAUNCHER_EOF'`,r,"TS_CLOUD_VITESS_LAUNCHER_EOF",`chmod 0755 ${j(t)}`);return e}function be(e){return["#!/bin/sh","set -e",`cd ${D}`,`PANTRY_ENV="$(pantry env 2>/dev/null | grep -E '^(export [A-Za-z_]|[A-Za-z_][A-Za-z0-9_]*=)' || true)"`,'if [ -n "$PANTRY_ENV" ]; then eval "$PANTRY_ENV"; fi',`VT_MYSQL_ROOT="$(dirname "$(dirname "$(readlink -f ${g}/mysqld 2>/dev/null)")")"`,`VTROOT="$(dirname "$(dirname "$(readlink -f ${g}/mysqlctld 2>/dev/null)")")"`,"export VT_MYSQL_ROOT VTROOT",'LD_LIBRARY_PATH="$VT_MYSQL_ROOT/lib:$VTROOT/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"',"export LD_LIBRARY_PATH",`exec ${e.join(" ")}`].join(`
|
|
5
5
|
`)}function A(e){let t=["[Unit]",`Description=${e.description}`,`After=network.target${e.after?.length?` ${e.after.join(" ")}`:""}`];if(e.requires?.length)t.push(`Requires=${e.requires.join(" ")}`);return t.push("","[Service]","Type=simple",`User=${S}`,`Group=${S}`,`Environment="PATH=${Pe}"`,`Environment="VTDATAROOT=${E}"`,...Object.entries(e.environment??{}).map(([r,n])=>`Environment="${r}=${n}"`),...(e.execStartPre??[]).map((r)=>`ExecStartPre=${r}`),`ExecStart=${e.execStart}`,"Restart=always","RestartSec=5","LimitNOFILE=65535","","[Install]","WantedBy=multi-user.target"),t.join(`
|
|
6
|
-
`)}function ie(e,t){return[`cat > /etc/systemd/system/${e}.service <<'TS_CLOUD_VITESS_UNIT_EOF'`,t,"TS_CLOUD_VITESS_UNIT_EOF"]}function De(e){let t=e.cell??"zone1",r=e.vtgatePort??W,o=`${((e.keyspaces?.length)?e.keyspaces:[{name:"app"}]).map((s)=>{let c=(s.sharded?["-80","80-"]:["0"]).map((p)=>`shards:{name:"${p}"}`).join(" ");return`keyspaces:{name:"${s.name}" ${c}}`}).join(" ")} cells:"${t}"`;return A({description:"Vitess (vtcombo, single-process development stack)",execStart:b("vtcombo",[`${g}/vtcombo`,`--cell ${t}`,`--proto-topo ${_(o)}`,`--mysql-server-port ${r}`,"--mysql-server-bind-address 127.0.0.1","--mysql-auth-server-impl none","--start-mysql",`--port ${K}`,`--grpc-port ${N}`])})}function Ae(){return A({description:"etcd (Vitess topology store)",execStart:b("etcd",[`${g}/etcd`,`--data-dir ${E}/etcd`,`--listen-client-urls http://127.0.0.1:${B}`,`--advertise-client-urls http://127.0.0.1:${B}`]),execStartPre:[`+/bin/mkdir -p ${E}/etcd`,`+/bin/chown ${S}:${S} ${E}/etcd`]})}function Q(e){return["--topo-implementation etcd2",`--topo-global-server-address ${e.etcdEndpoint??`http://127.0.0.1:${B}`}`,"--topo-global-root /vitess/global"]}function Oe(e){let t=!e.etcdEndpoint;return A({description:"Vitess vtctld (control plane)",after:t?["vitess-etcd.service"]:[],requires:t?["vitess-etcd.service"]:[],execStart:b("vtctld",[`${g}/vtctld`,...Q(e),`--cell ${e.cell??"zone1"}`,"--service-map grpc-vtctl,grpc-vtctld",`--grpc-port ${N}`,`--port ${N+1}`])})}function Le(e,t,r){let n=e.cell??"zone1";return A({description:`Vitess vttablet (${t}/${r})`,after:["vitess-vtctld.service","vitess-mysqlctld.service"],requires:["vitess-mysqlctld.service"],execStart:b("vttablet",[`${g}/vttablet`,...Q(e),`--tablet-path ${n}-${String(X).padStart(10,"0")}`,`--init-keyspace ${t}`,`--init-shard ${r}`,"--init-tablet-type replica",`--service-map ${_("grpc-queryservice,grpc-tabletmanager,grpc-updatestream")}`,`--port ${se}`,`--grpc-port ${se+1}`,`--db-port ${e.mysqlPort??3306}`,`--mycnf-mysql-port ${e.mysqlPort??3306}`])})}function Ue(e){return A({description:"Vitess mysqlctld (managed mysqld)",execStart:b("mysqlctld",[`${g}/mysqlctld`,`--tablet-uid ${X}`,`--mysql-port ${e.mysqlPort??3306}`,'--init-db-sql-file "$VTROOT/config/init_db.sql"',"--wait-time 2m"]),execStartPre:[`+/bin/mkdir -p ${E}`,`+/bin/chown ${S}:${S} ${E}`]})}var le="/etc/vitess/auth.json",U="/var/lib/vitess/vtgate-auth.sha256";function xe(e){let t=e.username??"vitess",r=e.password??"";return["mkdir -p /etc/vitess",'VTESS_AUTH_TMP="$(mktemp)"',`cat > "$VTESS_AUTH_TMP" <<'TS_CLOUD_VITESS_AUTH_EOF'`,JSON.stringify({[t]:[{Password:r,UserData:t}]}),"TS_CLOUD_VITESS_AUTH_EOF",`VTESS_VTGATE_AUTH_SHA="$(sha256sum "$VTESS_AUTH_TMP" | awk '{print $1}')"`,"VTESS_VTGATE_AUTH_CHANGED=1",`if [ -f ${U} ] && [ "$(cat ${U})" = "$VTESS_VTGATE_AUTH_SHA" ]; then VTESS_VTGATE_AUTH_CHANGED=0; fi`,`install -o ${S} -g ${S} -m 0600 "$VTESS_AUTH_TMP" ${le}`,'rm -f "$VTESS_AUTH_TMP"']}function Ie(e){let t=e.cell??"zone1";return A({description:"Vitess vtgate (query router)",after:["vitess-vtctld.service"],execStart:b("vtgate",[`${g}/vtgate`,...Q(e),`--cell ${t}`,`--cells-to-watch ${t}`,"--tablet-types-to-wait PRIMARY,REPLICA",`--service-map ${_("grpc-vtgateservice")}`,`--mysql-server-port ${e.vtgatePort??W}`,`--mysql-server-bind-address ${e.bindAddress??"127.0.0.1"}`,"--mysql-auth-server-impl static",`--mysql-auth-server-static-file ${le}`,`--port ${K}`,`--grpc-port ${K+1}`])})}function ke(e){let t=e.cell??"zone1",r=e.etcdEndpoint??`http://127.0.0.1:${B}`,n=`${g}/vtctldclient --server 127.0.0.1:${N}`,o=[`for i in $(seq 1 30); do ${n} GetCellInfoNames >/dev/null 2>&1 && break; sleep 2; done`,`if ! ${n} GetCellInfoNames 2>/dev/null | grep -qx ${_(t)}; then`,` ${n} AddCellInfo --root ${_(`/vitess/${t}`)} --server-address ${_(r)} ${_(t)}`,"fi"];for(let s of e.keyspaces??[]){let c=s.sharded?" --sharded":"";o.push(`if ! ${n} GetKeyspace ${_(s.name)} >/dev/null 2>&1; then`,` ${n} CreateKeyspace${c} ${_(s.name)}`,"fi");let p=`${t}-${String(X).padStart(10,"0")}`;for(let l of s.sharded?["-80","80-"]:["0"]){let i=`${s.name}/${l}`;o.push("for i in $(seq 1 90); do",` if ${n} GetShard ${_(i)} 2>/dev/null | grep -q '"is_primary_serving": *true'; then break; fi`,` ${n} PlannedReparentShard ${_(i)} --new-primary ${_(p)} >/dev/null 2>&1 && break`,` ${n} InitShardPrimary --force ${_(i)} ${_(p)} >/dev/null 2>&1 && break`," sleep 2","done",`if ! ${n} GetShard ${_(i)} 2>/dev/null | grep -q '"is_primary_serving": *true'; then`,` echo "no primary could be elected for ${i}" >&2; exit 1`,"fi")}o.push(`${n} RebuildKeyspaceGraph ${_(s.name)} >/dev/null`)}return o}function ae(e){let t=e.vtgatePort??W;return["for i in $(seq 1 60); do",` if (cd ${D} && eval "$(pantry env 2>/dev/null)"; MYSQL_PWD=${_(e.password??"")} ${g}/mysql -h 127.0.0.1 -P ${t} -u ${_(e.username??"vitess")} --connect-timeout=2 -e 'SHOW KEYSPACES') >/dev/null 2>&1; then`,` echo "vtgate is serving on ${t}"; exit 0`," fi"," sleep 2","done",`echo "vtgate did not become ready on port ${t}" >&2`,"exit 1"]}function Bo(e){if(!Ni(e))return[];let t=Ce(e),r=t.mode==="combo";z.clear();let n=['if [ "$(uname -m)" != "x86_64" ]; then',' echo "vitess: Vitess publishes only x86_64 release tarballs; this box is $(uname -m). Drop managedServices.vitess or use an x86_64 host." >&2'," exit 1","fi",...it(Re(t)),`VT_MYSQL_LIB="$(dirname "$(dirname "$(readlink -f ${g}/mysqld)")")/lib"`,'if [ -d "$VT_MYSQL_LIB" ]; then',` printf '%s\\n' "$VT_MYSQL_LIB" > /etc/ld.so.conf.d/vitess-mysql.conf`," ldconfig","else",' echo "mysqld library directory not found under $VT_MYSQL_LIB" >&2; exit 1',"fi",`id -u ${S} >/dev/null 2>&1 || useradd --system --home-dir ${E} --shell /usr/sbin/nologin ${S}`,`mkdir -p ${E}`,`chown -R ${S}:${S} ${E}`];if(r)return n.push(...ie("vitess-vtcombo",De(t)),...oe(),"systemctl daemon-reload","systemctl enable --now vitess-vtcombo.service",...ae(t)),n;n.push(...xe(t));let o=[];if(!t.etcdEndpoint)o.push(["vitess-etcd",Ae()]);o.push(["vitess-vtctld",Oe(t)],["vitess-mysqlctld",Ue(t)],["vitess-vtgate",Ie(t)]);for(let s of t.keyspaces??[])for(let c of s.sharded?["-80","80-"]:["0"])o.push([`vitess-vttablet-${s.name}-${c.replace(/-/g,"x")}`,Le(t,s.name,c)]);for(let[s,c]of o)n.push(...ie(s,c));n.push(...oe()),n.push("systemctl daemon-reload");for(let[s]of o)n.push(`systemctl enable --now ${s}.service`);return n.push(`if [ "$VTESS_VTGATE_AUTH_CHANGED" = 1 ]; then systemctl restart vitess-vtgate.service; printf '%s\\n' "$VTESS_VTGATE_AUTH_SHA" > ${U}; chown ${S}:${S} ${U}; chmod 0600 ${U}; fi`,...ke(t),...ae(t)),n}var Me=new Set(["singlestore","vitess"]);function xi(e){if(e?.engine&&Me.has(e.engine))return!1;return!e?.host||e.host==="127.0.0.1"||e.host==="localhost"}function xr(e,t="psql"){let r=e?.port??5432;if(xi(e))return`${t} -p ${r} -U postgres`;let n=e?.username||"postgres";return`${e?.password?`PGPASSWORD='${e.password.replace(/'/g,"'\\''")}' `:""}${t} -h ${e.host} -p ${r} -U ${n} -w`}function y(e){return e===!0||typeof e==="object"&&e!=null}function Ne(e){let t=[],r=[];if(y(e.mysql))t.push(typeof e.mysql==="object"&&e.mysql.version?`mysql.com@${e.mysql.version}`:"mysql.com@8.0.43"),r.push("mysql");else if(y(e.mariadb))t.push(L.mariadb),r.push("mariadb");if(y(e.postgres))t.push("postgresql.org"),r.push("postgres");if(y(e.redis))t.push("redis.io"),r.push("redis");if(y(e.memcached))t.push("memcached.org"),r.push("memcached");if(y(e.meilisearch))t.push("meilisearch.com"),r.push("meilisearch");return{packages:t,services:r}}function jo(e={},t={}){let r=Ne(e),n=Bo(e.vitess),o=t.mail?ne(t.mail):[];if(r.packages.length===0)return[...n,...o];return[...it(r.packages),...Fo(r.services),...n,...o]}function At(e,t={}){if(!e?.name)return[];if(!xi(e))return[];let r=e.name,n=e.username||r,o=e.password||"",s=y(t.postgres)||e.engine==="postgres",c=y(t.mariadb)||e.engine==="mariadb",p=y(t.mysql)||e.engine==="mysql";if(s&&!p&&!c){let a=(d)=>`"${d.replace(/"/g,'""')}"`,P=(d)=>`'${d.replace(/'/g,"''")}'`,O=(d,k)=>["DO $$ BEGIN",` IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = ${P(d)}) THEN`,` CREATE ROLE ${a(d)} LOGIN PASSWORD ${P(k)};`," ELSE",` ALTER ROLE ${a(d)} LOGIN PASSWORD ${P(k)};`," END IF;","END $$;"],x=(d)=>{let k=d.databases&&d.databases.length>0?d.databases:[r],V=[];for(let G of k)if(d.access==="readonly")V.push(`GRANT CONNECT ON DATABASE ${a(G)} TO ${a(d.username)};`,`\\connect ${a(G)}`,`GRANT USAGE ON SCHEMA public TO ${a(d.username)};`,`GRANT SELECT ON ALL TABLES IN SCHEMA public TO ${a(d.username)};`,`ALTER DEFAULT PRIVILEGES FOR ROLE ${a(n)} IN SCHEMA public GRANT SELECT ON TABLES TO ${a(d.username)};`,"\\connect postgres");else V.push(`GRANT ALL PRIVILEGES ON DATABASE ${a(G)} TO ${a(d.username)};`);return V},I=e.users||[],Se=e.port??5432;return[wt(),`for i in $(seq 1 30); do pg_isready -p ${Se} -q && break; sleep 2; done`,`${xr(e)} <<'TS_CLOUD_PG_EOF'`,...O(n,o),`SELECT 'CREATE DATABASE ${a(r)} OWNER ${a(n)}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = ${P(r)})\\gexec`,...I.flatMap((d)=>[...O(d.username,d.password),...x(d)]),"TS_CLOUD_PG_EOF",...Be(e)]}let l=c?"/var/lib/pantry/mariadb/mariadbd.sock":"/var/lib/pantry/mysql/mysqld.sock",i=(a)=>a.replace(/`/g,"``"),f=(a)=>a.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),C=(a)=>{let P=a.databases&&a.databases.length>0?a.databases:[r],O=a.access==="readonly"?"SELECT":"ALL PRIVILEGES",x=[`CREATE USER IF NOT EXISTS '${f(a.username)}'@'%' IDENTIFIED BY '${f(a.password)}';`,`CREATE USER IF NOT EXISTS '${f(a.username)}'@'localhost' IDENTIFIED BY '${f(a.password)}';`,`ALTER USER '${f(a.username)}'@'%' IDENTIFIED BY '${f(a.password)}';`,`ALTER USER '${f(a.username)}'@'localhost' IDENTIFIED BY '${f(a.password)}';`];for(let I of P)x.push(`GRANT ${O} ON \`${i(I)}\`.* TO '${f(a.username)}'@'%';`,`GRANT ${O} ON \`${i(I)}\`.* TO '${f(a.username)}'@'localhost';`);return x},u=e.users||[];return[wt(),`for i in $(seq 1 30); do mysqladmin --socket=${l} -u root ping 2>/dev/null | grep -q alive && break; sleep 2; done`,`mysql --socket=${l} -u root <<'TS_CLOUD_SQL_EOF'`,`CREATE DATABASE IF NOT EXISTS \`${i(r)}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`,...C({username:n,password:o}),...u.flatMap(C),"FLUSH PRIVILEGES;","TS_CLOUD_SQL_EOF"]}function Be(e){return[`${xr(e)} -tA <<'TS_CLOUD_PG_CAP_EOF' || true`,"\\set QUIET on","SELECT CASE WHEN used::float / NULLIF(cap, 0) >= 0.8"," THEN '[ts-cloud] postgres is at ' || used || '/' || cap || ' connections on this server.'"," || ' Raise max_connections (ALTER SYSTEM SET max_connections = ...; then restart) or'"," || ' set idle_session_timeout so abandoned pools are reclaimed.'"," ELSE NULL END","FROM (SELECT (SELECT count(*) FROM pg_stat_activity) AS used,"," (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS cap) c","WHERE CASE WHEN used::float / NULLIF(cap, 0) >= 0.8 THEN true ELSE false END;","SELECT '[ts-cloud] ' || coalesce(datname, '(background)') || ': ' || count(*) || ' connection(s), oldest idle ' ||"," coalesce(round(extract(epoch from max(now() - state_change)) / 60)::text || 'm', 'n/a')","FROM pg_stat_activity","WHERE (SELECT count(*)::float / NULLIF((SELECT setting::int FROM pg_settings WHERE name = 'max_connections'), 0) FROM pg_stat_activity) >= 0.8","GROUP BY datname ORDER BY count(*) DESC;","TS_CLOUD_PG_CAP_EOF"]}function Jc(e){if(!e?.name)return{};let t=e.engine==="singlestore",r=e.engine==="vitess",n=e.engine==="postgres"?"pgsql":t?"singlestore":r?"vitess":"mysql",o=e.port??(e.engine==="postgres"?5432:r?15306:3306),s={DB_CONNECTION:n,DB_HOST:e.host||"127.0.0.1",DB_PORT:String(o),DB_DATABASE:e.name};if(e.username)s.DB_USERNAME=e.username;if(e.password)s.DB_PASSWORD=e.password;if((t||r)&&e.ssl!==!1)s.DB_SSL="true";return s}var Z="/var/backups/ts-cloud",we="/etc/ts-cloud/backups.config.ts",pe="/etc/cron.d/ts-cloud-backups",hn="/usr/local/bin/ts-cloud-backup.sh";function Ve(e){if(!e.name)return null;let t=e.host||"127.0.0.1",r=e.engine==="postgres",n=r?"postgresql":"mysql",o=e.port??(r?5432:3306),s=(c)=>c.replace(/\\/g,"\\\\").replace(/'/g,"\\'");return[" {",` type: '${n}',`,` name: '${s(e.name)}',`," connection: {",` hostname: '${s(t)}',`,` port: ${o},`,` database: '${s(e.name)}',`,` username: '${s(e.username||e.name)}',`,` password: '${s(e.password||"")}',`," ssl: false,"," },"," includeSchema: true,"," includeData: true,"," },"].join(`
|
|
6
|
+
`)}function ie(e,t){return[`cat > /etc/systemd/system/${e}.service <<'TS_CLOUD_VITESS_UNIT_EOF'`,t,"TS_CLOUD_VITESS_UNIT_EOF"]}function De(e){let t=e.cell??"zone1",r=e.vtgatePort??W,o=`${((e.keyspaces?.length)?e.keyspaces:[{name:"app"}]).map((s)=>{let c=(s.sharded?["-80","80-"]:["0"]).map((p)=>`shards:{name:"${p}"}`).join(" ");return`keyspaces:{name:"${s.name}" ${c}}`}).join(" ")} cells:"${t}"`;return A({description:"Vitess (vtcombo, single-process development stack)",execStart:b("vtcombo",[`${g}/vtcombo`,`--cell ${t}`,`--proto-topo ${_(o)}`,`--mysql-server-port ${r}`,"--mysql-server-bind-address 127.0.0.1","--mysql-auth-server-impl none","--start-mysql",`--port ${K}`,`--grpc-port ${N}`])})}function Ae(){return A({description:"etcd (Vitess topology store)",execStart:b("etcd",[`${g}/etcd`,`--data-dir ${E}/etcd`,`--listen-client-urls http://127.0.0.1:${B}`,`--advertise-client-urls http://127.0.0.1:${B}`]),execStartPre:[`+/bin/mkdir -p ${E}/etcd`,`+/bin/chown ${S}:${S} ${E}/etcd`]})}function Q(e){return["--topo-implementation etcd2",`--topo-global-server-address ${e.etcdEndpoint??`http://127.0.0.1:${B}`}`,"--topo-global-root /vitess/global"]}function Oe(e){let t=!e.etcdEndpoint;return A({description:"Vitess vtctld (control plane)",after:t?["vitess-etcd.service"]:[],requires:t?["vitess-etcd.service"]:[],execStart:b("vtctld",[`${g}/vtctld`,...Q(e),`--cell ${e.cell??"zone1"}`,"--service-map grpc-vtctl,grpc-vtctld",`--grpc-port ${N}`,`--port ${N+1}`])})}function Le(e,t,r){let n=e.cell??"zone1";return A({description:`Vitess vttablet (${t}/${r})`,after:["vitess-vtctld.service","vitess-mysqlctld.service"],requires:["vitess-mysqlctld.service"],execStart:b("vttablet",[`${g}/vttablet`,...Q(e),`--tablet-path ${n}-${String(X).padStart(10,"0")}`,`--init-keyspace ${t}`,`--init-shard ${r}`,"--init-tablet-type replica",`--service-map ${_("grpc-queryservice,grpc-tabletmanager,grpc-updatestream")}`,`--port ${se}`,`--grpc-port ${se+1}`,`--db-port ${e.mysqlPort??3306}`,`--mycnf-mysql-port ${e.mysqlPort??3306}`])})}function Ue(e){return A({description:"Vitess mysqlctld (managed mysqld)",execStart:b("mysqlctld",[`${g}/mysqlctld`,`--tablet-uid ${X}`,`--mysql-port ${e.mysqlPort??3306}`,'--init-db-sql-file "$VTROOT/config/init_db.sql"',"--wait-time 2m"]),execStartPre:[`+/bin/mkdir -p ${E}`,`+/bin/chown ${S}:${S} ${E}`]})}var le="/etc/vitess/auth.json",U="/var/lib/vitess/vtgate-auth.sha256";function xe(e){let t=e.username??"vitess",r=e.password??"";return["mkdir -p /etc/vitess",'VTESS_AUTH_TMP="$(mktemp)"',`cat > "$VTESS_AUTH_TMP" <<'TS_CLOUD_VITESS_AUTH_EOF'`,JSON.stringify({[t]:[{Password:r,UserData:t}]}),"TS_CLOUD_VITESS_AUTH_EOF",`VTESS_VTGATE_AUTH_SHA="$(sha256sum "$VTESS_AUTH_TMP" | awk '{print $1}')"`,"VTESS_VTGATE_AUTH_CHANGED=1",`if [ -f ${U} ] && [ "$(cat ${U})" = "$VTESS_VTGATE_AUTH_SHA" ]; then VTESS_VTGATE_AUTH_CHANGED=0; fi`,`install -o ${S} -g ${S} -m 0600 "$VTESS_AUTH_TMP" ${le}`,'rm -f "$VTESS_AUTH_TMP"']}function Ie(e){let t=e.cell??"zone1";return A({description:"Vitess vtgate (query router)",after:["vitess-vtctld.service"],execStart:b("vtgate",[`${g}/vtgate`,...Q(e),`--cell ${t}`,`--cells-to-watch ${t}`,"--tablet-types-to-wait PRIMARY,REPLICA",`--service-map ${_("grpc-vtgateservice")}`,`--mysql-server-port ${e.vtgatePort??W}`,`--mysql-server-bind-address ${e.bindAddress??"127.0.0.1"}`,"--mysql-auth-server-impl static",`--mysql-auth-server-static-file ${le}`,`--port ${K}`,`--grpc-port ${K+1}`])})}function ke(e){let t=e.cell??"zone1",r=e.etcdEndpoint??`http://127.0.0.1:${B}`,n=`${g}/vtctldclient --server 127.0.0.1:${N}`,o=[`for i in $(seq 1 30); do ${n} GetCellInfoNames >/dev/null 2>&1 && break; sleep 2; done`,`if ! ${n} GetCellInfoNames 2>/dev/null | grep -qx ${_(t)}; then`,` ${n} AddCellInfo --root ${_(`/vitess/${t}`)} --server-address ${_(r)} ${_(t)}`,"fi"];for(let s of e.keyspaces??[]){let c=s.sharded?" --sharded":"";o.push(`if ! ${n} GetKeyspace ${_(s.name)} >/dev/null 2>&1; then`,` ${n} CreateKeyspace${c} ${_(s.name)}`,"fi");let p=`${t}-${String(X).padStart(10,"0")}`;for(let l of s.sharded?["-80","80-"]:["0"]){let i=`${s.name}/${l}`;o.push("for i in $(seq 1 90); do",` if ${n} GetShard ${_(i)} 2>/dev/null | grep -q '"is_primary_serving": *true'; then break; fi`,` ${n} PlannedReparentShard ${_(i)} --new-primary ${_(p)} >/dev/null 2>&1 && break`,` ${n} InitShardPrimary --force ${_(i)} ${_(p)} >/dev/null 2>&1 && break`," sleep 2","done",`if ! ${n} GetShard ${_(i)} 2>/dev/null | grep -q '"is_primary_serving": *true'; then`,` echo "no primary could be elected for ${i}" >&2; exit 1`,"fi")}o.push(`${n} RebuildKeyspaceGraph ${_(s.name)} >/dev/null`)}return o}function ae(e){let t=e.vtgatePort??W;return["for i in $(seq 1 60); do",` if (cd ${D} && eval "$(pantry env 2>/dev/null)"; MYSQL_PWD=${_(e.password??"")} ${g}/mysql -h 127.0.0.1 -P ${t} -u ${_(e.username??"vitess")} --connect-timeout=2 -e 'SHOW KEYSPACES') >/dev/null 2>&1; then`,` echo "vtgate is serving on ${t}"; exit 0`," fi"," sleep 2","done",`echo "vtgate did not become ready on port ${t}" >&2`,"exit 1"]}function Bo(e){if(!xi(e))return[];let t=Ce(e),r=t.mode==="combo";z.clear();let n=['if [ "$(uname -m)" != "x86_64" ]; then',' echo "vitess: Vitess publishes only x86_64 release tarballs; this box is $(uname -m). Drop managedServices.vitess or use an x86_64 host." >&2'," exit 1","fi",...it(Re(t)),`VT_MYSQL_LIB="$(dirname "$(dirname "$(readlink -f ${g}/mysqld)")")/lib"`,'if [ -d "$VT_MYSQL_LIB" ]; then',` printf '%s\\n' "$VT_MYSQL_LIB" > /etc/ld.so.conf.d/vitess-mysql.conf`," ldconfig","else",' echo "mysqld library directory not found under $VT_MYSQL_LIB" >&2; exit 1',"fi",`id -u ${S} >/dev/null 2>&1 || useradd --system --home-dir ${E} --shell /usr/sbin/nologin ${S}`,`mkdir -p ${E}`,`chown -R ${S}:${S} ${E}`];if(r)return n.push(...ie("vitess-vtcombo",De(t)),...oe(),"systemctl daemon-reload","systemctl enable --now vitess-vtcombo.service",...ae(t)),n;n.push(...xe(t));let o=[];if(!t.etcdEndpoint)o.push(["vitess-etcd",Ae()]);o.push(["vitess-vtctld",Oe(t)],["vitess-mysqlctld",Ue(t)],["vitess-vtgate",Ie(t)]);for(let s of t.keyspaces??[])for(let c of s.sharded?["-80","80-"]:["0"])o.push([`vitess-vttablet-${s.name}-${c.replace(/-/g,"x")}`,Le(t,s.name,c)]);for(let[s,c]of o)n.push(...ie(s,c));n.push(...oe()),n.push("systemctl daemon-reload");for(let[s]of o)n.push(`systemctl enable --now ${s}.service`);return n.push(`if [ "$VTESS_VTGATE_AUTH_CHANGED" = 1 ]; then systemctl restart vitess-vtgate.service; printf '%s\\n' "$VTESS_VTGATE_AUTH_SHA" > ${U}; chown ${S}:${S} ${U}; chmod 0600 ${U}; fi`,...ke(t),...ae(t)),n}var Me=new Set(["singlestore","vitess"]);function _i(e){if(e?.engine&&Me.has(e.engine))return!1;return!e?.host||e.host==="127.0.0.1"||e.host==="localhost"}function _r(e,t="psql"){let r=e?.port??5432;if(_i(e))return`${t} -p ${r} -U postgres`;let n=e?.username||"postgres";return`${e?.password?`PGPASSWORD='${e.password.replace(/'/g,"'\\''")}' `:""}${t} -h ${e.host} -p ${r} -U ${n} -w`}function y(e){return e===!0||typeof e==="object"&&e!=null}function Ne(e){let t=[],r=[];if(y(e.mysql))t.push(typeof e.mysql==="object"&&e.mysql.version?`mysql.com@${e.mysql.version}`:"mysql.com@8.0.43"),r.push("mysql");else if(y(e.mariadb))t.push(L.mariadb),r.push("mariadb");if(y(e.postgres))t.push("postgresql.org"),r.push("postgres");if(y(e.redis))t.push("redis.io"),r.push("redis");if(y(e.memcached))t.push("memcached.org"),r.push("memcached");if(y(e.meilisearch))t.push("meilisearch.com"),r.push("meilisearch");return{packages:t,services:r}}function jo(e={},t={}){let r=Ne(e),n=Bo(e.vitess),o=t.mail?ne(t.mail):[];if(r.packages.length===0)return[...n,...o];return[...it(r.packages),...Fo(r.services),...n,...o]}function At(e,t={}){if(!e?.name)return[];if(!_i(e))return[];let r=e.name,n=e.username||r,o=e.password||"",s=y(t.postgres)||e.engine==="postgres",c=y(t.mariadb)||e.engine==="mariadb",p=y(t.mysql)||e.engine==="mysql";if(s&&!p&&!c){let a=(d)=>`"${d.replace(/"/g,'""')}"`,P=(d)=>`'${d.replace(/'/g,"''")}'`,O=(d,k)=>["DO $$ BEGIN",` IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = ${P(d)}) THEN`,` CREATE ROLE ${a(d)} LOGIN PASSWORD ${P(k)};`," ELSE",` ALTER ROLE ${a(d)} LOGIN PASSWORD ${P(k)};`," END IF;","END $$;"],x=(d)=>{let k=d.databases&&d.databases.length>0?d.databases:[r],V=[];for(let G of k)if(d.access==="readonly")V.push(`GRANT CONNECT ON DATABASE ${a(G)} TO ${a(d.username)};`,`\\connect ${a(G)}`,`GRANT USAGE ON SCHEMA public TO ${a(d.username)};`,`GRANT SELECT ON ALL TABLES IN SCHEMA public TO ${a(d.username)};`,`ALTER DEFAULT PRIVILEGES FOR ROLE ${a(n)} IN SCHEMA public GRANT SELECT ON TABLES TO ${a(d.username)};`,"\\connect postgres");else V.push(`GRANT ALL PRIVILEGES ON DATABASE ${a(G)} TO ${a(d.username)};`);return V},I=e.users||[],Se=e.port??5432;return[wt(),`for i in $(seq 1 30); do pg_isready -p ${Se} -q && break; sleep 2; done`,`${_r(e)} <<'TS_CLOUD_PG_EOF'`,...O(n,o),`SELECT 'CREATE DATABASE ${a(r)} OWNER ${a(n)}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = ${P(r)})\\gexec`,...I.flatMap((d)=>[...O(d.username,d.password),...x(d)]),"TS_CLOUD_PG_EOF",...Be(e)]}let l=c?"/var/lib/pantry/mariadb/mariadbd.sock":"/var/lib/pantry/mysql/mysqld.sock",i=(a)=>a.replace(/`/g,"``"),f=(a)=>a.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),C=(a)=>{let P=a.databases&&a.databases.length>0?a.databases:[r],O=a.access==="readonly"?"SELECT":"ALL PRIVILEGES",x=[`CREATE USER IF NOT EXISTS '${f(a.username)}'@'%' IDENTIFIED BY '${f(a.password)}';`,`CREATE USER IF NOT EXISTS '${f(a.username)}'@'localhost' IDENTIFIED BY '${f(a.password)}';`,`ALTER USER '${f(a.username)}'@'%' IDENTIFIED BY '${f(a.password)}';`,`ALTER USER '${f(a.username)}'@'localhost' IDENTIFIED BY '${f(a.password)}';`];for(let I of P)x.push(`GRANT ${O} ON \`${i(I)}\`.* TO '${f(a.username)}'@'%';`,`GRANT ${O} ON \`${i(I)}\`.* TO '${f(a.username)}'@'localhost';`);return x},u=e.users||[];return[wt(),`for i in $(seq 1 30); do mysqladmin --socket=${l} -u root ping 2>/dev/null | grep -q alive && break; sleep 2; done`,`mysql --socket=${l} -u root <<'TS_CLOUD_SQL_EOF'`,`CREATE DATABASE IF NOT EXISTS \`${i(r)}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`,...C({username:n,password:o}),...u.flatMap(C),"FLUSH PRIVILEGES;","TS_CLOUD_SQL_EOF"]}function Be(e){return[`${_r(e)} -tA <<'TS_CLOUD_PG_CAP_EOF' || true`,"\\set QUIET on","SELECT CASE WHEN used::float / NULLIF(cap, 0) >= 0.8"," THEN '[ts-cloud] postgres is at ' || used || '/' || cap || ' connections on this server.'"," || ' Raise max_connections (ALTER SYSTEM SET max_connections = ...; then restart) or'"," || ' set idle_session_timeout so abandoned pools are reclaimed.'"," ELSE NULL END","FROM (SELECT (SELECT count(*) FROM pg_stat_activity) AS used,"," (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS cap) c","WHERE CASE WHEN used::float / NULLIF(cap, 0) >= 0.8 THEN true ELSE false END;","SELECT '[ts-cloud] ' || coalesce(datname, '(background)') || ': ' || count(*) || ' connection(s), oldest idle ' ||"," coalesce(round(extract(epoch from max(now() - state_change)) / 60)::text || 'm', 'n/a')","FROM pg_stat_activity","WHERE (SELECT count(*)::float / NULLIF((SELECT setting::int FROM pg_settings WHERE name = 'max_connections'), 0) FROM pg_stat_activity) >= 0.8","GROUP BY datname ORDER BY count(*) DESC;","TS_CLOUD_PG_CAP_EOF"]}function Jc(e){if(!e?.name)return{};let t=e.engine==="singlestore",r=e.engine==="vitess",n=e.engine==="postgres"?"pgsql":t?"singlestore":r?"vitess":"mysql",o=e.port??(e.engine==="postgres"?5432:r?15306:3306),s={DB_CONNECTION:n,DB_HOST:e.host||"127.0.0.1",DB_PORT:String(o),DB_DATABASE:e.name};if(e.username)s.DB_USERNAME=e.username;if(e.password)s.DB_PASSWORD=e.password;if((t||r)&&e.ssl!==!1)s.DB_SSL="true";return s}var Z="/var/backups/ts-cloud",we="/etc/ts-cloud/backups.config.ts",pe="/etc/cron.d/ts-cloud-backups",yn="/usr/local/bin/ts-cloud-backup.sh";function Ve(e){if(!e.name)return null;let t=e.host||"127.0.0.1",r=e.engine==="postgres",n=r?"postgresql":"mysql",o=e.port??(r?5432:3306),s=(c)=>c.replace(/\\/g,"\\\\").replace(/'/g,"\\'");return[" {",` type: '${n}',`,` name: '${s(e.name)}',`," connection: {",` hostname: '${s(t)}',`,` port: ${o},`,` database: '${s(e.name)}',`,` username: '${s(e.username||e.name)}',`,` password: '${s(e.password||"")}',`," ssl: false,"," },"," includeSchema: true,"," includeData: true,"," },"].join(`
|
|
7
7
|
`)}function He(e,t){let r=e?Ve(e):null,n=t.bucket?[" destinations: ["," {"," type: 's3',",` bucket: '${t.bucket}',`," prefix: 'db-backups',",...t.endpoint?[` endpoint: '${t.endpoint}',`]:[]," optional: false,"," },"," ],"]:[];return["import type { BackupConfig } from 'ts-backups'","","const config: BackupConfig = {"," verbose: true,",` outputPath: '${Z}',`," retention: {",` count: ${t.retentionCount??5},`,` maxAge: ${t.retentionDays??30},`," },"," databases: [",...r?[r]:[]," ],",...n,"}","","export default config",""].join(`
|
|
8
|
-
`)}function Vo(e){let{database:t,backups:r}=e;if(!r.enabled)return[];let n=r.schedule||"0 2 * * *",o=He(t,r);return["export DEBIAN_FRONTEND=noninteractive",`mkdir -p /etc/ts-cloud ${Z}`,"command -v bun >/dev/null 2>&1 || (curl -fsSL https://bun.sh/install | bash && ln -sf /root/.bun/bin/bun /usr/local/bin/bun)","bun add -g ts-backups || true",`cat > ${we} <<'TS_CLOUD_BACKUP_CFG_EOF'`,o.replace(/\n$/,""),"TS_CLOUD_BACKUP_CFG_EOF",`cat > ${hn} <<'TS_CLOUD_BACKUP_RUN_EOF'`,"#!/bin/bash","set -uo pipefail",'export PATH="/root/.bun/bin:/usr/local/bin:$PATH"','notify() { [ -x /usr/local/bin/ts-cloud-notify ] && /usr/local/bin/ts-cloud-notify "$1" || true; }',"cd /etc/ts-cloud",'if ! ts-backups start --config /etc/ts-cloud/backups.config.ts; then notify "❌ ts-cloud backup failed"; exit 1; fi',"TS_CLOUD_BACKUP_RUN_EOF",`chmod +x ${hn}`,`cat > ${pe} <<'TS_CLOUD_BACKUP_CRON_EOF'`,`${n} root ${hn} >> /var/log/ts-cloud-backup.log 2>&1`,"TS_CLOUD_BACKUP_CRON_EOF",`chmod 644 ${pe}`]}function Ge(e){return e==="mariadb"?"/var/lib/pantry/mariadb/mariadbd.sock":"/var/lib/pantry/mysql/mysqld.sock"}function _i(e,t={}){if(!e?.name)return[];let r=e.name,n=e.engine==="postgres",o=t.from?`TS_CLOUD_DUMP="${t.from}"`:`TS_CLOUD_DUMP="$(find ${Z} -type f -name '*${r}*.sql' -o -type f -name '*${r}*.sql.gz' 2>/dev/null | xargs -r ls -1t 2>/dev/null | head -1)"`,s=n?`${xr(e)} -d "${r}"`:`mysql --socket=${Ge(e.engine)} -u root "${r}"`;return["set -uo pipefail",'eval "$(cd /opt/pantry && pantry env 2>/dev/null)" || true',o,'[ -n "$TS_CLOUD_DUMP" ] && [ -f "$TS_CLOUD_DUMP" ] || { echo "no backup dump found to restore" >&2; exit 1; }','echo "[ts-cloud] restoring '+r+' from $TS_CLOUD_DUMP"',`case "$TS_CLOUD_DUMP" in *.gz) gunzip -c "$TS_CLOUD_DUMP" ;; *) cat "$TS_CLOUD_DUMP" ;; esac | ${s}`,'echo "restore complete"']}var zo=["storage",".env"],Oi=4;function v(e){return`${e.replace(/\/+$/,"")}/.ts-cloud`}function Ys(e){return`${v(e)}/deploy-history.log`}function qe(e,t){return`${v(e)}/deploys/${t}.log`}function ue(e){return`${v(e)}/shared-paths`}function Ho(e){return`${e.shared}/stx-images`}function $i(e){return`${e.shared}/stx-bundles`}function Wt(e,t){let r=e.replace(/\/+$/,"");return{base:r,releases:`${r}/releases`,shared:`${r}/shared`,current:`${r}/current`,release:`${r}/releases/${t}`}}function de(e){let t=e.split("/").pop()||e;if(t===".env"||t.startsWith(".env."))return!0;return/\.[a-z0-9]+$/i.test(t)}function Zs(e){return typeof e==="string"?e:e.path}function Xc(e){let t=new Map;for(let r of e)t.set(Zs(r),r);return[...t.values()]}function $e(e,t){if(typeof t==="string")return{path:t,target:`${e.shared}/${t}`,seed:!0};return{path:t.path,target:t.target??`${e.shared}/${t.path}`,seed:t.seed!==!1}}function Fe(e){return["ts_cloud_adopt_shared() {",' TS_CLOUD_SP="$1"',' TS_CLOUD_DST="$2"',` TS_CLOUD_SRC="${e.current}/$TS_CLOUD_SP"`,' if [ -e "$TS_CLOUD_DST" ]; then return 0; fi',' if [ -L "$TS_CLOUD_SRC" ] || [ ! -e "$TS_CLOUD_SRC" ]; then return 0; fi',' mkdir -p "$(dirname "$TS_CLOUD_DST")"',' cp -a "$TS_CLOUD_SRC" "$TS_CLOUD_DST"'," for TS_CLOUD_SIDECAR in -wal -shm; do",' if [ -f "$TS_CLOUD_SRC$TS_CLOUD_SIDECAR" ]; then cp -a "$TS_CLOUD_SRC$TS_CLOUD_SIDECAR" "$TS_CLOUD_DST$TS_CLOUD_SIDECAR"; fi'," done",' echo "[ts-cloud] adopted $TS_CLOUD_SP from the live release into shared/ — it now survives deploys"'," return 0","}"]}function Li(e,t=zo){let r=[`mkdir -p ${e.releases} ${e.shared} ${Ho(e)} ${$i(e)}`,...Fe(e)],n=t.map((s)=>$e(e,s));for(let{path:s,target:c,seed:p}of n){if(!p)continue;if(r.push(`ts_cloud_adopt_shared '${s}' '${c}'`),de(s))r.push(`mkdir -p "$(dirname ${c})"`,`touch ${c}`);else if(s==="storage")r.push(`mkdir -p ${c}/app/public`,`mkdir -p ${c}/framework/cache/data`,`mkdir -p ${c}/framework/sessions`,`mkdir -p ${c}/framework/testing`,`mkdir -p ${c}/framework/views`,`mkdir -p ${c}/logs`);else r.push(`mkdir -p ${c}`)}let o=ue(e.base);return r.push(`mkdir -p ${v(e.base)}`,`cat > ${o} <<'TS_CLOUD_SHARED_PATHS_EOF'`,...n.map((s)=>`${s.path} ${s.target}`),"TS_CLOUD_SHARED_PATHS_EOF"),r}function ea(e,t=900){let r=`${v(e.base)}/deploy.lock`;return[`mkdir -p "$(dirname ${r})"`,`exec 9>${r}`,`flock -w ${t} 9 || { echo "[ts-cloud] another deploy of this site has held the lock for ${t}s — refusing to race it" >&2; exit 1; }`]}function ta(e){let t=`${e.release}.incoming`;return[`rm -rf ${t}`,`mkdir -p ${t}`,...Ye(e),'if [ "$TS_CLOUD_IS_LIVE" = "yes" ]; then',` TS_CLOUD_STAGED=${t}`,"else",` rm -rf ${e.release}`,` mkdir -p ${e.release}`,` rmdir ${t}`,` TS_CLOUD_STAGED=${e.release}`,"fi"]}function ra(e){let t=`TS_CLOUD_TRAP_LIVE="$(readlink -f ${e.current} 2>/dev/null || true)"`,r=`TS_CLOUD_TRAP_TARGET="$(readlink -f ${e.release} 2>/dev/null || echo ${e.release})"`;return`trap '${`if [ $? -ne 0 ]; then ${t}; ${r}; [ "$TS_CLOUD_TRAP_LIVE" = "$TS_CLOUD_TRAP_TARGET" ] || rm -rf ${e.release}; fi`}' EXIT`}function Ye(e){return[`TS_CLOUD_LIVE_PATH="$(readlink -f ${e.current} 2>/dev/null || true)"`,`TS_CLOUD_RELEASE_PATH="$(readlink -f ${e.release} 2>/dev/null || echo ${e.release})"`,'if [ -n "$TS_CLOUD_LIVE_PATH" ] && [ "$TS_CLOUD_LIVE_PATH" = "$TS_CLOUD_RELEASE_PATH" ]; then TS_CLOUD_IS_LIVE=yes; else TS_CLOUD_IS_LIVE=no; fi']}function na(e){let t=`${e.release}.incoming`;return[`if [ "$TS_CLOUD_STAGED" = "${t}" ]; then`,` rm -rf ${e.release}.previous`,` mv ${e.release} ${e.release}.previous`,` mv ${t} ${e.release}`,` rm -rf ${e.release}.previous`,"fi"]}function Ke(e,t){return[`if [ -f ${e} ] && [ ! -L ${e} ] && [ -s ${e} ] && [ ! -s ${t} ]; then`,` cp -a ${e} ${t}`,` echo "[ts-cloud] seeded shared/ from the release's own copy of the file"`,"fi"]}function Go(e,t=zo){let r=[];for(let n of t){let{path:o,target:s,seed:c}=$e(e,n),p=`${e.release}/${o}`,l=[`rm -rf ${p}`,`mkdir -p "$(dirname ${p})"`,`ln -sfn ${s} ${p}`];if(c){if(o!==".env"&&de(o))r.push(...Ke(p,s));r.push(...l);continue}r.push(`if [ -e ${s} ]; then`,...l.map((i)=>` ${i}`),"fi")}return r}function je(e,t){let r=ue(e.base);return[`if [ -f ${r} ]; then`,' while IFS="\t" read -r TS_CLOUD_SP TS_CLOUD_TGT; do',' [ -n "$TS_CLOUD_SP" ] || continue',` [ -n "$TS_CLOUD_TGT" ] || TS_CLOUD_TGT="${e.shared}/$TS_CLOUD_SP"`,' [ -e "$TS_CLOUD_TGT" ] || continue',` rm -rf ${t}/"$TS_CLOUD_SP"`,` mkdir -p "$(dirname ${t}/"$TS_CLOUD_SP")"`,` ln -sfn "$TS_CLOUD_TGT" ${t}/"$TS_CLOUD_SP"`,` done < ${r}`,"fi"]}function yn(e){return[`ln -sfn ${e.release} ${e.current}.tmp`,`mv -Tf ${e.current}.tmp ${e.current}`]}function ee(e){return`${v(e)}/previous-release`}function ia(e,t="TS_CLOUD_PREV_CURRENT"){let r=ee(e.base);return[`if [ -n "\${${t}:-}" ] && [ -d "$${t}" ] && [ "$(readlink -f "$${t}")" != "$(readlink -f ${e.release})" ]; then mkdir -p ${v(e.base)}; basename "$${t}" > ${r}; fi`]}function _e(e,t){let r=ee(e.base);return[`TS_CLOUD_CURRENT=$(readlink -f ${e.current} 2>/dev/null || true)`,...t?[`TS_CLOUD_RB_TARGET=${e.releases}/${t}`]:["TS_CLOUD_RB_TARGET=",`if [ -f ${r} ]; then TS_CLOUD_REC="${e.releases}/$(cat ${r})"; if [ -d "$TS_CLOUD_REC" ] && [ "$(readlink -f "$TS_CLOUD_REC")" != "$TS_CLOUD_CURRENT" ]; then TS_CLOUD_RB_TARGET="$TS_CLOUD_REC"; fi; fi`,`[ -n "$TS_CLOUD_RB_TARGET" ] || TS_CLOUD_RB_TARGET=$(ls -1dt ${e.releases}/*/ 2>/dev/null | sed 's#/$##' | while read -r r; do [ "$(readlink -f "$r")" != "$TS_CLOUD_CURRENT" ] && { echo "$r"; break; }; done)`],'[ -n "$TS_CLOUD_RB_TARGET" ] && [ -d "$TS_CLOUD_RB_TARGET" ] || { echo "no release to roll back to (looked for ${TS_CLOUD_RB_TARGET:-a previous release})" >&2; exit 1; }','[ "$(readlink -f "$TS_CLOUD_RB_TARGET")" != "$TS_CLOUD_CURRENT" ] || { echo "$(basename "$TS_CLOUD_RB_TARGET") is already the live release" >&2; exit 1; }','TS_CLOUD_RB_ID=$(basename "$TS_CLOUD_RB_TARGET")']}function Qc(e,t={}){return[..._e(e,t.to),'echo "would roll back from $(basename "${TS_CLOUD_CURRENT:-none}") to $TS_CLOUD_RB_ID (dry run: nothing changed)"']}function Yc(e,t={}){let r=Math.max(1,t.gateSeconds??5),n=t.systemdDir??"/etc/systemd/system",o=[`ln -sfn "$TS_CLOUD_RB_TARGET" ${e.current}.tmp`,`mv -Tf ${e.current}.tmp ${e.current}`,`rm -f ${ee(e.base)}`,'echo "rolled back to $TS_CLOUD_RB_ID"'],s=[..._e(e,t.to),...je(e,'"$TS_CLOUD_RB_TARGET"')];if(!t.unitBase)return[...s,...o];let c=t.unitBase,p=`${c}@\${TS_CLOUD_RB_ID}.service`;return[...s,`if [ -f ${n}/${c}@.service ]; then`,` systemctl start "${p}"`,` for TS_CLOUD_I in $(seq 1 ${r}); do sleep 1; systemctl is-active --quiet "${p}" || { echo "the release rolled back to, $TS_CLOUD_RB_ID, did not stay up; the current release keeps serving" >&2; journalctl -u "${p}" -n 30 --no-pager >&2 || true; systemctl stop "${p}" 2>/dev/null || true; exit 1; }; done`,...o.map((l)=>` ${l}`),` systemctl enable "${p}" 2>/dev/null || true`,` systemctl list-units --plain --no-legend --type=service "${c}@*.service" 2>/dev/null | awk '{print $1}' | { grep -v "^${c}@\${TS_CLOUD_RB_ID}.service$" || true; } | while read -r TS_CLOUD_U; do systemctl stop "$TS_CLOUD_U" 2>/dev/null || true; systemctl disable "$TS_CLOUD_U" 2>/dev/null || true; done`,`elif [ -f ${n}/${c}.service ]; then`,...o.map((l)=>` ${l}`),` systemctl restart ${c}.service`,"else",...o.map((l)=>` ${l}`),"fi"]}function bn(e,t=4){let r=Math.max(1,t);return[`TS_CLOUD_CURRENT=$(readlink -f ${e.current} 2>/dev/null || true)`,`ls -1dt ${e.releases}/*/ 2>/dev/null | sed 's#/$##' | tail -n +${r+1} | while read -r TS_CLOUD_OLD; do`,' [ "$(readlink -f "$TS_CLOUD_OLD")" = "$TS_CLOUD_CURRENT" ] || rm -rf "$TS_CLOUD_OLD"',"done"]}function We(e){return`${v(e)}/owner`}function oa(e,t){let r=We(e);return[`if [ -f "${r}" ]; then`,` TS_CLOUD_OWNER=$(cat "${r}")`,` if [ "$TS_CLOUD_OWNER" != "${t}" ]; then`,` echo "[ts-cloud] REFUSING deploy: ${e} belongs to project '$TS_CLOUD_OWNER', not '${t}'. Another project on this box derives the same site key — give one of them a distinct site name/domain, or remove ${r} to transfer ownership." >&2`," exit 1"," fi","else",` mkdir -p "$(dirname "${r}")"`,` printf '%s\\n' "${t}" > "${r}"`,"fi"]}function qo(e,t){let r=v(e),n=qe(e,t.releaseId),o=Ys(e),s=Math.max(1,t.keepLogs??20),c=t.commit||"",p=t.branch||"";return[`mkdir -p ${r}/deploys`,`exec > >(tee -a ${n}) 2>&1`,`echo "[ts-cloud] deploy ${t.releaseId} commit=${c} branch=${p} starting $(date -u +%Y-%m-%dT%H:%M:%SZ)"`,"ts_cloud_record_deploy() {"," TS_CLOUD_RC=$?",' if [ "$TS_CLOUD_RC" -eq 0 ]; then TS_CLOUD_ST=success; else TS_CLOUD_ST=failed; fi',` printf '%s\\t%s\\t%s\\t%s\\trc=%s\\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${t.releaseId}" "${c}" "$TS_CLOUD_ST" "$TS_CLOUD_RC" >> ${o}`,"}","trap ts_cloud_record_deploy EXIT",`ls -1t ${r}/deploys/*.log 2>/dev/null | tail -n +${s+1} | while read -r TS_CLOUD_OLDLOG; do rm -f "$TS_CLOUD_OLDLOG"; done`]}
|
|
9
|
-
export{J,
|
|
8
|
+
`)}function Vo(e){let{database:t,backups:r}=e;if(!r.enabled)return[];let n=r.schedule||"0 2 * * *",o=He(t,r);return["export DEBIAN_FRONTEND=noninteractive",`mkdir -p /etc/ts-cloud ${Z}`,"command -v bun >/dev/null 2>&1 || (curl -fsSL https://bun.sh/install | bash && ln -sf /root/.bun/bin/bun /usr/local/bin/bun)","bun add -g ts-backups || true",`cat > ${we} <<'TS_CLOUD_BACKUP_CFG_EOF'`,o.replace(/\n$/,""),"TS_CLOUD_BACKUP_CFG_EOF",`cat > ${yn} <<'TS_CLOUD_BACKUP_RUN_EOF'`,"#!/bin/bash","set -uo pipefail",'export PATH="/root/.bun/bin:/usr/local/bin:$PATH"','notify() { [ -x /usr/local/bin/ts-cloud-notify ] && /usr/local/bin/ts-cloud-notify "$1" || true; }',"cd /etc/ts-cloud",'if ! ts-backups start --config /etc/ts-cloud/backups.config.ts; then notify "❌ ts-cloud backup failed"; exit 1; fi',"TS_CLOUD_BACKUP_RUN_EOF",`chmod +x ${yn}`,`cat > ${pe} <<'TS_CLOUD_BACKUP_CRON_EOF'`,`${n} root ${yn} >> /var/log/ts-cloud-backup.log 2>&1`,"TS_CLOUD_BACKUP_CRON_EOF",`chmod 644 ${pe}`]}function Ge(e){return e==="mariadb"?"/var/lib/pantry/mariadb/mariadbd.sock":"/var/lib/pantry/mysql/mysqld.sock"}function Oi(e,t={}){if(!e?.name)return[];let r=e.name,n=e.engine==="postgres",o=t.from?`TS_CLOUD_DUMP="${t.from}"`:`TS_CLOUD_DUMP="$(find ${Z} -type f -name '*${r}*.sql' -o -type f -name '*${r}*.sql.gz' 2>/dev/null | xargs -r ls -1t 2>/dev/null | head -1)"`,s=n?`${_r(e)} -d "${r}"`:`mysql --socket=${Ge(e.engine)} -u root "${r}"`;return["set -uo pipefail",'eval "$(cd /opt/pantry && pantry env 2>/dev/null)" || true',o,'[ -n "$TS_CLOUD_DUMP" ] && [ -f "$TS_CLOUD_DUMP" ] || { echo "no backup dump found to restore" >&2; exit 1; }','echo "[ts-cloud] restoring '+r+' from $TS_CLOUD_DUMP"',`case "$TS_CLOUD_DUMP" in *.gz) gunzip -c "$TS_CLOUD_DUMP" ;; *) cat "$TS_CLOUD_DUMP" ;; esac | ${s}`,'echo "restore complete"']}var zo=["storage",".env"],$i=4;function v(e){return`${e.replace(/\/+$/,"")}/.ts-cloud`}function Ys(e){return`${v(e)}/deploy-history.log`}function qe(e,t){return`${v(e)}/deploys/${t}.log`}function ue(e){return`${v(e)}/shared-paths`}function Ho(e){return`${e.shared}/stx-images`}function Li(e){return`${e.shared}/stx-bundles`}function Wt(e,t){let r=e.replace(/\/+$/,"");return{base:r,releases:`${r}/releases`,shared:`${r}/shared`,current:`${r}/current`,release:`${r}/releases/${t}`}}function de(e){let t=e.split("/").pop()||e;if(t===".env"||t.startsWith(".env."))return!0;return/\.[a-z0-9]+$/i.test(t)}function Zs(e){return typeof e==="string"?e:e.path}function Xc(e){let t=new Map;for(let r of e)t.set(Zs(r),r);return[...t.values()]}function $e(e,t){if(typeof t==="string")return{path:t,target:`${e.shared}/${t}`,seed:!0};return{path:t.path,target:t.target??`${e.shared}/${t.path}`,seed:t.seed!==!1}}function Fe(e){return["ts_cloud_adopt_shared() {",' TS_CLOUD_SP="$1"',' TS_CLOUD_DST="$2"',` TS_CLOUD_SRC="${e.current}/$TS_CLOUD_SP"`,' if [ -e "$TS_CLOUD_DST" ]; then return 0; fi',' if [ -L "$TS_CLOUD_SRC" ] || [ ! -e "$TS_CLOUD_SRC" ]; then return 0; fi',' mkdir -p "$(dirname "$TS_CLOUD_DST")"',' cp -a "$TS_CLOUD_SRC" "$TS_CLOUD_DST"'," for TS_CLOUD_SIDECAR in -wal -shm; do",' if [ -f "$TS_CLOUD_SRC$TS_CLOUD_SIDECAR" ]; then cp -a "$TS_CLOUD_SRC$TS_CLOUD_SIDECAR" "$TS_CLOUD_DST$TS_CLOUD_SIDECAR"; fi'," done",' echo "[ts-cloud] adopted $TS_CLOUD_SP from the live release into shared/ — it now survives deploys"'," return 0","}"]}function Mi(e,t=zo){let r=[`mkdir -p ${e.releases} ${e.shared} ${Ho(e)} ${Li(e)}`,...Fe(e)],n=t.map((s)=>$e(e,s));for(let{path:s,target:c,seed:p}of n){if(!p)continue;if(r.push(`ts_cloud_adopt_shared '${s}' '${c}'`),de(s))r.push(`mkdir -p "$(dirname ${c})"`,`touch ${c}`);else if(s==="storage")r.push(`mkdir -p ${c}/app/public`,`mkdir -p ${c}/framework/cache/data`,`mkdir -p ${c}/framework/sessions`,`mkdir -p ${c}/framework/testing`,`mkdir -p ${c}/framework/views`,`mkdir -p ${c}/logs`);else r.push(`mkdir -p ${c}`)}let o=ue(e.base);return r.push(`mkdir -p ${v(e.base)}`,`cat > ${o} <<'TS_CLOUD_SHARED_PATHS_EOF'`,...n.map((s)=>`${s.path} ${s.target}`),"TS_CLOUD_SHARED_PATHS_EOF"),r}function ea(e,t=900){let r=`${v(e.base)}/deploy.lock`;return[`mkdir -p "$(dirname ${r})"`,`exec 9>${r}`,`flock -w ${t} 9 || { echo "[ts-cloud] another deploy of this site has held the lock for ${t}s — refusing to race it" >&2; exit 1; }`]}function ta(e){let t=`${e.release}.incoming`;return[`rm -rf ${t}`,`mkdir -p ${t}`,...Ye(e),'if [ "$TS_CLOUD_IS_LIVE" = "yes" ]; then',` TS_CLOUD_STAGED=${t}`,"else",` rm -rf ${e.release}`,` mkdir -p ${e.release}`,` rmdir ${t}`,` TS_CLOUD_STAGED=${e.release}`,"fi"]}function ra(e){let t=`TS_CLOUD_TRAP_LIVE="$(readlink -f ${e.current} 2>/dev/null || true)"`,r=`TS_CLOUD_TRAP_TARGET="$(readlink -f ${e.release} 2>/dev/null || echo ${e.release})"`;return`trap '${`if [ $? -ne 0 ]; then ${t}; ${r}; [ "$TS_CLOUD_TRAP_LIVE" = "$TS_CLOUD_TRAP_TARGET" ] || rm -rf ${e.release}; fi`}' EXIT`}function Ye(e){return[`TS_CLOUD_LIVE_PATH="$(readlink -f ${e.current} 2>/dev/null || true)"`,`TS_CLOUD_RELEASE_PATH="$(readlink -f ${e.release} 2>/dev/null || echo ${e.release})"`,'if [ -n "$TS_CLOUD_LIVE_PATH" ] && [ "$TS_CLOUD_LIVE_PATH" = "$TS_CLOUD_RELEASE_PATH" ]; then TS_CLOUD_IS_LIVE=yes; else TS_CLOUD_IS_LIVE=no; fi']}function na(e){let t=`${e.release}.incoming`;return[`if [ "$TS_CLOUD_STAGED" = "${t}" ]; then`,` rm -rf ${e.release}.previous`,` mv ${e.release} ${e.release}.previous`,` mv ${t} ${e.release}`,` rm -rf ${e.release}.previous`,"fi"]}function Ke(e,t){return[`if [ -f ${e} ] && [ ! -L ${e} ] && [ -s ${e} ] && [ ! -s ${t} ]; then`,` cp -a ${e} ${t}`,` echo "[ts-cloud] seeded shared/ from the release's own copy of the file"`,"fi"]}function Go(e,t=zo){let r=[];for(let n of t){let{path:o,target:s,seed:c}=$e(e,n),p=`${e.release}/${o}`,l=[`rm -rf ${p}`,`mkdir -p "$(dirname ${p})"`,`ln -sfn ${s} ${p}`];if(c){if(o!==".env"&&de(o))r.push(...Ke(p,s));r.push(...l);continue}r.push(`if [ -e ${s} ]; then`,...l.map((i)=>` ${i}`),"fi")}return r}function je(e,t){let r=ue(e.base);return[`if [ -f ${r} ]; then`,' while IFS="\t" read -r TS_CLOUD_SP TS_CLOUD_TGT; do',' [ -n "$TS_CLOUD_SP" ] || continue',` [ -n "$TS_CLOUD_TGT" ] || TS_CLOUD_TGT="${e.shared}/$TS_CLOUD_SP"`,' [ -e "$TS_CLOUD_TGT" ] || continue',` rm -rf ${t}/"$TS_CLOUD_SP"`,` mkdir -p "$(dirname ${t}/"$TS_CLOUD_SP")"`,` ln -sfn "$TS_CLOUD_TGT" ${t}/"$TS_CLOUD_SP"`,` done < ${r}`,"fi"]}function bn(e){return[`ln -sfn ${e.release} ${e.current}.tmp`,`mv -Tf ${e.current}.tmp ${e.current}`]}function ee(e){return`${v(e)}/previous-release`}function ia(e,t="TS_CLOUD_PREV_CURRENT"){let r=ee(e.base);return[`if [ -n "\${${t}:-}" ] && [ -d "$${t}" ] && [ "$(readlink -f "$${t}")" != "$(readlink -f ${e.release})" ]; then mkdir -p ${v(e.base)}; basename "$${t}" > ${r}; fi`]}function _e(e,t){let r=ee(e.base);return[`TS_CLOUD_CURRENT=$(readlink -f ${e.current} 2>/dev/null || true)`,...t?[`TS_CLOUD_RB_TARGET=${e.releases}/${t}`]:["TS_CLOUD_RB_TARGET=",`if [ -f ${r} ]; then TS_CLOUD_REC="${e.releases}/$(cat ${r})"; if [ -d "$TS_CLOUD_REC" ] && [ "$(readlink -f "$TS_CLOUD_REC")" != "$TS_CLOUD_CURRENT" ]; then TS_CLOUD_RB_TARGET="$TS_CLOUD_REC"; fi; fi`,`[ -n "$TS_CLOUD_RB_TARGET" ] || TS_CLOUD_RB_TARGET=$(ls -1dt ${e.releases}/*/ 2>/dev/null | sed 's#/$##' | while read -r r; do [ "$(readlink -f "$r")" != "$TS_CLOUD_CURRENT" ] && { echo "$r"; break; }; done)`],'[ -n "$TS_CLOUD_RB_TARGET" ] && [ -d "$TS_CLOUD_RB_TARGET" ] || { echo "no release to roll back to (looked for ${TS_CLOUD_RB_TARGET:-a previous release})" >&2; exit 1; }','[ "$(readlink -f "$TS_CLOUD_RB_TARGET")" != "$TS_CLOUD_CURRENT" ] || { echo "$(basename "$TS_CLOUD_RB_TARGET") is already the live release" >&2; exit 1; }','TS_CLOUD_RB_ID=$(basename "$TS_CLOUD_RB_TARGET")']}function Qc(e,t={}){return[..._e(e,t.to),'echo "would roll back from $(basename "${TS_CLOUD_CURRENT:-none}") to $TS_CLOUD_RB_ID (dry run: nothing changed)"']}function Yc(e,t={}){let r=Math.max(1,t.gateSeconds??5),n=t.systemdDir??"/etc/systemd/system",o=[`ln -sfn "$TS_CLOUD_RB_TARGET" ${e.current}.tmp`,`mv -Tf ${e.current}.tmp ${e.current}`,`rm -f ${ee(e.base)}`,'echo "rolled back to $TS_CLOUD_RB_ID"'],s=[..._e(e,t.to),...je(e,'"$TS_CLOUD_RB_TARGET"')];if(!t.unitBase)return[...s,...o];let c=t.unitBase,p=`${c}@\${TS_CLOUD_RB_ID}.service`;return[...s,`if [ -f ${n}/${c}@.service ]; then`,` systemctl start "${p}"`,` for TS_CLOUD_I in $(seq 1 ${r}); do sleep 1; systemctl is-active --quiet "${p}" || { echo "the release rolled back to, $TS_CLOUD_RB_ID, did not stay up; the current release keeps serving" >&2; journalctl -u "${p}" -n 30 --no-pager >&2 || true; systemctl stop "${p}" 2>/dev/null || true; exit 1; }; done`,...o.map((l)=>` ${l}`),` systemctl enable "${p}" 2>/dev/null || true`,` systemctl list-units --plain --no-legend --type=service "${c}@*.service" 2>/dev/null | awk '{print $1}' | { grep -v "^${c}@\${TS_CLOUD_RB_ID}.service$" || true; } | while read -r TS_CLOUD_U; do systemctl stop "$TS_CLOUD_U" 2>/dev/null || true; systemctl disable "$TS_CLOUD_U" 2>/dev/null || true; done`,`elif [ -f ${n}/${c}.service ]; then`,...o.map((l)=>` ${l}`),` systemctl restart ${c}.service`,"else",...o.map((l)=>` ${l}`),"fi"]}function Sn(e,t=4){let r=Math.max(1,t);return[`TS_CLOUD_CURRENT=$(readlink -f ${e.current} 2>/dev/null || true)`,`ls -1dt ${e.releases}/*/ 2>/dev/null | sed 's#/$##' | tail -n +${r+1} | while read -r TS_CLOUD_OLD; do`,' [ "$(readlink -f "$TS_CLOUD_OLD")" = "$TS_CLOUD_CURRENT" ] || rm -rf "$TS_CLOUD_OLD"',"done"]}function We(e){return`${v(e)}/owner`}function oa(e,t){let r=We(e);return[`if [ -f "${r}" ]; then`,` TS_CLOUD_OWNER=$(cat "${r}")`,` if [ "$TS_CLOUD_OWNER" != "${t}" ]; then`,` echo "[ts-cloud] REFUSING deploy: ${e} belongs to project '$TS_CLOUD_OWNER', not '${t}'. Another project on this box derives the same site key — give one of them a distinct site name/domain, or remove ${r} to transfer ownership." >&2`," exit 1"," fi","else",` mkdir -p "$(dirname "${r}")"`,` printf '%s\\n' "${t}" > "${r}"`,"fi"]}function qo(e,t){let r=v(e),n=qe(e,t.releaseId),o=Ys(e),s=Math.max(1,t.keepLogs??20),c=t.commit||"",p=t.branch||"";return[`mkdir -p ${r}/deploys`,`exec > >(tee -a ${n}) 2>&1`,`echo "[ts-cloud] deploy ${t.releaseId} commit=${c} branch=${p} starting $(date -u +%Y-%m-%dT%H:%M:%SZ)"`,"ts_cloud_record_deploy() {"," TS_CLOUD_RC=$?",' if [ "$TS_CLOUD_RC" -eq 0 ]; then TS_CLOUD_ST=success; else TS_CLOUD_ST=failed; fi',` printf '%s\\t%s\\t%s\\t%s\\trc=%s\\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${t.releaseId}" "${c}" "$TS_CLOUD_ST" "$TS_CLOUD_RC" >> ${o}`,"}","trap ts_cloud_record_deploy EXIT",`ls -1t ${r}/deploys/*.log 2>/dev/null | tail -n +${s+1} | while read -r TS_CLOUD_OLDLOG; do rm -f "$TS_CLOUD_OLDLOG"; done`]}
|
|
9
|
+
export{J,Ni,Js,w,Uo,Xs,Qs,Wc,Kc,D,Et,wt,it,Fo,xi,Bo,_i,_r,jo,At,Jc,yn,Vo,Oi,zo,$i,Ys,Ho,Li,Wt,Zs,Xc,Mi,ea,ta,ra,na,Go,bn,ia,Qc,Yc,Sn,oa,qo};
|