@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.
Files changed (193) hide show
  1. package/dist/aws/client.d.ts +9 -0
  2. package/dist/aws/index.js +1 -1
  3. package/dist/bin/chunk-0cwbg3pf.js +1 -0
  4. package/dist/bin/{chunk-6cfpdb35.js → chunk-0xxc6dy8.js} +7 -7
  5. package/dist/bin/chunk-19tmmwmt.js +1 -0
  6. package/dist/bin/{chunk-2tk8egg8.js → chunk-1j9vy88a.js} +1 -1
  7. package/dist/bin/{chunk-wyanqf91.js → chunk-21jwbrap.js} +2 -2
  8. package/dist/bin/{chunk-j0zg3mbm.js → chunk-2q27v6vz.js} +1 -1
  9. package/dist/bin/{chunk-9h7yjtz2.js → chunk-3jjggqfj.js} +3 -3
  10. package/dist/bin/{chunk-zcabmq4p.js → chunk-3kvz4kyq.js} +3 -3
  11. package/dist/bin/chunk-4261t3bq.js +1 -0
  12. package/dist/bin/chunk-4a98nszr.js +1 -0
  13. package/dist/bin/{chunk-k1eezsj1.js → chunk-4r46kw46.js} +2 -2
  14. package/dist/bin/chunk-5mk3sxpw.js +34 -0
  15. package/dist/bin/{chunk-jtnv8nwz.js → chunk-6nm91cfw.js} +1 -1
  16. package/dist/bin/{chunk-ht6tpmqw.js → chunk-7412q5cz.js} +2 -2
  17. package/dist/bin/chunk-78tzgf65.js +1 -0
  18. package/dist/bin/{chunk-h90azajz.js → chunk-82sbpydz.js} +2 -2
  19. package/dist/bin/{chunk-ht318ydv.js → chunk-8knkt6sd.js} +1 -1
  20. package/dist/bin/{chunk-65rndjtr.js → chunk-8wnpx6n2.js} +42 -42
  21. package/dist/bin/{chunk-k052rtd5.js → chunk-9066j2kz.js} +4 -4
  22. package/dist/bin/{chunk-34kwhmbt.js → chunk-9464wvf2.js} +5 -5
  23. package/dist/bin/{chunk-cpwk0pbg.js → chunk-9rya3733.js} +65 -65
  24. package/dist/bin/chunk-ajv4z454.js +1 -0
  25. package/dist/bin/chunk-aqreqn37.js +1 -0
  26. package/dist/bin/chunk-cnmngqqg.js +1 -0
  27. package/dist/bin/chunk-db9zx72q.js +1 -0
  28. package/dist/bin/{chunk-8vm7tpyv.js → chunk-dh6kj6ce.js} +2 -2
  29. package/dist/bin/chunk-dhj4786e.js +1 -0
  30. package/dist/bin/chunk-eh3235zq.js +1 -0
  31. package/dist/bin/chunk-es4sdbrr.js +1 -0
  32. package/dist/bin/{chunk-xs6afjat.js → chunk-fdsh3m2q.js} +3 -3
  33. package/dist/bin/chunk-g0gqwszk.js +1 -0
  34. package/dist/bin/chunk-gj530nqd.js +1 -0
  35. package/dist/bin/chunk-h1618tyv.js +1 -0
  36. package/dist/bin/chunk-hje6rsxj.js +2 -0
  37. package/dist/bin/chunk-hwqvx1zb.js +1 -0
  38. package/dist/bin/chunk-ksfr2ya8.js +1 -0
  39. package/dist/bin/{chunk-f2yhthd1.js → chunk-mdbzfvba.js} +2 -2
  40. package/dist/bin/chunk-mfer1e5z.js +1 -0
  41. package/dist/bin/chunk-mh172wt8.js +1 -0
  42. package/dist/bin/chunk-mrte8smv.js +1 -0
  43. package/dist/bin/{chunk-90kpnjdm.js → chunk-n5zwm2z4.js} +12 -12
  44. package/dist/bin/chunk-n8ya6q6d.js +2 -0
  45. package/dist/bin/{chunk-en7sf83z.js → chunk-ntmnpteh.js} +6 -6
  46. package/dist/bin/{chunk-f3sd1hpa.js → chunk-nxyhheav.js} +5 -5
  47. package/dist/bin/chunk-p1cv4n00.js +2 -0
  48. package/dist/bin/{chunk-t1jpqn4x.js → chunk-q3xwh0r8.js} +6 -6
  49. package/dist/bin/chunk-s7axkfrs.js +1 -0
  50. package/dist/bin/{chunk-tyqxz92e.js → chunk-t5gkbppg.js} +105 -105
  51. package/dist/bin/{chunk-jbpkwxht.js → chunk-td8zgch7.js} +5 -5
  52. package/dist/bin/{chunk-gzpwf3n4.js → chunk-tnzp96vn.js} +2 -2
  53. package/dist/bin/{chunk-0r45d0s3.js → chunk-v4e4726j.js} +1 -1
  54. package/dist/bin/{chunk-33e0t7e5.js → chunk-w23en85y.js} +2 -2
  55. package/dist/bin/{chunk-21zhm1mk.js → chunk-wsedynyb.js} +6 -6
  56. package/dist/bin/{chunk-v002yxaf.js → chunk-xss6yj73.js} +2 -2
  57. package/dist/bin/{chunk-btr6zq53.js → chunk-y4g86dpe.js} +3 -3
  58. package/dist/bin/{chunk-hqmkfh4a.js → chunk-y6rgvb7r.js} +1 -1
  59. package/dist/bin/chunk-yavtz60y.js +1 -0
  60. package/dist/bin/{chunk-yxyvhqhr.js → chunk-z5ycwy38.js} +2 -2
  61. package/dist/bin/{chunk-gfwkmttt.js → chunk-z96ssb7e.js} +1 -1
  62. package/dist/bin/chunk-zq02x716.js +1 -0
  63. package/dist/bin/cli.js +285 -285
  64. package/dist/bin/dashboard-server.js +1 -1
  65. package/dist/{chunk-hpq0rrve.js → chunk-08tswmb3.js} +1 -1
  66. package/dist/{chunk-gm0qysea.js → chunk-0p7ddjt6.js} +10 -10
  67. package/dist/chunk-2nma0bd8.js +92 -0
  68. package/dist/chunk-31qham3c.js +1 -0
  69. package/dist/chunk-3zv0e36t.js +34 -0
  70. package/dist/{chunk-c836kdrx.js → chunk-49p5cx21.js} +29 -29
  71. package/dist/{chunk-t7q4awss.js → chunk-5db32a4x.js} +2 -2
  72. package/dist/{chunk-60fn008g.js → chunk-6e5j40n9.js} +2 -2
  73. package/dist/chunk-7fbfmpyx.js +1 -0
  74. package/dist/{chunk-4apkvhsc.js → chunk-7p1653g6.js} +83 -83
  75. package/dist/{chunk-cpyrhh52.js → chunk-826gp2kd.js} +142 -142
  76. package/dist/{chunk-92gn9ght.js → chunk-98qx6m9h.js} +19 -19
  77. package/dist/{chunk-rq0wrpz6.js → chunk-b10n1xy5.js} +4 -4
  78. package/dist/{chunk-j2w0cvnr.js → chunk-dm6kyz6e.js} +1 -1
  79. package/dist/chunk-dschvakr.js +1 -0
  80. package/dist/chunk-e44ajkha.js +5 -0
  81. package/dist/chunk-e4z4tfh6.js +1 -0
  82. package/dist/{chunk-bz1hp7es.js → chunk-gvybjt7y.js} +1 -1
  83. package/dist/{chunk-xassxhvq.js → chunk-h85wqdvr.js} +7 -7
  84. package/dist/{chunk-nfkdgsgh.js → chunk-jwx5t3vf.js} +11 -11
  85. package/dist/chunk-kmwnzw91.js +1 -0
  86. package/dist/{chunk-14zcywnp.js → chunk-q0g0rjn3.js} +2 -2
  87. package/dist/{chunk-ckwdjb5q.js → chunk-qfqh21rq.js} +5 -5
  88. package/dist/{chunk-b5xjjz3y.js → chunk-r1730x8g.js} +5 -5
  89. package/dist/{chunk-g6aev693.js → chunk-rr1qjxyj.js} +1 -1
  90. package/dist/chunk-rxs4y74z.js +2 -0
  91. package/dist/{chunk-xkqx98bx.js → chunk-setpnrtg.js} +2 -2
  92. package/dist/chunk-tvwrthfq.js +2 -0
  93. package/dist/{chunk-ds2v2xpb.js → chunk-w23wrsa4.js} +123 -123
  94. package/dist/{chunk-5vxpgw8q.js → chunk-wrpnnrdf.js} +5 -5
  95. package/dist/{chunk-pdmfmsm9.js → chunk-x9bpm5s1.js} +1 -1
  96. package/dist/deploy/index.js +1 -1
  97. package/dist/dns/index.js +1 -1
  98. package/dist/drivers/index.js +1 -1
  99. package/dist/index.js +43 -43
  100. package/dist/operations/index.js +1 -1
  101. package/dist/protection/index.js +1 -1
  102. package/dist/spend/index.js +1 -1
  103. package/dist/ui/404.html +1 -1
  104. package/dist/ui/accept-invitation.html +1 -1
  105. package/dist/ui/access-denied.html +1 -1
  106. package/dist/ui/account/automation.html +6 -6
  107. package/dist/ui/account/security.html +2 -2
  108. package/dist/ui/applications/compose.html +6 -6
  109. package/dist/ui/applications/new.html +2 -2
  110. package/dist/ui/data/backups.html +6 -6
  111. package/dist/ui/data/services.html +6 -6
  112. package/dist/ui/data/volumes.html +6 -6
  113. package/dist/ui/index.html +5 -5
  114. package/dist/ui/infrastructure/topology.html +6 -6
  115. package/dist/ui/integrations.html +2 -2
  116. package/dist/ui/operations/alerts.html +6 -6
  117. package/dist/ui/operations/configuration.html +6 -6
  118. package/dist/ui/operations/jobs.html +6 -6
  119. package/dist/ui/operations/maintenance.html +6 -6
  120. package/dist/ui/operations/observability.html +6 -6
  121. package/dist/ui/operations/previews.html +6 -6
  122. package/dist/ui/operations/queue.html +6 -6
  123. package/dist/ui/operations/regions.html +6 -6
  124. package/dist/ui/operations/releases.html +6 -6
  125. package/dist/ui/operations/spend.html +6 -6
  126. package/dist/ui/operations/workloads.html +6 -6
  127. package/dist/ui/security.html +2 -2
  128. package/dist/ui/server/actions.html +6 -6
  129. package/dist/ui/server/activity.html +1 -1
  130. package/dist/ui/server/capacity.html +6 -6
  131. package/dist/ui/server/database.html +6 -6
  132. package/dist/ui/server/deployments.html +6 -6
  133. package/dist/ui/server/diagnostics.html +2 -2
  134. package/dist/ui/server/firewall.html +5 -5
  135. package/dist/ui/server/fleet.html +6 -6
  136. package/dist/ui/server/logs.html +6 -6
  137. package/dist/ui/server/metrics.html +6 -6
  138. package/dist/ui/server/security.html +2 -2
  139. package/dist/ui/server/services.html +2 -2
  140. package/dist/ui/server/sites.html +6 -6
  141. package/dist/ui/server/ssh-keys.html +6 -6
  142. package/dist/ui/server/team.html +6 -6
  143. package/dist/ui/server/terminal.html +2 -2
  144. package/dist/ui/serverless/alarms.html +6 -6
  145. package/dist/ui/serverless/assets.html +2 -2
  146. package/dist/ui/serverless/cost.html +2 -2
  147. package/dist/ui/serverless/data.html +6 -6
  148. package/dist/ui/serverless/deployments.html +2 -2
  149. package/dist/ui/serverless/firewall.html +1 -1
  150. package/dist/ui/serverless/functions.html +6 -6
  151. package/dist/ui/serverless/logs.html +6 -6
  152. package/dist/ui/serverless/metrics.html +1 -1
  153. package/dist/ui/serverless/queues.html +6 -6
  154. package/dist/ui/serverless/secrets.html +6 -6
  155. package/dist/ui/serverless/traces.html +6 -6
  156. package/dist/ui/serverless.html +5 -5
  157. package/package.json +3 -3
  158. package/dist/bin/chunk-0d98bem8.js +0 -2
  159. package/dist/bin/chunk-2g1j00yc.js +0 -1
  160. package/dist/bin/chunk-4xmhrvfa.js +0 -1
  161. package/dist/bin/chunk-6crapvp1.js +0 -1
  162. package/dist/bin/chunk-7b4gf64x.js +0 -1
  163. package/dist/bin/chunk-818tj49e.js +0 -1
  164. package/dist/bin/chunk-92qsww97.js +0 -1
  165. package/dist/bin/chunk-9947rscj.js +0 -1
  166. package/dist/bin/chunk-cas0bp91.js +0 -2
  167. package/dist/bin/chunk-cyap08qg.js +0 -1
  168. package/dist/bin/chunk-dk92s260.js +0 -1
  169. package/dist/bin/chunk-ejxp74ks.js +0 -1
  170. package/dist/bin/chunk-gx98tkpf.js +0 -1
  171. package/dist/bin/chunk-hcdbw9j1.js +0 -1
  172. package/dist/bin/chunk-hdsgfgnz.js +0 -34
  173. package/dist/bin/chunk-kay11qc7.js +0 -1
  174. package/dist/bin/chunk-n28a9a9c.js +0 -1
  175. package/dist/bin/chunk-n298azax.js +0 -2
  176. package/dist/bin/chunk-q8w7fa56.js +0 -1
  177. package/dist/bin/chunk-qdnx952p.js +0 -1
  178. package/dist/bin/chunk-tr0pkm4p.js +0 -1
  179. package/dist/bin/chunk-tytvrehe.js +0 -1
  180. package/dist/bin/chunk-wpp0fa94.js +0 -1
  181. package/dist/bin/chunk-xzgxwnb7.js +0 -1
  182. package/dist/bin/chunk-y21yk6zv.js +0 -1
  183. package/dist/bin/chunk-yt1t5ct8.js +0 -1
  184. package/dist/bin/chunk-zs8ddeaz.js +0 -1
  185. package/dist/chunk-01rbgche.js +0 -2
  186. package/dist/chunk-2hy7ny4k.js +0 -5
  187. package/dist/chunk-4rb7stp5.js +0 -92
  188. package/dist/chunk-cwgy9pvc.js +0 -34
  189. package/dist/chunk-e4qh4c2n.js +0 -1
  190. package/dist/chunk-pj9z4fjv.js +0 -1
  191. package/dist/chunk-twhbns31.js +0 -1
  192. package/dist/chunk-wkg22nj5.js +0 -1
  193. package/dist/chunk-xtd0s5ep.js +0 -1
@@ -1,6 +1,6 @@
1
- import{et,A,qt,Pr,Ei}from"./chunk-tyqxz92e.js";import{execSync as D}from"node:child_process";import{randomBytes as R}from"node:crypto";import{chmodSync as j,copyFileSync as x,existsSync as u,mkdirSync as w,readFileSync as U,statSync as N,writeFileSync as m}from"node:fs";import{tmpdir as E}from"node:os";import{basename as P,dirname as v,isAbsolute as O,join as a,resolve as B}from"node:path";import{fileURLToPath as C}from"node:url";function h(e){if(!e||typeof e!=="object")return e;return Object.fromEntries(Object.keys(e).map((r)=>[r,""]))}function M(e){let r=JSON.parse(JSON.stringify(e??{}));if(r.hetzner)delete r.hetzner.apiToken;delete r.aws,delete r.stateDir;for(let t of Object.values(r.sites??{})){if(t?.env)t.env=h(t.env);if(t?.environment)t.environment=h(t.environment)}for(let t of Object.values(r.environments??{}))if(t?.variables)t.variables=h(t.variables);for(let t of Object.values(r.infrastructure?.databases??{}))if(t?.password)t.password="";if(r.infrastructure?.appDatabase?.password)r.infrastructure.appDatabase.password="";if(r.infrastructure?.compute?.database?.password)r.infrastructure.compute.database.password="";if(r.infrastructure?.compute?.managedServices?.vitess?.password)r.infrastructure.compute.managedServices.vitess.password="";return r}function y(e){let r=M(e);return["// Generated by ts-cloud for the management dashboard — do not edit.","//","// This is the project's resolved cloud config, inlined so it needs no","// imports on the box. Credentials are deliberately absent.",`export default ${JSON.stringify(r,null,2)}`,""].join(`
2
- `)}var Td="dashboard";function oc(){return et("dashboard-credentials.json")}function F(){return R(24).toString("base64url")}function Ed(e,r,t){let s=process.env.TS_CLOUD_UI_PASSWORD?.trim();if(s)return{password:s,source:"env"};if(b(process.env.TS_CLOUD_UI_PUBLIC))return{password:void 0,source:"public"};let n=oc(),i=A(e,"dashboard-credentials.json");try{if(u(i)){let o=JSON.parse(U(i,"utf8"));if(o?.password)return{password:o.password,source:"generated"}}}catch{}let d=F();try{w(v(i),{recursive:!0}),m(i,`${JSON.stringify({username:r,password:d,generatedAt:new Date().toISOString()},null,2)}
1
+ import{et,A,qt,Pr,Ei}from"./chunk-t5gkbppg.js";import{execSync as D}from"node:child_process";import{randomBytes as R}from"node:crypto";import{chmodSync as j,copyFileSync as x,existsSync as u,mkdirSync as w,readFileSync as U,statSync as N,writeFileSync as m}from"node:fs";import{tmpdir as E}from"node:os";import{basename as P,dirname as v,isAbsolute as O,join as a,resolve as B}from"node:path";import{fileURLToPath as C}from"node:url";function h(e){if(!e||typeof e!=="object")return e;return Object.fromEntries(Object.keys(e).map((r)=>[r,""]))}function M(e){let r=JSON.parse(JSON.stringify(e??{}));if(r.hetzner)delete r.hetzner.apiToken;delete r.aws,delete r.stateDir;for(let t of Object.values(r.sites??{})){if(t?.env)t.env=h(t.env);if(t?.environment)t.environment=h(t.environment)}for(let t of Object.values(r.environments??{}))if(t?.variables)t.variables=h(t.variables);for(let t of Object.values(r.infrastructure?.databases??{}))if(t?.password)t.password="";if(r.infrastructure?.appDatabase?.password)r.infrastructure.appDatabase.password="";if(r.infrastructure?.compute?.database?.password)r.infrastructure.compute.database.password="";if(r.infrastructure?.compute?.managedServices?.vitess?.password)r.infrastructure.compute.managedServices.vitess.password="";return r}function y(e){let r=M(e);return["// Generated by ts-cloud for the management dashboard — do not edit.","//","// This is the project's resolved cloud config, inlined so it needs no","// imports on the box. Credentials are deliberately absent.",`export default ${JSON.stringify(r,null,2)}`,""].join(`
2
+ `)}var Ed="dashboard";function sc(){return et("dashboard-credentials.json")}function F(){return R(24).toString("base64url")}function wd(e,r,t){let s=process.env.TS_CLOUD_UI_PASSWORD?.trim();if(s)return{password:s,source:"env"};if(b(process.env.TS_CLOUD_UI_PUBLIC))return{password:void 0,source:"public"};let n=sc(),i=A(e,"dashboard-credentials.json");try{if(u(i)){let o=JSON.parse(U(i,"utf8"));if(o?.password)return{password:o.password,source:"generated"}}}catch{}let d=F();try{w(v(i),{recursive:!0}),m(i,`${JSON.stringify({username:r,password:d,generatedAt:new Date().toISOString()},null,2)}
3
3
  `),j(i,384),t.info(`Management dashboard: generated a password for '${r}' and saved it to ${n} (read it there — it is not printed). Set TS_CLOUD_UI_PASSWORD to pin your own, or TS_CLOUD_UI_PUBLIC=1 to serve without auth.`)}catch(o){t.warn(`Management dashboard: could not persist the generated password (${o?.message??o}). Using it for this deploy only — pass: ${d}
4
4
  This password is now in your deploy log. Set TS_CLOUD_UI_PASSWORD to a value of your own and redeploy once ${n} is writable.`)}return{password:d,source:"generated"}}var I={info:()=>{},warn:()=>{}};function b(e){return e!=null&&e!==""&&e!=="0"&&e.toLowerCase()!=="false"}function J(){return et("dashboard-release")}function L(){let e=v(C(import.meta.url));for(let r of[a(e,"..","..","package.json"),a(e,"..","package.json")])try{let t=JSON.parse(U(r,"utf8"));if(t.name==="@stacksjs/ts-cloud"&&t.version)return`^${t.version}`}catch{}return"latest"}function z(){return process.env.TS_CLOUD_UI_VERSION?.trim()||L()}function V(e,r,t){if(!e?.project?.slug)return t.warn("Management dashboard: the cloud config has no project slug — skipping the live dashboard."),null;let s=A(r,"dashboard-release");try{w(s,{recursive:!0}),m(a(s,"cloud.config.ts"),y(e));let n=z();if(n.startsWith("file:")){let d=n.slice(5),o=O(d)?d:B(r,d);if(!u(o)||!N(o).isFile())n=L(),t.warn(`Management dashboard: TS_CLOUD_UI_VERSION points to a missing package file (${o}); using the deploying ts-cloud version ${n} instead.`);else{let c=P(o),l=a(s,c);if(o!==l)x(o,l);n=`file:./${c}`}}let i={name:"ts-cloud-dashboard",private:!0,type:"module",dependencies:{"@stacksjs/ts-cloud":n}};return m(a(s,"package.json"),`${JSON.stringify(i,null,2)}
5
- `),J()}catch(n){return t.warn(`Management dashboard: could not stage the live release (${n?.message??n}) — skipping.`),null}}function ao(e){if(u(a(e,"packages","ui","pages"))||u(a(e,"packages","ui","package.json")))return{uiRoot:"packages/ui/dist",build:"cd packages/ui && bun install && bun run build"};let r=v(C(import.meta.url)),t=[a(r,"ui"),a(r,"..","ui"),a(r,"..","..","ui"),a(r,"..","dist","ui")];for(let s of t)if(u(a(s,"index.html"))||u(a(s,"serverless.html")))return{uiRoot:s,build:!1};return null}function co(e,r={}){let t=r.logger??I,s=r.cwd??process.cwd();if(b(process.env.TS_CLOUD_UI_DISABLE))return t.info("Management dashboard: skipped (TS_CLOUD_UI_DISABLE set)."),e;if(e.cloud?.attachTo)return t.info(`Management dashboard: ${e.project.slug} is attached to ${e.cloud.attachTo}; the server owner's dashboard monitors every attached project.`),e;if(qt(e))return e;let n=e.environments&&Object.keys(e.environments)[0],i=process.env.TS_CLOUD_UI_DOMAIN?.trim()||void 0,d=Number(process.env.TS_CLOUD_UI_PORT)||void 0,o={...e.sites??{}};if(!b(process.env.TS_CLOUD_UI_STATIC)){let g=V(e,s,t);if(!g)return e;let p=Ei(e,n??"production",{uiRoot:g,build:!1,domain:i,port:d,live:!0});if(p.length===0)return t.info("Management dashboard: no domain resolved (set TS_CLOUD_UI_DOMAIN or configure a site domain) — skipping."),e;for(let{name:k,site:_}of p)o[k]=_,t.info(`Management dashboard → https://${_.domain} (sign in with your ts-cloud account; the first deploy prints an admin password once)`);return e.sites=o,e}let c=ao(s);if(!c)return t.info("Management dashboard: UI not found (no local ui/ or packaged dist/ui) — skipping auto-deploy."),e;let l=process.env.TS_CLOUD_UI_USERNAME?.trim()||"admin",f=Ed(s,l,t),S=Ei(e,n??"production",{uiRoot:c.uiRoot,build:c.build,domain:i,username:l,password:f.password,realm:process.env.TS_CLOUD_UI_REALM?.trim()||void 0,live:!1,port:d});if(S.length===0)return t.info("Management dashboard: no domain resolved (set TS_CLOUD_UI_DOMAIN or configure a site domain) — skipping."),e;let T=f.source==="public"?"NO AUTH — TS_CLOUD_UI_PUBLIC is set (dashboard is publicly reachable)":f.source==="env"?"htpasswd-protected (TS_CLOUD_UI_PASSWORD)":`htpasswd-protected (auto-generated — see ${oc()})`;t.warn("Management dashboard: static mode — one shared password, and no per-site collaborators. Unset TS_CLOUD_UI_STATIC for the live dashboard.");for(let{name:g,site:p}of S)o[g]=p,t.info(`Management dashboard → https://${p.domain} (${T})`);return e.sites=o,e}function lo(e){return Object.keys(e.sites??{}).filter(Pr)}function vs(e,r){if(!e?.root)return null;let t=r.cwd??process.cwd(),s=r.logger??I;try{if(typeof e.build==="string"&&e.build.trim())s.info(`Management dashboard: building UI (${e.build})`),D(e.build,{cwd:t,stdio:"inherit"});let n=O(e.root)?e.root:a(t,e.root);if(!u(n))return s.warn(`Management dashboard: build output not found at ${n} — skipping dashboard artifact.`),null;let i=a(E(),`${r.slug}-${r.siteName??Td}-${r.sha}.tar.gz`);return D(`tar czf "${i}" -C "${n}" .`,{stdio:"inherit"}),i}catch(n){return s.warn(`Management dashboard: failed to build artifact — ${n?.message??n}. Skipping dashboard deploy.`),null}}
6
- export{Td,oc,Ed,ao,co,lo,vs};
5
+ `),J()}catch(n){return t.warn(`Management dashboard: could not stage the live release (${n?.message??n}) — skipping.`),null}}function ao(e){if(u(a(e,"packages","ui","pages"))||u(a(e,"packages","ui","package.json")))return{uiRoot:"packages/ui/dist",build:"cd packages/ui && bun install && bun run build"};let r=v(C(import.meta.url)),t=[a(r,"ui"),a(r,"..","ui"),a(r,"..","..","ui"),a(r,"..","dist","ui")];for(let s of t)if(u(a(s,"index.html"))||u(a(s,"serverless.html")))return{uiRoot:s,build:!1};return null}function co(e,r={}){let t=r.logger??I,s=r.cwd??process.cwd();if(b(process.env.TS_CLOUD_UI_DISABLE))return t.info("Management dashboard: skipped (TS_CLOUD_UI_DISABLE set)."),e;if(e.cloud?.attachTo)return t.info(`Management dashboard: ${e.project.slug} is attached to ${e.cloud.attachTo}; the server owner's dashboard monitors every attached project.`),e;if(qt(e))return e;let n=e.environments&&Object.keys(e.environments)[0],i=process.env.TS_CLOUD_UI_DOMAIN?.trim()||void 0,d=Number(process.env.TS_CLOUD_UI_PORT)||void 0,o={...e.sites??{}};if(!b(process.env.TS_CLOUD_UI_STATIC)){let g=V(e,s,t);if(!g)return e;let p=Ei(e,n??"production",{uiRoot:g,build:!1,domain:i,port:d,live:!0});if(p.length===0)return t.info("Management dashboard: no domain resolved (set TS_CLOUD_UI_DOMAIN or configure a site domain) — skipping."),e;for(let{name:k,site:_}of p)o[k]=_,t.info(`Management dashboard → https://${_.domain} (sign in with your ts-cloud account; the first deploy prints an admin password once)`);return e.sites=o,e}let c=ao(s);if(!c)return t.info("Management dashboard: UI not found (no local ui/ or packaged dist/ui) — skipping auto-deploy."),e;let l=process.env.TS_CLOUD_UI_USERNAME?.trim()||"admin",f=wd(s,l,t),S=Ei(e,n??"production",{uiRoot:c.uiRoot,build:c.build,domain:i,username:l,password:f.password,realm:process.env.TS_CLOUD_UI_REALM?.trim()||void 0,live:!1,port:d});if(S.length===0)return t.info("Management dashboard: no domain resolved (set TS_CLOUD_UI_DOMAIN or configure a site domain) — skipping."),e;let T=f.source==="public"?"NO AUTH — TS_CLOUD_UI_PUBLIC is set (dashboard is publicly reachable)":f.source==="env"?"htpasswd-protected (TS_CLOUD_UI_PASSWORD)":`htpasswd-protected (auto-generated — see ${sc()})`;t.warn("Management dashboard: static mode — one shared password, and no per-site collaborators. Unset TS_CLOUD_UI_STATIC for the live dashboard.");for(let{name:g,site:p}of S)o[g]=p,t.info(`Management dashboard → https://${p.domain} (${T})`);return e.sites=o,e}function lo(e){return Object.keys(e.sites??{}).filter(Pr)}function Ts(e,r){if(!e?.root)return null;let t=r.cwd??process.cwd(),s=r.logger??I;try{if(typeof e.build==="string"&&e.build.trim())s.info(`Management dashboard: building UI (${e.build})`),D(e.build,{cwd:t,stdio:"inherit"});let n=O(e.root)?e.root:a(t,e.root);if(!u(n))return s.warn(`Management dashboard: build output not found at ${n} — skipping dashboard artifact.`),null;let i=a(E(),`${r.slug}-${r.siteName??Ed}-${r.sha}.tar.gz`);return D(`tar czf "${i}" -C "${n}" .`,{stdio:"inherit"}),i}catch(n){return s.warn(`Management dashboard: failed to build artifact — ${n?.message??n}. Skipping dashboard deploy.`),null}}
6
+ export{Ed,sc,wd,ao,co,lo,Ts};
@@ -1,8 +1,8 @@
1
- var l={mode:"detection",paranoiaLevel:1,inboundThreshold:5,outboundThreshold:4,maxBodyBytes:13107200,rejectOversizedBody:!0,auditLogPath:"/var/log/ts-cloud/waf-audit.log",blockStatus:403},d={bypassBase:1e5,exclusionBase:101000,rateLimitBase:102000,customBase:109000};function Xe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/[\r\n]+/g," ")}function hs(e){if(e.length>1000)return!1;if(/\([^)]*[+*]\)[+*]/.test(e))return!1;if(/\[[^\]]*\][+*]\{/.test(e))return!1;try{return new RegExp(e),!0}catch{return!1}}function b(e,r){let t=[],o=[],s=r;for(let n of e){if(n.enabled===!1)continue;if(n.key&&(n.key.source==="cookie"||n.key.source==="header")&&!n.key.name){o.push({ruleId:n.id,reason:"The rule keys on a header or cookie but names none."});continue}let c=n.path?ic(n.path):".*";if(!hs(c)){o.push({ruleId:n.id,reason:"The path pattern compiles to an unsafe regular expression."});continue}let u=[`SecRule REQUEST_URI "@rx ${Xe(c)}"`];if(n.methods?.length)u.push(` "chain,id:${s},phase:1,pass,nolog,setvar:'tx.ts_cloud_ratelimit=${Xe(n.id)}'"`);else u.push(` "id:${s},phase:1,pass,nolog,setvar:'tx.ts_cloud_ratelimit=${Xe(n.id)}'"`);if(t.push(`# Marks requests governed by the ts-cloud rate limit "${Xe(n.id)}".`),t.push(u.join(" \\\n")),n.methods?.length)t.push(` SecRule REQUEST_METHOD "@within ${Xe(n.methods.join(" ").toUpperCase())}" "t:none"`);t.push(""),s++}return{lines:t,unmapped:o}}function ic(e){return`^${e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"\x01").replace(/\*/g,"[^/]*").replace(/\u0001/g,".*")}$`}function oi(e={},r=[]){let t=e.mode??l.mode,o=[],s=e.paranoiaLevel??l.paranoiaLevel,n=e.inboundThreshold??l.inboundThreshold,c=e.outboundThreshold??l.outboundThreshold,u=e.maxBodyBytes??l.maxBodyBytes,h=e.rejectOversizedBody!==!1;if(t==="blocking"&&s>=3)o.push(`Paranoia level ${s} blocks legitimate traffic on most applications until it is tuned. Run it in detection mode first.`);if(t==="blocking")o.push("zig-waf is pre-alpha. Blocking mode makes it a failure path for every request.");if(!h)o.push("Oversized bodies are passed through uninspected, so padding a request bypasses every rule.");if(e.bypassPaths?.length)o.push(`${e.bypassPaths.length} path(s) bypass inspection entirely.`);let i=["# Managed by ts-cloud. Edits are overwritten on the next deploy.",`# Mode: ${t}. Paranoia level: ${s}.`,""];if(t==="off")return i.push("SecRuleEngine Off",""),{config:`${i.join(`
1
+ var l={mode:"detection",paranoiaLevel:1,inboundThreshold:5,outboundThreshold:4,maxBodyBytes:13107200,rejectOversizedBody:!0,auditLogPath:"/var/log/ts-cloud/waf-audit.log",blockStatus:403},d={bypassBase:1e5,exclusionBase:101000,rateLimitBase:102000,customBase:109000};function Xe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/[\r\n]+/g," ")}function ys(e){if(e.length>1000)return!1;if(/\([^)]*[+*]\)[+*]/.test(e))return!1;if(/\[[^\]]*\][+*]\{/.test(e))return!1;try{return new RegExp(e),!0}catch{return!1}}function b(e,r){let t=[],o=[],s=r;for(let n of e){if(n.enabled===!1)continue;if(n.key&&(n.key.source==="cookie"||n.key.source==="header")&&!n.key.name){o.push({ruleId:n.id,reason:"The rule keys on a header or cookie but names none."});continue}let c=n.path?oc(n.path):".*";if(!ys(c)){o.push({ruleId:n.id,reason:"The path pattern compiles to an unsafe regular expression."});continue}let u=[`SecRule REQUEST_URI "@rx ${Xe(c)}"`];if(n.methods?.length)u.push(` "chain,id:${s},phase:1,pass,nolog,setvar:'tx.ts_cloud_ratelimit=${Xe(n.id)}'"`);else u.push(` "id:${s},phase:1,pass,nolog,setvar:'tx.ts_cloud_ratelimit=${Xe(n.id)}'"`);if(t.push(`# Marks requests governed by the ts-cloud rate limit "${Xe(n.id)}".`),t.push(u.join(" \\\n")),n.methods?.length)t.push(` SecRule REQUEST_METHOD "@within ${Xe(n.methods.join(" ").toUpperCase())}" "t:none"`);t.push(""),s++}return{lines:t,unmapped:o}}function oc(e){return`^${e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"\x01").replace(/\*/g,"[^/]*").replace(/\u0001/g,".*")}$`}function oi(e={},r=[]){let t=e.mode??l.mode,o=[],s=e.paranoiaLevel??l.paranoiaLevel,n=e.inboundThreshold??l.inboundThreshold,c=e.outboundThreshold??l.outboundThreshold,u=e.maxBodyBytes??l.maxBodyBytes,h=e.rejectOversizedBody!==!1;if(t==="blocking"&&s>=3)o.push(`Paranoia level ${s} blocks legitimate traffic on most applications until it is tuned. Run it in detection mode first.`);if(t==="blocking")o.push("zig-waf is pre-alpha. Blocking mode makes it a failure path for every request.");if(!h)o.push("Oversized bodies are passed through uninspected, so padding a request bypasses every rule.");if(e.bypassPaths?.length)o.push(`${e.bypassPaths.length} path(s) bypass inspection entirely.`);let i=["# Managed by ts-cloud. Edits are overwritten on the next deploy.",`# Mode: ${t}. Paranoia level: ${s}.`,""];if(t==="off")return i.push("SecRuleEngine Off",""),{config:`${i.join(`
2
2
  `)}
3
- `,unmappedRateLimits:[],warnings:o,mode:t};i.push(`SecRuleEngine ${t==="blocking"?"On":"DetectionOnly"}`,"SecRequestBodyAccess On","SecResponseBodyAccess Off",`SecRequestBodyLimit ${u}`,`SecRequestBodyNoFilesLimit ${Math.min(u,131072)}`,`SecRequestBodyLimitAction ${h?"Reject":"ProcessPartial"}`,"SecRequestBodyInMemoryLimit 131072",`SecAuditEngine ${t==="blocking"?"RelevantOnly":"On"}`,"SecAuditLogParts ABIJDEFHZ",`SecAuditLog ${Xe(e.auditLogPath??l.auditLogPath)}`,"SecAuditLogType Serial",`SecDefaultAction "phase:1,log,auditlog,${t==="blocking"?`deny,status:${e.blockStatus??l.blockStatus}`:"pass"}"`,"","# CRS anomaly scoring setup.",`SecAction "id:900000,phase:1,pass,nolog,t:none,setvar:tx.paranoia_level=${s}"`,`SecAction "id:900001,phase:1,pass,nolog,t:none,setvar:tx.inbound_anomaly_score_threshold=${n}"`,`SecAction "id:900002,phase:1,pass,nolog,t:none,setvar:tx.outbound_anomaly_score_threshold=${c}"`,'SecAction "id:900003,phase:1,pass,nolog,t:none,setvar:tx.critical_anomaly_score=5,setvar:tx.error_anomaly_score=4,setvar:tx.warning_anomaly_score=3,setvar:tx.notice_anomaly_score=2"','SecAction "id:900004,phase:1,pass,nolog,t:none,setvar:tx.anomaly_score=0"',"");let g=d.bypassBase;for(let a of e.bypassPaths??[]){let y=ic(a);if(!hs(y)){o.push(`Bypass path "${a}" was dropped: it compiles to an unsafe regular expression.`);continue}i.push(`# Inspection bypass for ${Xe(a)}. Every bypass is an unguarded route.`,`SecRule REQUEST_URI "@rx ${Xe(y)}" "id:${g},phase:1,pass,nolog,ctl:ruleEngine=Off"`,""),g++}let m=d.exclusionBase;for(let a of e.exclusions??[]){if(!Number.isInteger(a.ruleId)||a.ruleId<=0){o.push(`Exclusion with rule id "${a.ruleId}" was dropped: the id is not a positive integer.`);continue}if(i.push(`# ${Xe(a.reason)}`),a.pathPattern){if(!hs(a.pathPattern)){o.push(`Exclusion for rule ${a.ruleId} was dropped: its path pattern is unsafe.`);continue}i.push(`SecRule REQUEST_URI "@rx ${Xe(a.pathPattern)}" "id:${m},phase:1,pass,nolog,ctl:ruleRemoveById=${a.ruleId}"`),m++}else i.push(`SecRuleRemoveById ${a.ruleId}`);i.push("")}let p=b(r,d.rateLimitBase);if(p.lines.length>0)i.push("# Rate-limit route markers. SecLang has no counters, so the tag is set","# here and the counting stays in the ts-cloud limiter.",...p.lines);let f=d.customBase;for(let a of e.customRules??[])i.push(`# Operator-supplied rule ${f}.`,a.trim(),""),f++;if(t==="blocking")i.push("# Blocking decision: one rule, at the end, on the accumulated score.",`SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" "id:949110,phase:2,deny,status:${e.blockStatus??l.blockStatus},log,msg:'Inbound anomaly score exceeded (total: %{tx.anomaly_score})'"`,"");return{config:`${i.join(`
3
+ `,unmappedRateLimits:[],warnings:o,mode:t};i.push(`SecRuleEngine ${t==="blocking"?"On":"DetectionOnly"}`,"SecRequestBodyAccess On","SecResponseBodyAccess Off",`SecRequestBodyLimit ${u}`,`SecRequestBodyNoFilesLimit ${Math.min(u,131072)}`,`SecRequestBodyLimitAction ${h?"Reject":"ProcessPartial"}`,"SecRequestBodyInMemoryLimit 131072",`SecAuditEngine ${t==="blocking"?"RelevantOnly":"On"}`,"SecAuditLogParts ABIJDEFHZ",`SecAuditLog ${Xe(e.auditLogPath??l.auditLogPath)}`,"SecAuditLogType Serial",`SecDefaultAction "phase:1,log,auditlog,${t==="blocking"?`deny,status:${e.blockStatus??l.blockStatus}`:"pass"}"`,"","# CRS anomaly scoring setup.",`SecAction "id:900000,phase:1,pass,nolog,t:none,setvar:tx.paranoia_level=${s}"`,`SecAction "id:900001,phase:1,pass,nolog,t:none,setvar:tx.inbound_anomaly_score_threshold=${n}"`,`SecAction "id:900002,phase:1,pass,nolog,t:none,setvar:tx.outbound_anomaly_score_threshold=${c}"`,'SecAction "id:900003,phase:1,pass,nolog,t:none,setvar:tx.critical_anomaly_score=5,setvar:tx.error_anomaly_score=4,setvar:tx.warning_anomaly_score=3,setvar:tx.notice_anomaly_score=2"','SecAction "id:900004,phase:1,pass,nolog,t:none,setvar:tx.anomaly_score=0"',"");let g=d.bypassBase;for(let a of e.bypassPaths??[]){let y=oc(a);if(!ys(y)){o.push(`Bypass path "${a}" was dropped: it compiles to an unsafe regular expression.`);continue}i.push(`# Inspection bypass for ${Xe(a)}. Every bypass is an unguarded route.`,`SecRule REQUEST_URI "@rx ${Xe(y)}" "id:${g},phase:1,pass,nolog,ctl:ruleEngine=Off"`,""),g++}let m=d.exclusionBase;for(let a of e.exclusions??[]){if(!Number.isInteger(a.ruleId)||a.ruleId<=0){o.push(`Exclusion with rule id "${a.ruleId}" was dropped: the id is not a positive integer.`);continue}if(i.push(`# ${Xe(a.reason)}`),a.pathPattern){if(!ys(a.pathPattern)){o.push(`Exclusion for rule ${a.ruleId} was dropped: its path pattern is unsafe.`);continue}i.push(`SecRule REQUEST_URI "@rx ${Xe(a.pathPattern)}" "id:${m},phase:1,pass,nolog,ctl:ruleRemoveById=${a.ruleId}"`),m++}else i.push(`SecRuleRemoveById ${a.ruleId}`);i.push("")}let p=b(r,d.rateLimitBase);if(p.lines.length>0)i.push("# Rate-limit route markers. SecLang has no counters, so the tag is set","# here and the counting stays in the ts-cloud limiter.",...p.lines);let f=d.customBase;for(let a of e.customRules??[])i.push(`# Operator-supplied rule ${f}.`,a.trim(),""),f++;if(t==="blocking")i.push("# Blocking decision: one rule, at the end, on the accumulated score.",`SecRule TX:ANOMALY_SCORE "@ge %{tx.inbound_anomaly_score_threshold}" "id:949110,phase:2,deny,status:${e.blockStatus??l.blockStatus},log,msg:'Inbound anomaly score exceeded (total: %{tx.anomaly_score})'"`,"");return{config:`${i.join(`
4
4
  `)}
5
- `,unmappedRateLimits:p.unmapped,warnings:o,mode:t}}function ys(e={},r=[],t={}){let o=t.binary??"/usr/local/bin/zig-waf",s=t.configPath??"/etc/ts-cloud/waf.conf",n=oi(e,r);return`#!/usr/bin/env bash
5
+ `,unmappedRateLimits:p.unmapped,warnings:o,mode:t}}function Ss(e={},r=[],t={}){let o=t.binary??"/usr/local/bin/zig-waf",s=t.configPath??"/etc/ts-cloud/waf.conf",n=oi(e,r);return`#!/usr/bin/env bash
6
6
  # Managed by ts-cloud. Installs the zig-waf ruleset.
7
7
  set -euo pipefail
8
8
 
@@ -33,5 +33,5 @@ fi
33
33
 
34
34
  mv "${s}.new" "${s}"
35
35
  echo "ts-cloud: WAF config installed (mode: ${n.mode})"
36
- `}function sp(e,r){return e.map((t)=>({projectId:r.projectId,environmentId:r.environmentId,resourceId:r.resourceId,kind:"event",source:"zig-waf",name:t.action==="blocked"?"waf.blocked":"waf.matched",timestamp:t.timestamp,value:1,host:t.host,pathTemplate:t.path,method:t.method,attributes:{ruleId:t.ruleId??null,anomalyScore:t.anomalyScore,action:t.action,messages:t.messages.slice(0,5)}}))}
37
- export{Xe,hs,ic,oi,ys,sp};
36
+ `}function ap(e,r){return e.map((t)=>({projectId:r.projectId,environmentId:r.environmentId,resourceId:r.resourceId,kind:"event",source:"zig-waf",name:t.action==="blocked"?"waf.blocked":"waf.matched",timestamp:t.timestamp,value:1,host:t.host,pathTemplate:t.path,method:t.method,attributes:{ruleId:t.ruleId??null,anomalyScore:t.anomalyScore,action:t.action,messages:t.messages.slice(0,5)}}))}
37
+ export{Xe,ys,oc,oi,Ss,ap};