@stacksjs/ts-cloud 0.16.23 → 0.16.25
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/client.d.ts +9 -0
- package/dist/aws/index.js +1 -1
- package/dist/bin/chunk-0cwbg3pf.js +1 -0
- package/dist/bin/{chunk-6cfpdb35.js → chunk-0xxc6dy8.js} +7 -7
- package/dist/bin/chunk-19tmmwmt.js +1 -0
- package/dist/bin/{chunk-2tk8egg8.js → chunk-1j9vy88a.js} +1 -1
- package/dist/bin/{chunk-wyanqf91.js → chunk-21jwbrap.js} +2 -2
- package/dist/bin/{chunk-j0zg3mbm.js → chunk-2q27v6vz.js} +1 -1
- package/dist/bin/{chunk-9h7yjtz2.js → chunk-3jjggqfj.js} +3 -3
- package/dist/bin/{chunk-zcabmq4p.js → chunk-3kvz4kyq.js} +3 -3
- package/dist/bin/chunk-4261t3bq.js +1 -0
- package/dist/bin/chunk-4a98nszr.js +1 -0
- package/dist/bin/{chunk-k1eezsj1.js → chunk-4r46kw46.js} +2 -2
- package/dist/bin/chunk-5mk3sxpw.js +34 -0
- package/dist/bin/{chunk-jtnv8nwz.js → chunk-6nm91cfw.js} +1 -1
- package/dist/bin/{chunk-ht6tpmqw.js → chunk-7412q5cz.js} +2 -2
- package/dist/bin/chunk-78tzgf65.js +1 -0
- package/dist/bin/{chunk-h90azajz.js → chunk-82sbpydz.js} +2 -2
- package/dist/bin/{chunk-ht318ydv.js → chunk-8knkt6sd.js} +1 -1
- package/dist/bin/{chunk-65rndjtr.js → chunk-8wnpx6n2.js} +42 -42
- package/dist/bin/{chunk-k052rtd5.js → chunk-9066j2kz.js} +4 -4
- package/dist/bin/{chunk-34kwhmbt.js → chunk-9464wvf2.js} +5 -5
- package/dist/bin/{chunk-cpwk0pbg.js → chunk-9rya3733.js} +65 -65
- package/dist/bin/chunk-ajv4z454.js +1 -0
- package/dist/bin/chunk-aqreqn37.js +1 -0
- package/dist/bin/chunk-cnmngqqg.js +1 -0
- package/dist/bin/chunk-db9zx72q.js +1 -0
- package/dist/bin/{chunk-8vm7tpyv.js → chunk-dh6kj6ce.js} +2 -2
- package/dist/bin/chunk-dhj4786e.js +1 -0
- package/dist/bin/chunk-eh3235zq.js +1 -0
- package/dist/bin/chunk-es4sdbrr.js +1 -0
- package/dist/bin/{chunk-xs6afjat.js → chunk-fdsh3m2q.js} +3 -3
- package/dist/bin/chunk-g0gqwszk.js +1 -0
- package/dist/bin/chunk-gj530nqd.js +1 -0
- package/dist/bin/chunk-h1618tyv.js +1 -0
- package/dist/bin/chunk-hje6rsxj.js +2 -0
- package/dist/bin/chunk-hwqvx1zb.js +1 -0
- package/dist/bin/chunk-ksfr2ya8.js +1 -0
- package/dist/bin/{chunk-f2yhthd1.js → chunk-mdbzfvba.js} +2 -2
- package/dist/bin/chunk-mfer1e5z.js +1 -0
- package/dist/bin/chunk-mh172wt8.js +1 -0
- package/dist/bin/chunk-mrte8smv.js +1 -0
- package/dist/bin/{chunk-90kpnjdm.js → chunk-n5zwm2z4.js} +12 -12
- package/dist/bin/chunk-n8ya6q6d.js +2 -0
- package/dist/bin/{chunk-en7sf83z.js → chunk-ntmnpteh.js} +6 -6
- package/dist/bin/{chunk-f3sd1hpa.js → chunk-nxyhheav.js} +5 -5
- package/dist/bin/chunk-p1cv4n00.js +2 -0
- package/dist/bin/{chunk-t1jpqn4x.js → chunk-q3xwh0r8.js} +6 -6
- package/dist/bin/chunk-s7axkfrs.js +1 -0
- package/dist/bin/{chunk-tyqxz92e.js → chunk-t5gkbppg.js} +105 -105
- package/dist/bin/{chunk-jbpkwxht.js → chunk-td8zgch7.js} +5 -5
- package/dist/bin/{chunk-gzpwf3n4.js → chunk-tnzp96vn.js} +2 -2
- package/dist/bin/{chunk-0r45d0s3.js → chunk-v4e4726j.js} +1 -1
- package/dist/bin/{chunk-33e0t7e5.js → chunk-w23en85y.js} +2 -2
- package/dist/bin/{chunk-21zhm1mk.js → chunk-wsedynyb.js} +6 -6
- package/dist/bin/{chunk-v002yxaf.js → chunk-xss6yj73.js} +2 -2
- package/dist/bin/{chunk-btr6zq53.js → chunk-y4g86dpe.js} +3 -3
- package/dist/bin/{chunk-hqmkfh4a.js → chunk-y6rgvb7r.js} +1 -1
- package/dist/bin/chunk-yavtz60y.js +1 -0
- package/dist/bin/{chunk-yxyvhqhr.js → chunk-z5ycwy38.js} +2 -2
- package/dist/bin/{chunk-gfwkmttt.js → chunk-z96ssb7e.js} +1 -1
- package/dist/bin/chunk-zq02x716.js +1 -0
- package/dist/bin/cli.js +285 -285
- package/dist/bin/dashboard-server.js +1 -1
- package/dist/{chunk-hpq0rrve.js → chunk-08tswmb3.js} +1 -1
- package/dist/{chunk-gm0qysea.js → chunk-0p7ddjt6.js} +10 -10
- package/dist/chunk-2nma0bd8.js +92 -0
- package/dist/chunk-31qham3c.js +1 -0
- package/dist/chunk-3zv0e36t.js +34 -0
- package/dist/{chunk-c836kdrx.js → chunk-49p5cx21.js} +29 -29
- package/dist/{chunk-t7q4awss.js → chunk-5db32a4x.js} +2 -2
- package/dist/{chunk-60fn008g.js → chunk-6e5j40n9.js} +2 -2
- package/dist/chunk-7fbfmpyx.js +1 -0
- package/dist/{chunk-4apkvhsc.js → chunk-7p1653g6.js} +83 -83
- package/dist/{chunk-cpyrhh52.js → chunk-826gp2kd.js} +142 -142
- package/dist/{chunk-92gn9ght.js → chunk-98qx6m9h.js} +19 -19
- package/dist/{chunk-rq0wrpz6.js → chunk-b10n1xy5.js} +4 -4
- package/dist/{chunk-j2w0cvnr.js → chunk-dm6kyz6e.js} +1 -1
- package/dist/chunk-dschvakr.js +1 -0
- package/dist/chunk-e44ajkha.js +5 -0
- package/dist/chunk-e4z4tfh6.js +1 -0
- package/dist/{chunk-bz1hp7es.js → chunk-gvybjt7y.js} +1 -1
- package/dist/{chunk-xassxhvq.js → chunk-h85wqdvr.js} +7 -7
- package/dist/{chunk-nfkdgsgh.js → chunk-jwx5t3vf.js} +11 -11
- package/dist/chunk-kmwnzw91.js +1 -0
- package/dist/{chunk-14zcywnp.js → chunk-q0g0rjn3.js} +2 -2
- package/dist/{chunk-ckwdjb5q.js → chunk-qfqh21rq.js} +5 -5
- package/dist/{chunk-b5xjjz3y.js → chunk-r1730x8g.js} +5 -5
- package/dist/{chunk-g6aev693.js → chunk-rr1qjxyj.js} +1 -1
- package/dist/chunk-rxs4y74z.js +2 -0
- package/dist/{chunk-xkqx98bx.js → chunk-setpnrtg.js} +2 -2
- package/dist/chunk-tvwrthfq.js +2 -0
- package/dist/{chunk-ds2v2xpb.js → chunk-w23wrsa4.js} +123 -123
- package/dist/{chunk-5vxpgw8q.js → chunk-wrpnnrdf.js} +5 -5
- package/dist/{chunk-pdmfmsm9.js → chunk-x9bpm5s1.js} +1 -1
- 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 +43 -43
- 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 +5 -5
- 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 +6 -6
- 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 +6 -6
- 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 +2 -2
- 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 +6 -6
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +5 -5
- package/dist/ui/server/fleet.html +6 -6
- package/dist/ui/server/logs.html +6 -6
- package/dist/ui/server/metrics.html +6 -6
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- 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 +5 -5
- package/package.json +3 -3
- package/dist/bin/chunk-0d98bem8.js +0 -2
- package/dist/bin/chunk-2g1j00yc.js +0 -1
- package/dist/bin/chunk-4xmhrvfa.js +0 -1
- package/dist/bin/chunk-6crapvp1.js +0 -1
- package/dist/bin/chunk-7b4gf64x.js +0 -1
- package/dist/bin/chunk-818tj49e.js +0 -1
- package/dist/bin/chunk-92qsww97.js +0 -1
- package/dist/bin/chunk-9947rscj.js +0 -1
- package/dist/bin/chunk-cas0bp91.js +0 -2
- package/dist/bin/chunk-cyap08qg.js +0 -1
- package/dist/bin/chunk-dk92s260.js +0 -1
- package/dist/bin/chunk-ejxp74ks.js +0 -1
- package/dist/bin/chunk-gx98tkpf.js +0 -1
- package/dist/bin/chunk-hcdbw9j1.js +0 -1
- package/dist/bin/chunk-hdsgfgnz.js +0 -34
- package/dist/bin/chunk-kay11qc7.js +0 -1
- package/dist/bin/chunk-n28a9a9c.js +0 -1
- package/dist/bin/chunk-n298azax.js +0 -2
- package/dist/bin/chunk-q8w7fa56.js +0 -1
- package/dist/bin/chunk-qdnx952p.js +0 -1
- package/dist/bin/chunk-tr0pkm4p.js +0 -1
- package/dist/bin/chunk-tytvrehe.js +0 -1
- package/dist/bin/chunk-wpp0fa94.js +0 -1
- package/dist/bin/chunk-xzgxwnb7.js +0 -1
- package/dist/bin/chunk-y21yk6zv.js +0 -1
- package/dist/bin/chunk-yt1t5ct8.js +0 -1
- package/dist/bin/chunk-zs8ddeaz.js +0 -1
- package/dist/chunk-01rbgche.js +0 -2
- package/dist/chunk-2hy7ny4k.js +0 -5
- package/dist/chunk-4rb7stp5.js +0 -92
- package/dist/chunk-cwgy9pvc.js +0 -34
- package/dist/chunk-e4qh4c2n.js +0 -1
- package/dist/chunk-pj9z4fjv.js +0 -1
- package/dist/chunk-twhbns31.js +0 -1
- package/dist/chunk-wkg22nj5.js +0 -1
- package/dist/chunk-xtd0s5ep.js +0 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import{ut,
|
|
2
|
-
`)){let r=n.trim();if(!r.startsWith("site:"))continue;let[,s,o,i]=r.split(":");if(!s||o!=="no")continue;e.push({name:s,size:i||"?"})}return e}function
|
|
1
|
+
import{ut,ui,pi,gi}from"./chunk-b10n1xy5.js";function S(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function rf(t,e="/var/www"){let n=`${e}/${t}-`;return["set -u",`for TS_CLOUD_DIR in ${n}*; do`,' [ -d "$TS_CLOUD_DIR" ] || continue',' [ -d "$TS_CLOUD_DIR/releases" ] || continue',` TS_CLOUD_SITE="\${TS_CLOUD_DIR#${n}}"`," TS_CLOUD_ACTIVE=no",` for TS_CLOUD_UNIT in $(ls /etc/systemd/system/ 2>/dev/null | grep -E "^${S(t)}-$TS_CLOUD_SITE[-@.]" || true); do`,' systemctl is-active "$TS_CLOUD_UNIT" >/dev/null 2>&1 && TS_CLOUD_ACTIVE=yes'," done",' TS_CLOUD_SIZE="$(du -sh "$TS_CLOUD_DIR" 2>/dev/null | cut -f1)"',' echo "site:$TS_CLOUD_SITE:$TS_CLOUD_ACTIVE:${TS_CLOUD_SIZE:-?}"',"done","exit 0"]}function nf(t){if(!t)return[];let e=[];for(let n of t.split(`
|
|
2
|
+
`)){let r=n.trim();if(!r.startsWith("site:"))continue;let[,s,o,i]=r.split(":");if(!s||o!=="no")continue;e.push({name:s,size:i||"?"})}return e}function sf(t,e,n){let r=t.map((o)=>` ${e}-${o.name} (${o.size})`).join(`
|
|
3
3
|
`),s=t.length===1?"it":"them";return`This server still holds ${t.length} site tree${t.length===1?"":"s"} with nothing running for ${s}:
|
|
4
4
|
${r}
|
|
5
5
|
`+"A site moved off this box keeps its files here on purpose — they are the rollback, and they are what makes "+`the move reversible until this server is destroyed. Destroying it now discards that.
|
|
6
|
-
Verify the site is serving from its new home first, then re-run with ${n} to destroy it anyway.`}var
|
|
7
|
-
`)[0]||`remote command exited ${r.code}`;return{server:t.name,ip:t.ipv4,routes:[],unavailable:s}}return{server:t.name,ip:t.ipv4,routes:
|
|
8
|
-
`)[0]:String(r);return{server:t.name,ip:t.ipv4,routes:[],unavailable:s}}}function u(t,e){let n=e==="/"?"/":e.replace(/\/+$/,"");return`${t.toLowerCase()}${n||"/"}`}function
|
|
9
|
-
`)}function
|
|
10
|
-
`)}function m(t,e){return`^${t}-${e}-((queue|daemon)-.*|scheduler)\\.service$`}function
|
|
11
|
-
`)}function
|
|
12
|
-
`).some((e)=>e.trim().startsWith("active:"))}function
|
|
13
|
-
`)}function
|
|
14
|
-
`)}function
|
|
15
|
-
`)}function
|
|
16
|
-
`)}function
|
|
17
|
-
`)}function v(t,e){return`^${t}-${e}[-@.]`}function
|
|
18
|
-
`).some((e)=>e.trim().startsWith("active:"))}function
|
|
19
|
-
`)}function
|
|
20
|
-
`)){let r=n.trim();if(!r.startsWith("cert:"))continue;let[,s,o]=r.split(":");if(s&&o)e.set(s,o)}return e}function
|
|
21
|
-
`)}function
|
|
22
|
-
`)}async function
|
|
6
|
+
Verify the site is serving from its new home first, then re-run with ${n} to destroy it anyway.`}var fp="ts-cloud/project",Ap="ts-cloud/environment",yp="ts-cloud/role";function d(t){return typeof t==="string"&&t.trim()?t.trim():void 0}function h(t){if(typeof t==="string")return d(t);if(t&&typeof t==="object")return d(t.name);return}function of(t){let e={};for(let[n,r]of Object.entries(t?.labels??{}))if(typeof r==="string")e[n]=r;return{id:String(t?.id??""),name:d(t?.name)??"(unnamed)",status:d(t?.status)??"unknown",ipv4:d(t?.public_net?.ipv4?.ip)??d(t?.ipv4),ipv6:d(t?.public_net?.ipv6?.ip)??d(t?.ipv6),type:d(t?.server_type?.name)??d(t?.type),location:h(t?.location)??h(t?.datacenter?.location)??h(t?.datacenter),labels:e,project:d(e[fp]),environment:d(e[Ap]),role:d(e[yp])}}function w(t){return t.slug?.trim()||"app"}function Ip(t){let e=[];for(let n of t){let r=w(n);for(let s of n.proxies??[]){let o=d(s?.to);if(!o)continue;e.push({slug:r,host:o,path:d(s?.path)??"/",...x(s)})}}return e.sort((n,r)=>n.slug.localeCompare(r.slug)||n.host.localeCompare(r.host)||n.path.localeCompare(r.path))}function x(t){let e=t?.from;if(typeof e==="string"&&e.trim())return{target:e.trim(),kind:"app"};if(Array.isArray(e)&&e.length>0)return{target:e.filter((s)=>typeof s==="string").join(", "),kind:"app"};let n=t?.static;if(typeof n==="string"&&n.trim())return{target:n.trim(),kind:"static"};if(n&&typeof n==="object"&&d(n.dir))return{target:d(n.dir),kind:"static"};let r=typeof t?.redirect==="string"?d(t.redirect):d(t?.redirect?.to);if(r)return{target:r,kind:"redirect"};return{target:"(no upstream)",kind:"unknown"}}function Sp(t){let e=new Map;for(let n of t){let r=e.get(n.slug);if(r)r.push(n);else e.set(n.slug,[n])}return[...e.entries()].map(([n,r])=>({slug:n,routes:r})).sort((n,r)=>r.routes.length-n.routes.length||n.slug.localeCompare(r.slug))}async function af(t,e,n=ut){if(!t.ipv4)return{server:t.name,routes:[],unavailable:"no public IPv4 address to reach it on"};if(t.status!=="running")return{server:t.name,ip:t.ipv4,routes:[],unavailable:`server is ${t.status}`};try{let r=await e(t.ipv4,pi(n));if(r.code!==0){let s=r.stderr.trim().split(`
|
|
7
|
+
`)[0]||`remote command exited ${r.code}`;return{server:t.name,ip:t.ipv4,routes:[],unavailable:s}}return{server:t.name,ip:t.ipv4,routes:Ip(gi(r.stdout))}}catch(r){let s=r instanceof Error?r.message.split(`
|
|
8
|
+
`)[0]:String(r);return{server:t.name,ip:t.ipv4,routes:[],unavailable:s}}}function u(t,e){let n=e==="/"?"/":e.replace(/\/+$/,"");return`${t.toLowerCase()}${n||"/"}`}function cf(t,e,n){let r=new Set(e.filter((a)=>a.slug===n).map((a)=>u(a.host,a.path))),s=[],o=[],i=[];for(let a of t)if(a.loopbackOnly)i.push(a);else if(a.domain&&r.has(u(a.domain,a.path)))s.push(a);else o.push(a);return{present:s,absent:o,loopback:i,foreign:e.filter((a)=>a.slug!==n)}}function Cp(t,e,n){let r=new Set;for(let s of e)for(let o of s.routes)if(o.slug===n)r.add(u(o.host,o.path));return t.filter((s)=>!s.loopbackOnly&&s.domain!==void 0&&!r.has(u(s.domain,s.path)))}function df(t){let{slug:e,servers:n,probes:r,declared:s}=t,o=[];if(o.push(n.length===0?"No servers found.":`${n.length} server${n.length===1?"":"s"}:`),n.length>0)o.push("");let i=new Map(r.map((a)=>[a.server,a]));for(let a of n){let p=[a.ipv4,a.type,a.location,a.status].filter(Boolean);o.push(` ${a.name} ${p.join(" ")}`),o.push(` ${k(a)}`);let c=i.get(a.name);if(!c)o.push(" not probed, so co-tenants on this box are not listed");else if(c.unavailable)o.push(` could not read ${ut}: ${c.unavailable}`);else o.push(...P(c,e));o.push("")}return o.push(...C(t)),o}function k(t){if(!t.project)return"no ts-cloud labels: provisioned outside ts-cloud, or by a version that did not label boxes";let e=[t.environment,t.role&&`role ${t.role}`].filter(Boolean).join(", ");return`owned by '${t.project}'${e?` (${e})`:""}`}function P(t,e){let n=Sp(t.routes);if(n.length===0)return[` serves nothing: ${ut} is empty or absent`];let r=[` serves ${t.routes.length} route${t.routes.length===1?"":"s"} for ${n.length} project${n.length===1?"":"s"}:`];for(let s of n){r.push(` ${s.slug}${s.slug===e?" (this project)":""}`);for(let o of s.routes)r.push(` ${o.host}${o.path==="/"?"/":o.path} -> ${O(o)}`)}return r}function O(t){if(t.kind==="redirect")return`redirect to ${t.target}`;if(t.kind==="static")return`static ${t.target}`;return t.target}function C(t){let{slug:e,declared:n,probes:r,servers:s}=t;if(n.length===0)return[`This project ('${e}') declares no sites.`];let o=[`This project ('${e}') declares ${n.length} site${n.length===1?"":"s"}: `+n.map((c)=>c.name).join(", ")],i=n.filter((c)=>c.loopbackOnly);if(i.length>0)o.push(` ${i.length} with no domain, so the gateway never routes ${i.length===1?"it":"them"} (reached through another site's proxy): ${i.map((c)=>c.name).join(", ")}`);let a=r.filter((c)=>!c.unavailable);if(a.length===0)return o.push(" Nothing to reconcile them against: no box reported what it serves."),o;let p=Cp(n,a,e);if(o.push(` ${n.length-i.length-p.length} routed by a box above`),p.length>0){o.push(` ${p.length} not routed by any box above: ${p.map((b)=>b.name).join(", ")}`);let c=r.length-a.length,g=s.length-r.length;if(c>0)o.push(` Either they were never deployed, or they are on one of the ${c} server${c===1?"":"s"} that could not be read.`);else if(g>0)o.push(` Either they were never deployed, or they are on one of the ${g} server${g===1?"":"s"} this run did not probe.`);else o.push(" Either they were never deployed, or they are on a server this listing did not cover.")}return o}async function lf(t){let e=[];for(let n of t.steps)try{e.push({step:n,state:await n.satisfied()?"satisfied":"pending"})}catch(r){e.push({step:n,state:"unknown",reason:r instanceof Error?r.message:String(r)})}return e}function _c(t){return t.filter((e)=>e.state!=="satisfied")}function Ep(t){return _c(t).some((e)=>e.step.destructive===!0)}function uf(t,e){let n=_c(e),r=[`${t.operation} ${t.target}`];if(n.length===0)return r.push(" Nothing to do — every step is already satisfied."),r;for(let{step:o,state:i,reason:a}of e){let p=i==="satisfied"?"ok ":i==="unknown"?"? ":"→ ",c=[o.destructive?"DESTRUCTIVE":"",i==="satisfied"?"already done":""].filter(Boolean);if(r.push(` ${p}${o.title}${c.length>0?` [${c.join(", ")}]`:""}`),o.change)r.push(` ${o.change.from} → ${o.change.to}`);if(a)r.push(` could not check: ${a}`)}let s=n.filter((o)=>o.step.destructive).length;return r.push(` ${n.length} step(s) would run`+(s>0?`, ${s} irreversible — re-run with --confirm ${t.target}`:"")),r}async function pf(t,e,n={}){let r={operation:t.operation,target:t.target,steps:[],success:!0};if(Ep(e)&&n.confirm!==t.target)throw Error(`${t.operation} includes an irreversible step. Re-run with --confirm ${t.target} to authorize it.`);for(let{step:s,state:o}of e){if(o==="satisfied"){r.steps.push({id:s.id,title:s.title,state:"skipped"}),n.log?.(`skip ${s.title} (already done)`);continue}n.audit?.({operation:t.operation,target:t.target,step:s.id,state:"started"});try{await s.apply(),r.steps.push({id:s.id,title:s.title,state:"applied"}),n.log?.(`done ${s.title}`),n.audit?.({operation:t.operation,target:t.target,step:s.id,state:"applied"})}catch(i){let a=i instanceof Error?i.message:String(i);return r.steps.push({id:s.id,title:s.title,state:"failed",error:a}),r.success=!1,n.log?.(`FAIL ${s.title}: ${a}`),n.audit?.({operation:t.operation,target:t.target,step:s.id,state:"failed",error:a}),r}}return r}function bp(t){if(t.length===0)throw Error("A server name cannot be empty.");if(t.length>253)throw Error(`'${t}' is longer than the 253 characters a hostname allows.`);for(let e of t.split(".")){if(e.length===0)throw Error(`'${t}' has an empty label — a hostname cannot contain '..'.`);if(e.length>63)throw Error(`'${e}' is longer than the 63 characters a hostname label allows.`);if(!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(e))throw Error(`'${e}' is not a valid hostname label. Use letters, digits and hyphens, not starting or ending with a hyphen.`)}}async function gf(t,e,n){if(bp(e),t===e)throw Error(`'${t}' is already named that.`);if((await n.takenNames()).some((o)=>o===e&&o!==t))throw Error(`'${e}' is already taken. Server names have to be unique within a provider project.`);let s=[];if(n.providerName&&n.renameProvider){let{providerName:o,renameProvider:i}=n;s.push({id:"provider",title:"Rename the server at the provider",change:{from:t,to:e},satisfied:async()=>await o()===e,apply:()=>i(e)})}if(n.stateName&&n.writeStateName){let{stateName:o,writeStateName:i}=n;s.push({id:"state-pin",title:"Update the recorded name in the local driver state",change:{from:t,to:e},satisfied:async()=>{let a=await o();return a===void 0||a===e},apply:()=>i(e)})}if(n.remoteHostname&&n.setRemoteHostname){let{remoteHostname:o,setRemoteHostname:i}=n;s.push({id:"hostname",title:"Set the hostname on the box",change:{from:t,to:e},satisfied:async()=>await o()===e,apply:()=>i(e)})}return s.push({id:"inventory",title:"Rename the fleet inventory record",change:{from:t,to:e},satisfied:async()=>n.inventoryName()===e,apply:async()=>{await n.renameInventory(e)}}),{operation:"server:rename",target:t,steps:s}}function mf(t){let e=`'${t.replace(/'/g,`'"'"'`)}'`;return["set -eu",'TS_CLOUD_OLD="$(hostname)"',`hostnamectl set-hostname ${e} 2>/dev/null || { echo ${e} > /etc/hostname && hostname ${e}; }`,'if grep -q "^127.0.1.1" /etc/hosts; then',` TS_CLOUD_HOSTS="$(sed -E "s/^127\\.0\\.1\\.1.*/127.0.1.1\\t${t}/" /etc/hosts)"`,` printf '%s\\n' "$TS_CLOUD_HOSTS" > /etc/hosts`,"else",` printf '127.0.1.1\\t%s\\n' ${e} >> /etc/hosts`,"fi",'printf "%s -> %s\\n" "$TS_CLOUD_OLD" "$(hostname)"'].join(`
|
|
9
|
+
`)}function hf(t,e,n){let r=e.trim();if(!r)return{problem:"No server named."};let[s,...o]=t.filter((c)=>c.name===r);if(s&&o.length===0)return{server:s};let i=t.filter((c)=>c.project===r);if(i.length>1&&n)i=i.filter((c)=>!c.environment||c.environment===n);let[a,...p]=i;if(a&&p.length===0)return{server:a};if(i.length>1)return{problem:`'${r}' owns ${i.length} servers (${i.map((c)=>c.name).join(", ")}). Name one of them, or narrow it by environment.`};return{problem:`No server matched '${r}'. Nothing is named that, and no box carries the label ts-cloud/project=${r}.`}}function ff(t,e){let n=[];if(!e.project)n.push(`'${e.name}' carries no ts-cloud/project label, so it is not a box ts-cloud provisioned. Attaching to it would deploy into a host nothing manages.`);else if(e.project===t)n.push(`This project's slug is '${t}', which is also the slug that owns '${e.name}'. A tenant deploy owns the gateway fragment named after its slug, so attaching would overwrite '${e.project}'s own fragment and take its sites down. Change this project's slug first.`);if(e.status!=="running")n.push(`'${e.name}' is ${e.status}, so what it serves could not be read.`);if(!e.ipv4)n.push(`'${e.name}' has no public IPv4 address, so it cannot be reached to check what it serves.`);return n}function f(t,e){let n=e==="/"?"/":e.replace(/\/+$/,"");return`${t.toLowerCase()}${n||"/"}`}function Af(t,e,n){let r=[],s=ui(n.filter((i)=>i.kind==="app").map((i)=>({slug:i.slug,proxies:[{from:i.target.split(",").map((a)=>a.trim())}]})),{ignoreSlug:t}),o=new Map;for(let i of n)if(i.slug!==t)o.set(f(i.host,i.path),i.slug);for(let i of e){if(i.port!==void 0){let a=s.get(i.port);if(a)r.push({kind:"port",site:i.name,detail:`port ${i.port}`,heldBy:a})}if(i.domain){let a=o.get(f(i.domain,i.path));if(a)r.push({kind:"route",site:i.name,detail:`${i.domain}${i.path==="/"?"/":i.path}`,heldBy:a})}}return r}function yf(t){return t.registryRead&&t.conflicts.length===0}function If(t){let{slug:e,owner:n,server:r,declared:s,conflicts:o}=t,i=[];i.push(`Attach '${e}' to '${r.name}' (${r.ipv4??"no IPv4"}), owned by '${n}'.`,""),i.push(` ${s.length} site${s.length===1?"":"s"} would deploy onto this box:`);for(let a of s){let p=a.loopbackOnly?`loopback only${a.port?` on :${a.port}`:""}`:`${a.domain}${a.path==="/"?"/":a.path}${a.port?` on :${a.port}`:""}`;i.push(` ${a.name} ${p} -> ${a.installBase??"(install path unresolved)"}`)}if(i.push(""),!t.registryRead)i.push(` Could not read what '${r.name}' already serves: ${t.registryProblem??"unknown reason"}`),i.push(" So this attach is UNCHECKED: a port or hostname already taken by another"),i.push(" project would not error, it would serve that project's site from your domain.");else if(o.length>0){i.push(` ${o.length} conflict${o.length===1?"":"s"} with what the box already serves:`);for(let a of o)i.push(` site '${a.site}' wants ${a.detail}, held by '${a.heldBy}'`);i.push(""),i.push(" Two services on one port do not error: the kernel load-balances, and each"),i.push(" domain serves the other's site about half the time. Pick free ports and"),i.push(" hostnames, then re-run.")}else i.push(` No conflicts with what '${r.name}' already serves.`);return i}function li(t,e){return`/tmp/ts-cloud-move-${t}-${e}.tar.gz`}function xc(t,e){return`${t}-${e}*.service`}function l(t){return`'${t.split("'").join("'\\''")}'`}function vp(t,e){return["set -eu",`for unit in $(ls /etc/systemd/system/ 2>/dev/null | grep -E ${l(m(t,e))} || true); do`,' systemctl stop "$unit" 2>/dev/null || true',"done"].join(`
|
|
10
|
+
`)}function m(t,e){return`^${t}-${e}-((queue|daemon)-.*|scheduler)\\.service$`}function Tp(t,e){return y(m(t,e))}function y(t){return[`ls /etc/systemd/system/ 2>/dev/null | grep -E ${l(t)} | while read -r unit; do`,' systemctl is-active "$unit" >/dev/null 2>&1 && echo "active:$unit" || true',"done"].join(`
|
|
11
|
+
`)}function wp(t){return!t.split(`
|
|
12
|
+
`).some((e)=>e.trim().startsWith("active:"))}function Rp(t,e,n){let r=li(t,e);return["set -eu",`test -d ${l(n)} || { echo "no site tree at ${n}" >&2; exit 1; }`,`rm -f ${l(r)}`,`tar czf ${l(r)} -C "$(dirname ${l(n)})" "$(basename ${l(n)})" -C /etc/systemd/system $(cd /etc/systemd/system && ls ${xc(t,e)} 2>/dev/null | tr '\\n' ' ')`,`sha256sum ${l(r)} | cut -d' ' -f1`].join(`
|
|
13
|
+
`)}function Dp(t,e,n){let r=li(t,e);return["set -eu",`test -f ${l(r)} || { echo "archive not staged at ${r}" >&2; exit 1; }`,`mkdir -p "$(dirname ${l(n)})"`,`tar xzf ${l(r)} -C "$(dirname ${l(n)})" "$(basename ${l(n)})"`,`tar xzf ${l(r)} -C /etc/systemd/system --wildcards ${l(xc(t,e))} 2>/dev/null || true`,"systemctl daemon-reload",`systemctl enable ${t}-${e}.service 2>/dev/null || true`,`systemctl restart ${t}-${e}.service`,`rm -f ${l(r)}`].join(`
|
|
14
|
+
`)}function Pp(t,e,n){return[`test -d ${l(n)} && echo tree:present || echo tree:absent`,`systemctl is-active ${t}-${e}.service >/dev/null 2>&1 && echo unit:active || echo unit:inactive`].join(`
|
|
15
|
+
`)}function Np(t){return t.includes("tree:present")&&t.includes("unit:active")}function kp(t,e="/",n=10){let r=`http://127.0.0.1:${t}${e.startsWith("/")?e:`/${e}`}`;return["set -eu",`for i in $(seq 1 ${n}); do`,` if curl -fsS -o /dev/null --max-time 5 ${l(r)}; then echo healthy; exit 0; fi`," sleep 3","done",`echo "no healthy response from ${r}" >&2`,"exit 1"].join(`
|
|
16
|
+
`)}function Bp(t,e){return["set -eu",`for unit in $(ls /etc/systemd/system/ 2>/dev/null | grep -E ${l(v(t,e))} || true); do`,' systemctl disable --now "$unit" 2>/dev/null || true',"done",`rm -f /etc/rpx/sites.d/${t}.json 2>/dev/null || true`,"systemctl reload rpx-gateway.service 2>/dev/null || systemctl restart rpx-gateway.service 2>/dev/null || true"].join(`
|
|
17
|
+
`)}function v(t,e){return`^${t}-${e}[-@.]`}function _p(t,e){return y(v(t,e))}function xp(t){return!t.split(`
|
|
18
|
+
`).some((e)=>e.trim().startsWith("active:"))}function Sf(t,e){return`/tmp/ts-cloud-move-${t}-${e}-certs.tar.gz`}function Cf(t,e){return["set -u",...e.map((n)=>`if [ -s ${l(`${t}/${n}.crt`)} ]; then echo "cert:${n}:$(sha256sum ${l(`${t}/${n}.crt`)} | cut -d' ' -f1)"; else echo "cert:${n}:absent"; fi`)].join(`
|
|
19
|
+
`)}function Ef(t){let e=new Map;for(let n of t.split(`
|
|
20
|
+
`)){let r=n.trim();if(!r.startsWith("cert:"))continue;let[,s,o]=r.split(":");if(s&&o)e.set(s,o)}return e}function bf(t,e){for(let[n,r]of t){if(r==="absent")continue;if(e.get(n)!==r)return!1}return!0}function vf(t,e,n){let r=e.flatMap((s)=>[`${s}.crt`,`${s}.key`]);return["set -eu",`rm -f ${l(n)}`,`cd ${l(t)} 2>/dev/null || { echo "no certs dir at ${t}" >&2; exit 0; }`,`TS_CLOUD_CERTS="$(ls ${r.map(l).join(" ")} 2>/dev/null | tr '\\n' ' ' || true)"`,'[ -n "$TS_CLOUD_CERTS" ] || { echo "no certificates to carry"; exit 0; }',`tar czf ${l(n)} $TS_CLOUD_CERTS`].join(`
|
|
21
|
+
`)}function Tf(t,e){return["set -eu",`[ -s ${l(e)} ] || { echo "no certificate archive staged"; exit 0; }`,`mkdir -p ${l(t)}`,`tar xzf ${l(e)} -C ${l(t)}`,`chmod 600 ${l(t)}/*.key 2>/dev/null || true`,`rm -f ${l(e)}`].join(`
|
|
22
|
+
`)}async function wf(t,e){let{slug:n,siteName:r,appBase:s,from:o,to:i,targetAddress:a}=t;if(o===i)throw Error(`'${r}' is already on ${i}.`);if(t.database&&!e.database)throw Error(`'${r}' uses the on-box database '${t.database.name}', which lives in the engine's own data directory rather than in the site tree, and this move has no way to carry it. Moving the site without it would cut traffic over to an empty database.`);if(t.database&&e.database&&await e.database.targetHasData())throw Error(`${i} already has a database named '${t.database.name}' with tables in it. Restoring this site's dump over it would destroy that data. Rename or drop it on the target first, or point this project at a different database name.`);let p=[{id:"pause-workers",title:`Stop background work on ${o} so the snapshot is consistent`,satisfied:async()=>wp(await e.runOnSource(Tp(n,r))),apply:async()=>{await e.runOnSource(vp(n,r))}},...e.database?[{id:"database-dump",title:`Dump the '${t.database?.name}' database on ${o}`,satisfied:async()=>!1,apply:()=>e.database.dump()}]:[],{id:"snapshot",title:`Archive the site's tree and units on ${o}`,change:{from:`${o}:${s}`,to:li(n,r)},satisfied:async()=>!1,apply:async()=>{await e.runOnSource(Rp(n,r,s))}},{id:"transfer",title:`Carry the archive to ${i}`,change:{from:o,to:i},satisfied:()=>e.archiveStaged(),apply:()=>e.transferArchive()},...e.database?[{id:"database-transfer",title:`Carry the database dump to ${i}`,change:{from:o,to:i},satisfied:()=>e.database.dumpStaged(),apply:()=>e.database.transferDump()},{id:"database-restore",title:`Create and load '${t.database?.name}' on ${i}`,satisfied:async()=>!1,apply:()=>e.database.restore()}]:[],{id:"restore",title:`Unpack the site on ${i} and start it`,change:{from:li(n,r),to:`${i}:${s}`},satisfied:async()=>Np(await e.runOnTarget(Pp(n,r,s))),apply:async()=>{await e.runOnTarget(Dp(n,r,s))}}];if(t.port!=null){let{port:c}=t;p.push({id:"health",title:`Wait for the site to answer on ${i} (127.0.0.1:${c})`,satisfied:async()=>!1,apply:async()=>{await e.runOnTarget(kp(c,t.healthCheckPath??"/"))}})}return p.push(...e.certificates?[{id:"certificates",title:`Carry the site's TLS material to ${i}`,satisfied:()=>e.certificates.inPlace(),apply:()=>e.certificates.carry()}]:[],{id:"gateway",title:`Route the site on ${i}`,satisfied:()=>e.targetRoutesSite(),apply:()=>e.refreshTargetGateway()},{id:"dns",title:`Point DNS at ${i}`,change:{from:`${o}`,to:a},satisfied:async()=>await e.publishedAddress()===a,apply:async()=>{let c=await e.cutoverDns();if(c.length>0)throw Error(c.join("; "))}},{id:"drain-source",title:`Stop the site on ${o}, leaving its files in place`,satisfied:async()=>xp(await e.runOnSource(_p(n,r))),apply:async()=>{await e.runOnSource(Bp(n,r))}}),{operation:"site:move",target:r,steps:p}}export{rf,nf,sf,fp,Ap,yp,of,Ip,Sp,af,cf,Cp,df,lf,_c,Ep,uf,pf,bp,gf,mf,hf,ff,Af,yf,If,li,xc,vp,Tp,wp,Rp,Dp,Pp,Np,kp,Bp,_p,xp,Sf,Cf,Ef,bf,vf,Tf,wf};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{u}from"./chunk-
|
|
2
|
-
`)}function
|
|
3
|
-
`)){let n=e.trim();if(!n)continue;try{let o=JSON.parse(Buffer.from(n,"base64").toString("utf8"));if(o&&typeof o==="object"&&!Array.isArray(o))r.push(o)}catch{continue}}return r}function
|
|
4
|
-
export{ut,
|
|
1
|
+
import{u}from"./chunk-q0g0rjn3.js";var ut="/etc/rpx/sites.d",Rf={start:3000,end:3999};function g(t){return t.slug?.trim()||"app"}function Oc(t){let r=t.lastIndexOf(":");if(r<0||r===t.length-1)return;let e=t.slice(r+1).trim();if(!/^\d+$/.test(e))return;let n=Number(e);return n>=1&&n<=65535?n:void 0}function ui(t,r={}){let e=r.ignoreSlug?.trim(),n=new Map;for(let o of t){let c=g(o);if(e&&c===e)continue;for(let a of o.proxies??[]){let f=typeof a.from==="string"?[a.from]:a.from??[];for(let i of f){let d=Oc(i);if(d!==void 0&&!n.has(d))n.set(d,c)}}}return n}function pi(t=ut){return[`for __tsc_fragment in ${t}/*.json; do`,' [ -f "$__tsc_fragment" ] || continue',` base64 < "$__tsc_fragment" | tr -d '\\n'`," printf '\\n'","done"].join(`
|
|
2
|
+
`)}function gi(t){let r=[];for(let e of t.split(`
|
|
3
|
+
`)){let n=e.trim();if(!n)continue;try{let o=JSON.parse(Buffer.from(n,"base64").toString("utf8"));if(o&&typeof o==="object"&&!Array.isArray(o))r.push(o)}catch{continue}}return r}function Op(t,r,e=Rf){let n=[],o=[],c=new Set(r.keys());for(let[a,f]of Object.entries(t.sites??{})){if(!f||u(f)!=="server-app")continue;let i=typeof f.port==="number"?f.port:void 0,d=Math.max(i??e.start,e.start),p;for(let s=d;s<=e.end;s++)if(!c.has(s)){p=s;break}if(p===void 0){let s=i!==void 0?r.get(i):void 0;o.push(`No free port for site '${a}' in ${e.start}-${e.end}${i!==void 0?` (wanted ${i}${s?`, held by '${s}'`:""})`:""}. Widen the range or free a port on the box.`);continue}c.add(p),n.push({site:a,port:p,declared:i,moved:i!==void 0&&p!==i})}return{allocations:n,errors:o}}
|
|
4
|
+
export{ut,Rf,Oc,ui,pi,gi,Op};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n}from"./chunk-
|
|
1
|
+
import{n}from"./chunk-wrpnnrdf.js";class Le{client;region;constructor(e="us-east-1",r){this.region=e,this.client=new n(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{Le};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{K}from"./chunk-tvwrthfq.js";import"./chunk-wrpnnrdf.js";export{K as RDSClient};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{Io,Kr,Gd,xi,To,wo}from"./chunk-w23wrsa4.js";import{Le}from"./chunk-dm6kyz6e.js";import{execFileSync as A}from"node:child_process";import{mkdirSync as S,mkdtempSync as U,rmSync as L,writeFileSync as d}from"node:fs";import{tmpdir as O}from"node:os";import{dirname as j,join as s}from"node:path";var r={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m"};function I(t,e){return`${r[e]}${t}${r.reset}`}function fn(t){console.log(`${r.green}✓${r.reset} ${t}`)}function Cu(t){console.error(`${r.red}✗${r.reset} ${t}`)}function cs(t){console.warn(`${r.yellow}⚠${r.reset} ${t}`)}function k(t){console.log(`${r.blue}ℹ${r.reset} ${t}`)}function w(t){console.log(`${r.cyan}→${r.reset} ${t}`)}function ds(t){console.log(`
|
|
2
|
+
${r.bright}${r.cyan}${t}${r.reset}
|
|
3
|
+
`)}var F=!!(process.env.CI||process.env.GITHUB_ACTIONS||process.env.BUILDKITE||process.env.CIRCLECI||process.env.GITLAB_CI);function Eu(t,e="cyan"){let n=t.split(`
|
|
4
|
+
`),i=Math.max(...n.map((l)=>l.length)),a="─".repeat(i+2);console.log(I(`┌${a}┐`,e)),n.forEach((l)=>{console.log(I(`│ ${l.padEnd(i)} │`,e))}),console.log(I(`└${a}┘`,e))}function R(t,e){for(let n of e){let i=s(t,n.name);S(j(i),{recursive:!0}),d(i,n.data,n.mode?{mode:n.mode}:void 0)}}async function Ua(t){let{app:e,projectRoot:n,region:i,repository:a}=t,l=e.architecture??"x86_64",P=l==="arm64"?"linux/arm64":"linux/amd64",E=e.kind==="php",c=t.onStep??(()=>{}),p=U(s(O(),"tscloud-img-"));try{let f=s(p,"app");S(f,{recursive:!0});let y,v;if(E){To({projectRoot:n,app:e,skipBuild:t.skipBuild,onStep:c}),c("staging application tree");let o=wo(n);R(f,o),R(s(p,"runtime"),xi().map((g)=>({name:g.path,data:g.contents,mode:g.mode})));let b=e.handlers?.http??"public/index.php";y={http:b,queue:e.handlers?.queue??b,cli:e.handlers?.cli??b},v=Io(o.map((g)=>`${g.name}:${g.data.length}`).join("|"))}else{c("bundling application");let o=await Kr({projectRoot:n,app:e,skipBuild:t.skipBuild,onStep:c});d(s(f,"index.mjs"),o.bundle),y=o.handlers,v=o.sha256}let C=v.slice(0,16);d(s(p,"Dockerfile"),Gd({kind:e.kind??"node",phpVersion:e.phpVersion,architecture:l}));let x=new Le(i),u;try{u=(await x.describeRepositories({repositoryNames:[a]})).repositories?.[0]?.repositoryUri??""}catch{u=""}if(!u)c(`creating ECR repository ${a}`),u=(await x.createRepository({repositoryName:a,imageScanningConfiguration:{scanOnPush:!0}})).repository?.repositoryUri??"";if(!u)throw Error(`could not resolve ECR repository URI for ${a}`);let m=`${u}:${C}`;c("docker build"),A("docker",["build","--platform",P,"--provenance=false","--sbom=false","-t",m,p],{stdio:"inherit"}),c("ecr auth + push");let h=(await x.getAuthorizationToken()).authorizationData?.[0];if(!h?.authorizationToken||!h.proxyEndpoint)throw Error("failed to get an ECR authorization token");let T=h.proxyEndpoint.replace(/^https?:\/\//,""),B=s(p,".docker");return S(B,{recursive:!0}),d(s(B,"config.json"),JSON.stringify({auths:{[T]:{auth:h.authorizationToken}}})),A("docker",["push",m],{stdio:"inherit",env:{...process.env,DOCKER_CONFIG:B}}),k(`Image: ${m}`),{imageUri:m,tag:C,handlers:y}}finally{L(p,{recursive:!0,force:!0})}}
|
|
5
|
+
export{fn,Cu,cs,k,w,ds,Eu,Ua};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Rr,di,n,l,tf}from"./chunk-wrpnnrdf.js";export{n as AWSClient,l as buildQueryParams,di as coerceXmlValues,tf as detectCredentialSource,Rr as resolveS3Endpoint};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Qr}from"./chunk-
|
|
1
|
+
import{Qr}from"./chunk-h85wqdvr.js";var Xd="\x00";function Ro(t,i){if(t==="*"||t==="**")return!0;let e=t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"\x01").replace(/\*/g,"[^/]*").replace(/\u0001/g,".*");return new RegExp(`^${e}$`).test(i)}function f(t,i){if(t.startsWith("*.")){let e=t.slice(1);return i.endsWith(e)&&i.length>e.length}return t===i}function Oi(t,i){if(t.enabled===!1)return!1;if(t.methods?.length&&!t.methods.some((e)=>e.toUpperCase()===i.method.toUpperCase()))return!1;if(t.path&&!Ro(t.path,i.path))return!1;if(t.host&&!f(t.host,i.host??""))return!1;return!0}function Li(t,i){let e=t.key??{source:"ip"},o=e.fallbackToIp!==!1,r;if(e.source==="ip")r=i.ip;else if(e.source==="global")r="global";else if(e.source==="host")r=i.host??"";else if(e.source==="path")r=i.path;else if(e.source==="header")r=e.name?i.headers?.[e.name.toLowerCase()]:void 0;else if(e.source==="cookie")r=e.name?i.cookies?.[e.name]:void 0;if(!r&&e.source!=="global")r=o?i.ip:"__missing__";return`${t.id}\x00${r}`}class Do{clock;maxTrackedKeys;buckets=new Map;windows=new Map;rules;constructor(t,i=()=>Date.now(),e=1e5){this.clock=i;this.maxTrackedKeys=e;this.rules=[...t].sort((o,r)=>(o.priority??0)-(r.priority??0))}check(t){let i=this.clock(),e=this.rules.filter((n)=>Oi(n,t)),o;for(let n of e){let s=this.test(n,t,i);if(s.allowed)continue;if(!o||d(s.action)>d(o.action))o=s}if(o)return o;let r={action:"allow",allowed:!0};for(let n of e){let s=this.consume(n,t,i);if(s.remaining!=null&&(r.remaining??1/0)>s.remaining)r=s}return r}test(t,i,e){let o=Li(t,i);if((t.algorithm??"token_bucket")==="token_bucket"){let n=t.burst??t.limit,s=this.buckets.get(o),a=s?Math.min(n,s.tokens+this.refill(t,e-s.updatedAt)):n;if(a>=1)return{action:"allow",allowed:!0};return this.blocked(t,o,0,this.msPerToken(t)*(1-a),e)}let r=(this.windows.get(o)?.hits??[]).filter((n)=>n>e-t.windowMs);if(r.length<t.limit)return{action:"allow",allowed:!0};return this.blocked(t,o,0,r[0]+t.windowMs-e,e)}peek(t){let i=this.clock();for(let e of this.rules){if(!Oi(e,t))continue;let o=this.test(e,t,i);if(!o.allowed)return o}return{action:"allow",allowed:!0}}msPerToken(t){return t.windowMs/Math.max(1,t.limit)}refill(t,i){return Math.max(0,i)/this.msPerToken(t)}blocked(t,i,e,o,r){let n=t.action??"deny";return{action:n,allowed:n==="allow"||n==="log",ruleId:t.id,limit:t.limit,remaining:e,retryAfterMs:Math.max(0,Math.ceil(o)),resetAt:r+Math.max(0,o),key:i}}consume(t,i,e){let o=Li(t,i);if((t.algorithm??"token_bucket")==="token_bucket"){let l=t.burst??t.limit,u=this.buckets.get(o)??{tokens:l,updatedAt:e},c=Math.min(l,u.tokens+this.refill(t,e-u.updatedAt));if(c<1)return this.buckets.set(o,{tokens:c,updatedAt:e}),this.blocked(t,o,0,this.msPerToken(t)*(1-c),e);return this.evictIfNeeded(this.buckets),this.buckets.set(o,{tokens:c-1,updatedAt:e}),{action:"allow",allowed:!0,ruleId:t.id,limit:l,remaining:Math.floor(c-1),resetAt:e+this.msPerToken(t)*(l-(c-1)),key:o}}let n=this.windows.get(o)??{hits:[]},s=e-t.windowMs,a=n.hits.filter((l)=>l>s);if(a.length>=t.limit)return this.windows.set(o,{hits:a}),this.blocked(t,o,0,a[0]+t.windowMs-e,e);return a.push(e),this.evictIfNeeded(this.windows),this.windows.set(o,{hits:a}),{action:"allow",allowed:!0,ruleId:t.id,limit:t.limit,remaining:t.limit-a.length,resetAt:a[0]+t.windowMs,key:o}}evictIfNeeded(t){if(t.size<this.maxTrackedKeys)return;let i=t.size-this.maxTrackedKeys+1,e=0;for(let o of t.keys())if(t.delete(o),++e>=i)break}sweep(){let t=this.clock(),i=0;for(let[e,o]of this.windows){let r=e.split("\x00")[0],n=this.rules.find((s)=>s.id===r);if(!n){this.windows.delete(e),i++;continue}if(o.hits.every((s)=>s<=t-n.windowMs))this.windows.delete(e),i++}for(let[e,o]of this.buckets){let r=e.split("\x00")[0],n=this.rules.find((s)=>s.id===r);if(!n||t-o.updatedAt>n.windowMs*2)this.buckets.delete(e),i++}return i}get trackedKeys(){return this.buckets.size+this.windows.size}}function d(t){return{allow:0,log:1,throttle:2,challenge:3,deny:4}[t]}function Yd(t){let i={};if(t.limit!=null)i["ratelimit-limit"]=String(t.limit);if(t.remaining!=null)i["ratelimit-remaining"]=String(t.remaining);if(t.resetAt!=null)i["ratelimit-reset"]=String(Math.max(0,Math.ceil((t.resetAt-Date.now())/1000)));if(!t.allowed&&t.retryAfterMs!=null)i["retry-after"]=String(Math.max(1,Math.ceil(t.retryAfterMs/1000)));return i}function Zd(){return[{id:"global-ip",limit:600,windowMs:60000,burst:100,key:{source:"ip"},action:"deny",priority:100},{id:"api-ip",limit:120,windowMs:60000,burst:30,path:"/api/**",key:{source:"ip"},action:"deny",priority:50},{id:"auth-ip",limit:10,windowMs:60000,algorithm:"sliding_window",path:"/auth/**",methods:["POST"],key:{source:"ip"},action:"challenge",priority:10}]}var el="protection.controls",$i=24,Po=4,g={ipRules:{allow:[],block:[]}};function m(t,i){if(!t?.enabled)return;return new Date(t.expiresAt).getTime()>i.getTime()?t:void 0}function p(t,i){let e=Number.isFinite(t)?Number(t):i;return Math.min($i,Math.max(0.25,e))}var h=500;class No{controlPlane;options;constructor(t,i={}){this.controlPlane=t;this.options=i}now(){return this.options.now?.()??new Date}read(){let t=this.controlPlane.getSetting(el);if(!t||typeof t!=="object"||Array.isArray(t))return{...g,ipRules:{allow:[],block:[]}};let i=t;return{attackMode:i.attackMode,mitigationPause:i.mitigationPause,ipRules:{allow:Array.isArray(i.ipRules?.allow)?i.ipRules.allow:[],block:Array.isArray(i.ipRules?.block)?i.ipRules.block:[]},updatedAt:i.updatedAt}}write(t){let i={...t,updatedAt:this.now().toISOString()};return this.controlPlane.setSetting(el,i),i}raw(){return this.read()}current(){let t=this.now(),i=this.read();return{attackMode:m(i.attackMode,t),mitigationPause:m(i.mitigationPause,t),ipRules:i.ipRules}}enableAttackMode(t){let i=this.now(),e={enabled:!0,startedAt:i.toISOString(),expiresAt:new Date(i.getTime()+p(t.hours,Po)*3600000).toISOString(),reason:t.reason.trim()||"Attack mode enabled by an operator.",actorId:t.actorId};return this.write({...this.read(),attackMode:e}),e}disableAttackMode(){let t=this.read();if(!t.attackMode?.enabled)return!1;return this.write({...t,attackMode:{...t.attackMode,enabled:!1}}),!0}pauseMitigations(t){let i=t.reason.trim();if(!i)throw Error("Pausing mitigations requires a reason: you are liable for the traffic it admits.");let e=this.now(),o={enabled:!0,startedAt:e.toISOString(),expiresAt:new Date(e.getTime()+p(t.hours,$i)*3600000).toISOString(),reason:i,actorId:t.actorId};return this.write({...this.read(),mitigationPause:o}),o}resumeMitigations(){let t=this.read();if(!t.mitigationPause?.enabled)return!1;return this.write({...t,mitigationPause:{...t.mitigationPause,enabled:!1}}),!0}addIpRule(t,i){let e=i.trim();if(!Qr(e))throw Error(`Not a valid IP or CIDR: ${i}`);let o=this.read(),r={...o.ipRules,[t]:[...new Set([...o.ipRules[t],e])]};if(r[t].length>h)throw Error(`At most ${h} ${t} rules are supported.`);let n=t==="allow"?"block":"allow";return r[n]=r[n].filter((s)=>s!==e),this.write({...o,ipRules:r}),r}removeIpRule(t,i){let e=this.read(),o={...e.ipRules,[t]:e.ipRules[t].filter((r)=>r!==i.trim())};return this.write({...e,ipRules:o}),o}}function tl(t){if(t.mitigationPause)return{attackMode:!!t.attackMode,mitigationPaused:!0,summary:`Automatic mitigation is paused until ${t.mitigationPause.expiresAt}. All traffic is being served and billed.`,expiresAt:t.mitigationPause.expiresAt};if(t.attackMode)return{attackMode:!0,mitigationPaused:!1,summary:`Attack mode is on until ${t.attackMode.expiresAt}. Every visitor is being challenged.`,expiresAt:t.attackMode.expiresAt};return{attackMode:!1,mitigationPaused:!1,summary:"Protection is in its normal posture."}}function rl(t,i){if(i.mitigationPause)return t.map((e)=>({...e,enabled:!1}));if(!i.attackMode)return[...t];return t.map((e)=>({...e,action:e.action==="deny"?"deny":"challenge",burst:Math.max(1,Math.min(e.burst??e.limit,5))}))}function ko(t,i){let e=[...new Set([...t.allowlist??[],...i.ipRules.allow])],o=[...new Set([...t.blocklist??[],...i.ipRules.block])];if(i.mitigationPause)return{...t,allowlist:e,blocklist:o,monitorOnly:!0};if(!i.attackMode)return{...t,allowlist:e,blocklist:o};let r=t.thresholds??{};return{...t,allowlist:e,blocklist:o,thresholds:{...r,newConnectionsPerSecond:Math.max(1,Math.floor((r.newConnectionsPerSecond??50)/5)),concurrentPerSource:Math.max(1,Math.floor((r.concurrentPerSource??100)/5))}}}function py(t,i){let e=t?.infrastructure?.compute;if(!e||e.ddos===!1)return t;let o=typeof e.ddos==="object"&&e.ddos!==null?e.ddos:{};return{...t,infrastructure:{...t.infrastructure,compute:{...e,ddos:ko(o,i)}}}}export{Xd,Ro,Oi,Li,Do,Yd,Zd,el,$i,Po,No,tl,rl,ko,py};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var
|
|
1
|
+
var Ad={newConnectionsPerSecond:50,concurrentPerSource:100,synPerSecond:2000,burst:100,icmpPerSecond:5,banSeconds:600};function h(e){return{...Ad,...e.thresholds}}var _=/^(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,2})?$|^[0-9a-f:]+(?:\/\d{1,3})?$/i;function Qr(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(Qr))]}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 yd(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 Id(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(yd(e)))t.push(`${n} = ${s}`);return`${t.join(`
|
|
2
2
|
`)}
|
|
3
|
-
`}function
|
|
4
|
-
`)}function
|
|
3
|
+
`}function Sd(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 Ri(e={}){return`#!/usr/bin/env bash
|
|
5
5
|
# Managed by ts-cloud. Installs L3/L4 flood mitigation.
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
@@ -13,11 +13,11 @@ fi
|
|
|
13
13
|
|
|
14
14
|
install -d -m 0755 /etc/ts-cloud /etc/nftables.d
|
|
15
15
|
cat > /etc/sysctl.d/90-ts-cloud-ddos.conf <<'SYSCTL_EOF'
|
|
16
|
-
${
|
|
16
|
+
${Id(e)}SYSCTL_EOF
|
|
17
17
|
sysctl --system >/dev/null
|
|
18
18
|
|
|
19
19
|
cat > /etc/nftables.d/ts-cloud-ddos.nft.new <<'NFT_EOF'
|
|
20
|
-
${
|
|
20
|
+
${Sd(e)}NFT_EOF
|
|
21
21
|
|
|
22
22
|
# Syntax-check before applying: a bad ruleset would leave the box unprotected.
|
|
23
23
|
if ! nft -c -f /etc/nftables.d/ts-cloud-ddos.nft.new; then
|
|
@@ -40,5 +40,5 @@ include "/etc/nftables.d/ts-cloud-ddos.nft"
|
|
|
40
40
|
fi
|
|
41
41
|
systemctl enable nftables >/dev/null 2>&1 || true
|
|
42
42
|
echo "ts-cloud: L3/L4 mitigation active"
|
|
43
|
-
`}var b=["off","monitor","rate_limit","challenge","lockdown"];function
|
|
44
|
-
export{
|
|
43
|
+
`}var b=["off","monitor","rate_limit","challenge","lockdown"];function ag(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 Hr(e,t){return Math.max(1,Math.floor(e*t.rateLimitFactor))}
|
|
44
|
+
export{Ad,Qr,yd,Id,Sd,Ri,ag,Hr};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n}from"./chunk-
|
|
1
|
+
import{n}from"./chunk-wrpnnrdf.js";import{I}from"./chunk-rxs4y74z.js";function S(e){let i=Array.isArray(e?.Items)?e.Items:I(e?.Items?.CNAME);return{Quantity:i.length,Items:i.map(String)}}class y{client;constructor(e,i){this.client=i??new n(void 0,{profile:e})}collectionItems(e,i){let t=e?.Items??e?.[i];if(!t)return[];if(Array.isArray(t))return t;let r=t[i]??t.Item;if(r===void 0)return typeof t==="object"&&(t.Id||t.PathPattern)?[t]:[];return Array.isArray(r)?r:[r]}validateExistingOriginInput(e,i){if(!/^[A-Z0-9]{8,32}$/.test(e))throw Error("CloudFront distribution ID is invalid");if(!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(i.id))throw Error("CloudFront origin ID is invalid");if(!/^(?=.{1,253}$)(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?$/.test(i.domainName))throw Error("CloudFront origin must be a hostname without a scheme or path");let t=i.pathPattern.startsWith("/")?i.pathPattern:`/${i.pathPattern}`;if(t==="/"||t==="/*"||!/^\/[A-Za-z0-9_.*?~!$&'()+,;=:@%/-]{1,255}$/.test(t))throw Error("CloudFront path pattern must be a non-default absolute pattern");if(i.originPath&&(!i.originPath.startsWith("/")||i.originPath.includes("..")))throw Error("CloudFront origin path must be absolute and traversal-free");if(Object.entries(i.customHeaders??{}).some(([r,o])=>!/^[A-Za-z0-9-]{1,64}$/.test(r)||!o||o.length>1024))throw Error("CloudFront custom origin headers are invalid");return{...i,pathPattern:t}}async upsertExistingDistributionOrigin(e,i){let t=this.validateExistingOriginInput(e,i),r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/config`,returnHeaders:!0}),o=r.headers?.etag||r.headers?.ETag||r.ETag||"",s=r.body?.DistributionConfig||r.DistributionConfig||r.body;if(!s||s.Enabled===void 0||!o)throw Error("Failed to read an ETag-protected CloudFront distribution config");let a=this.collectionItems(s.Origins,"Origin"),c=this.collectionItems(s.CacheBehaviors,"CacheBehavior"),g=a.find((p)=>String(p.Id)===t.id),u=c.find((p)=>String(p.PathPattern)===t.pathPattern);if(g&&String(g.DomainName)!==t.domainName&&!t.replaceExisting)throw Error(`Origin ${t.id} already targets ${g.DomainName}; pass replaceExisting only after reviewing the live config`);if(u&&String(u.TargetOriginId)!==t.id&&!t.replaceExisting)throw Error(`Path ${t.pathPattern} already targets ${u.TargetOriginId}; pass replaceExisting only after reviewing the live config`);let d={Id:t.id,DomainName:t.domainName,OriginPath:t.originPath??"",CustomHeaders:{Quantity:Object.keys(t.customHeaders??{}).length,...Object.keys(t.customHeaders??{}).length?{Items:{OriginCustomHeader:Object.entries(t.customHeaders).map(([p,A])=>({HeaderName:p,HeaderValue:A}))}}:{}},CustomOriginConfig:{HTTPPort:80,HTTPSPort:443,OriginProtocolPolicy:t.protocolPolicy??"https-only",OriginSslProtocols:{Quantity:1,Items:{SslProtocol:["TLSv1.2"]}},OriginReadTimeout:30,OriginKeepaliveTimeout:5},ConnectionAttempts:3,ConnectionTimeout:10,...t.originAccessControlId?{OriginAccessControlId:t.originAccessControlId}:{}},h=["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"],l={PathPattern:t.pathPattern,TargetOriginId:t.id,ViewerProtocolPolicy:"redirect-to-https",Compress:!0,CachePolicyId:"4135ea2d-6df8-44a3-9df3-4b5a84be39ad",OriginRequestPolicyId:"b689b0a8-53d0-40ab-baf2-68738e2966ac",AllowedMethods:{Quantity:h.length,Items:{Method:h},CachedMethods:{Quantity:2,Items:{Method:["GET","HEAD"]}}},SmoothStreaming:!1,FieldLevelEncryptionId:"",TrustedSigners:{Enabled:!1,Quantity:0},TrustedKeyGroups:{Enabled:!1,Quantity:0},LambdaFunctionAssociations:{Quantity:0},FunctionAssociations:{Quantity:0}},f=g?a.map((p)=>String(p.Id)===t.id?d:p):[...a,d],m=u?c.map((p)=>String(p.PathPattern)===t.pathPattern?l:p):[...c,l],b=JSON.stringify(a)!==JSON.stringify(f)||JSON.stringify(c)!==JSON.stringify(m);if(!b||t.dryRun)return{distributionId:e,originId:t.id,domainName:t.domainName,pathPattern:t.pathPattern,changed:b,applied:!1,etag:o};s.Origins={Quantity:f.length,Items:{Origin:f}},s.CacheBehaviors={Quantity:m.length,...m.length?{Items:{CacheBehavior:m}}:{}};let E=await this.client.request({service:"cloudfront",region:"us-east-1",method:"PUT",path:`/2020-05-31/distribution/${e}/config`,body:this.buildDistributionConfigXml(s),headers:{"Content-Type":"application/xml","If-Match":o},returnHeaders:!0});return{distributionId:e,originId:t.id,domainName:t.domainName,pathPattern:t.pathPattern,changed:!0,applied:!0,etag:E.headers?.etag||E.headers?.ETag||""}}async removeExistingDistributionOrigin(e,i){let t=this.validateExistingOriginInput(e,i),r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/config`,returnHeaders:!0}),o=r.headers?.etag||r.headers?.ETag||r.ETag||"",s=r.body?.DistributionConfig||r.DistributionConfig||r.body;if(!s||s.Enabled===void 0||!o)throw Error("Failed to read an ETag-protected CloudFront distribution config");let a=this.collectionItems(s.Origins,"Origin"),c=this.collectionItems(s.CacheBehaviors,"CacheBehavior"),g=a.find((m)=>String(m.Id)===t.id),u=c.find((m)=>String(m.PathPattern)===t.pathPattern);if(g&&String(g.DomainName)!==t.domainName)throw Error(`Origin ${t.id} no longer targets ${t.domainName}; refusing ambiguous removal`);if(u&&String(u.TargetOriginId)!==t.id)throw Error(`Path ${t.pathPattern} no longer targets ${t.id}; refusing ambiguous removal`);if(!u)return{distributionId:e,originId:t.id,domainName:t.domainName,pathPattern:t.pathPattern,changed:!1,applied:!1,originRemoved:!1,etag:o};let d=c.filter((m)=>String(m.PathPattern)!==t.pathPattern),h=String(s.DefaultCacheBehavior?.TargetOriginId)===t.id||d.some((m)=>String(m.TargetOriginId)===t.id),l=h?a:a.filter((m)=>String(m.Id)!==t.id);if(t.dryRun)return{distributionId:e,originId:t.id,domainName:t.domainName,pathPattern:t.pathPattern,changed:!0,applied:!1,originRemoved:!h&&!!g,etag:o};s.Origins={Quantity:l.length,Items:{Origin:l}},s.CacheBehaviors={Quantity:d.length,...d.length?{Items:{CacheBehavior:d}}:{}};let f=await this.client.request({service:"cloudfront",region:"us-east-1",method:"PUT",path:`/2020-05-31/distribution/${e}/config`,body:this.buildDistributionConfigXml(s),headers:{"Content-Type":"application/xml","If-Match":o},returnHeaders:!0});return{distributionId:e,originId:t.id,domainName:t.domainName,pathPattern:t.pathPattern,changed:!0,applied:!0,originRemoved:!h&&!!g,etag:f.headers?.etag||f.headers?.ETag||""}}async createInvalidation(e){let i=e.callerReference||Date.now().toString(),t=`<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<InvalidationBatch>
|
|
3
3
|
<Paths>
|
|
4
4
|
<Quantity>${e.paths.length}</Quantity>
|
|
@@ -8,15 +8,15 @@ import{n}from"./chunk-5vxpgw8q.js";class y{client;constructor(e,i){this.client=i
|
|
|
8
8
|
</Items>
|
|
9
9
|
</Paths>
|
|
10
10
|
<CallerReference>${i}</CallerReference>
|
|
11
|
-
</InvalidationBatch>`,r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:`/2020-05-31/distribution/${e.distributionId}/invalidation`,body:t,headers:{"Content-Type":"application/xml"}});return{Id:r.Id||r.Invalidation?.Id,Status:r.Status||r.Invalidation?.Status||"InProgress",CreateTime:r.CreateTime||r.Invalidation?.CreateTime||new Date().toISOString()}}async getInvalidation(e,i){let t=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/invalidation/${i}`});return{Id:t.Id||t.Invalidation?.Id,Status:t.Status||t.Invalidation?.Status,CreateTime:t.CreateTime||t.Invalidation?.CreateTime}}async listInvalidations(e){let i=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/invalidation`}),t=[];if(i.InvalidationSummary){let r=Array.isArray(i.InvalidationSummary)?i.InvalidationSummary:[i.InvalidationSummary];t.push(...r.map((o)=>({Id:o.Id,Status:o.Status,CreateTime:o.CreateTime})))}return t}async waitForInvalidation(e,i){let r=0;while(r<60){if((await this.getInvalidation(e,i)).Status==="Completed")return;await new Promise((s)=>setTimeout(s,5000)),r++}throw Error(`Timeout waiting for invalidation ${i} to complete`)}async listDistributions(){let e=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:"/2020-05-31/distribution"}),i=[],r=(e.DistributionList||e).Items,o=[];if(Array.isArray(r))o=r;else if(r?.DistributionSummary)o=Array.isArray(r.DistributionSummary)?r.DistributionSummary:[r.DistributionSummary];return i.push(...o.map((s)=>({Id:s.Id,ARN:s.ARN,Status:s.Status,DomainName:s.DomainName,Aliases:s.Aliases
|
|
11
|
+
</InvalidationBatch>`,r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:`/2020-05-31/distribution/${e.distributionId}/invalidation`,body:t,headers:{"Content-Type":"application/xml"}});return{Id:r.Id||r.Invalidation?.Id,Status:r.Status||r.Invalidation?.Status||"InProgress",CreateTime:r.CreateTime||r.Invalidation?.CreateTime||new Date().toISOString()}}async getInvalidation(e,i){let t=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/invalidation/${i}`});return{Id:t.Id||t.Invalidation?.Id,Status:t.Status||t.Invalidation?.Status,CreateTime:t.CreateTime||t.Invalidation?.CreateTime}}async listInvalidations(e){let i=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/invalidation`}),t=[];if(i.InvalidationSummary){let r=Array.isArray(i.InvalidationSummary)?i.InvalidationSummary:[i.InvalidationSummary];t.push(...r.map((o)=>({Id:o.Id,Status:o.Status,CreateTime:o.CreateTime})))}return t}async waitForInvalidation(e,i){let r=0;while(r<60){if((await this.getInvalidation(e,i)).Status==="Completed")return;await new Promise((s)=>setTimeout(s,5000)),r++}throw Error(`Timeout waiting for invalidation ${i} to complete`)}async listDistributions(){let e=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:"/2020-05-31/distribution"}),i=[],r=(e.DistributionList||e).Items,o=[];if(Array.isArray(r))o=r;else if(r?.DistributionSummary)o=Array.isArray(r.DistributionSummary)?r.DistributionSummary:[r.DistributionSummary];return i.push(...o.map((s)=>({Id:s.Id,ARN:s.ARN,Status:s.Status,DomainName:s.DomainName,Aliases:s.Aliases?S(s.Aliases):void 0,Enabled:s.Enabled==="true"||s.Enabled===!0}))),i}async getDistribution(e){let i=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}`}),t=i.Distribution||i;return{Id:t.Id,ARN:t.ARN,Status:t.Status,DomainName:t.DomainName,Aliases:S(t.DistributionConfig?.Aliases??t.Aliases),Enabled:t.DistributionConfig?.Enabled==="true"||t.DistributionConfig?.Enabled===!0}}async getDistributionConfig(e){let i=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/config`,returnHeaders:!0}),t={...i.body?.DistributionConfig??i.body??{}};return delete t["@_xmlns"],{ETag:i.headers?.etag||i.headers?.ETag||"",DistributionConfig:t}}async invalidateAll(e){return this.createInvalidation({distributionId:e,paths:["/*"]})}async invalidatePaths(e,i){let t=i.map((r)=>r.startsWith("/")?r:`/${r}`);return this.createInvalidation({distributionId:e,paths:t})}async invalidatePattern(e,i){let t=i.startsWith("/")?i:`/${i}`;return this.createInvalidation({distributionId:e,paths:[t]})}async invalidateAfterDeployment(e){let{distributionId:i,changedPaths:t,invalidateAll:r=!1,wait:o=!1}=e,s;if(r||!t||t.length===0)s=await this.invalidateAll(i);else s=await this.invalidatePaths(i,t);if(o)await this.waitForInvalidation(i,s.Id);return{invalidationId:s.Id,status:s.Status}}async findDistributionByDomain(e){return(await this.listDistributions()).find((r)=>{if(r.DomainName===e)return!0;if(r.Aliases?.Items&&r.Aliases.Items.includes(e))return!0;return!1})||null}async batchInvalidate(e,i=["/*"]){return await Promise.all(e.map(async(r)=>{let o=await this.createInvalidation({distributionId:r,paths:i});return{distributionId:r,invalidationId:o.Id,status:o.Status}}))}async updateCustomErrorResponses(e){let{distributionId:i,customErrorResponses:t}=e,r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${i}/config`,returnHeaders:!0}),o=r.headers?.etag||r.headers?.ETag||"",s=r.body?.DistributionConfig||(r.body?.Enabled!==void 0?r.body:void 0)||r.DistributionConfig;if(!s||s.Enabled===void 0)throw Error("Failed to get current distribution config");if(t.length===0)s.CustomErrorResponses={Quantity:0};else s.CustomErrorResponses={Quantity:t.length,Items:{CustomErrorResponse:t.map((u)=>({ErrorCode:u.errorCode,...u.responsePagePath&&{ResponsePagePath:u.responsePagePath},...u.responseCode&&{ResponseCode:u.responseCode},...u.errorCachingMinTTL!==void 0&&{ErrorCachingMinTTL:u.errorCachingMinTTL}}))}};let a=this.buildDistributionConfigXml(s),c=await this.client.request({service:"cloudfront",region:"us-east-1",method:"PUT",path:`/2020-05-31/distribution/${i}/config`,body:a,headers:{"Content-Type":"application/xml","If-Match":o},returnHeaders:!0}),g=c.body?.Distribution??c.body??{};return{Distribution:{Id:g.Id,ARN:g.ARN,Status:g.Status,DomainName:g.DomainName,Aliases:S(g.DistributionConfig?.Aliases),Enabled:g.DistributionConfig?.Enabled==="true"||g.DistributionConfig?.Enabled===!0},ETag:c.headers?.etag||c.headers?.ETag||""}}async removeCustomErrorResponses(e){return this.updateCustomErrorResponses({distributionId:e,customErrorResponses:[]})}async updateDistribution(e){let{distributionId:i,aliases:t,certificateArn:r,comment:o}=e,s=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${i}/config`,returnHeaders:!0}),a=s.headers?.etag||s.headers?.ETag||"",c=s.body?.DistributionConfig||(s.body?.Enabled!==void 0?s.body:void 0)||s.DistributionConfig;if(!c||c.Enabled===void 0)throw Error("Failed to get current distribution config");if(t&&t.length>0)c.Aliases={Quantity:t.length,Items:{Item:t}};if(r)c.ViewerCertificate={ACMCertificateArn:r,SSLSupportMethod:"sni-only",MinimumProtocolVersion:"TLSv1.2_2021",CertificateSource:"acm"};if(o)c.Comment=o;let g=this.buildDistributionConfigXml(c),u=await this.client.request({service:"cloudfront",region:"us-east-1",method:"PUT",path:`/2020-05-31/distribution/${i}/config`,body:g,headers:{"Content-Type":"application/xml","If-Match":a},returnHeaders:!0}),d=u.body?.Distribution??u.body??{};return{Distribution:{Id:d.Id,ARN:d.ARN,Status:d.Status,DomainName:d.DomainName,Aliases:t?{Quantity:t.length,Items:t}:{Quantity:0,Items:[]},Enabled:d.DistributionConfig?.Enabled==="true"||d.DistributionConfig?.Enabled===!0},ETag:u.headers?.etag||u.headers?.ETag||""}}buildDistributionConfigXml(e){let i=(s)=>s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),t={Items:"",Methods:"Method",Headers:"Name",Cookies:"Name",QueryStringCacheKeys:"Name",TrustedKeyGroups:"KeyGroup",TrustedSigners:"AwsAccountNumber",LambdaFunctionAssociations:"LambdaFunctionAssociation",FunctionAssociations:"FunctionAssociation",CacheBehaviors:"CacheBehavior",CustomErrorResponses:"CustomErrorResponse",GeoRestriction:"Location"},r={Origins:"Origin",Aliases:"CNAME",AllowedMethods:"Method",CachedMethods:"Method",CustomErrorResponses:"CustomErrorResponse",CacheBehaviors:"CacheBehavior"},o=(s,a,c="",g="")=>{if(a===null||a===void 0)return"";if(s.startsWith("@_")||s==="?xml")return"";if(typeof a==="boolean")return`${c}<${s}>${a}</${s}>
|
|
12
12
|
`;if(typeof a==="number"||typeof a==="string")return`${c}<${s}>${i(String(a))}</${s}>
|
|
13
13
|
`;if(Array.isArray(a)){let u=t[s]||s.replace(/s$/,"");return a.map((d)=>o(u,d,c,s)).join("")}if(typeof a==="object"){if(s==="Items"){let d=r[g]||"",h=Object.keys(a).filter((l)=>!l.startsWith("@_"));if(h.length===1&&!Array.isArray(a[h[0]])){let l=h[0],f=a[l];if(typeof f==="string")return`${c}<Items>
|
|
14
14
|
${c} <${l}>${i(f)}</${l}>
|
|
15
15
|
${c}</Items>
|
|
16
16
|
`;else if(typeof f==="object"&&!Array.isArray(f))return`${c}<Items>
|
|
17
17
|
${o(l,f,c+" ",s)}${c}</Items>
|
|
18
|
-
`}if(h.length===1&&Array.isArray(a[h[0]])){let l=h[0],f=a[l],m="";for(let
|
|
19
|
-
`;else m+=o(l,
|
|
18
|
+
`}if(h.length===1&&Array.isArray(a[h[0]])){let l=h[0],f=a[l],m="";for(let b of f)if(typeof b==="string")m+=`${c} <${l}>${i(b)}</${l}>
|
|
19
|
+
`;else m+=o(l,b,c+" ",s);return`${c}<Items>
|
|
20
20
|
${m}${c}</Items>
|
|
21
21
|
`}if(Array.isArray(a)){let l="",f=d||"Item";for(let m of a)if(typeof m==="string")l+=`${c} <${f}>${i(m)}</${f}>
|
|
22
22
|
`;else l+=o(f,m,c+" ",s);return`${c}<Items>
|
|
@@ -34,7 +34,7 @@ ${Object.entries(e).filter(([s])=>!s.startsWith("@_")).map(([s,a])=>o(s,a," ","
|
|
|
34
34
|
<Runtime>${o}</Runtime>
|
|
35
35
|
</FunctionConfig>
|
|
36
36
|
<FunctionCode>${Buffer.from(t).toString("base64")}</FunctionCode>
|
|
37
|
-
</CreateFunctionRequest>`,a=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/function",body:s,headers:{"Content-Type":"application/xml"}}),c=a.FunctionSummary
|
|
37
|
+
</CreateFunctionRequest>`,a=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/function",body:s,headers:{"Content-Type":"application/xml"},returnHeaders:!0}),c=a.body?.FunctionSummary??a.body??{};return{FunctionARN:c.FunctionMetadata?.FunctionARN||c.FunctionARN,Name:c.Name||i,Stage:c.FunctionMetadata?.Stage||"DEVELOPMENT",ETag:a.headers?.etag||a.headers?.ETag||""}}async listFunctions(){let e=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:"/2020-05-31/function"}),i=[],t=(e.FunctionList??e)?.Items?.FunctionSummary;if(t){let r=Array.isArray(t)?t:[t];for(let o of r)i.push({Name:o.Name,FunctionARN:o.FunctionMetadata?.FunctionARN,Stage:o.FunctionMetadata?.Stage,CreatedTime:o.FunctionMetadata?.CreatedTime,LastModifiedTime:o.FunctionMetadata?.LastModifiedTime})}return i}async getFunction(e,i="LIVE"){try{let t=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/function/${e}`,queryParams:{Stage:i},returnHeaders:!0}),r=t.body?.FunctionSummary||t.FunctionSummary||t.body||t;return{FunctionARN:r.FunctionMetadata?.FunctionARN,Name:r.Name||e,Stage:r.FunctionMetadata?.Stage||i,ETag:t.headers?.etag||t.ETag||"",FunctionCode:r.FunctionCode}}catch(t){if(t.message?.includes("404")||t.message?.includes("NoSuchFunctionExists"))return null;throw t}}async publishFunction(e,i){let t,r;if(typeof e==="object")t=e.Name,r=e.IfMatch;else t=e,r=i;if(!r){let a=await this.getFunction(t,"DEVELOPMENT");if(!a)throw Error(`Function ${t} not found`);r=a.ETag}let o=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:`/2020-05-31/function/${t}/publish`,headers:{"If-Match":r}}),s=o.FunctionSummary||o;return{FunctionARN:s.FunctionMetadata?.FunctionARN,Stage:s.FunctionMetadata?.Stage||"LIVE",FunctionSummary:s}}async describeFunction(e){let{Name:i,Stage:t="DEVELOPMENT"}=e,r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/function/${i}/describe`,queryParams:{Stage:t},returnHeaders:!0});return{ETag:r.headers?.etag||r.ETag||"",FunctionSummary:r.body?.FunctionSummary||r.FunctionSummary||r.body||r}}async updateFunction(e){let{Name:i,FunctionCode:t,FunctionConfig:r,IfMatch:o}=e,s=`<?xml version="1.0" encoding="UTF-8"?>
|
|
38
38
|
<UpdateFunctionRequest xmlns="http://cloudfront.amazonaws.com/doc/2020-05-31/">
|
|
39
39
|
<FunctionConfig>
|
|
40
40
|
<Comment>${r.Comment}</Comment>
|
|
@@ -63,11 +63,11 @@ ${Object.entries(e).filter(([s])=>!s.startsWith("@_")).map(([s,a])=>o(s,a," ","
|
|
|
63
63
|
<SigningProtocol>${r}</SigningProtocol>
|
|
64
64
|
<SigningBehavior>${o}</SigningBehavior>
|
|
65
65
|
<OriginAccessControlOriginType>${s}</OriginAccessControlOriginType>
|
|
66
|
-
</OriginAccessControlConfig>`,c=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/origin-access-control",body:a,headers:{"Content-Type":"application/xml"},returnHeaders:!0}),g=c.body?.OriginAccessControl||c.OriginAccessControl||c.body||c;return{Id:g.Id,Name:g.OriginAccessControlConfig?.Name||i,Description:g.OriginAccessControlConfig?.Description||t,SigningProtocol:g.OriginAccessControlConfig?.SigningProtocol||r,SigningBehavior:g.OriginAccessControlConfig?.SigningBehavior||o,OriginAccessControlOriginType:g.OriginAccessControlConfig?.OriginAccessControlOriginType||s,ETag:c.headers?.etag||c.ETag||""}}async findOrCreateOriginAccessControl(e,i="s3"){let r=(await this.listOriginAccessControls()).find((s)=>s.Name===e&&s.OriginAccessControlOriginType===i);if(r)return{Id:r.Id,Name:r.Name,isNew:!1};let o=await this.createOriginAccessControl({name:e,originType:i});return{Id:o.Id,Name:o.Name,isNew:!0}}async createDistributionForS3(e){let{bucketName:i,bucketRegion:t,originAccessControlId:r,aliases:o=[],certificateArn:s,defaultRootObject:a="index.html",comment:c=`Distribution for ${i}`,priceClass:g="PriceClass_100",enabled:u=!0,trustedKeyGroupIds:d=[],mediaDelivery:h=!1}=e,l=`S3-${i}`,f=`${i}.s3.${t}.amazonaws.com`,m=`${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
66
|
+
</OriginAccessControlConfig>`,c=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/origin-access-control",body:a,headers:{"Content-Type":"application/xml"},returnHeaders:!0}),g=c.body?.OriginAccessControl||c.OriginAccessControl||c.body||c;return{Id:g.Id,Name:g.OriginAccessControlConfig?.Name||i,Description:g.OriginAccessControlConfig?.Description||t,SigningProtocol:g.OriginAccessControlConfig?.SigningProtocol||r,SigningBehavior:g.OriginAccessControlConfig?.SigningBehavior||o,OriginAccessControlOriginType:g.OriginAccessControlConfig?.OriginAccessControlOriginType||s,ETag:c.headers?.etag||c.ETag||""}}async findOrCreateOriginAccessControl(e,i="s3"){let r=(await this.listOriginAccessControls()).find((s)=>s.Name===e&&s.OriginAccessControlOriginType===i);if(r)return{Id:r.Id,Name:r.Name,isNew:!1};let o=await this.createOriginAccessControl({name:e,originType:i});return{Id:o.Id,Name:o.Name,isNew:!0}}async createDistributionForS3(e){let{bucketName:i,bucketRegion:t,originAccessControlId:r,aliases:o=[],certificateArn:s,defaultRootObject:a="index.html",comment:c=`Distribution for ${i}`,priceClass:g="PriceClass_100",enabled:u=!0,trustedKeyGroupIds:d=[],mediaDelivery:h=!1}=e,l=`S3-${i}`,f=`${i}.s3.${t}.amazonaws.com`,m=`${Date.now()}-${Math.random().toString(36).slice(2)}`,b=d.length>0?`<TrustedKeyGroups>
|
|
67
67
|
<Enabled>true</Enabled>
|
|
68
68
|
<Quantity>${d.length}</Quantity>
|
|
69
69
|
<Items>${d.map((P)=>`<KeyGroup>${P}</KeyGroup>`).join("")}</Items>
|
|
70
|
-
</TrustedKeyGroups>`:"<TrustedKeyGroups><Enabled>false</Enabled><Quantity>0</Quantity></TrustedKeyGroups>",
|
|
70
|
+
</TrustedKeyGroups>`:"<TrustedKeyGroups><Enabled>false</Enabled><Quantity>0</Quantity></TrustedKeyGroups>",E="<Aliases><Quantity>0</Quantity></Aliases>";if(o.length>0)E=`<Aliases>
|
|
71
71
|
<Quantity>${o.length}</Quantity>
|
|
72
72
|
<Items>
|
|
73
73
|
${o.map((P)=>`<CNAME>${P}</CNAME>`).join(`
|
|
@@ -80,7 +80,7 @@ ${Object.entries(e).filter(([s])=>!s.startsWith("@_")).map(([s,a])=>o(s,a," ","
|
|
|
80
80
|
<SSLSupportMethod>sni-only</SSLSupportMethod>
|
|
81
81
|
<MinimumProtocolVersion>TLSv1.2_2021</MinimumProtocolVersion>
|
|
82
82
|
<CertificateSource>acm</CertificateSource>
|
|
83
|
-
</ViewerCertificate>`;let
|
|
83
|
+
</ViewerCertificate>`;let A=`<?xml version="1.0" encoding="UTF-8"?>
|
|
84
84
|
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2020-05-31/">
|
|
85
85
|
<CallerReference>${m}</CallerReference>
|
|
86
86
|
<Comment>${c}</Comment>
|
|
@@ -118,9 +118,9 @@ ${Object.entries(e).filter(([s])=>!s.startsWith("@_")).map(([s,a])=>o(s,a," ","
|
|
|
118
118
|
</AllowedMethods>
|
|
119
119
|
<Compress>true</Compress>
|
|
120
120
|
<CachePolicyId>658327ea-f89d-4fab-a63d-7e88639e58f6</CachePolicyId>
|
|
121
|
-
${
|
|
121
|
+
${b}
|
|
122
122
|
</DefaultCacheBehavior>
|
|
123
|
-
${
|
|
123
|
+
${E}
|
|
124
124
|
${p}
|
|
125
125
|
<PriceClass>${g}</PriceClass>
|
|
126
126
|
<Enabled>${u}</Enabled>
|
|
@@ -137,5 +137,5 @@ ${Object.entries(e).filter(([s])=>!s.startsWith("@_")).map(([s,a])=>o(s,a," ","
|
|
|
137
137
|
</CustomErrorResponse>
|
|
138
138
|
</Items>
|
|
139
139
|
</CustomErrorResponses>`}
|
|
140
|
-
</DistributionConfig>`,
|
|
140
|
+
</DistributionConfig>`,C=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/distribution",body:A,headers:{"Content-Type":"application/xml"},returnHeaders:!0}),T=C.body?.Distribution||C.Distribution||C.body||C;return{Id:T.Id,ARN:T.ARN,DomainName:T.DomainName,Status:T.Status,ETag:C.headers?.etag||C.ETag||""}}async createMediaDistributionForS3(e){return this.createDistributionForS3({...e,defaultRootObject:"",mediaDelivery:!0,comment:e.comment??`Media distribution for ${e.bucketName}`})}async listPublicKeys(){let e=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:"/2020-05-31/public-key"});return this.collectionItems(e.PublicKeyList??e,"PublicKeySummary").map((t)=>({Id:String(t.Id),Name:String(t.Name),Comment:t.Comment?String(t.Comment):void 0}))}async createPublicKey(e){if(!/^[A-Za-z0-9_-]{1,128}$/.test(e.name))throw TypeError("CloudFront public key name is invalid");if(!e.encodedKey.includes("BEGIN PUBLIC KEY"))throw TypeError("CloudFront public key must be PEM encoded");let i=(o)=>o.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">"),t=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/public-key",headers:{"Content-Type":"application/xml"},body:`<PublicKeyConfig xmlns="http://cloudfront.amazonaws.com/doc/2020-05-31/"><CallerReference>${i(e.callerReference??`${Date.now()}-${e.name}`)}</CallerReference><Name>${i(e.name)}</Name><EncodedKey>${i(e.encodedKey)}</EncodedKey><Comment>${i(e.comment??"")}</Comment></PublicKeyConfig>`}),r=t.PublicKey??t;return{Id:String(r.Id),Name:String(r.PublicKeyConfig?.Name??e.name),EncodedKey:String(r.PublicKeyConfig?.EncodedKey??e.encodedKey),Comment:String(r.PublicKeyConfig?.Comment??e.comment??"")}}async listKeyGroups(){let e=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:"/2020-05-31/key-group"});return this.collectionItems(e.KeyGroupList??e,"KeyGroupSummary").map((t)=>({Id:String(t.KeyGroup?.Id??t.Id),Name:String(t.KeyGroup?.KeyGroupConfig?.Name??t.KeyGroupConfig?.Name??t.Name),Items:this.collectionItems(t.KeyGroup?.KeyGroupConfig?.Items??t.KeyGroupConfig?.Items??t.Items,"Item").map(String),Comment:t.KeyGroup?.KeyGroupConfig?.Comment??t.KeyGroupConfig?.Comment??t.Comment}))}async createKeyGroup(e){if(!/^[A-Za-z0-9_-]{1,128}$/.test(e.name))throw TypeError("CloudFront key group name is invalid");let i=[...new Set(e.publicKeyIds)];if(i.length===0)throw TypeError("CloudFront key group requires at least one public key");let t=(a)=>a.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">"),r=i.map((a)=>`<Item>${t(a)}</Item>`).join(""),o=await this.client.request({service:"cloudfront",region:"us-east-1",method:"POST",path:"/2020-05-31/key-group",headers:{"Content-Type":"application/xml"},body:`<KeyGroupConfig xmlns="http://cloudfront.amazonaws.com/doc/2020-05-31/"><Name>${t(e.name)}</Name><Items>${r}</Items><Comment>${t(e.comment??"")}</Comment></KeyGroupConfig>`}),s=o.KeyGroup??o;return{Id:String(s.Id),Name:String(s.KeyGroupConfig?.Name??e.name),Items:i,Comment:String(s.KeyGroupConfig?.Comment??e.comment??"")}}static getS3BucketPolicyForCloudFront(e,i){return{Version:"2012-10-17",Statement:[{Sid:"AllowCloudFrontServicePrincipal",Effect:"Allow",Principal:{Service:"cloudfront.amazonaws.com"},Action:"s3:GetObject",Resource:`arn:aws:s3:::${e}/*`,Condition:{StringEquals:{"AWS:SourceArn":i}}}]}}async waitForDistributionDeployed(e,i=60){for(let t=0;t<i;t++){if((await this.getDistribution(e)).Status==="Deployed")return!0;await new Promise((o)=>setTimeout(o,30000))}return!1}async disableDistribution(e){let i=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/config`,returnHeaders:!0}),t=i.headers?.etag||i.headers?.ETag||"",r=i.body?.DistributionConfig||(i.body?.Enabled!==void 0?i.body:void 0)||i.DistributionConfig;if(!r||r.Enabled===void 0)throw Error("Failed to get current distribution config");r.Enabled=!1;let o=this.buildDistributionConfigXml(r),s=await this.client.request({service:"cloudfront",region:"us-east-1",method:"PUT",path:`/2020-05-31/distribution/${e}/config`,body:o,headers:{"Content-Type":"application/xml","If-Match":t},returnHeaders:!0});return{ETag:s.headers?.etag||s.headers?.ETag||s.ETag||""}}async deleteDistribution(e,i){let t=i||"";if(!t){let r=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}`,returnHeaders:!0});t=r.headers?.etag||r.headers?.ETag||""}await this.client.request({service:"cloudfront",region:"us-east-1",method:"DELETE",path:`/2020-05-31/distribution/${e}`,headers:{"If-Match":t}})}async waitForDistributionDisabled(e,i=60){for(let t=0;t<i;t++){let r=await this.getDistribution(e);if(r.Status==="Deployed"&&!r.Enabled)return!0;await new Promise((o)=>setTimeout(o,30000))}return!1}async removeAlias(e,i){let t=await this.client.request({service:"cloudfront",region:"us-east-1",method:"GET",path:`/2020-05-31/distribution/${e}/config`,returnHeaders:!0}),r=t.headers?.etag||t.headers?.ETag||"",o=t.body?.DistributionConfig||(t.body?.Enabled!==void 0?t.body:void 0)||t.DistributionConfig;if(!o||o.Enabled===void 0)throw Error("Failed to get current distribution config");let s=[];if(o.Aliases?.Items){if(Array.isArray(o.Aliases.Items))s=o.Aliases.Items;else if(typeof o.Aliases.Items==="object"){let u=o.Aliases.Items.CNAME;if(typeof u==="string")s=[u];else if(Array.isArray(u))s=u}}if(s.length===0)throw Error("Distribution has no aliases to remove");let a=s.filter((u)=>u!==i);if(a.length===s.length)throw Error(`Alias ${i} not found in distribution`);if(o.Aliases.Quantity=a.length,o.Aliases.Items=a.length>0?a:void 0,a.length===0)o.ViewerCertificate={CloudFrontDefaultCertificate:!0,MinimumProtocolVersion:"TLSv1.2_2021"};let c=this.buildDistributionConfigXml(o),g=await this.client.request({service:"cloudfront",region:"us-east-1",method:"PUT",path:`/2020-05-31/distribution/${e}/config`,body:c,headers:{"Content-Type":"application/xml","If-Match":r},returnHeaders:!0});return{ETag:g.headers?.etag||g.headers?.ETag||g.ETag||""}}}
|
|
141
141
|
export{y};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{is,ss,os,as,Ma,Fa}from"./chunk-r1730x8g.js";import"./chunk-jwx5t3vf.js";import"./chunk-setpnrtg.js";import"./chunk-5db32a4x.js";import"./chunk-08tswmb3.js";import"./chunk-2nma0bd8.js";import"./chunk-wrpnnrdf.js";export{Ma as deleteStaticSite,ss as deployStaticSite,Fa as deployStaticSiteFull,is as generateStaticSiteTemplate,as as invalidateCache,os as uploadStaticFiles};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{M,
|
|
2
|
-
export{x,Dr,Pr,
|
|
1
|
+
import{M,vd}from"./chunk-w23wrsa4.js";function x(t,s){return`/var/www/${t}-${s}`}var y=new Set(["laravel","php","statamic","wordpress"]);function Dr(t){return t.type!=null&&y.has(t.type)}function Pr(t){let s=t.proxyTo;if(s==null)return[];return(Array.isArray(s)?s:[s]).map((n)=>String(n).trim()).filter((n)=>n.length>0)}function Lc(t){return Pr(t).length>0}function Ms(t){if(t.deploy)return t.deploy;if(Dr(t))return"server";if(t.start)return"server";return"bucket"}function u(t){if(t.redirect)return"redirect";if(Lc(t))return"proxy";if(Dr(t))return"server-php";if(Ms(t)==="bucket")return"bucket";return t.start?"server-app":"server-static"}function Df(t){return t.infrastructure?.compute!=null||Boolean(t.cloud?.attachTo?.trim())}function Lp(t,s={}){let r=[],n=[],c=t.sites||{},p=Df(t),f=vd(t);if(f)r.push(f);let d=new Map;for(let[o,e]of Object.entries(c)){if(!e)continue;let h=Ms(e),l=u(e);if(l==="redirect"){if(!e.domain)r.push(`Site '${o}' is a redirect site but has no \`domain\` to redirect from.`);if(!(typeof e.redirect==="string"?e.redirect:e.redirect?.to))r.push(`Site '${o}' is a redirect site but has no redirect target (\`redirect\` / \`redirect.to\`).`);if(!p)r.push(`Site '${o}' is a redirect site but no \`infrastructure.compute\` is configured to host the gateway that serves the redirect.`);let a=[];if(e.start)a.push("start");if(e.root)a.push("root");if(e.proxyTo)a.push("proxyTo");if(a.length>0)n.push(`Site '${o}' is a redirect site but also sets ${a.join(", ")}. These are ignored.`);continue}if(l==="proxy"){if(!e.domain)r.push(`Site '${o}' is a proxy site but has no \`domain\` to route from.`);if(!p)r.push(`Site '${o}' is a proxy site but no \`infrastructure.compute\` is configured to host the gateway that forwards it.`);let i=[];if(e.start)i.push("start");if(e.root)i.push("root");if(typeof e.port==="number")i.push("port");if(e.build)i.push("build");if(e.preStart&&e.preStart.length>0)i.push("preStart");if(i.length>0)n.push(`Site '${o}' sets \`proxyTo\`, so ts-cloud ships and supervises nothing for it. ${i.join(", ")} ${i.length===1?"is":"are"} ignored — remove ${i.length===1?"it":"them"}, or drop \`proxyTo\` to let ts-cloud own the service.`);continue}if(h==="server"&&!e.start&&!e.root){r.push(`Site '${o}' sets deploy:'server' but declares neither \`start\` (dynamic app) nor \`root\` (static site to serve). Add one.`);continue}if(l==="server-php"){if(!p)r.push(`Site '${o}' is a PHP site (type:'${e.type}') but no \`infrastructure.compute\` is configured. Add a server (infrastructure.compute) with PHP provisioning.`);if(!e.repository?.url)r.push(`Site '${o}' is a PHP site (type:'${e.type}') but has no \`repository.url\` to clone. PHP sites deploy via git.`)}else if(l==="server-app"){if(!p)r.push(`Site '${o}' deploys to a server (deploy:'server'${e.deploy?"":" inferred from `start`"}) but no \`infrastructure.compute\` is configured. Set deploy:'bucket' or add a server (infrastructure.compute).`);if(typeof e.port==="number"){let i=s.occupiedPorts?.get(e.port);if(i)r.push(`Site '${o}' wants port ${e.port}, which project '${i}' already serves on this box. Attached projects share one port namespace. Give '${o}' a free port, or let the attach allocate one.`);let a=d.get(e.port);if(a)r.push(`Sites '${a}' and '${o}' both use port ${e.port}. Server apps sharing a box must use distinct ports.`);else d.set(e.port,o)}}else if(l==="server-static"){if(!e.root)r.push(`Site '${o}' is a server static site (deploy:'server', no \`start\`) but has no \`root\` directory to serve.`);if(!p)r.push(`Site '${o}' deploys to a server (deploy:'server') but no \`infrastructure.compute\` is configured. Set deploy:'bucket' or add a server (infrastructure.compute).`)}else{if(!e.root)r.push(`Site '${o}' deploys to a bucket but has no \`root\` directory to upload.`);let i=[];if(e.start)i.push("start");if(typeof e.port==="number")i.push("port");if(e.preStart&&e.preStart.length>0)i.push("preStart");if(i.length>0)n.push(`Site '${o}' deploys to a bucket but sets server-only field(s): ${i.join(", ")}. These are ignored. Set deploy:'server' to use them.`)}}return{errors:r,warnings:n}}function $p(t){let s=u(t);return s!=="bucket"&&s!=="redirect"&&s!=="proxy"}function oI(t){return u(t)==="bucket"}function aI(t,s){if(M(t)==="serverless")return!0;let r=Object.entries(t.sites??{}).filter(([,c])=>c!=null),n=s?r.filter(([c])=>c===s):r;if(n.length===0)return!0;return!n.every(([,c])=>{let p=u(c);return p==="redirect"||p==="proxy"})}
|
|
2
|
+
export{x,Dr,Pr,Lc,Ms,u,Df,Lp,$p,oI,aI};
|