@stacksjs/ts-cloud 0.12.10 → 0.12.12
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-d7ke90zt.js → chunk-0b49jjgr.js} +1 -1
- package/dist/bin/chunk-0xnnkeb1.js +1 -0
- package/dist/bin/{chunk-9a88fp00.js → chunk-227jmf2b.js} +2 -2
- package/dist/bin/chunk-2nyyg44g.js +1 -0
- package/dist/bin/{chunk-e2bybahr.js → chunk-2ztr119n.js} +1 -1
- package/dist/bin/chunk-43xj5cny.js +1 -0
- package/dist/bin/chunk-5w6y9pmz.js +1 -0
- package/dist/bin/{chunk-8ewncfce.js → chunk-5x4rdx8k.js} +1 -1
- package/dist/bin/chunk-6zc6a6t3.js +725 -0
- package/dist/bin/chunk-7aagqqr9.js +1 -0
- package/dist/{chunk-pb47hr0h.js → bin/chunk-85qrgshq.js} +1 -1
- package/dist/bin/{chunk-c0bdafbx.js → chunk-8zk8msx0.js} +1 -1
- package/dist/bin/chunk-9j83q0r4.js +1 -0
- package/dist/bin/{chunk-b4wt9jcg.js → chunk-9nhqbes6.js} +2 -2
- package/dist/bin/chunk-a4js49mx.js +1 -0
- package/dist/bin/{chunk-6tfwm33r.js → chunk-a9e0hvwe.js} +3 -3
- package/dist/bin/{chunk-cd0ps58j.js → chunk-a9tgxf2h.js} +1 -1
- package/dist/bin/chunk-aahrv359.js +1 -0
- package/dist/bin/{chunk-zpe64t4r.js → chunk-bfx23be3.js} +1 -1
- package/dist/bin/{chunk-tfbs8k8v.js → chunk-bpps61am.js} +1 -1
- package/dist/bin/{chunk-ja1vjdn1.js → chunk-bzth6d1s.js} +1 -1
- package/dist/bin/{chunk-0zwknfwp.js → chunk-ca3taw2m.js} +1 -1
- package/dist/bin/chunk-cgzp0328.js +1 -0
- package/dist/{chunk-w2ddj42w.js → bin/chunk-d2aaef9v.js} +1 -1
- package/dist/bin/{chunk-xk08030d.js → chunk-e0z2t4mf.js} +2 -2
- package/dist/bin/{chunk-btsyjhk7.js → chunk-e2dnxp8d.js} +2 -2
- package/dist/bin/{chunk-s4yzes15.js → chunk-empfsmdk.js} +1 -1
- package/dist/bin/chunk-er3mww4m.js +1 -0
- package/dist/bin/{chunk-azymqbcy.js → chunk-fmp5bv0j.js} +1 -1
- package/dist/bin/{chunk-71t1gmsq.js → chunk-g3kp5ddx.js} +1 -1
- package/dist/bin/{chunk-q5cmfpzt.js → chunk-grepda40.js} +1 -1
- package/dist/{chunk-c8cadhgc.js → bin/chunk-h6xqtypj.js} +2 -2
- package/dist/bin/{chunk-3aph4c1w.js → chunk-hwk9ahms.js} +1 -1
- package/dist/bin/{chunk-dz1ec589.js → chunk-jxd3j00s.js} +2 -2
- package/dist/bin/{chunk-my3ewh3a.js → chunk-k1xw3zbm.js} +2 -2
- package/dist/bin/{chunk-ehc63fvs.js → chunk-m07s5esk.js} +1 -1
- package/dist/bin/{chunk-e5ab5twy.js → chunk-m9r5jype.js} +2 -2
- package/dist/bin/{chunk-4q6tad44.js → chunk-n20kbxwb.js} +91 -91
- package/dist/bin/{chunk-kg61p5hw.js → chunk-n2fnav53.js} +2 -2
- package/dist/bin/{chunk-w32xv8n4.js → chunk-nv211m42.js} +2 -2
- package/dist/bin/chunk-psgjy3z4.js +1 -0
- package/dist/bin/chunk-qmnr82da.js +1 -0
- package/dist/bin/{chunk-mcr0r4at.js → chunk-qqpb82ty.js} +2 -2
- package/dist/bin/{chunk-xhwqpgwq.js → chunk-rqc8btkj.js} +1 -1
- package/dist/bin/chunk-rs85xvt7.js +1 -0
- package/dist/bin/{chunk-hq9x489e.js → chunk-t5ngva49.js} +1 -1
- package/dist/bin/{chunk-82mj52xr.js → chunk-t7rcfwqc.js} +1 -1
- package/dist/bin/{chunk-vj2dp0nh.js → chunk-tjgy10zm.js} +6 -6
- package/dist/bin/chunk-v0beqdna.js +1 -0
- package/dist/bin/chunk-vf2s3tba.js +1 -0
- package/dist/bin/{chunk-0thy7q96.js → chunk-vzkfjrx2.js} +74 -75
- package/dist/bin/{chunk-rtecnmts.js → chunk-wcem4cqb.js} +2 -2
- package/dist/bin/chunk-wsh5ervz.js +1 -0
- package/dist/bin/chunk-xenhbdmr.js +1 -0
- package/dist/bin/chunk-xrdpxwbf.js +1 -0
- package/dist/bin/{chunk-mfrf9q4b.js → chunk-y68m9bx7.js} +1 -1
- package/dist/bin/cli.js +143 -143
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/{chunk-982rye5b.js → chunk-2ybcnrte.js} +1 -1
- package/dist/chunk-4884der5.js +1 -0
- package/dist/{bin/chunk-9kf0np8j.js → chunk-4wdxsnn2.js} +1 -1
- package/dist/{bin/chunk-xkfrqqcs.js → chunk-5hhyyhjt.js} +1 -1
- package/dist/chunk-5zkacdw1.js +1 -0
- package/dist/{chunk-557qj7q9.js → chunk-6cxb8d6y.js} +2 -2
- package/dist/chunk-6f68caq0.js +1 -0
- package/dist/{chunk-2qm3rw8b.js → chunk-7z50g5xz.js} +2 -2
- package/dist/chunk-8fh4m5ge.js +1 -0
- package/dist/chunk-97pb7wb1.js +1 -0
- package/dist/{chunk-a368cs92.js → chunk-ac87ds1k.js} +1 -1
- package/dist/{chunk-qrte4gy2.js → chunk-dndxwssj.js} +1 -1
- package/dist/{chunk-y3tbcxb7.js → chunk-ea7tn8nn.js} +89 -90
- package/dist/{bin/chunk-a7w13qfm.js → chunk-ess6vxfj.js} +2 -2
- package/dist/{chunk-rg7d67xk.js → chunk-j06r5rwv.js} +1 -1
- package/dist/{chunk-70v77sqv.js → chunk-j1g67djb.js} +2 -2
- package/dist/{chunk-fbwpm0zm.js → chunk-k8x8mrkr.js} +1 -1
- package/dist/{chunk-82gezmen.js → chunk-mnmz8t7q.js} +1 -1
- package/dist/{chunk-7j100g7w.js → chunk-n1fyryha.js} +1 -1
- package/dist/{chunk-c1hr34a5.js → chunk-n1hg0jxs.js} +2 -2
- package/dist/{chunk-bcffjsnj.js → chunk-n5xmh0ma.js} +1 -1
- package/dist/chunk-q22qfwsc.js +22 -0
- package/dist/{chunk-5hkq5081.js → chunk-q9a1z53k.js} +2 -2
- package/dist/{chunk-fsssdd5k.js → chunk-r8t25tbm.js} +91 -91
- package/dist/chunk-t8hzekmk.js +585 -0
- package/dist/{chunk-2k0mt6j5.js → chunk-whyttetx.js} +1 -1
- package/dist/{chunk-gkj1tpsn.js → chunk-yf8stygs.js} +1 -1
- package/dist/{chunk-jphewtbx.js → chunk-ze5x2bpm.js} +1 -1
- package/dist/{chunk-jxrs1219.js → chunk-zh0apedk.js} +2 -2
- package/dist/{chunk-0hw5wjjg.js → chunk-zjyz926j.js} +1 -1
- package/dist/deploy/index.js +1 -1
- package/dist/dns/index.js +1 -1
- package/dist/drivers/hetzner/cloud-init.d.ts +14 -1
- package/dist/drivers/hetzner/driver.d.ts +2 -15
- package/dist/drivers/hetzner/state.d.ts +17 -2
- package/dist/drivers/index.d.ts +17 -1
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/local-box/driver.d.ts +1 -1
- package/dist/drivers/shared/compute-deploy.d.ts +0 -12
- package/dist/drivers/shared/compute-provision.d.ts +7 -0
- package/dist/drivers/shared/driver-state.d.ts +68 -0
- package/dist/drivers/shared/remote-exec.d.ts +10 -1
- package/dist/drivers/shared/remote-failure.d.ts +41 -0
- package/dist/drivers/shared/rpx-gateway.d.ts +124 -4
- package/dist/drivers/shared/ssh-transport.d.ts +121 -0
- package/dist/drivers/ssh/bootstrap.d.ts +71 -0
- package/dist/drivers/ssh/config.d.ts +94 -0
- package/dist/drivers/ssh/config.test.d.ts +1 -0
- package/dist/drivers/ssh/driver.d.ts +107 -0
- package/dist/drivers/ssh/factory-wiring.test.d.ts +1 -0
- package/dist/drivers/ssh/first-boot.d.ts +38 -0
- package/dist/drivers/ssh/preflight.d.ts +76 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -7
- package/dist/operations/index.js +1 -1
- package/dist/operations/inventory.d.ts +46 -1
- package/dist/protection/index.js +1 -1
- package/dist/push/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 +5 -5
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +5 -5
- 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 +5 -5
- package/dist/ui/index.html +6 -6
- package/dist/ui/infrastructure/topology.html +6 -6
- package/dist/ui/integrations.html +2 -2
- package/dist/ui/operations/alerts.html +6 -6
- package/dist/ui/operations/configuration.html +6 -6
- package/dist/ui/operations/jobs.html +6 -6
- 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 +5 -5
- package/dist/ui/security.html +1 -1
- package/dist/ui/server/actions.html +5 -5
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +6 -6
- package/dist/ui/server/database.html +5 -5
- 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 +5 -5
- 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 +1 -1
- package/dist/ui/server/sites.html +6 -6
- 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 +6 -6
- package/dist/ui/serverless/logs.html +6 -6
- package/dist/ui/serverless/metrics.html +1 -1
- 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 +6 -6
- package/dist/ui-src/src/charts.ts +1 -1
- package/dist/ui-src/src/topology.ts +1 -1
- package/package.json +3 -3
- package/dist/bin/chunk-04dkwaqp.js +0 -1
- package/dist/bin/chunk-5nkqza92.js +0 -1
- package/dist/bin/chunk-64vczwwt.js +0 -1
- package/dist/bin/chunk-7g2ahkse.js +0 -1
- package/dist/bin/chunk-aw8bhggq.js +0 -594
- package/dist/bin/chunk-cxt74wsj.js +0 -1
- package/dist/bin/chunk-djg4zyqk.js +0 -1
- package/dist/bin/chunk-dkaz333b.js +0 -1
- package/dist/bin/chunk-edvvx3hg.js +0 -1
- package/dist/bin/chunk-f06c5np9.js +0 -1
- package/dist/bin/chunk-gq8794k6.js +0 -1
- package/dist/bin/chunk-k3120rx6.js +0 -1
- package/dist/bin/chunk-nw3d4k52.js +0 -1
- package/dist/bin/chunk-p70bc9yr.js +0 -1
- package/dist/bin/chunk-sg1g92cf.js +0 -1
- package/dist/bin/chunk-tvz9c388.js +0 -1
- package/dist/bin/chunk-y1h63vpm.js +0 -1
- package/dist/bin/chunk-zdt2rjk6.js +0 -1
- package/dist/bin/chunk-zh2d4704.js +0 -1
- package/dist/chunk-1bj94sc2.js +0 -1
- package/dist/chunk-3swnmwfc.js +0 -454
- package/dist/chunk-5pbtmy2k.js +0 -1
- package/dist/chunk-7sc8t7v1.js +0 -1
- package/dist/chunk-gny5s4kp.js +0 -1
- package/dist/chunk-qpjcd415.js +0 -22
- package/dist/chunk-xkw7h4pw.js +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{tj as s}from"./chunk-ac87ds1k.js";class a{client;region;constructor(e="us-east-1",r){this.region=e,this.client=new s(void 0,{profile:r})}async createRepository(e){let r={repositoryName:e.repositoryName};if(e.imageTagMutability)r.imageTagMutability=e.imageTagMutability;if(e.imageScanningConfiguration)r.imageScanningConfiguration=e.imageScanningConfiguration;if(e.encryptionConfiguration)r.encryptionConfiguration=e.encryptionConfiguration;if(e.tags&&e.tags.length>0)r.tags=e.tags;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.CreateRepository","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{repository:t.repository?this.parseRepository(t.repository):void 0}}async describeRepositories(e){let r={};if(e?.repositoryNames&&e.repositoryNames.length>0)r.repositoryNames=e.repositoryNames;if(e?.registryId)r.registryId=e.registryId;if(e?.maxResults)r.maxResults=e.maxResults;if(e?.nextToken)r.nextToken=e.nextToken;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.DescribeRepositories","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{repositories:t.repositories?.map((i)=>this.parseRepository(i)),nextToken:t.nextToken}}async getAuthorizationToken(e){let r={};if(e&&e.length>0)r.registryIds=e;return{authorizationData:(await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.GetAuthorizationToken","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)})).authorizationData?.map((i)=>({authorizationToken:i.authorizationToken,expiresAt:i.expiresAt,proxyEndpoint:i.proxyEndpoint}))}}async deleteRepository(e){let r={repositoryName:e.repositoryName};if(e.registryId)r.registryId=e.registryId;if(e.force!==void 0)r.force=e.force;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.DeleteRepository","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{repository:t.repository?this.parseRepository(t.repository):void 0}}async describeImages(e){let r={repositoryName:e.repositoryName};if(e.registryId)r.registryId=e.registryId;if(e.imageIds&&e.imageIds.length>0)r.imageIds=e.imageIds;if(e.filter)r.filter=e.filter;if(e.maxResults)r.maxResults=e.maxResults;if(e.nextToken)r.nextToken=e.nextToken;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.DescribeImages","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{imageDetails:t.imageDetails?.map((i)=>this.parseImageDetail(i)),nextToken:t.nextToken}}async batchDeleteImage(e){let r={repositoryName:e.repositoryName,imageIds:e.imageIds};if(e.registryId)r.registryId=e.registryId;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.BatchDeleteImage","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{imageIds:t.imageIds,failures:t.failures}}async putLifecyclePolicy(e){let r={repositoryName:e.repositoryName,lifecyclePolicyText:e.lifecyclePolicyText};if(e.registryId)r.registryId=e.registryId;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.PutLifecyclePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{registryId:t.registryId,repositoryName:t.repositoryName,lifecyclePolicyText:t.lifecyclePolicyText}}async getLifecyclePolicy(e){let r={repositoryName:e.repositoryName};if(e.registryId)r.registryId=e.registryId;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.GetLifecyclePolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{registryId:t.registryId,repositoryName:t.repositoryName,lifecyclePolicyText:t.lifecyclePolicyText,lastEvaluatedAt:t.lastEvaluatedAt}}async setRepositoryPolicy(e){let r={repositoryName:e.repositoryName,policyText:e.policyText};if(e.registryId)r.registryId=e.registryId;if(e.force!==void 0)r.force=e.force;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.SetRepositoryPolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{registryId:t.registryId,repositoryName:t.repositoryName,policyText:t.policyText}}async getRepositoryPolicy(e){let r={repositoryName:e.repositoryName};if(e.registryId)r.registryId=e.registryId;let t=await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.GetRepositoryPolicy","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)});return{registryId:t.registryId,repositoryName:t.repositoryName,policyText:t.policyText}}async tagResource(e){let r={resourceArn:e.resourceArn,tags:e.tags};await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.TagResource","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)})}async listTagsForResource(e){let r={resourceArn:e};return{tags:(await this.client.request({service:"ecr",region:this.region,method:"POST",path:"/",headers:{"X-Amz-Target":"AmazonEC2ContainerRegistry_V20150921.ListTagsForResource","Content-Type":"application/x-amz-json-1.1"},body:JSON.stringify(r)})).tags}}createLifecyclePolicyText(e){return JSON.stringify({rules:e.map((r)=>({rulePriority:r.rulePriority,description:r.description,selection:r.selection,action:r.action}))})}async getDockerLoginCommand(){let e=await this.getAuthorizationToken();if(!e.authorizationData?.[0])throw Error("Failed to get authorization token");let r=e.authorizationData[0],t=r.authorizationToken||"",i=r.proxyEndpoint||"";return`echo "${Buffer.from(t,"base64").toString("utf8").split(":")[1]}" | docker login --username AWS --password-stdin ${i}`}getRegistryUri(e){return`${e}.dkr.ecr.${this.region}.amazonaws.com`}parseRepository(e){return{repositoryArn:e.repositoryArn,registryId:e.registryId,repositoryName:e.repositoryName,repositoryUri:e.repositoryUri,createdAt:e.createdAt,imageTagMutability:e.imageTagMutability,imageScanningConfiguration:e.imageScanningConfiguration,encryptionConfiguration:e.encryptionConfiguration}}parseImageDetail(e){return{registryId:e.registryId,repositoryName:e.repositoryName,imageDigest:e.imageDigest,imageTags:e.imageTags,imageSizeInBytes:e.imageSizeInBytes,imagePushedAt:e.imagePushedAt,imageScanStatus:e.imageScanStatus,imageScanFindingsSummary:e.imageScanFindingsSummary}}}
|
|
2
2
|
export{a as Vf};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{Uf as U}from"./chunk-
|
|
1
|
+
import{Uf as U}from"./chunk-n1fyryha.js";import{eg as Z,jg as _,ng as K,rg as L,sg as Y}from"./chunk-j06r5rwv.js";import{tg as M}from"./chunk-2ybcnrte.js";import{pj as W}from"./chunk-ess6vxfj.js";import{rj as B}from"./chunk-j1g67djb.js";import{Ov as j}from"./chunk-zjyz926j.js";function J(t){let{bucketName:s,domain:l,aliases:e,certificateArn:m,defaultRootObject:i="index.html",errorDocument:r="404.html",passthroughUrls:a=!1,singlePageApp:d=!1,dynamicApp:b=!1,computeOriginDomain:k,computeOriginPort:R=3008,computeOriginId:P="app-compute",retainOnStackDelete:x=!1}=t,A=x?{DeletionPolicy:"Retain",UpdateReplacePolicy:"Retain"}:{},y=b&&!!k,T=y?["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"]:["GET","HEAD"],F=y?["GET","HEAD"]:["GET","HEAD"],N={},O={};N.S3Bucket={Type:"AWS::S3::Bucket",...A,Properties:{BucketName:s,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!1,IgnorePublicAcls:!0,RestrictPublicBuckets:!1},WebsiteConfiguration:{IndexDocument:i,ErrorDocument:r}}},O.BucketName={Description:"S3 Bucket Name",Value:{Ref:"S3Bucket"}},O.BucketArn={Description:"S3 Bucket ARN",Value:{"Fn::GetAtt":["S3Bucket","Arn"]}},N.CloudFrontOAC={Type:"AWS::CloudFront::OriginAccessControl",...A,Properties:{OriginAccessControlConfig:{Name:`OAC-${s}`,Description:`OAC for ${s}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}};let D;if(a&&y)D="InstallRootRedirectFunction",N[D]={Type:"AWS::CloudFront::Function",Properties:{Name:{"Fn::Sub":"${AWS::StackName}-install-root-redirect"},AutoPublish:!0,FunctionConfig:{Comment:"Redirect curl pantry.dev | bash (GET /) to /install.sh on S3",Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) {
|
|
2
2
|
var request = event.request;
|
|
3
3
|
if (request.uri === '/' || request.uri === '') {
|
|
4
4
|
return {
|
|
@@ -42,7 +42,7 @@ import{Uf as U}from"./chunk-7j100g7w.js";import{eg as Z,jg as _,ng as K,rg as L,
|
|
|
42
42
|
│ │
|
|
43
43
|
│ Verification typically takes 1-2 business days. │
|
|
44
44
|
│ After verification, re-run: bunx bunpress deploy │
|
|
45
|
-
└─────────────────────────────────────────────────────────────────────────────┘`),{success:!1,stackId:O,stackName:i,bucket:y,message:"CloudFront account verification required. Please contact AWS Support."}}return{success:!1,stackId:O,stackName:i,bucket:y,message:`Stack deployment failed: ${o.message}`}}let u=(await r.describeStacks({stackName:i})).Stacks[0]?.Outputs||[],C=(o)=>u.find((n)=>n.OutputKey===o)?.OutputValue,f=C("DistributionDomain");if(f&&d)console.log(`Creating DNS records via ${d.name}...`),await q(d,e,f);else if(f&&!d)console.log("Skipping DNS record creation (DNS verification was skipped)");return{success:!0,stackId:O,stackName:i,bucket:C("BucketName")||y,distributionId:C("DistributionId"),distributionDomain:f,domain:e,certificateArn:b,message:"Static site infrastructure deployed successfully with external DNS"}}async function q(t,s,l){if(!t){console.log("Skipping DNS record creation (DNS verification was skipped)");return}if(s.split(".").length===2)if(t instanceof Z){console.log(`Creating Route53 alias record for apex domain ${s} -> ${l}`);let i=await t.createCloudFrontAlias({domain:s,name:s,cloudFrontDomainName:l});if(!i.success)console.warn(`Warning: Could not create Route53 alias record: ${i.message}`),console.warn("Please manually create an A-record alias in Route53:"),console.warn(` ${s} -> ${l}`);else console.log(`Created Route53 alias record: ${s} -> ${l}`);let r=`www.${s}`;console.log(`Creating Route53 alias record for ${r} -> ${l}`);let a=await t.createCloudFrontAlias({domain:s,name:r,cloudFrontDomainName:l});if(!a.success)console.warn(`Warning: Could not create www Route53 alias: ${a.message}`),console.warn("Please manually create an A-record alias in Route53:"),console.warn(` ${r} -> ${l}`);else console.log(`Created Route53 alias record: ${r} -> ${l}`)}else{try{let d=await t.listRecords(s,"A");if(d.success)for(let b of d.records){let k=b.name.replace(/\.$/,"");if(k===s||k==="")console.log(`Removing existing root A record (${b.content}) to make room for ALIAS...`),await t.deleteRecord(s,{name:s,type:"A",content:b.content})}}catch(d){console.log(`Note: Could not check for conflicting A records: ${d instanceof Error?d.message:d}`)}console.log(`Creating ALIAS record for apex domain ${s} -> ${l}`);let i=await t.upsertRecord(s,{name:s,type:"ALIAS",content:l,ttl:600});if(!i.success)console.warn(`Warning: Could not create ALIAS record: ${i.message}`),console.warn("Please manually create an ALIAS record in your DNS provider:"),console.warn(` ${s} -> ${l}`);else console.log(`Created ALIAS record: ${s} -> ${l}`);let r=`www.${s}`;console.log(`Creating CNAME record for ${r} -> ${l}`);let a=await t.upsertRecord(s,{name:r,type:"CNAME",content:l,ttl:600});if(!a.success)console.warn(`Warning: Could not create www DNS record: ${a.message}`),console.warn("Please manually create a CNAME record:"),console.warn(` ${r} -> ${l}`);else console.log(`Created CNAME record: ${r} -> ${l}`)}else{console.log(`Creating CNAME record for ${s} -> ${l}`);let i=await t.upsertRecord(s,{name:s,type:"CNAME",content:l,ttl:600});if(!i.success)console.warn(`Warning: Could not create DNS record: ${i.message}`),console.warn("Please manually create a CNAME record:"),console.warn(` ${s} -> ${l}`);else console.log(`Created CNAME record: ${s} -> ${l}`)}}async function le(t){let{sourceDir:s,cleanBucket:l=!1,onProgress:e,...m}=t;e?.("infrastructure","Deploying CloudFormation stack...");let i=await G(m);if(!i.success)return i;if(l){e?.("clean","Cleaning old files from S3...");try{await new B(m.region||"us-east-1").emptyBucket(i.bucket)}catch(b){console.log(`Note: Could not clean bucket: ${b.message}`)}}e?.("upload","Uploading files to S3...");let{uploadStaticFiles:r}=await import("./chunk-
|
|
45
|
+
└─────────────────────────────────────────────────────────────────────────────┘`),{success:!1,stackId:O,stackName:i,bucket:y,message:"CloudFront account verification required. Please contact AWS Support."}}return{success:!1,stackId:O,stackName:i,bucket:y,message:`Stack deployment failed: ${o.message}`}}let u=(await r.describeStacks({stackName:i})).Stacks[0]?.Outputs||[],C=(o)=>u.find((n)=>n.OutputKey===o)?.OutputValue,f=C("DistributionDomain");if(f&&d)console.log(`Creating DNS records via ${d.name}...`),await q(d,e,f);else if(f&&!d)console.log("Skipping DNS record creation (DNS verification was skipped)");return{success:!0,stackId:O,stackName:i,bucket:C("BucketName")||y,distributionId:C("DistributionId"),distributionDomain:f,domain:e,certificateArn:b,message:"Static site infrastructure deployed successfully with external DNS"}}async function q(t,s,l){if(!t){console.log("Skipping DNS record creation (DNS verification was skipped)");return}if(s.split(".").length===2)if(t instanceof Z){console.log(`Creating Route53 alias record for apex domain ${s} -> ${l}`);let i=await t.createCloudFrontAlias({domain:s,name:s,cloudFrontDomainName:l});if(!i.success)console.warn(`Warning: Could not create Route53 alias record: ${i.message}`),console.warn("Please manually create an A-record alias in Route53:"),console.warn(` ${s} -> ${l}`);else console.log(`Created Route53 alias record: ${s} -> ${l}`);let r=`www.${s}`;console.log(`Creating Route53 alias record for ${r} -> ${l}`);let a=await t.createCloudFrontAlias({domain:s,name:r,cloudFrontDomainName:l});if(!a.success)console.warn(`Warning: Could not create www Route53 alias: ${a.message}`),console.warn("Please manually create an A-record alias in Route53:"),console.warn(` ${r} -> ${l}`);else console.log(`Created Route53 alias record: ${r} -> ${l}`)}else{try{let d=await t.listRecords(s,"A");if(d.success)for(let b of d.records){let k=b.name.replace(/\.$/,"");if(k===s||k==="")console.log(`Removing existing root A record (${b.content}) to make room for ALIAS...`),await t.deleteRecord(s,{name:s,type:"A",content:b.content})}}catch(d){console.log(`Note: Could not check for conflicting A records: ${d instanceof Error?d.message:d}`)}console.log(`Creating ALIAS record for apex domain ${s} -> ${l}`);let i=await t.upsertRecord(s,{name:s,type:"ALIAS",content:l,ttl:600});if(!i.success)console.warn(`Warning: Could not create ALIAS record: ${i.message}`),console.warn("Please manually create an ALIAS record in your DNS provider:"),console.warn(` ${s} -> ${l}`);else console.log(`Created ALIAS record: ${s} -> ${l}`);let r=`www.${s}`;console.log(`Creating CNAME record for ${r} -> ${l}`);let a=await t.upsertRecord(s,{name:r,type:"CNAME",content:l,ttl:600});if(!a.success)console.warn(`Warning: Could not create www DNS record: ${a.message}`),console.warn("Please manually create a CNAME record:"),console.warn(` ${r} -> ${l}`);else console.log(`Created CNAME record: ${r} -> ${l}`)}else{console.log(`Creating CNAME record for ${s} -> ${l}`);let i=await t.upsertRecord(s,{name:s,type:"CNAME",content:l,ttl:600});if(!i.success)console.warn(`Warning: Could not create DNS record: ${i.message}`),console.warn("Please manually create a CNAME record:"),console.warn(` ${s} -> ${l}`);else console.log(`Created CNAME record: ${s} -> ${l}`)}}async function le(t){let{sourceDir:s,cleanBucket:l=!1,onProgress:e,...m}=t;e?.("infrastructure","Deploying CloudFormation stack...");let i=await G(m);if(!i.success)return i;if(l){e?.("clean","Cleaning old files from S3...");try{await new B(m.region||"us-east-1").emptyBucket(i.bucket)}catch(b){console.log(`Note: Could not clean bucket: ${b.message}`)}}e?.("upload","Uploading files to S3...");let{uploadStaticFiles:r}=await import("./chunk-8fh4m5ge.js"),a=await r({sourceDir:s,bucket:i.bucket,region:m.region||"us-east-1",cacheControl:m.cacheControl,onProgress:(b,k,R)=>{e?.("upload",`${b}/${k}: ${R}`)}});if(a.errors.length>0)return{...i,success:!1,message:`Upload errors: ${a.errors.join(", ")}`,filesUploaded:a.uploaded};if(i.distributionId&&a.uploaded>0){e?.("invalidate","Invalidating CloudFront cache...");let{invalidateCache:b}=await import("./chunk-8fh4m5ge.js");await b(i.distributionId)}e?.("complete","Deployment complete!");let d=a.skipped>0?`Deployed ${a.uploaded} files (${a.skipped} unchanged) with external DNS`:`Deployed ${a.uploaded} files successfully with external DNS`;return{...i,filesUploaded:a.uploaded,filesSkipped:a.skipped,message:d}}function Q(t){let{bucketName:s,domain:l,certificateArn:e,hostedZoneId:m,defaultRootObject:i="index.html",errorDocument:r="404.html"}=t,a={},d={};a.S3Bucket={Type:"AWS::S3::Bucket",Properties:{BucketName:s,PublicAccessBlockConfiguration:{BlockPublicAcls:!0,BlockPublicPolicy:!1,IgnorePublicAcls:!0,RestrictPublicBuckets:!1},WebsiteConfiguration:{IndexDocument:i,ErrorDocument:r}}},d.BucketName={Description:"S3 Bucket Name",Value:{Ref:"S3Bucket"}},d.BucketArn={Description:"S3 Bucket ARN",Value:{"Fn::GetAtt":["S3Bucket","Arn"]}},a.CloudFrontOAC={Type:"AWS::CloudFront::OriginAccessControl",Properties:{OriginAccessControlConfig:{Name:`OAC-${s}`,Description:`OAC for ${s}`,OriginAccessControlOriginType:"s3",SigningBehavior:"always",SigningProtocol:"sigv4"}}},a.UrlRewriteFunction={Type:"AWS::CloudFront::Function",Properties:{Name:{"Fn::Sub":"${AWS::StackName}-url-rewrite"},AutoPublish:!0,FunctionConfig:{Comment:"Append .html extension to URLs without extensions",Runtime:"cloudfront-js-2.0"},FunctionCode:`function handler(event) {
|
|
46
46
|
const request = event.request;
|
|
47
47
|
var uri = request.uri;
|
|
48
48
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{createRequire as q}from"node:module";var j=Object.create;var{getPrototypeOf:k,defineProperty:i,getOwnPropertyNames:l}=Object;var m=Object.prototype.hasOwnProperty;function n(a){return this[a]}var o,p,r=(a,b,d)=>{var f=a!=null&&typeof a==="object";if(f){var g=b?o??=new WeakMap:p??=new WeakMap,h=g.get(a);if(h)return h}d=a!=null?j(k(a)):{};let c=b||!a||!a.__esModule?i(d,"default",{value:a,enumerable:!0}):d;if(a&&typeof a==="object"||typeof a==="function"){for(let e of l(a))if(!m.call(c,e))i(c,e,{get:n.bind(a,e),enumerable:!0})}if(f)g.set(a,c);return c};var s=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var u=q(import.meta.url);
|
|
2
|
-
export{r as
|
|
2
|
+
export{r as Mv,s as Nv,u as Ov};
|
package/dist/deploy/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$c as ra,Ac as I,Bc as J,Cc as K,Dc as L,Ec as M,Fc as N,Gc as O,Hc as P,Ic as Q,Jc as R,Kc as S,Lc as T,Mc as U,Nc as V,Oc as W,Pc as X,Pd as Ha,Qc as ga,Qd as Ia,Rc as ha,Rd as Ja,Sc as ia,Sd as Ka,Tc as ja,Uc as ka,Vc as la,Wc as ma,Xc as na,Yc as oa,Zc as pa,_c as qa,ad as ta,bd as ua,cd as va,dd as wa,ed as xa,fd as ya,gd as za,hd as Aa,id as Ba,jd as Ca,kd as Da,ld as Ea,md as Fa,nd as Ga,xc as F,yc as G,zc as H}from"../chunk-
|
|
1
|
+
import{$c as ra,Ac as I,Bc as J,Cc as K,Dc as L,Ec as M,Fc as N,Gc as O,Hc as P,Ic as Q,Jc as R,Kc as S,Lc as T,Mc as U,Nc as V,Oc as W,Pc as X,Pd as Ha,Qc as ga,Qd as Ia,Rc as ha,Rd as Ja,Sc as ia,Sd as Ka,Tc as ja,Uc as ka,Vc as la,Wc as ma,Xc as na,Yc as oa,Zc as pa,_c as qa,ad as ta,bd as ua,cd as va,dd as wa,ed as xa,fd as ya,gd as za,hd as Aa,id as Ba,jd as Ca,kd as Da,ld as Ea,md as Fa,nd as Ga,xc as F,yc as G,zc as H}from"../chunk-ea7tn8nn.js";import{$d as fa,Td as Y,Ud as Z,Vd as _,Wd as aa,Xd as ba,Yd as ca,Zd as da,_d as ea}from"../chunk-zh0apedk.js";import{he as sa}from"../chunk-whyttetx.js";import"../chunk-yf8stygs.js";import"../chunk-mnmz8t7q.js";import"../chunk-n1fyryha.js";import"../chunk-ze5x2bpm.js";import"../chunk-k8x8mrkr.js";import"../chunk-j06r5rwv.js";import"../chunk-2ybcnrte.js";import{Ag as y,Ui as z,Vi as A,Wi as B,Xi as C,Yi as D,Zi as E,ug as s,vg as t,wg as u,xg as v,yg as w,zg as x}from"../chunk-t8hzekmk.js";import"../chunk-n5xmh0ma.js";import"../chunk-6cxb8d6y.js";import"../chunk-ess6vxfj.js";import"../chunk-j1g67djb.js";import"../chunk-ac87ds1k.js";import{ok as l,pk as m,qk as n,rk as o,sk as p,tk as q,uk as r}from"../chunk-7z50g5xz.js";import{Ak as f,Bk as g,Ck as h,Dk as i,Ek as j,Fk as k,vk as a,wk as b,xk as c,yk as d,zk as e}from"../chunk-n1hg0jxs.js";import"../chunk-q9a1z53k.js";import"../chunk-4wdxsnn2.js";import"../chunk-r8t25tbm.js";import"../chunk-zjyz926j.js";export{m as DEFAULT_SITE_PORT_RANGE,l as HOST_SITES_DIR,v as IPV6_EXCLUDED_HOST_LABELS,z as MANAGEMENT_DASHBOARD_SITE,F as addSiteToCloudConfig,r as allocateSitePorts,ra as buildAndPushContainerImage,sa as buildAndPushServerlessImage,ua as buildFunctionEnv,p as buildHostSitePortsScript,E as buildManagementDashboardArtifact,Aa as buildServerTopology,Ba as buildServerlessTopology,Ca as buildTopology,Ga as collectEgressMetrics,s as collectServerDnsDomains,qa as createContainerImageDependencies,la as createExistingStaticFullStackDependencies,ha as createStaticApiOriginDependencies,Ia as dashboardActions,A as dashboardCredentialsFile,V as dashboardPageRoutes,ea as deleteStaticSite,na as deployExistingStaticFullStack,va as deployServerlessApp,k as deployShipsFiles,ga as deploySite,ia as deployStaticApiOrigin,ba as deployStaticSite,fa as deployStaticSiteFull,Z as deployStaticSiteWithExternalDns,_ as deployStaticSiteWithExternalDnsFull,Ea as egressReportMetrics,R as ensureDashboardActor,D as ensureManagementDashboard,oa as estimateExistingStaticFullStackMonthlyCost,ka as estimateStaticApiOriginMonthlyCost,Fa as fetchEgressReport,ma as generateExistingStaticFullStackTemplate,Y as generateExternalDnsStaticSiteTemplate,aa as generateStaticSiteTemplate,g as hasComputeConfigured,d as hasProxyUpstream,pa as hashContainerContext,w as hostAcceptsIpv6,ta as infraEnvFromOutputs,S as initializeDashboardControlPlane,da as invalidateCache,b as isPhpSite,M as isValidHostname,u as normalizePublicIpv6,o as occupiedHostPorts,q as parseHostSiteFragments,n as parseUpstreamPort,x as reconcileAddressRecords,wa as redeployServerlessApp,G as removeSiteFromCloudConfig,t as removeStaleServerAddressRecords,N as renderAliasesValue,L as renderEnvValue,O as renderRedirectsValue,P as renderSiteSnippet,J as renderSslValue,K as renderStringValue,Ja as resolveDashboardAction,B as resolveDashboardAuth,Da as resolveDashboardData,W as resolveLegacyDashboardRoute,c as resolveProxyUpstreams,e as resolveSiteDeployTarget,f as resolveSiteKind,C as resolveUiSource,xa as rollbackServerlessApp,X as routesForDashboard,za as runRemoteCommand,Ha as sanitizeCloudConfig,Q as setAttachToInCloudConfig,ya as setMaintenance,I as setSitePropertyInCloudConfig,i as shipsARelease,j as shipsToBucket,a as siteInstallBase,Ka as startLocalDashboardServer,T as synchronizeDashboardUsers,U as trackDashboardOperation,H as updateSiteInCloudConfig,ca as uploadStaticFiles,h as validateDeploymentConfig,y as verifyAddressRecord,ja as verifyStaticApiOrigin};
|
package/dist/dns/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$f as d,Xf as a,Yf as b,Zf as c,ag as e,bg as f,cg as g,dg as h,eg as i,fg as j,gg as k,hg as l,ig as m,jg as n,kg as o,lg as p,mg as q,ng as r,og as s,pg as t,qg as u}from"../chunk-
|
|
1
|
+
import{$f as d,Xf as a,Yf as b,Zf as c,ag as e,bg as f,cg as g,dg as h,eg as i,fg as j,gg as k,hg as l,ig as m,jg as n,kg as o,lg as p,mg as q,ng as r,og as s,pg as t,qg as u}from"../chunk-j06r5rwv.js";import"../chunk-2ybcnrte.js";import"../chunk-ac87ds1k.js";import"../chunk-zjyz926j.js";export{d as CloudflareProvider,t as DnsProviderFactory,c as GoDaddyProvider,a as PROXIABLE_RECORD_TYPES,b as PorkbunProvider,i as Route53Provider,n as UnifiedDnsValidator,l as applyZoneMigration,r as createDnsProvider,p as createGoDaddyValidator,o as createPorkbunValidator,q as createRoute53Validator,s as detectDnsProvider,u as dnsProviders,j as exportRoute53Zone,k as planZoneMigration,e as policyTag,f as qualifyName,h as reconcileDeclaredRecords,g as resolveDeclaredRecords,m as verifyZoneParity};
|
|
@@ -17,4 +17,17 @@ export { buildUbuntuBootstrapScript as generateUbuntuAppCloudInit, type UbuntuBo
|
|
|
17
17
|
* inline under `runcmd:` silently breaks bun/caddy installation. Writing the
|
|
18
18
|
* file (shebang preserved) and running `bash <file>` guarantees a bash shell.
|
|
19
19
|
*/
|
|
20
|
-
export
|
|
20
|
+
export interface CloudInitUserDataExtras {
|
|
21
|
+
/** Where the script is written on the box. @default '/var/lib/cloud/ts-cloud-bootstrap.sh' */
|
|
22
|
+
scriptPath?: string;
|
|
23
|
+
/** File mode of the written script. @default '0755' */
|
|
24
|
+
permissions?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Top-level cloud-config YAML emitted before `write_files:` (hostname,
|
|
27
|
+
* users, packages, ...). Complete lines, already at top-level indentation.
|
|
28
|
+
*/
|
|
29
|
+
before?: string;
|
|
30
|
+
/** Top-level cloud-config YAML emitted after `runcmd:`. */
|
|
31
|
+
after?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function wrapCloudInitUserData(bootstrapScript: string, extras?: CloudInitUserDataExtras): string;
|
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
import type { CloudDriver, ComputeStackOutputs, ComputeTarget, FindComputeTargetsOptions, ProvisionComputeOptions, ReachableResource, RemoteDeployResult, RunRemoteDeployOptions, UploadReleaseOptions, UploadReleaseResult } from '@ts-cloud/core';
|
|
2
2
|
import { HetznerClient } from './client';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* A syntax error names a line number in a file that only ever existed on the
|
|
7
|
-
* box, and the deploy deletes it on the way out — so the one thing needed to
|
|
8
|
-
* understand the failure is the one thing nobody can look at. Without this you
|
|
9
|
-
* are reduced to guessing which generated fragment is unbalanced, or to
|
|
10
|
-
* reproducing the whole script by hand from its builders.
|
|
11
|
-
*
|
|
12
|
-
* Only a window around the reported line, and every `KEY="value"` line inside
|
|
13
|
-
* it is redacted: the script carries the runtime environment, and a deploy
|
|
14
|
-
* failure must not become the reason a database password is in a CI log.
|
|
15
|
-
*/
|
|
16
|
-
export declare function describeScriptSyntaxError(error: unknown, script: string): string;
|
|
17
|
-
export declare function formatSshFailure(error: unknown): string;
|
|
3
|
+
import { describeScriptSyntaxError, formatSshFailure } from '../shared/remote-failure';
|
|
4
|
+
export { describeScriptSyntaxError, formatSshFailure };
|
|
18
5
|
export interface HetznerDriverOptions {
|
|
19
6
|
apiToken?: string;
|
|
20
7
|
/**
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hetzner driver state.
|
|
3
|
+
*
|
|
4
|
+
* The file handling itself lives in `../shared/driver-state` (one reader and
|
|
5
|
+
* writer for every SSH-style driver); this module keeps the Hetzner-typed
|
|
6
|
+
* view of it so the driver, the dashboard and the CLI read `serverId` and
|
|
7
|
+
* friends without a cast at every call site.
|
|
8
|
+
*/
|
|
9
|
+
import type { DriverState } from '../shared/driver-state';
|
|
10
|
+
export { LEGACY_DRIVER_STATE_DIR } from '../shared/driver-state';
|
|
1
11
|
export interface HetznerDriverState {
|
|
2
12
|
provider: 'hetzner';
|
|
3
13
|
stackName: string;
|
|
@@ -30,7 +40,12 @@ export interface HetznerDriverState {
|
|
|
30
40
|
lbServerId?: number;
|
|
31
41
|
appServerIds?: number[];
|
|
32
42
|
}
|
|
33
|
-
|
|
43
|
+
/**
|
|
44
|
+
* The legacy, project-relative driver-state directory. Kept for callers that
|
|
45
|
+
* spell the path by hand; new code should ask `driverStateDir()` instead,
|
|
46
|
+
* which also honours a configured state directory.
|
|
47
|
+
*/
|
|
48
|
+
export declare const STATE_DIR: string;
|
|
34
49
|
export declare function driverStatePath(stackName: string): string;
|
|
35
50
|
export declare function readDriverState(stackName: string): Promise<HetznerDriverState | null>;
|
|
36
|
-
export declare function writeDriverState(stackName: string, state:
|
|
51
|
+
export declare function writeDriverState(stackName: string, state: DriverState): Promise<void>;
|
package/dist/drivers/index.d.ts
CHANGED
|
@@ -2,6 +2,21 @@ export * from './factory';
|
|
|
2
2
|
export { AwsDriver } from './aws/driver';
|
|
3
3
|
export { HetznerDriver } from './hetzner/driver';
|
|
4
4
|
export { isBoxMode, LocalBoxDriver } from './local-box/driver';
|
|
5
|
+
export { assertSshComputeConfig, SSH_DEPLOY_STORAGE_PATH, SSH_SKIP_BOOTSTRAP_ENV, SshDriver } from './ssh/driver';
|
|
6
|
+
export type { SshDriverOptions } from './ssh/driver';
|
|
7
|
+
export { resolveSshHostKeyPolicy, resolveSshHosts, resolveSshLan, resolveSshPort, resolveSshPrivateKeyPath, resolveSshProfile, resolveSshPublicIp, resolveSshSettings, resolveSshSudo, resolveSshUser, SSH_DEFAULTS, } from './ssh/config';
|
|
8
|
+
export type { ResolvedSshHost, ResolvedSshSettings, SshHostKeyPolicyName, SshLanConfig, SshOverrides, SshProfile } from './ssh/config';
|
|
9
|
+
export { assertArchSupported, buildSshBootstrapScript, RASPBERRY_PI_DEFAULT_SWAP_GB, SSH_BOOTSTRAP_MARKER_DIR, SSH_BOOTSTRAP_VERSION, sshBootstrapMarkerPath, } from './ssh/bootstrap';
|
|
10
|
+
export type { SshBootstrapOptions } from './ssh/bootstrap';
|
|
11
|
+
export { evaluatePreflight, formatPreflightFindings, parsePreflightFacts, preflightFailed, SSH_PREFLIGHT_SCRIPT, } from './ssh/preflight';
|
|
12
|
+
export type { PreflightContext, SshPreflightFacts } from './ssh/preflight';
|
|
13
|
+
export { BOOT_PARTITION_LABEL, buildCloudInitFirstBoot, FIRST_BOOT_SCRIPT_PATH } from './ssh/first-boot';
|
|
14
|
+
export type { FirstBootBundle, FirstBootIdentity, FirstBootOptions, FirstBootOs, FirstBootWifi } from './ssh/first-boot';
|
|
15
|
+
export { buildScpArgsFor, buildSshArgsFor, findKnownHostKey, knownHostsLine, knownHostsToken, scanHostKey, SSH_INSECURE_HOST_KEY_OPTS, SSH_KEEPALIVE_OPTS, sshHostKeyFingerprint, sshKnownHostsPath, SystemSshTransport, } from './shared/ssh-transport';
|
|
16
|
+
export type { CommandResult, CommandRunner, ScannedHostKey, SshExecOptions, SshHostKeyPolicy, SshHostKeyResult, SshTransport, SshTransportOptions, SystemSshTransportDeps, } from './shared/ssh-transport';
|
|
17
|
+
export { driverStateDir, driverStatePath, LEGACY_DRIVER_STATE_DIR, readDriverState, writeDriverState, } from './shared/driver-state';
|
|
18
|
+
export type { DriverState, SshDriverState } from './shared/driver-state';
|
|
19
|
+
export { describeScriptSyntaxError, formatSshFailure, summarizeRemoteFailures, surfaceRemoteNotices } from './shared/remote-failure';
|
|
5
20
|
export { HetznerClient, normalizeSshPublicKey, resolveHetznerApiToken } from './hetzner/client';
|
|
6
21
|
export { executeHetznerServerResize, isHetznerCapacityError, planHetznerServerResize, } from './hetzner/resize';
|
|
7
22
|
export type { ExecuteHetznerResizeOptions, HetznerResizeHooks, HetznerResizePhase, HetznerResizePlan, HetznerResizeResult, HetznerResizeVerification, } from './hetzner/resize';
|
|
@@ -12,9 +27,10 @@ export type { HetznerHostOptimizationOptions, HetznerHostOptimizationPlan, Hetzn
|
|
|
12
27
|
export { acquireResizeLock, readResizeCheckpoint, resizeCheckpointPath, resizeLockPath, writeResizeCheckpoint, } from './hetzner/resize-state';
|
|
13
28
|
export type { HetznerResizeCheckpoint } from './hetzner/resize-state';
|
|
14
29
|
export { generateUbuntuAppCloudInit, wrapCloudInitUserData } from './hetzner/cloud-init';
|
|
30
|
+
export type { CloudInitUserDataExtras } from './hetzner/cloud-init';
|
|
15
31
|
export { ensureFirewall, ensureServer, ensureSshKey, serverPublicIpv4 } from './hetzner/provision';
|
|
16
32
|
export type { EnsuredResource, EnsuredServer, EnsureFirewallOptions, EnsureServerOptions, EnsureSshKeyOptions, } from './hetzner/provision';
|
|
17
|
-
export { buildSshArgs, scpUpload, sshExec, sshExecOrThrow, waitForCloudInit, waitForSsh } from './shared/remote-exec';
|
|
33
|
+
export { buildSshArgs, REMOTE_SCRIPT_RUNNER, remoteScriptRunner, scpUpload, sshExec, sshExecOrThrow, waitForCloudInit, waitForSsh } from './shared/remote-exec';
|
|
18
34
|
export type { RemoteExecOptions, RemoteExecResult, WaitOptions } from './shared/remote-exec';
|
|
19
35
|
export { AwsBoxProvisioner, buildBoxUserData, createBoxProvisioner, HetznerBoxProvisioner, UBUNTU_2404_AMI_PARAM, } from './shared/box-provision';
|
|
20
36
|
export type { AwsBoxProvisionerOptions, BoxPort, BoxProviderName, BoxProvisioner, BoxSpec, CreateBoxProvisionerOptions, ProvisionedBox, } from './shared/box-provision';
|
package/dist/drivers/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$g as q,Ah as Q,Bh as R,Ch as S,Dh as T,Eh as U,Fh as V,Gh as W,Hh as X,Ih as Y,Jh as Z,Kh as _,
|
|
1
|
+
import{$g as q,$h as qa,$i as hb,Ah as Q,Ai as Ra,Bg as a,Bh as R,Bi as Sa,Cg as b,Ch as S,Ci as Ta,Dg as c,Dh as T,Di as Ua,Eg as d,Eh as U,Ei as Va,Fh as V,Fi as Wa,Gh as W,Gi as Xa,Hh as X,Hi as Ya,Ih as Y,Ii as Za,Jh as Z,Ji as _a,Kh as _,Ki as $a,Lh as aa,Mh as ba,Nh as ca,Ni as ab,Oh as da,Oi as bb,Pg as e,Ph as ea,Pi as cb,Qg as f,Qh as fa,Qi as db,Rg as g,Rh as ga,Ri as eb,Sg as h,Sh as ha,Si as fb,Tg as i,Th as ia,Ti as gb,Ug as j,Uh as ja,Vg as k,Vh as ka,Wg as l,Wh as la,Xg as m,Xh as ma,Yg as n,Yh as na,Zg as o,Zh as oa,_g as p,_h as pa,ah as r,ai as ra,aj as ib,bh as s,bi as sa,bj as jb,ch as t,ci as ta,cj as kb,dh as u,di as ua,dj as lb,eh as v,ei as va,ej as mb,fh as w,fi as wa,fj as nb,gh as x,gi as xa,gj as ob,hh as y,hi as ya,ih as z,ii as za,jh as A,ji as Aa,ki as Ba,lh as B,li as Ca,mh as C,mi as Da,nh as D,ni as Ea,oh as E,oi as Fa,ph as F,pi as Ga,qh as G,qi as Ha,rh as H,ri as Ia,sh as I,si as Ja,th as J,ti as Ka,uh as K,ui as La,vh as L,vi as Ma,wh as M,wi as Na,xh as N,xi as Oa,yh as O,yi as Pa,zh as P,zi as Qa}from"../chunk-t8hzekmk.js";import"../chunk-n5xmh0ma.js";import"../chunk-6cxb8d6y.js";import"../chunk-ess6vxfj.js";import"../chunk-j1g67djb.js";import"../chunk-ac87ds1k.js";import"../chunk-n1hg0jxs.js";import"../chunk-4wdxsnn2.js";import"../chunk-r8t25tbm.js";import"../chunk-zjyz926j.js";export{_a as AwsBoxProvisioner,s as AwsDriver,Ba as BOOT_PARTITION_LABEL,ya as CloudDriverFactory,e as DEFAULT_RPX_CERTS_DIR,Aa as FIRST_BOOT_SCRIPT_PATH,Za as HetznerBoxProvisioner,B as HetznerClient,K as HetznerDriver,F as LEGACY_DRIVER_STATE_DIR,L as LocalBoxDriver,mb as MANAGED_CACHE_POLICY_DISABLED,lb as MANAGED_CACHE_POLICY_OPTIMIZED,nb as MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER,aa as RASPBERRY_PI_DEFAULT_SWAP_GB,A as REMOTE_SCRIPT_RUNNER,m as RPX_DIR,n as RPX_LAUNCHER_PATH,o as RPX_SERVICE_NAME,Z as SSH_BOOTSTRAP_MARKER_DIR,Y as SSH_BOOTSTRAP_VERSION,da as SSH_DEFAULTS,ta as SSH_DEPLOY_STORAGE_PATH,N as SSH_INSECURE_HOST_KEY_OPTS,O as SSH_KEEPALIVE_OPTS,oa as SSH_PREFLIGHT_SCRIPT,ua as SSH_SKIP_BOOTSTRAP_ENV,wa as SshDriver,X as SystemSshTransport,Xa as UBUNTU_2404_AMI_PARAM,Sa as acquireResizeLock,La as applyHetznerHostOptimization,ba as assertArchSupported,va as assertSshComputeConfig,eb as buildAwsArtifactFetch,Ya as buildBoxUserData,ob as buildCloudFrontOriginConfig,Ca as buildCloudInitFirstBoot,Ka as buildHetznerHostOptimizationScript,gb as buildHostCleanupScript,fb as buildLocalArtifactFetch,j as buildRpxConfig,q as buildRpxFragmentRefreshScript,k as buildRpxLbConfig,p as buildRpxProvisionScript,Q as buildScpArgsFor,bb as buildSiteDeployScript,t as buildSshArgs,P as buildSshArgsFor,ca as buildSshBootstrapScript,cb as buildStaticSiteDeployScript,za as cloudDrivers,Ma as collectHetznerHostOptimizationReport,Ga as collectHetznerResizeManifest,$a as createBoxProvisioner,xa as createCloudDriver,ib as deployAllComputeSites,hb as deploySiteRelease,i as deriveRouteId,a as describeScriptSyntaxError,G as driverStateDir,H as driverStatePath,Ua as ensureFirewall,Va as ensureServer,Ta as ensureSshKey,qa as evaluatePreflight,Fa as executeHetznerServerResize,V as findKnownHostKey,sa as formatPreflightFindings,b as formatSshFailure,g as gatewayHostnames,r as generateUbuntuAppCloudInit,f as hasAutoWwwVariant,M as isBoxMode,Ea as isHetznerCapacityError,U as knownHostsLine,T as knownHostsToken,h as normalizeRoutePath,D as normalizeSshPublicKey,pa as parsePreflightFacts,Da as planHetznerServerResize,ra as preflightFailed,Ha as prepareHetznerResize,I as readDriverState,Qa as readResizeCheckpoint,db as releaseTarballTmpPath,jb as reloadRpxGateway,z as remoteScriptRunner,l as renderRpxLauncher,kb as renewRpxCertificates,Oa as resizeCheckpointPath,Pa as resizeLockPath,ab as resolveExecStart,C as resolveHetznerApiToken,Ja as resolveHetznerHostOptimizationPlan,ia as resolveSshHostKeyPolicy,ea as resolveSshHosts,ma as resolveSshLan,ga as resolveSshPort,ha as resolveSshPrivateKeyPath,ka as resolveSshProfile,la as resolveSshPublicIp,na as resolveSshSettings,ja as resolveSshSudo,fa as resolveSshUser,S as scanHostKey,w as scpUpload,Wa as serverPublicIpv4,_ as sshBootstrapMarkerPath,u as sshExec,v as sshExecOrThrow,R as sshHostKeyFingerprint,W as sshKnownHostsPath,d as summarizeRemoteFailures,c as surfaceRemoteNotices,Na as verifyHetznerHostOptimization,Ia as verifyHetznerResize,y as waitForCloudInit,x as waitForSsh,E as wrapCloudInitUserData,J as writeDriverState,Ra as writeResizeCheckpoint};
|
|
@@ -9,7 +9,7 @@ import type { CloudDriver, ComputeStackOutputs, ComputeTarget, FindComputeTarget
|
|
|
9
9
|
* the box; provisioning/upload methods are inert (the box is already up).
|
|
10
10
|
*/
|
|
11
11
|
export declare class LocalBoxDriver implements CloudDriver {
|
|
12
|
-
readonly name: '
|
|
12
|
+
readonly name: 'ssh';
|
|
13
13
|
readonly usesCloudFormation = false;
|
|
14
14
|
getComputeOutputs(): Promise<ComputeStackOutputs>;
|
|
15
15
|
uploadRelease(options: UploadReleaseOptions): Promise<UploadReleaseResult>;
|
|
@@ -49,18 +49,6 @@ export declare function buildManagementDashboardServiceReconciliationScript(slug
|
|
|
49
49
|
* without `start`, shipped to `/var/www/<site>`). Bucket sites are skipped.
|
|
50
50
|
*/
|
|
51
51
|
export declare function deployAllComputeSites(options: DeployAllSitesOptions): Promise<boolean>;
|
|
52
|
-
/**
|
|
53
|
-
* Regenerate the rpx gateway config from the sites model and (re)start the
|
|
54
|
-
* gateway. No-op (returns `true`) unless `compute.proxy.engine === 'rpx'`.
|
|
55
|
-
*
|
|
56
|
-
* Two shapes, resolved by probing for a dedicated load-balancer target:
|
|
57
|
-
* - **Fleet** (bun-style: one rpx LB box fronts N gateway-less app boxes) —
|
|
58
|
-
* rewrite ONLY the LB's route fragment with the multi-upstream LB config
|
|
59
|
-
* ({@link buildRpxLbConfig} + {@link buildRpxFragmentRefreshScript}).
|
|
60
|
-
* - **Single box** — the gateway is co-located with the app, so the full
|
|
61
|
-
* provision script runs on the app targets. Re-runnable: it rewrites the
|
|
62
|
-
* launcher + unit and `systemctl restart`s, reloading the new routes.
|
|
63
|
-
*/
|
|
64
52
|
export declare function reloadRpxGateway(options: DeployAllSitesOptions): Promise<boolean>;
|
|
65
53
|
/**
|
|
66
54
|
* Request the first production certificates after DNS has been reconciled.
|
|
@@ -33,6 +33,13 @@ export interface ComputeProvisionOptions {
|
|
|
33
33
|
* than one that offers SMTP to the internet.
|
|
34
34
|
*/
|
|
35
35
|
environment?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Where the managed `authorized_keys` block is written. Defaults to root's
|
|
38
|
+
* file; a bootstrap that deploys as another user (the ssh provider with a
|
|
39
|
+
* `pi` or `deploy` user) points it at that user's home, or the operator
|
|
40
|
+
* keys in `compute.sshKeys` would authorize logins for the wrong account.
|
|
41
|
+
*/
|
|
42
|
+
authorizedKeysPath?: string;
|
|
36
43
|
}
|
|
37
44
|
/**
|
|
38
45
|
* Build the machine provisioning scripts from a CloudConfig. Returns the
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-stack state a compute driver records on the machine running deploys.
|
|
3
|
+
*
|
|
4
|
+
* Every SSH-style driver has to remember which box a stack lives on: Hetzner
|
|
5
|
+
* pins a server id so CI can find the existing box instead of provisioning a
|
|
6
|
+
* duplicate, and the ssh driver pins the host it adopted plus what it did to
|
|
7
|
+
* it. One file per stack, one reader and one writer, so a driver, the
|
|
8
|
+
* dashboard and the CLI cannot disagree about where that file is.
|
|
9
|
+
*
|
|
10
|
+
* ## Where the file lives
|
|
11
|
+
*
|
|
12
|
+
* Driver state predates the configurable state directory and has a legacy
|
|
13
|
+
* home of its own, `storage/cloud/state/` (the Stacks storage convention),
|
|
14
|
+
* which is meant to be COMMITTED: unlike dashboard credentials it holds
|
|
15
|
+
* nothing secret, and a checkout without it re-provisions. A project that
|
|
16
|
+
* configured `stateDir` (or set `TS_CLOUD_STATE_DIR`) keeps driver state
|
|
17
|
+
* under it instead, in `<stateDir>/state/`. A Stacks application sets
|
|
18
|
+
* `stateDir: 'storage/cloud'`, so for it the two spellings name the same
|
|
19
|
+
* directory and nothing moves.
|
|
20
|
+
*/
|
|
21
|
+
import type { HetznerDriverState } from '../hetzner/state';
|
|
22
|
+
/** The committed driver-state directory used when no state directory is configured. */
|
|
23
|
+
export declare const LEGACY_DRIVER_STATE_DIR = "storage/cloud/state";
|
|
24
|
+
/** What the ssh driver remembers about a host it adopted. */
|
|
25
|
+
export interface SshDriverState {
|
|
26
|
+
provider: 'ssh';
|
|
27
|
+
stackName: string;
|
|
28
|
+
/** The hostname or address deploys connect to, exactly as configured. */
|
|
29
|
+
host: string;
|
|
30
|
+
sshUser: string;
|
|
31
|
+
sshPort: number;
|
|
32
|
+
/** `SHA256:...` of the pinned host key, when the host-key policy pins. */
|
|
33
|
+
hostKeyFingerprint?: string;
|
|
34
|
+
/** The address DNS should point at, when known (configured, or detected). */
|
|
35
|
+
publicIp?: string;
|
|
36
|
+
/** The host's first LAN address, as reported by the preflight. */
|
|
37
|
+
lanIp?: string;
|
|
38
|
+
deployStoragePath?: string;
|
|
39
|
+
profile?: 'raspberry-pi' | 'generic';
|
|
40
|
+
/** The bootstrap recipe version last applied to the host. */
|
|
41
|
+
bootstrapVersion?: number;
|
|
42
|
+
/** When that bootstrap ran, ISO 8601. */
|
|
43
|
+
bootstrappedAt?: string;
|
|
44
|
+
}
|
|
45
|
+
export type DriverState = HetznerDriverState | SshDriverState;
|
|
46
|
+
/**
|
|
47
|
+
* The directory driver state files live in, absolute.
|
|
48
|
+
*
|
|
49
|
+
* `<stateDir>/state` when a state directory is configured, the legacy
|
|
50
|
+
* `storage/cloud/state` otherwise. See the module comment for why the legacy
|
|
51
|
+
* path is not simply `.ts-cloud/state`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function driverStateDir(cwd?: string): string;
|
|
54
|
+
/** Absolute path of the state file for `stackName`. */
|
|
55
|
+
export declare function driverStatePath(stackName: string, cwd?: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Read the state file for `stackName`, or null when there is none (or it is
|
|
58
|
+
* unreadable: a corrupt file is treated as absent, and the atomic write below
|
|
59
|
+
* is what keeps that from ever losing a pin).
|
|
60
|
+
*/
|
|
61
|
+
export declare function readDriverState<T extends DriverState = DriverState>(stackName: string, cwd?: string): Promise<T | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Replace the state file for `stackName` atomically: a crash mid-write would
|
|
64
|
+
* corrupt the JSON, and the reader's catch-all would then lose the pinned box
|
|
65
|
+
* (silently re-provisioning a duplicate). Temp file + rename on the same
|
|
66
|
+
* filesystem is atomic.
|
|
67
|
+
*/
|
|
68
|
+
export declare function writeDriverState(stackName: string, state: DriverState, cwd?: string): Promise<void>;
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
export interface RemoteExecOptions {
|
|
10
10
|
/** SSH user. @default 'root' */
|
|
11
11
|
user?: string;
|
|
12
|
+
/** SSH port. Omit for the ambient default (22, or whatever `~/.ssh/config` says). */
|
|
13
|
+
port?: number;
|
|
12
14
|
/** Private key passed as `ssh -i`. Omit to use the ambient SSH config/agent. */
|
|
13
15
|
identityFile?: string;
|
|
14
16
|
/** SSH `ConnectTimeout` in seconds. @default 10 */
|
|
@@ -23,8 +25,11 @@ export interface RemoteExecResult {
|
|
|
23
25
|
* The ssh/scp CLI arguments implied by {@link RemoteExecOptions}. Host key
|
|
24
26
|
* checking is disabled because these helpers target freshly-created servers
|
|
25
27
|
* whose host keys cannot be known in advance.
|
|
28
|
+
*
|
|
29
|
+
* `scp` spells the port flag differently (`-P`; its `-p` preserves file
|
|
30
|
+
* times), so say which binary the arguments are for.
|
|
26
31
|
*/
|
|
27
|
-
export declare function buildSshArgs(options?: RemoteExecOptions): string[];
|
|
32
|
+
export declare function buildSshArgs(options?: RemoteExecOptions, binary?: 'ssh' | 'scp'): string[];
|
|
28
33
|
/** Run a command on the host over SSH, capturing exit code and output. */
|
|
29
34
|
export declare function sshExec(host: string, command: string, options?: RemoteExecOptions): Promise<RemoteExecResult>;
|
|
30
35
|
/** Like {@link sshExec}, but throws on non-zero exit and returns stdout. */
|
|
@@ -63,4 +68,8 @@ export declare function waitForCloudInit(host: string, options?: WaitOptions): P
|
|
|
63
68
|
* `-s` in the first place), and `mktemp` creates the file 0600, so the window
|
|
64
69
|
* where they touch disk is both short and unreadable to other users.
|
|
65
70
|
*/
|
|
71
|
+
export declare function remoteScriptRunner(options?: {
|
|
72
|
+
sudo?: boolean;
|
|
73
|
+
}): string;
|
|
74
|
+
/** The runner for a root deploy user; see {@link remoteScriptRunner}. */
|
|
66
75
|
export declare const REMOTE_SCRIPT_RUNNER: string;
|
|
@@ -12,6 +12,47 @@
|
|
|
12
12
|
* `formatSshFailure`), so this only has to decide what is worth showing.
|
|
13
13
|
*/
|
|
14
14
|
import type { RemoteDeployInstanceResult } from '@ts-cloud/core';
|
|
15
|
+
/**
|
|
16
|
+
* The part of the deploy script bash refused to parse.
|
|
17
|
+
*
|
|
18
|
+
* A syntax error names a line number in a file that only ever existed on the
|
|
19
|
+
* box, and the deploy deletes it on the way out, so the one thing needed to
|
|
20
|
+
* understand the failure is the one thing nobody can look at. Without this you
|
|
21
|
+
* are reduced to guessing which generated fragment is unbalanced, or to
|
|
22
|
+
* reproducing the whole script by hand from its builders.
|
|
23
|
+
*
|
|
24
|
+
* Only a window around the reported line, and every `KEY="value"` line inside
|
|
25
|
+
* it is redacted: the script carries the runtime environment, and a deploy
|
|
26
|
+
* failure must not become the reason a database password is in a CI log.
|
|
27
|
+
*/
|
|
28
|
+
export declare function describeScriptSyntaxError(error: unknown, script: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* One operator-facing line (plus redacted output) for a failed ssh/scp child.
|
|
31
|
+
*
|
|
32
|
+
* Takes the shape Node's `execFileSync` error has (`status`, `signal`,
|
|
33
|
+
* `stdout`, `stderr`) so a `Bun.spawn`-based transport only has to build the
|
|
34
|
+
* same object. Never includes the command line: it carries the deploy script.
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatSshFailure(error: unknown): string;
|
|
37
|
+
/**
|
|
38
|
+
* Print the lines a remote deploy script meant a human to read.
|
|
39
|
+
*
|
|
40
|
+
* The remote stdout has always been captured and then dropped on the floor,
|
|
41
|
+
* which is why nothing the box says has ever reached a CI log: not the
|
|
42
|
+
* memory-commitment report, not `migrate`, not `catalog:sync`. A deploy that
|
|
43
|
+
* cannot tell you what it did on the box is one you have to SSH in to
|
|
44
|
+
* understand, and by then you are debugging rather than reading.
|
|
45
|
+
*
|
|
46
|
+
* Only `[ts-cloud]`-prefixed lines are surfaced, and that restraint is
|
|
47
|
+
* deliberate rather than tidy. The script fed to `bash -s` carries the runtime
|
|
48
|
+
* environment here-document - database credentials, APP_KEY, provider tokens -
|
|
49
|
+
* which is why {@link formatSshFailure} refuses to echo a failing command back.
|
|
50
|
+
* Remote *stdout* is not the script, so it does not contain those secrets by
|
|
51
|
+
* construction, but it is whatever arbitrary `preStart` commands chose to
|
|
52
|
+
* print, and an app that logs its own config on boot would leak it here. An
|
|
53
|
+
* explicit marker means ts-cloud only ever republishes lines ts-cloud wrote.
|
|
54
|
+
*/
|
|
55
|
+
export declare function surfaceRemoteNotices(output: string): void;
|
|
15
56
|
/**
|
|
16
57
|
* Build the `error` for a {@link import('@ts-cloud/core').RemoteDeployResult}
|
|
17
58
|
* whose run did not fully succeed. `summary` is the one-line what-failed (e.g.
|
|
@@ -19,10 +19,27 @@
|
|
|
19
19
|
* It replaces the old Caddyfile generation — pantry/stacks use rpx (their own
|
|
20
20
|
* tooling), so the gateway is rpx, not Caddy.
|
|
21
21
|
*/
|
|
22
|
-
import type { ComputeProxyConfig, RpxLoadBalancerConfig, SiteConfig, SiteRedirectConfig } from '@ts-cloud/core';
|
|
22
|
+
import type { CloudConfig, ComputeProxyConfig, RpxLoadBalancerConfig, SiteConfig, SiteRedirectConfig } from '@ts-cloud/core';
|
|
23
23
|
/** Default directory on the box that holds real per-domain TLS certs. */
|
|
24
24
|
export declare const DEFAULT_RPX_CERTS_DIR = "/etc/rpx/certs";
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Where the LAN certificate authority lives on the box. rpx writes the CA
|
|
27
|
+
* (`rpx-root-ca.crt` / `.key`) and the leaf it signs here; the CA cert is the
|
|
28
|
+
* one file an operator copies off the box to trust on a laptop or a phone.
|
|
29
|
+
*/
|
|
30
|
+
export declare const DEFAULT_LOCAL_CA_DIR = "/etc/rpx/local-ca";
|
|
31
|
+
/** rpx's own filename for the CA certificate inside {@link DEFAULT_LOCAL_CA_DIR}. */
|
|
32
|
+
export declare const LOCAL_CA_ROOT_CERT_FILENAME = "rpx-root-ca.crt";
|
|
33
|
+
/** Absolute path to the CA certificate a client has to trust. */
|
|
34
|
+
export declare function localCaCertPath(dir?: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the gateway adds a `www.` redirect for `domain` on its own.
|
|
37
|
+
*
|
|
38
|
+
* Apex domains only, and never an mDNS name: `pi-app.local` also has two
|
|
39
|
+
* labels, but nobody types `www.pi-app.local`, no LAN resolves it, and the
|
|
40
|
+
* route it would create is a host the LAN certificate does not cover, so it
|
|
41
|
+
* is a browser warning on a name that exists for no reason.
|
|
42
|
+
*/
|
|
26
43
|
export declare function hasAutoWwwVariant(domain: string): boolean;
|
|
27
44
|
/**
|
|
28
45
|
* Every hostname the gateway will answer for a sites config.
|
|
@@ -137,6 +154,68 @@ export interface RpxRoute {
|
|
|
137
154
|
* enabled (default) AND a password is present — no password is ever invented.
|
|
138
155
|
*/
|
|
139
156
|
export declare function resolveRouteAuth(site: SiteConfig): RpxRoute['auth'];
|
|
157
|
+
/**
|
|
158
|
+
* The gateway's LAN certificate authority, mirroring rpx's `LocalCaConfig`
|
|
159
|
+
* (see `@stacksjs/rpx`'s `types.ts`, available since 0.11.49). rpx loads or
|
|
160
|
+
* creates the CA under `dir`, signs ONE leaf covering `hosts` + `ips`, and
|
|
161
|
+
* registers it both per server name and as the default TLS context, so a
|
|
162
|
+
* connection that sends no SNI at all (an IP-literal URL) still gets it.
|
|
163
|
+
*/
|
|
164
|
+
export interface RpxLocalCaConfig {
|
|
165
|
+
/** Directory holding the CA and the leaf it signs. See {@link DEFAULT_LOCAL_CA_DIR}. */
|
|
166
|
+
dir: string;
|
|
167
|
+
/** dNSName SANs on the leaf, e.g. `['pi-app.local']`. Never empty. */
|
|
168
|
+
hosts: string[];
|
|
169
|
+
/** iPAddress SANs, so the box is also reachable by address over TLS. */
|
|
170
|
+
ips?: string[];
|
|
171
|
+
/** Install the CA into the box's OWN system trust store (rpx runs as root here). */
|
|
172
|
+
installTrust?: boolean;
|
|
173
|
+
/** Leaf validity in days. Omitted so rpx applies its documented default (825). */
|
|
174
|
+
validityDays?: number;
|
|
175
|
+
/** Re-mint when fewer than this many days remain. Omitted for rpx's default (30). */
|
|
176
|
+
renewBeforeDays?: number;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* LAN settings for a gateway on a host that is not on the public internet.
|
|
180
|
+
*
|
|
181
|
+
* This is the ONLY input that makes {@link buildRpxConfig} emit `localCa` or
|
|
182
|
+
* `https: false`, and it is passed exclusively on the ssh-provider path (see
|
|
183
|
+
* {@link resolveGatewayLan}), which is what keeps every cloud driver's
|
|
184
|
+
* emitted config byte-identical to what it produced before LAN TLS existed.
|
|
185
|
+
*/
|
|
186
|
+
export interface RpxLanOptions {
|
|
187
|
+
/** The LAN name the gateway's certificate covers. Defaults to `<slug>.local`. */
|
|
188
|
+
hostname?: string;
|
|
189
|
+
/** `'local-ca'` issues a LAN certificate; `'off'` serves plain HTTP. @default 'local-ca' */
|
|
190
|
+
tls?: 'local-ca' | 'off';
|
|
191
|
+
/**
|
|
192
|
+
* The box's LAN address, when it is actually known: the ssh preflight's
|
|
193
|
+
* `lanIp`, else the configured ssh host when that is an IP literal. Never
|
|
194
|
+
* guessed: a wrong iPAddress SAN is worse than an absent one.
|
|
195
|
+
*/
|
|
196
|
+
ip?: string;
|
|
197
|
+
}
|
|
198
|
+
/** `lan.tls` with its default applied, or `undefined` when there is no LAN config. */
|
|
199
|
+
export declare function lanTlsMode(lan?: RpxLanOptions): 'local-ca' | 'off' | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* The LAN options for a config, or `undefined` when LAN TLS does not apply.
|
|
202
|
+
*
|
|
203
|
+
* The provider gate lives HERE, in one function, rather than at each call
|
|
204
|
+
* site: `ssh.lan` is meaningless for a cloud box (a Hetzner host has no LAN an
|
|
205
|
+
* operator can reach), and a driver that reads it anyway would start emitting
|
|
206
|
+
* a `localCa` the box can never use. Callers with resolved ssh settings should
|
|
207
|
+
* pass those instead; this reads `cloud.config.ts` alone, so a `TS_CLOUD_SSH_*`
|
|
208
|
+
* override is not visible to it.
|
|
209
|
+
*/
|
|
210
|
+
export declare function resolveGatewayLan(config: Pick<CloudConfig, 'cloud' | 'ssh'>, lanIp?: string): RpxLanOptions | undefined;
|
|
211
|
+
/** The host profile the gateway unit should be tuned for, when one is known. */
|
|
212
|
+
export declare function resolveGatewayProfile(config: Pick<CloudConfig, 'cloud' | 'ssh'>): 'raspberry-pi' | 'generic' | undefined;
|
|
213
|
+
/**
|
|
214
|
+
* Is `domain` a name only a LAN can resolve? Either an mDNS `.local` name or a
|
|
215
|
+
* bare single-label hostname. Public CAs cannot issue for either, so these are
|
|
216
|
+
* exactly the names that need the box's own CA instead.
|
|
217
|
+
*/
|
|
218
|
+
export declare function isLanHostname(domain: string): boolean;
|
|
140
219
|
/** The rpx daemon/proxy config produced from a sites model. */
|
|
141
220
|
export interface RpxGatewayConfig {
|
|
142
221
|
/** Multi-proxy route list (host + path keyed). */
|
|
@@ -167,8 +246,18 @@ export interface RpxGatewayConfig {
|
|
|
167
246
|
* down to free `:80`. Omitted ⇒ the `:80` server only redirects.
|
|
168
247
|
*/
|
|
169
248
|
acmeChallengeWebroot?: string;
|
|
170
|
-
/**
|
|
171
|
-
|
|
249
|
+
/**
|
|
250
|
+
* `true` (the only value any public deploy produces) terminates TLS on the
|
|
251
|
+
* box. `false` is the LAN opt-out (`ssh.lan.tls: 'off'`): rpx then binds the
|
|
252
|
+
* HTTP port only, and nothing on `:443`.
|
|
253
|
+
*/
|
|
254
|
+
https: boolean;
|
|
255
|
+
/**
|
|
256
|
+
* LAN certificate authority: rpx signs one leaf for these names with a CA it
|
|
257
|
+
* keeps on the box. Emitted ONLY on the ssh-provider path; see
|
|
258
|
+
* {@link RpxLanOptions}.
|
|
259
|
+
*/
|
|
260
|
+
localCa?: RpxLocalCaConfig;
|
|
172
261
|
/** Never touch `/etc/hosts` on a real server with real DNS. */
|
|
173
262
|
hostsManagement: false;
|
|
174
263
|
/** Don't remove certs/hosts on exit. */
|
|
@@ -199,6 +288,12 @@ export interface BuildRpxConfigOptions {
|
|
|
199
288
|
* wrong directory.
|
|
200
289
|
*/
|
|
201
290
|
slug?: string;
|
|
291
|
+
/**
|
|
292
|
+
* LAN settings for a host with no public DNS. Passed on the ssh-provider
|
|
293
|
+
* path only (see {@link resolveGatewayLan}); every other driver leaves it
|
|
294
|
+
* undefined and gets exactly the config it always got.
|
|
295
|
+
*/
|
|
296
|
+
lan?: RpxLanOptions;
|
|
202
297
|
}
|
|
203
298
|
/**
|
|
204
299
|
* Normalize a path prefix to a leading-slash, no-trailing-slash form, or
|
|
@@ -313,7 +408,32 @@ export interface BuildRpxProvisionOptions {
|
|
|
313
408
|
bunBin?: string;
|
|
314
409
|
/** Keep the dashboard route currently running on the box during an app-only deploy. */
|
|
315
410
|
preserveManagementDashboardRoutes?: boolean;
|
|
411
|
+
/**
|
|
412
|
+
* Host profile, when the caller knows it (the ssh provider resolves one; the
|
|
413
|
+
* cloud drivers do not and leave this undefined, keeping their unit byte for
|
|
414
|
+
* byte what it was). `raspberry-pi` lowers the gateway's memory ceilings, see
|
|
415
|
+
* {@link RASPBERRY_PI_PROXY_MEMORY}.
|
|
416
|
+
*/
|
|
417
|
+
profile?: 'raspberry-pi' | 'generic';
|
|
316
418
|
}
|
|
419
|
+
/**
|
|
420
|
+
* Gateway cgroup ceilings by host profile.
|
|
421
|
+
*
|
|
422
|
+
* The generic defaults are sized for a 4G+ cloud box. A Pi is commonly a 2G
|
|
423
|
+
* board also running the app, a database and swap on an SD card, where a
|
|
424
|
+
* 768M ceiling is not a bound at all: the gateway can take a third of RAM
|
|
425
|
+
* before systemd notices, and the reclaim that follows lands on the SD card.
|
|
426
|
+
* The gateway's steady state is well under 100M on either machine, so the
|
|
427
|
+
* lower pair still leaves the same order of magnitude of burst room.
|
|
428
|
+
*/
|
|
429
|
+
export declare const RASPBERRY_PI_PROXY_MEMORY: {
|
|
430
|
+
readonly high: '256M';
|
|
431
|
+
readonly max: '384M';
|
|
432
|
+
};
|
|
433
|
+
export declare const DEFAULT_PROXY_MEMORY: {
|
|
434
|
+
readonly high: '512M';
|
|
435
|
+
readonly max: '768M';
|
|
436
|
+
};
|
|
317
437
|
export declare const RPX_CERT_RENEW_SCRIPT = "/etc/rpx/renew-certs.sh";
|
|
318
438
|
export declare const RPX_CERT_RENEW_SERVICE = "rpx-cert-renew.service";
|
|
319
439
|
export declare const RPX_CERT_RENEW_TIMER = "rpx-cert-renew.timer";
|