@stacksjs/ts-cloud 0.16.40 → 0.16.42

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 (137) hide show
  1. package/dist/aws/ec2-launch.test.d.ts +1 -0
  2. package/dist/aws/ec2.d.ts +47 -0
  3. package/dist/aws/index.js +1 -1
  4. package/dist/bin/{chunk-cxcgqqdb.js → chunk-04s4mqs2.js} +1 -1
  5. package/dist/bin/chunk-26rf5dy2.js +1 -0
  6. package/dist/bin/{chunk-h0s69e9p.js → chunk-3hkppc7h.js} +1 -1
  7. package/dist/bin/{chunk-sfzdr2b3.js → chunk-3v2pd05g.js} +2 -2
  8. package/dist/bin/{chunk-45a8yv3j.js → chunk-5amvqed8.js} +3 -3
  9. package/dist/bin/{chunk-t5kqyr8m.js → chunk-5nc1g18b.js} +1 -1
  10. package/dist/bin/chunk-71ep1g7k.js +1 -0
  11. package/dist/bin/chunk-7fh7b8r1.js +1 -0
  12. package/dist/bin/chunk-7nsjehvx.js +1 -0
  13. package/dist/bin/{chunk-8fxksvw4.js → chunk-8z4wgqkh.js} +1 -1
  14. package/dist/bin/{chunk-7453cepa.js → chunk-bj7ashn6.js} +1 -1
  15. package/dist/bin/{chunk-w9rx90s2.js → chunk-ce1qnjs2.js} +1 -1
  16. package/dist/bin/{chunk-5k3npcm6.js → chunk-cqc4e8md.js} +3 -3
  17. package/dist/bin/{chunk-22x7vxxw.js → chunk-dryvqne2.js} +1 -1
  18. package/dist/bin/{chunk-nqn983fx.js → chunk-erf79tm2.js} +29 -29
  19. package/dist/bin/{chunk-b2kdxqd5.js → chunk-gn03w47w.js} +2 -2
  20. package/dist/bin/{chunk-js888a3w.js → chunk-hfnpjy9y.js} +1 -1
  21. package/dist/bin/{chunk-jmkfx9th.js → chunk-jaexpxs8.js} +2 -2
  22. package/dist/bin/{chunk-az504aqf.js → chunk-jh1vmant.js} +1 -1
  23. package/dist/bin/{chunk-5wx26yjy.js → chunk-kdsgbvep.js} +2 -2
  24. package/dist/bin/{chunk-w232tc20.js → chunk-kg3nbcfs.js} +1 -1
  25. package/dist/bin/{chunk-0716rh6x.js → chunk-knzje4ka.js} +1 -1
  26. package/dist/bin/{chunk-pj5svs6q.js → chunk-mgwmt2et.js} +1 -1
  27. package/dist/bin/chunk-nfb3ew1v.js +1 -0
  28. package/dist/bin/{chunk-ecd4swb7.js → chunk-nk7fqc8z.js} +2 -2
  29. package/dist/bin/chunk-pf9dbm3b.js +4 -0
  30. package/dist/bin/{chunk-mex7tac5.js → chunk-pnj95hwr.js} +1 -1
  31. package/dist/bin/{chunk-1dqn0y04.js → chunk-qj6tr7bw.js} +2 -2
  32. package/dist/bin/{chunk-9vszh4dj.js → chunk-rsnmb1cd.js} +2 -2
  33. package/dist/bin/chunk-s64d5nw2.js +1 -0
  34. package/dist/bin/{chunk-f2q239cy.js → chunk-sg8hcdev.js} +1 -1
  35. package/dist/bin/{chunk-bmj1d9xc.js → chunk-t80pxn04.js} +20 -20
  36. package/dist/bin/{chunk-1jwmkbzx.js → chunk-tf8qxy9k.js} +40 -40
  37. package/dist/bin/{chunk-v9wf266f.js → chunk-vjfwnj9z.js} +2 -2
  38. package/dist/bin/{chunk-p9baztvr.js → chunk-vn05n5z6.js} +1 -1
  39. package/dist/bin/{chunk-4g1z81pt.js → chunk-xxe9ga9r.js} +4 -4
  40. package/dist/bin/cli.js +211 -211
  41. package/dist/bin/dashboard-server.js +1 -1
  42. package/dist/{chunk-qg03hfb6.js → chunk-13pfck91.js} +1 -1
  43. package/dist/{chunk-5n1y5ehd.js → chunk-bj4kvqwz.js} +97 -97
  44. package/dist/chunk-c9zjh5bx.js +1 -0
  45. package/dist/{chunk-mxprxjd4.js → chunk-ct72f70x.js} +2 -2
  46. package/dist/{chunk-bez9ytaz.js → chunk-cv5e8c74.js} +61 -61
  47. package/dist/{chunk-yt6m703r.js → chunk-e3evn28t.js} +1 -1
  48. package/dist/{chunk-74yycwrd.js → chunk-epbe0p3n.js} +1 -1
  49. package/dist/chunk-fwcf0n8f.js +4 -0
  50. package/dist/{chunk-bfbahave.js → chunk-hc140wnm.js} +1 -1
  51. package/dist/{chunk-v6hysd5c.js → chunk-j1adw51p.js} +2 -2
  52. package/dist/{chunk-yjh3y68t.js → chunk-nqb7yefs.js} +1 -1
  53. package/dist/chunk-pahyn8p3.js +1 -0
  54. package/dist/{chunk-kexwq2h0.js → chunk-qztdtcc8.js} +1 -1
  55. package/dist/{chunk-ype3pqh5.js → chunk-vps4v353.js} +4 -4
  56. package/dist/{chunk-jbtnyhrh.js → chunk-xejwnb6f.js} +1 -1
  57. package/dist/{chunk-3w7q4sjs.js → chunk-zy0crzsb.js} +2 -2
  58. package/dist/deploy/index.js +1 -1
  59. package/dist/dns/index.js +1 -1
  60. package/dist/drivers/index.js +1 -1
  61. package/dist/index.d.ts +1 -0
  62. package/dist/index.js +26 -26
  63. package/dist/operations/index.js +1 -1
  64. package/dist/protection/index.js +1 -1
  65. package/dist/spend/index.js +1 -1
  66. package/dist/ui/404.html +1 -1
  67. package/dist/ui/accept-invitation.html +1 -1
  68. package/dist/ui/access-denied.html +1 -1
  69. package/dist/ui/account/automation.html +6 -6
  70. package/dist/ui/account/security.html +2 -2
  71. package/dist/ui/applications/compose.html +6 -6
  72. package/dist/ui/applications/new.html +2 -2
  73. package/dist/ui/data/backups.html +6 -6
  74. package/dist/ui/data/services.html +6 -6
  75. package/dist/ui/data/volumes.html +6 -6
  76. package/dist/ui/index.html +6 -6
  77. package/dist/ui/infrastructure/topology.html +5 -5
  78. package/dist/ui/integrations.html +2 -2
  79. package/dist/ui/operations/alerts.html +6 -6
  80. package/dist/ui/operations/configuration.html +5 -5
  81. package/dist/ui/operations/jobs.html +5 -5
  82. package/dist/ui/operations/maintenance.html +6 -6
  83. package/dist/ui/operations/observability.html +6 -6
  84. package/dist/ui/operations/previews.html +6 -6
  85. package/dist/ui/operations/queue.html +6 -6
  86. package/dist/ui/operations/regions.html +6 -6
  87. package/dist/ui/operations/releases.html +5 -5
  88. package/dist/ui/operations/spend.html +6 -6
  89. package/dist/ui/operations/workloads.html +6 -6
  90. package/dist/ui/security.html +2 -2
  91. package/dist/ui/server/actions.html +6 -6
  92. package/dist/ui/server/activity.html +1 -1
  93. package/dist/ui/server/capacity.html +6 -6
  94. package/dist/ui/server/database.html +6 -6
  95. package/dist/ui/server/deployments.html +6 -6
  96. package/dist/ui/server/diagnostics.html +2 -2
  97. package/dist/ui/server/firewall.html +6 -6
  98. package/dist/ui/server/fleet.html +6 -6
  99. package/dist/ui/server/logs.html +6 -6
  100. package/dist/ui/server/metrics.html +6 -6
  101. package/dist/ui/server/security.html +2 -2
  102. package/dist/ui/server/services.html +1 -1
  103. package/dist/ui/server/sites.html +5 -5
  104. package/dist/ui/server/ssh-keys.html +5 -5
  105. package/dist/ui/server/team.html +5 -5
  106. package/dist/ui/server/terminal.html +1 -1
  107. package/dist/ui/serverless/alarms.html +6 -6
  108. package/dist/ui/serverless/assets.html +2 -2
  109. package/dist/ui/serverless/cost.html +1 -1
  110. package/dist/ui/serverless/data.html +6 -6
  111. package/dist/ui/serverless/deployments.html +2 -2
  112. package/dist/ui/serverless/firewall.html +1 -1
  113. package/dist/ui/serverless/functions.html +6 -6
  114. package/dist/ui/serverless/logs.html +6 -6
  115. package/dist/ui/serverless/metrics.html +2 -2
  116. package/dist/ui/serverless/queues.html +6 -6
  117. package/dist/ui/serverless/secrets.html +6 -6
  118. package/dist/ui/serverless/traces.html +6 -6
  119. package/dist/ui/serverless.html +6 -6
  120. package/dist/workers/bundle.d.ts +27 -0
  121. package/dist/workers/bundle.test.d.ts +1 -0
  122. package/dist/workers/index.d.ts +11 -0
  123. package/dist/workers/provider.d.ts +215 -0
  124. package/dist/workers/provider.test.d.ts +1 -0
  125. package/dist/workers/reconcile.d.ts +99 -0
  126. package/dist/workers/reconcile.test.d.ts +1 -0
  127. package/package.json +3 -3
  128. package/dist/bin/chunk-0scywedn.js +0 -4
  129. package/dist/bin/chunk-459waehf.js +0 -1
  130. package/dist/bin/chunk-4y8zhe38.js +0 -1
  131. package/dist/bin/chunk-68tgx5j2.js +0 -1
  132. package/dist/bin/chunk-jxfgkhkc.js +0 -1
  133. package/dist/bin/chunk-k2mdcb66.js +0 -1
  134. package/dist/bin/chunk-kva8aybv.js +0 -1
  135. package/dist/chunk-1yhrkahz.js +0 -1
  136. package/dist/chunk-27y037yh.js +0 -1
  137. package/dist/chunk-ysx5m6cs.js +0 -4
@@ -1,4 +1,4 @@
1
- import{re,h}from"./chunk-mex7tac5.js";import{ho}from"./chunk-k343q24p.js";var Gp=["edge.requests","edge.egress_gb","function.invocations","function.gb_seconds","build.minutes","compute.instance_hours","storage.gb_hours","object.egress_gb","object.requests","database.gb_hours","database.io_requests","telemetry.ingest_gb","image.transformations"],an={"edge.requests":{key:"edge.requests",unit:"requests",label:"Edge requests",precision:0},"edge.egress_gb":{key:"edge.egress_gb",unit:"gb",label:"Edge egress",precision:3},"function.invocations":{key:"function.invocations",unit:"invocations",label:"Function invocations",precision:0},"function.gb_seconds":{key:"function.gb_seconds",unit:"gb_seconds",label:"Function compute",precision:2},"build.minutes":{key:"build.minutes",unit:"minutes",label:"Build minutes",precision:2},"compute.instance_hours":{key:"compute.instance_hours",unit:"hours",label:"Instance hours",precision:2},"storage.gb_hours":{key:"storage.gb_hours",unit:"gb_hours",label:"Block storage",precision:2},"object.egress_gb":{key:"object.egress_gb",unit:"gb",label:"Object storage egress",precision:3},"object.requests":{key:"object.requests",unit:"requests",label:"Object storage requests",precision:0},"database.gb_hours":{key:"database.gb_hours",unit:"gb_hours",label:"Database storage",precision:2},"database.io_requests":{key:"database.io_requests",unit:"requests",label:"Database I/O",precision:0},"telemetry.ingest_gb":{key:"telemetry.ingest_gb",unit:"gb",label:"Telemetry ingest",precision:3},"image.transformations":{key:"image.transformations",unit:"count",label:"Image transformations",precision:0}},so=["notify","block_builds","block_deployments","throttle_requests","suspend_functions","serve_static","suspend_project"],se={notify:0,block_builds:1,block_deployments:2,throttle_requests:3,suspend_functions:4,serve_static:5,suspend_project:6};var qp=1e6;function tr(e){if(e.tiers&&e.tiers.length>0)return e.tiers;return[{upToQuantity:null,microCentsPerUnit:e.microCentsPerUnit??0}]}function Tc(e,t){if(!(e>0))return 0;let r=[...t].sort((s,a)=>{if(s.upToQuantity===null)return 1;if(a.upToQuantity===null)return-1;return s.upToQuantity-a.upToQuantity}),n=e,o=0,i=0;for(let s of r){if(n<=0)break;let d=(s.upToQuantity===null?1/0:s.upToQuantity)-o;if(d<=0)continue;let c=Math.min(n,d);i+=c*s.microCentsPerUnit,n-=c,o+=c}if(n>0){let s=r.reduce((a,d)=>Math.max(a,d.microCentsPerUnit),0);i+=n*s}return i}function Rd(e,t,r,n){let o=e.entries.filter((a)=>a.meter===t);if(o.length===0)return;let i=o.filter((a)=>a.provider===r),s=i.length>0?i:o.filter((a)=>a.provider==="*");return s.find((a)=>a.region===n)??s.find((a)=>a.region==null)}function hs(e,t,r=0){let n=Rd(e,t.meter,t.provider,t.region),o=Math.max(0,t.quantity);if(!n)return{meter:t.meter,provider:t.provider??"unknown",region:t.region,quantity:o,includedQuantity:0,billableQuantity:o,costCents:0,unpriced:!0};let i=Math.max(0,n.includedQuantity??0),s=Math.max(0,r-i),a=Math.max(0,i-Math.max(0,r)),d=Math.min(o,a),c=o-d,u=tr(n),p=Tc(s+c,u)-Tc(s,u);return{meter:t.meter,provider:n.provider,region:n.region??t.region,quantity:o,includedQuantity:d,billableQuantity:c,costCents:p/1e6,unpriced:!1}}function Wp(e,t){let r=new Map,n=[];for(let o of t){let i=`${o.meter}\x00${o.provider??""}\x00${o.region??""}`,s=r.get(i)??0,a=hs(e,o,s);r.set(i,s+a.quantity),n.push(a)}return{currency:e.currency,totalCents:n.reduce((o,i)=>o+i.costCents,0),lines:n,unpricedMeters:[...new Set(n.filter((o)=>o.unpriced).map((o)=>String(o.meter)))]}}function Kp(e){return Math.round(e*100)/100}function Jp(e,...t){let r=new Map,n=(i)=>`${i.meter}\x00${i.provider}\x00${i.region??""}`;for(let i of e.entries)r.set(n(i),i);let o=e.currency;for(let i of t){o=i.currency||o;for(let s of i.entries)r.set(n(s),s)}return{currency:o,entries:[...r.values()]}}var V=(e)=>Math.round(e*1e6),N=(e)=>Math.round(e*1e6),Ec={currency:"USD",entries:[{meter:"edge.requests",provider:"aws",microCentsPerUnit:N(0.00075)},{meter:"edge.egress_gb",provider:"aws",includedQuantity:100,tiers:[{upToQuantity:10240,microCentsPerUnit:V(8.5)},{upToQuantity:51200,microCentsPerUnit:V(8)},{upToQuantity:null,microCentsPerUnit:V(6)}]},{meter:"function.invocations",provider:"aws",includedQuantity:1e6,microCentsPerUnit:N(0.002)},{meter:"function.gb_seconds",provider:"aws",includedQuantity:400000,microCentsPerUnit:N(0.00166667)},{meter:"storage.gb_hours",provider:"aws",microCentsPerUnit:N(0.010958904109589041)},{meter:"object.egress_gb",provider:"aws",includedQuantity:100,microCentsPerUnit:V(9)},{meter:"object.requests",provider:"aws",microCentsPerUnit:N(0.000039999999999999996)},{meter:"database.gb_hours",provider:"aws",microCentsPerUnit:N(0.015753424657534248)},{meter:"compute.instance_hours",provider:"aws",microCentsPerUnit:N(4.16)},{meter:"edge.egress_gb",provider:"hetzner",includedQuantity:20480,microCentsPerUnit:V(0.108)},{meter:"object.egress_gb",provider:"hetzner",includedQuantity:1024,microCentsPerUnit:V(0.108)},{meter:"compute.instance_hours",provider:"hetzner",microCentsPerUnit:N(0.95)},{meter:"storage.gb_hours",provider:"hetzner",microCentsPerUnit:N(0.006027397260273972)},{meter:"edge.requests",provider:"hetzner",microCentsPerUnit:0},{meter:"edge.requests",provider:"local",microCentsPerUnit:0},{meter:"edge.egress_gb",provider:"local",microCentsPerUnit:0},{meter:"function.invocations",provider:"local",microCentsPerUnit:0},{meter:"function.gb_seconds",provider:"local",microCentsPerUnit:0},{meter:"build.minutes",provider:"*",includedQuantity:6000,microCentsPerUnit:N(0.8)},{meter:"telemetry.ingest_gb",provider:"*",includedQuantity:5,microCentsPerUnit:V(50)},{meter:"image.transformations",provider:"*",includedQuantity:5000,microCentsPerUnit:N(0.05)}]};var tt=new Map;function rt(e){let t=tt.get(e);if(!t)t=new Intl.DateTimeFormat("en-US",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",weekday:"short",hourCycle:"h23"}),tt.set(e,t);return t}var rr={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};function ao(e){try{return rt(e),!0}catch{return!1}}function ys(e,t){let r=rt(t).formatToParts(e),n=(o)=>r.find((i)=>i.type===o)?.value??"0";return{year:Number(n("year")),month:Number(n("month")),day:Number(n("day")),hour:Number(n("hour")),minute:Number(n("minute")),second:Number(n("second")),weekday:rr[n("weekday")]??0}}function wc(e,t){let r=ys(e,t);return Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second)-Math.floor(e.getTime()/1000)*1000}function cn(e,t,r,n,o=0){let i=Date.UTC(t,r-1,n,o),s=new Date(i-wc(new Date(i),e));return new Date(i-wc(s,e))}function nr(e,t){return new Date(Date.UTC(e,t-1,1)).toLocaleString("en-US",{month:"long",year:"numeric",timeZone:"UTC"})}function br(e,t,r=new Date){let n=ao(t)?t:"UTC",o=ys(r,n),i,s,a;if(e==="daily")i=cn(n,o.year,o.month,o.day),s=cn(n,o.year,o.month,o.day+1),a=`${o.year}-${String(o.month).padStart(2,"0")}-${String(o.day).padStart(2,"0")}`;else if(e==="weekly"){let u=(o.weekday+6)%7;i=cn(n,o.year,o.month,o.day-u),s=cn(n,o.year,o.month,o.day-u+7);let p=ys(i,n);a=`week of ${p.year}-${String(p.month).padStart(2,"0")}-${String(p.day).padStart(2,"0")}`}else i=cn(n,o.year,o.month,1),s=cn(n,o.year,o.month+1,1),a=nr(o.year,o.month);let d=s.getTime()-i.getTime(),c=Math.max(0,Math.min(d,r.getTime()-i.getTime()));return{start:i.toISOString(),end:s.toISOString(),elapsedMs:c,totalMs:d,label:a}}function Xp(e,t,r=new Date){let n=br(e,t,r),o=new Date(new Date(n.start).getTime()-1),i=br(e,t,o);return{...i,elapsedMs:i.totalMs}}function yi(e){let r=(typeof e==="string"?new Date(e):e).getTime();if(!Number.isFinite(r))throw Error("hourBucket requires a valid date");return new Date(Math.floor(r/3600000)*3600000).toISOString()}function Qp(e,t,r=9600){let n=Math.floor(new Date(e).getTime()/3600000)*3600000,o=new Date(t).getTime();if(!Number.isFinite(n)||!Number.isFinite(o))throw Error("hourBucketsBetween requires valid dates");let i=[];for(let s=n;s<o&&i.length<r;s+=3600000)i.push(new Date(s).toISOString());return i}import{createHash as or}from"node:crypto";var le=1073741824,Ac=[{match:"request.count",meter:"edge.requests"},{match:"traffic.requests",meter:"edge.requests"},{match:"http.request",meter:"edge.requests",field:"count"},{match:"traffic.bytes_out",meter:"edge.egress_gb",scale:1/le},{match:"storage.egress.day",meter:"object.egress_gb",scale:1/le},{match:"storage.egress.month",meter:"object.egress_gb",scale:1/le,cumulative:!0},{match:"storage.egress.day_downloads",meter:"object.requests"},{match:"function.invocation",meter:"function.invocations",field:"count"},{match:"function.duration_ms",meter:"function.gb_seconds",scale:0.001},{match:"build.duration_ms",meter:"build.minutes",scale:0.000016666666666666667},{match:"telemetry.ingest_bytes",meter:"telemetry.ingest_gb",scale:1/le},{match:"image.transform",meter:"image.transformations",field:"count"}];function ir(e,t){return e.match.endsWith("*")?t.startsWith(e.match.slice(0,-1)):e.match===t}function Id(e,t=Ac){return t.find((r)=>!r.match.endsWith("*")&&r.match===e)??t.find((r)=>ir(r,e))}function sr(e,t){let r=t.field??"value",n=r==="count"?1:r==="bytesOut"?e.bytesOut:r==="bytesIn"?e.bytesIn:r==="durationMs"?e.durationMs:e.value;if(n==null||!Number.isFinite(n))return;return n*(t.scale??1)}function Pd(e,t){return or("sha256").update([t,e.meter,e.organizationId,e.projectId??"",e.environmentId??"",e.resourceId??"",e.timestamp].join("\x00")).digest("hex").slice(0,32)}class bs{resetToleranceRatio;last=new Map;constructor(e=0.999){this.resetToleranceRatio=e}delta(e,t,r=new Date){if(!Number.isFinite(t)||t<0)return;let n=new Date(r).getTime(),o=this.last.get(e);if(!o)return this.last.set(e,{value:t,at:n}),t>0?t:void 0;if(n<o.at)return;if(t<o.value&&t>=o.value*this.resetToleranceRatio)return;if(this.last.set(e,{value:t,at:n}),t>=o.value){let i=t-o.value;return i>0?i:void 0}return t>0?t:void 0}prune(e){let t=e.getTime(),r=0;for(let[n,o]of this.last)if(o.at<t)this.last.delete(n),r++;return r}get size(){return this.last.size}}function nt(e,t){let r=e[t];return typeof r==="string"&&r.length>0?r:void 0}function Rc(e,t,r={}){let n=r.mappings??Ac,o=r.counters,i=[];for(let s of t){let a=Id(s.name,n);if(!a)continue;let d=sr(s,a);if(d==null)continue;if(a.cumulative){if(!o)continue;let u=[s.projectId,s.environmentId??"",s.resourceId??"",s.name,s.source].join("\x00"),p=o.delta(u,d,s.timestamp);if(p==null)continue;d=p}if(!(d>0))continue;let c={organizationId:e,projectId:s.projectId,environmentId:s.environmentId,resourceId:s.resourceId,provider:nt(s.attributes,"provider")??r.defaultProvider,region:s.region??nt(s.attributes,"region"),meter:a.meter,quantity:d,timestamp:s.timestamp,attributes:{source:s.source,signal:s.name}};i.push({...c,key:Pd(c,s.id)})}return i}function Ic(e){let t=new Map;for(let r of e){let n=new Date(Math.floor(new Date(r.timestamp).getTime()/3600000)*3600000).toISOString(),o=[r.organizationId,r.projectId??"",r.environmentId??"",r.resourceId??"",r.provider??"",r.region??"",r.meter,n].join("\x00"),i=t.get(o);if(i)i.quantity+=r.quantity;else t.set(o,{...r,timestamp:n})}return[...t.values()]}import{createHash as ar}from"node:crypto";var K=(e)=>{if(typeof e!=="string")return{};try{return JSON.parse(e)}catch{return{}}},j=(e)=>typeof e==="string"&&e!==""?e:void 0,ue=(e)=>Number(e)===1,ot=(e)=>e==null?void 0:Number(e);function it(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:j(e.project_id),environmentId:j(e.environment_id),name:String(e.name),period:String(e.period),timezone:String(e.timezone),currency:String(e.currency),softLimitCents:ot(e.soft_limit_cents),hardLimitCents:ot(e.hard_limit_cents),thresholds:K(e.thresholds),meters:K(e.meters),graceSeconds:Number(e.grace_seconds),hysteresisPercent:Number(e.hysteresis_percent),dryRun:ue(e.dry_run),enabled:ue(e.enabled),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ae(e){return{id:String(e.id),budgetId:String(e.budget_id),organizationId:String(e.organization_id),projectId:j(e.project_id),environmentId:j(e.environment_id),action:String(e.action),state:String(e.state),reason:String(e.reason),restore:K(e.restore),triggeredAtPercent:Number(e.triggered_at_percent),simulated:ue(e.simulated),appliedAt:j(e.applied_at),releasedAt:j(e.released_at),error:j(e.error),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function st(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:j(e.project_id),environmentId:j(e.environment_id),signal:String(e.signal),direction:String(e.direction),observed:Number(e.observed),expected:Number(e.expected),score:Number(e.score),deltaPercent:Number(e.delta_percent),severity:String(e.severity),bucketStart:String(e.bucket_start),evidence:K(e.evidence),acknowledgedAt:j(e.acknowledged_at),createdAt:String(e.created_at)}}function dr(e){return{organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:String(e.environment_id),resourceId:String(e.resource_id),provider:String(e.provider),region:String(e.region),meter:String(e.meter),bucketStart:String(e.bucket_start),quantity:Number(e.quantity),costCents:Number(e.cost_cents),sampleCount:Number(e.sample_count),updatedAt:String(e.updated_at)}}function Sr(e,t,r){return[e,t??"",r??""].join("/")}var co=[{atPercent:50,actions:["notify"]},{atPercent:80,actions:["notify"]},{atPercent:100,actions:["notify"],onProjection:!0},{atPercent:100,actions:["notify","block_builds","block_deployments"]},{atPercent:115,actions:["notify","block_builds","block_deployments","throttle_requests"]}];class vr{controlPlane;options;constructor(e,t={}){this.controlPlane=e;this.options=t}now(){return(this.options.now?.()??new Date).toISOString()}get priceBook(){return this.options.priceBook??Ec}query(e,t=[]){return this.controlPlane.database.query(e).all(...t)}createBudget(e){let t=e.name.trim();if(!t)throw Error("Budgets require a name.");if(e.softLimitCents==null&&e.hardLimitCents==null)throw Error("A budget needs a soft limit, a hard limit, or both.");if(e.softLimitCents!=null&&e.hardLimitCents!=null&&e.softLimitCents>e.hardLimitCents)throw Error("The soft limit must not exceed the hard limit.");let r=e.timezone??"UTC";if(!ao(r))throw Error(`Unknown timezone: ${r}`);let n=(e.thresholds??[...co]).filter((s)=>Number.isFinite(s.atPercent)&&s.atPercent>=0);if(e.environmentId&&!e.projectId)throw Error("An environment-scoped budget must also name its project.");let o=crypto.randomUUID(),i=this.now();return this.controlPlane.database.run("INSERT INTO spend_budgets (id,organization_id,project_id,environment_id,name,period,timezone,currency,soft_limit_cents,hard_limit_cents,thresholds,meters,grace_seconds,hysteresis_percent,dry_run,enabled,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,?,?)",[o,e.organizationId,e.projectId??null,e.environmentId??null,t,e.period,r,e.currency??"USD",e.softLimitCents??null,e.hardLimitCents??null,JSON.stringify(n),JSON.stringify(e.meters??[]),Math.max(0,Math.floor(e.graceSeconds??0)),Math.max(0,e.hysteresisPercent??5),e.dryRun?1:0,e.enabled===!1?0:1,i,i]),this.getBudget(o)}getBudget(e){let t=this.query("SELECT * FROM spend_budgets WHERE id = ?",[e])[0];return t?it(t):void 0}listBudgets(e){let t=["organization_id = ?"],r=[e.organizationId];if(e.projectId)t.push("(project_id IS NULL OR project_id = ?)"),r.push(e.projectId);if(e.enabledOnly)t.push("enabled = 1");return this.query(`SELECT * FROM spend_budgets WHERE ${t.join(" AND ")} ORDER BY created_at`,r).map(it)}budgetsForScope(e,t,r){return this.listBudgets({organizationId:e,enabledOnly:!0}).filter((n)=>{if(n.projectId&&n.projectId!==t)return!1;if(n.environmentId&&n.environmentId!==r)return!1;return!0}).sort((n,o)=>Number(!!n.projectId)-Number(!!o.projectId)||Number(!!n.environmentId)-Number(!!o.environmentId))}updateBudget(e,t,r){let n=this.getBudget(e);if(!n)throw Error("Budget was not found.");if(r!=null&&r!==n.version)throw Error(`Budget was modified concurrently (expected version ${r}, found ${n.version}).`);let o={...n,...t};if(o.softLimitCents==null&&o.hardLimitCents==null)throw Error("A budget needs a soft limit, a hard limit, or both.");if(o.softLimitCents!=null&&o.hardLimitCents!=null&&o.softLimitCents>o.hardLimitCents)throw Error("The soft limit must not exceed the hard limit.");if(t.timezone&&!ao(t.timezone))throw Error(`Unknown timezone: ${t.timezone}`);return this.controlPlane.database.run("UPDATE spend_budgets SET name=?,period=?,timezone=?,currency=?,soft_limit_cents=?,hard_limit_cents=?,thresholds=?,meters=?,grace_seconds=?,hysteresis_percent=?,dry_run=?,enabled=?,version=version+1,updated_at=? WHERE id=?",[o.name,o.period,o.timezone,o.currency??"USD",o.softLimitCents??null,o.hardLimitCents??null,JSON.stringify(o.thresholds??[]),JSON.stringify(o.meters??[]),Math.max(0,Math.floor(o.graceSeconds??0)),Math.max(0,o.hysteresisPercent??5),o.dryRun?1:0,o.enabled===!1?0:1,this.now(),e]),this.getBudget(e)}deleteBudget(e){return this.controlPlane.database.run("DELETE FROM spend_budgets WHERE id = ?",[e]).changes>0}ingestUsage(e){let t={applied:0,duplicates:0,costCents:0,unpricedMeters:[]},r=new Set,n=this.now();return this.controlPlane.database.transaction((i)=>{for(let s of i){if(!(s.quantity>0)||!Number.isFinite(s.quantity))continue;let a=s.key??this.deltaFallbackKey(s);if(this.controlPlane.database.run("INSERT OR IGNORE INTO spend_usage_receipts (key,organization_id,bucket_start,created_at) VALUES (?,?,?,?)",[a,s.organizationId,yi(s.timestamp),n]).changes===0){t.duplicates++;continue}let c={projectId:s.projectId??"",environmentId:s.environmentId??"",resourceId:s.resourceId??"",provider:s.provider??"",region:s.region??""},u=this.periodQuantity(s),p=hs(this.priceBook,{meter:s.meter,quantity:s.quantity,provider:s.provider,region:s.region},u);if(p.unpriced)r.add(String(s.meter));this.controlPlane.database.run(`INSERT INTO spend_usage (organization_id,project_id,environment_id,resource_id,provider,region,meter,bucket_start,quantity,cost_cents,sample_count,updated_at)
1
+ import{re,h}from"./chunk-pnj95hwr.js";import{ho}from"./chunk-k343q24p.js";var qp=["edge.requests","edge.egress_gb","function.invocations","function.gb_seconds","build.minutes","compute.instance_hours","storage.gb_hours","object.egress_gb","object.requests","database.gb_hours","database.io_requests","telemetry.ingest_gb","image.transformations"],an={"edge.requests":{key:"edge.requests",unit:"requests",label:"Edge requests",precision:0},"edge.egress_gb":{key:"edge.egress_gb",unit:"gb",label:"Edge egress",precision:3},"function.invocations":{key:"function.invocations",unit:"invocations",label:"Function invocations",precision:0},"function.gb_seconds":{key:"function.gb_seconds",unit:"gb_seconds",label:"Function compute",precision:2},"build.minutes":{key:"build.minutes",unit:"minutes",label:"Build minutes",precision:2},"compute.instance_hours":{key:"compute.instance_hours",unit:"hours",label:"Instance hours",precision:2},"storage.gb_hours":{key:"storage.gb_hours",unit:"gb_hours",label:"Block storage",precision:2},"object.egress_gb":{key:"object.egress_gb",unit:"gb",label:"Object storage egress",precision:3},"object.requests":{key:"object.requests",unit:"requests",label:"Object storage requests",precision:0},"database.gb_hours":{key:"database.gb_hours",unit:"gb_hours",label:"Database storage",precision:2},"database.io_requests":{key:"database.io_requests",unit:"requests",label:"Database I/O",precision:0},"telemetry.ingest_gb":{key:"telemetry.ingest_gb",unit:"gb",label:"Telemetry ingest",precision:3},"image.transformations":{key:"image.transformations",unit:"count",label:"Image transformations",precision:0}},so=["notify","block_builds","block_deployments","throttle_requests","suspend_functions","serve_static","suspend_project"],se={notify:0,block_builds:1,block_deployments:2,throttle_requests:3,suspend_functions:4,serve_static:5,suspend_project:6};var Gp=1e6;function tr(e){if(e.tiers&&e.tiers.length>0)return e.tiers;return[{upToQuantity:null,microCentsPerUnit:e.microCentsPerUnit??0}]}function Tc(e,t){if(!(e>0))return 0;let r=[...t].sort((s,a)=>{if(s.upToQuantity===null)return 1;if(a.upToQuantity===null)return-1;return s.upToQuantity-a.upToQuantity}),n=e,o=0,i=0;for(let s of r){if(n<=0)break;let d=(s.upToQuantity===null?1/0:s.upToQuantity)-o;if(d<=0)continue;let c=Math.min(n,d);i+=c*s.microCentsPerUnit,n-=c,o+=c}if(n>0){let s=r.reduce((a,d)=>Math.max(a,d.microCentsPerUnit),0);i+=n*s}return i}function Rd(e,t,r,n){let o=e.entries.filter((a)=>a.meter===t);if(o.length===0)return;let i=o.filter((a)=>a.provider===r),s=i.length>0?i:o.filter((a)=>a.provider==="*");return s.find((a)=>a.region===n)??s.find((a)=>a.region==null)}function hs(e,t,r=0){let n=Rd(e,t.meter,t.provider,t.region),o=Math.max(0,t.quantity);if(!n)return{meter:t.meter,provider:t.provider??"unknown",region:t.region,quantity:o,includedQuantity:0,billableQuantity:o,costCents:0,unpriced:!0};let i=Math.max(0,n.includedQuantity??0),s=Math.max(0,r-i),a=Math.max(0,i-Math.max(0,r)),d=Math.min(o,a),c=o-d,u=tr(n),p=Tc(s+c,u)-Tc(s,u);return{meter:t.meter,provider:n.provider,region:n.region??t.region,quantity:o,includedQuantity:d,billableQuantity:c,costCents:p/1e6,unpriced:!1}}function Wp(e,t){let r=new Map,n=[];for(let o of t){let i=`${o.meter}\x00${o.provider??""}\x00${o.region??""}`,s=r.get(i)??0,a=hs(e,o,s);r.set(i,s+a.quantity),n.push(a)}return{currency:e.currency,totalCents:n.reduce((o,i)=>o+i.costCents,0),lines:n,unpricedMeters:[...new Set(n.filter((o)=>o.unpriced).map((o)=>String(o.meter)))]}}function Kp(e){return Math.round(e*100)/100}function Jp(e,...t){let r=new Map,n=(i)=>`${i.meter}\x00${i.provider}\x00${i.region??""}`;for(let i of e.entries)r.set(n(i),i);let o=e.currency;for(let i of t){o=i.currency||o;for(let s of i.entries)r.set(n(s),s)}return{currency:o,entries:[...r.values()]}}var V=(e)=>Math.round(e*1e6),N=(e)=>Math.round(e*1e6),Ec={currency:"USD",entries:[{meter:"edge.requests",provider:"aws",microCentsPerUnit:N(0.00075)},{meter:"edge.egress_gb",provider:"aws",includedQuantity:100,tiers:[{upToQuantity:10240,microCentsPerUnit:V(8.5)},{upToQuantity:51200,microCentsPerUnit:V(8)},{upToQuantity:null,microCentsPerUnit:V(6)}]},{meter:"function.invocations",provider:"aws",includedQuantity:1e6,microCentsPerUnit:N(0.002)},{meter:"function.gb_seconds",provider:"aws",includedQuantity:400000,microCentsPerUnit:N(0.00166667)},{meter:"storage.gb_hours",provider:"aws",microCentsPerUnit:N(0.010958904109589041)},{meter:"object.egress_gb",provider:"aws",includedQuantity:100,microCentsPerUnit:V(9)},{meter:"object.requests",provider:"aws",microCentsPerUnit:N(0.000039999999999999996)},{meter:"database.gb_hours",provider:"aws",microCentsPerUnit:N(0.015753424657534248)},{meter:"compute.instance_hours",provider:"aws",microCentsPerUnit:N(4.16)},{meter:"edge.egress_gb",provider:"hetzner",includedQuantity:20480,microCentsPerUnit:V(0.108)},{meter:"object.egress_gb",provider:"hetzner",includedQuantity:1024,microCentsPerUnit:V(0.108)},{meter:"compute.instance_hours",provider:"hetzner",microCentsPerUnit:N(0.95)},{meter:"storage.gb_hours",provider:"hetzner",microCentsPerUnit:N(0.006027397260273972)},{meter:"edge.requests",provider:"hetzner",microCentsPerUnit:0},{meter:"edge.requests",provider:"local",microCentsPerUnit:0},{meter:"edge.egress_gb",provider:"local",microCentsPerUnit:0},{meter:"function.invocations",provider:"local",microCentsPerUnit:0},{meter:"function.gb_seconds",provider:"local",microCentsPerUnit:0},{meter:"build.minutes",provider:"*",includedQuantity:6000,microCentsPerUnit:N(0.8)},{meter:"telemetry.ingest_gb",provider:"*",includedQuantity:5,microCentsPerUnit:V(50)},{meter:"image.transformations",provider:"*",includedQuantity:5000,microCentsPerUnit:N(0.05)}]};var tt=new Map;function rt(e){let t=tt.get(e);if(!t)t=new Intl.DateTimeFormat("en-US",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",weekday:"short",hourCycle:"h23"}),tt.set(e,t);return t}var rr={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};function ao(e){try{return rt(e),!0}catch{return!1}}function ys(e,t){let r=rt(t).formatToParts(e),n=(o)=>r.find((i)=>i.type===o)?.value??"0";return{year:Number(n("year")),month:Number(n("month")),day:Number(n("day")),hour:Number(n("hour")),minute:Number(n("minute")),second:Number(n("second")),weekday:rr[n("weekday")]??0}}function wc(e,t){let r=ys(e,t);return Date.UTC(r.year,r.month-1,r.day,r.hour,r.minute,r.second)-Math.floor(e.getTime()/1000)*1000}function cn(e,t,r,n,o=0){let i=Date.UTC(t,r-1,n,o),s=new Date(i-wc(new Date(i),e));return new Date(i-wc(s,e))}function nr(e,t){return new Date(Date.UTC(e,t-1,1)).toLocaleString("en-US",{month:"long",year:"numeric",timeZone:"UTC"})}function br(e,t,r=new Date){let n=ao(t)?t:"UTC",o=ys(r,n),i,s,a;if(e==="daily")i=cn(n,o.year,o.month,o.day),s=cn(n,o.year,o.month,o.day+1),a=`${o.year}-${String(o.month).padStart(2,"0")}-${String(o.day).padStart(2,"0")}`;else if(e==="weekly"){let u=(o.weekday+6)%7;i=cn(n,o.year,o.month,o.day-u),s=cn(n,o.year,o.month,o.day-u+7);let p=ys(i,n);a=`week of ${p.year}-${String(p.month).padStart(2,"0")}-${String(p.day).padStart(2,"0")}`}else i=cn(n,o.year,o.month,1),s=cn(n,o.year,o.month+1,1),a=nr(o.year,o.month);let d=s.getTime()-i.getTime(),c=Math.max(0,Math.min(d,r.getTime()-i.getTime()));return{start:i.toISOString(),end:s.toISOString(),elapsedMs:c,totalMs:d,label:a}}function Xp(e,t,r=new Date){let n=br(e,t,r),o=new Date(new Date(n.start).getTime()-1),i=br(e,t,o);return{...i,elapsedMs:i.totalMs}}function yi(e){let r=(typeof e==="string"?new Date(e):e).getTime();if(!Number.isFinite(r))throw Error("hourBucket requires a valid date");return new Date(Math.floor(r/3600000)*3600000).toISOString()}function Qp(e,t,r=9600){let n=Math.floor(new Date(e).getTime()/3600000)*3600000,o=new Date(t).getTime();if(!Number.isFinite(n)||!Number.isFinite(o))throw Error("hourBucketsBetween requires valid dates");let i=[];for(let s=n;s<o&&i.length<r;s+=3600000)i.push(new Date(s).toISOString());return i}import{createHash as or}from"node:crypto";var le=1073741824,Ac=[{match:"request.count",meter:"edge.requests"},{match:"traffic.requests",meter:"edge.requests"},{match:"http.request",meter:"edge.requests",field:"count"},{match:"traffic.bytes_out",meter:"edge.egress_gb",scale:1/le},{match:"storage.egress.day",meter:"object.egress_gb",scale:1/le},{match:"storage.egress.month",meter:"object.egress_gb",scale:1/le,cumulative:!0},{match:"storage.egress.day_downloads",meter:"object.requests"},{match:"function.invocation",meter:"function.invocations",field:"count"},{match:"function.duration_ms",meter:"function.gb_seconds",scale:0.001},{match:"build.duration_ms",meter:"build.minutes",scale:0.000016666666666666667},{match:"telemetry.ingest_bytes",meter:"telemetry.ingest_gb",scale:1/le},{match:"image.transform",meter:"image.transformations",field:"count"}];function ir(e,t){return e.match.endsWith("*")?t.startsWith(e.match.slice(0,-1)):e.match===t}function Id(e,t=Ac){return t.find((r)=>!r.match.endsWith("*")&&r.match===e)??t.find((r)=>ir(r,e))}function sr(e,t){let r=t.field??"value",n=r==="count"?1:r==="bytesOut"?e.bytesOut:r==="bytesIn"?e.bytesIn:r==="durationMs"?e.durationMs:e.value;if(n==null||!Number.isFinite(n))return;return n*(t.scale??1)}function Pd(e,t){return or("sha256").update([t,e.meter,e.organizationId,e.projectId??"",e.environmentId??"",e.resourceId??"",e.timestamp].join("\x00")).digest("hex").slice(0,32)}class bs{resetToleranceRatio;last=new Map;constructor(e=0.999){this.resetToleranceRatio=e}delta(e,t,r=new Date){if(!Number.isFinite(t)||t<0)return;let n=new Date(r).getTime(),o=this.last.get(e);if(!o)return this.last.set(e,{value:t,at:n}),t>0?t:void 0;if(n<o.at)return;if(t<o.value&&t>=o.value*this.resetToleranceRatio)return;if(this.last.set(e,{value:t,at:n}),t>=o.value){let i=t-o.value;return i>0?i:void 0}return t>0?t:void 0}prune(e){let t=e.getTime(),r=0;for(let[n,o]of this.last)if(o.at<t)this.last.delete(n),r++;return r}get size(){return this.last.size}}function nt(e,t){let r=e[t];return typeof r==="string"&&r.length>0?r:void 0}function Rc(e,t,r={}){let n=r.mappings??Ac,o=r.counters,i=[];for(let s of t){let a=Id(s.name,n);if(!a)continue;let d=sr(s,a);if(d==null)continue;if(a.cumulative){if(!o)continue;let u=[s.projectId,s.environmentId??"",s.resourceId??"",s.name,s.source].join("\x00"),p=o.delta(u,d,s.timestamp);if(p==null)continue;d=p}if(!(d>0))continue;let c={organizationId:e,projectId:s.projectId,environmentId:s.environmentId,resourceId:s.resourceId,provider:nt(s.attributes,"provider")??r.defaultProvider,region:s.region??nt(s.attributes,"region"),meter:a.meter,quantity:d,timestamp:s.timestamp,attributes:{source:s.source,signal:s.name}};i.push({...c,key:Pd(c,s.id)})}return i}function Ic(e){let t=new Map;for(let r of e){let n=new Date(Math.floor(new Date(r.timestamp).getTime()/3600000)*3600000).toISOString(),o=[r.organizationId,r.projectId??"",r.environmentId??"",r.resourceId??"",r.provider??"",r.region??"",r.meter,n].join("\x00"),i=t.get(o);if(i)i.quantity+=r.quantity;else t.set(o,{...r,timestamp:n})}return[...t.values()]}import{createHash as ar}from"node:crypto";var K=(e)=>{if(typeof e!=="string")return{};try{return JSON.parse(e)}catch{return{}}},j=(e)=>typeof e==="string"&&e!==""?e:void 0,ue=(e)=>Number(e)===1,ot=(e)=>e==null?void 0:Number(e);function it(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:j(e.project_id),environmentId:j(e.environment_id),name:String(e.name),period:String(e.period),timezone:String(e.timezone),currency:String(e.currency),softLimitCents:ot(e.soft_limit_cents),hardLimitCents:ot(e.hard_limit_cents),thresholds:K(e.thresholds),meters:K(e.meters),graceSeconds:Number(e.grace_seconds),hysteresisPercent:Number(e.hysteresis_percent),dryRun:ue(e.dry_run),enabled:ue(e.enabled),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Ae(e){return{id:String(e.id),budgetId:String(e.budget_id),organizationId:String(e.organization_id),projectId:j(e.project_id),environmentId:j(e.environment_id),action:String(e.action),state:String(e.state),reason:String(e.reason),restore:K(e.restore),triggeredAtPercent:Number(e.triggered_at_percent),simulated:ue(e.simulated),appliedAt:j(e.applied_at),releasedAt:j(e.released_at),error:j(e.error),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function st(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:j(e.project_id),environmentId:j(e.environment_id),signal:String(e.signal),direction:String(e.direction),observed:Number(e.observed),expected:Number(e.expected),score:Number(e.score),deltaPercent:Number(e.delta_percent),severity:String(e.severity),bucketStart:String(e.bucket_start),evidence:K(e.evidence),acknowledgedAt:j(e.acknowledged_at),createdAt:String(e.created_at)}}function dr(e){return{organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:String(e.environment_id),resourceId:String(e.resource_id),provider:String(e.provider),region:String(e.region),meter:String(e.meter),bucketStart:String(e.bucket_start),quantity:Number(e.quantity),costCents:Number(e.cost_cents),sampleCount:Number(e.sample_count),updatedAt:String(e.updated_at)}}function Sr(e,t,r){return[e,t??"",r??""].join("/")}var co=[{atPercent:50,actions:["notify"]},{atPercent:80,actions:["notify"]},{atPercent:100,actions:["notify"],onProjection:!0},{atPercent:100,actions:["notify","block_builds","block_deployments"]},{atPercent:115,actions:["notify","block_builds","block_deployments","throttle_requests"]}];class vr{controlPlane;options;constructor(e,t={}){this.controlPlane=e;this.options=t}now(){return(this.options.now?.()??new Date).toISOString()}get priceBook(){return this.options.priceBook??Ec}query(e,t=[]){return this.controlPlane.database.query(e).all(...t)}createBudget(e){let t=e.name.trim();if(!t)throw Error("Budgets require a name.");if(e.softLimitCents==null&&e.hardLimitCents==null)throw Error("A budget needs a soft limit, a hard limit, or both.");if(e.softLimitCents!=null&&e.hardLimitCents!=null&&e.softLimitCents>e.hardLimitCents)throw Error("The soft limit must not exceed the hard limit.");let r=e.timezone??"UTC";if(!ao(r))throw Error(`Unknown timezone: ${r}`);let n=(e.thresholds??[...co]).filter((s)=>Number.isFinite(s.atPercent)&&s.atPercent>=0);if(e.environmentId&&!e.projectId)throw Error("An environment-scoped budget must also name its project.");let o=crypto.randomUUID(),i=this.now();return this.controlPlane.database.run("INSERT INTO spend_budgets (id,organization_id,project_id,environment_id,name,period,timezone,currency,soft_limit_cents,hard_limit_cents,thresholds,meters,grace_seconds,hysteresis_percent,dry_run,enabled,version,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,?,?)",[o,e.organizationId,e.projectId??null,e.environmentId??null,t,e.period,r,e.currency??"USD",e.softLimitCents??null,e.hardLimitCents??null,JSON.stringify(n),JSON.stringify(e.meters??[]),Math.max(0,Math.floor(e.graceSeconds??0)),Math.max(0,e.hysteresisPercent??5),e.dryRun?1:0,e.enabled===!1?0:1,i,i]),this.getBudget(o)}getBudget(e){let t=this.query("SELECT * FROM spend_budgets WHERE id = ?",[e])[0];return t?it(t):void 0}listBudgets(e){let t=["organization_id = ?"],r=[e.organizationId];if(e.projectId)t.push("(project_id IS NULL OR project_id = ?)"),r.push(e.projectId);if(e.enabledOnly)t.push("enabled = 1");return this.query(`SELECT * FROM spend_budgets WHERE ${t.join(" AND ")} ORDER BY created_at`,r).map(it)}budgetsForScope(e,t,r){return this.listBudgets({organizationId:e,enabledOnly:!0}).filter((n)=>{if(n.projectId&&n.projectId!==t)return!1;if(n.environmentId&&n.environmentId!==r)return!1;return!0}).sort((n,o)=>Number(!!n.projectId)-Number(!!o.projectId)||Number(!!n.environmentId)-Number(!!o.environmentId))}updateBudget(e,t,r){let n=this.getBudget(e);if(!n)throw Error("Budget was not found.");if(r!=null&&r!==n.version)throw Error(`Budget was modified concurrently (expected version ${r}, found ${n.version}).`);let o={...n,...t};if(o.softLimitCents==null&&o.hardLimitCents==null)throw Error("A budget needs a soft limit, a hard limit, or both.");if(o.softLimitCents!=null&&o.hardLimitCents!=null&&o.softLimitCents>o.hardLimitCents)throw Error("The soft limit must not exceed the hard limit.");if(t.timezone&&!ao(t.timezone))throw Error(`Unknown timezone: ${t.timezone}`);return this.controlPlane.database.run("UPDATE spend_budgets SET name=?,period=?,timezone=?,currency=?,soft_limit_cents=?,hard_limit_cents=?,thresholds=?,meters=?,grace_seconds=?,hysteresis_percent=?,dry_run=?,enabled=?,version=version+1,updated_at=? WHERE id=?",[o.name,o.period,o.timezone,o.currency??"USD",o.softLimitCents??null,o.hardLimitCents??null,JSON.stringify(o.thresholds??[]),JSON.stringify(o.meters??[]),Math.max(0,Math.floor(o.graceSeconds??0)),Math.max(0,o.hysteresisPercent??5),o.dryRun?1:0,o.enabled===!1?0:1,this.now(),e]),this.getBudget(e)}deleteBudget(e){return this.controlPlane.database.run("DELETE FROM spend_budgets WHERE id = ?",[e]).changes>0}ingestUsage(e){let t={applied:0,duplicates:0,costCents:0,unpricedMeters:[]},r=new Set,n=this.now();return this.controlPlane.database.transaction((i)=>{for(let s of i){if(!(s.quantity>0)||!Number.isFinite(s.quantity))continue;let a=s.key??this.deltaFallbackKey(s);if(this.controlPlane.database.run("INSERT OR IGNORE INTO spend_usage_receipts (key,organization_id,bucket_start,created_at) VALUES (?,?,?,?)",[a,s.organizationId,yi(s.timestamp),n]).changes===0){t.duplicates++;continue}let c={projectId:s.projectId??"",environmentId:s.environmentId??"",resourceId:s.resourceId??"",provider:s.provider??"",region:s.region??""},u=this.periodQuantity(s),p=hs(this.priceBook,{meter:s.meter,quantity:s.quantity,provider:s.provider,region:s.region},u);if(p.unpriced)r.add(String(s.meter));this.controlPlane.database.run(`INSERT INTO spend_usage (organization_id,project_id,environment_id,resource_id,provider,region,meter,bucket_start,quantity,cost_cents,sample_count,updated_at)
2
2
  VALUES (?,?,?,?,?,?,?,?,?,?,1,?)
3
3
  ON CONFLICT(organization_id,project_id,environment_id,resource_id,provider,region,meter,bucket_start) DO UPDATE SET
4
4
  quantity = quantity + excluded.quantity,
@@ -108,4 +108,4 @@ volumes:
108
108
  `).map((i)=>i.trim()).filter(F.test.bind(F))){let i=await this.inspect(o);if(i)n.push(i)}return n}async create(e){let t=typeof e.desiredState.nativeName==="string"?e.desiredState.nativeName:e.name;if(!F.test(t))throw Error("Docker volume name is invalid.");return await this.run(["volume","create","--label",`ts-cloud.volume=${e.id}`,"--label",`ts-cloud.project=${e.projectId}`,t]),await this.inspect(t)??{providerId:t}}async attach(e,t){}async detach(e,t){}async resize(){throw Error(this.capabilities().resize.reason)}async snapshot(){throw Error(this.capabilities().snapshot.reason)}async restore(e,t,r){throw Error(this.capabilities().restore.reason)}async delete(e){if(!e.providerId||!F.test(e.providerId))throw Error("Docker volume provider identity is missing or invalid.");await this.run(["volume","rm",e.providerId])}async usage(e){let t=await this.run(["system","df","-v","--format","{{json .}}"],!0),r=t.split(`
109
109
  `).find((n)=>n.includes(`"Name":"${e.providerId}"`));if(!r)return{};try{let n=JSON.parse(r);return{usedBytes:typeof n.Size==="number"?n.Size:void 0}}catch{return{}}}}class on{provider="server";type="server_path";root;constructor(e){this.root=Wt(e)}capabilities(){return Be(["create","attach","detach","delete","adopt","usage"],{resize:{supported:!1,reason:"Server paths use the capacity of their containing filesystem."},snapshot:{supported:!1,reason:"Attach a filesystem backup policy for verified recovery points."},restore:{supported:!1,reason:"Restore a filesystem recovery point into a new managed path."}})}path(e){if(!F.test(e))throw Error("Server path volume name is invalid.");let t=Wt(this.root,e);if(!t.startsWith(`${this.root}${Bn}`)||Vn(t)!==e)throw Error("Server path escaped the managed volume root.");return t}async discover(e,t){return await ze(this.root,{recursive:!0,mode:488}),(await Ln(this.root,{withFileTypes:!0})).filter((n)=>n.isDirectory()&&F.test(n.name)).map((n)=>({providerId:n.name,raw:{path:this.path(n.name)}}))}async create(e){let t=typeof e.desiredState.nativeName==="string"?e.desiredState.nativeName:e.name,r=this.path(t);return await ze(this.root,{recursive:!0,mode:488}),await ze(r,{recursive:!1,mode:488}),{providerId:t,filesystem:"host",raw:{path:r}}}async attach(e,t){}async detach(e,t){}async resize(){throw Error(this.capabilities().resize.reason)}async snapshot(){throw Error(this.capabilities().snapshot.reason)}async restore(e,t,r){throw Error(this.capabilities().restore.reason)}async delete(e){if(!e.providerId)throw Error("Server path provider identity is unavailable.");await qn(this.path(e.providerId),{recursive:!0,force:!1})}async usage(e){if(!e.providerId)return{};return{usedBytes:(await $n(this.path(e.providerId))).size}}}var D=(e)=>e==null?void 0:String(e),de=(e,t)=>{try{return JSON.parse(String(e))}catch{return t}},He=(e)=>Number(e)===1,H=(e)=>e().toISOString();function Kt(e){return{id:String(e.id),organizationId:String(e.organization_id),projectId:String(e.project_id),environmentId:D(e.environment_id),resourceId:D(e.resource_id),name:String(e.name),provider:String(e.provider),providerId:D(e.provider_id),type:String(e.type),status:String(e.status),capacityBytes:e.capacity_bytes==null?void 0:Number(e.capacity_bytes),usedBytes:e.used_bytes==null?void 0:Number(e.used_bytes),filesystem:D(e.filesystem),encrypted:He(e.encrypted),capabilities:de(e.capabilities,{}),desiredState:de(e.desired_state,{}),observedState:de(e.observed_state,{}),backupPolicyId:D(e.backup_policy_id),lastBackupAt:D(e.last_backup_at),orphanedAt:D(e.orphaned_at),adoptedAt:D(e.adopted_at),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),deletedAt:D(e.deleted_at)}}function Fe(e){return{id:String(e.id),volumeId:String(e.volume_id),resourceId:String(e.resource_id),targetPath:String(e.target_path),readOnly:He(e.read_only),uid:e.uid==null?void 0:Number(e.uid),gid:e.gid==null?void 0:Number(e.gid),mode:D(e.mode),propagation:String(e.propagation),driverOptions:de(e.driver_options,{}),desiredState:String(e.desired_state),observedState:String(e.observed_state),operationId:D(e.operation_id),lastError:D(e.last_error),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function Gt(e){return{id:String(e.id),volumeId:String(e.volume_id),recoveryPointId:D(e.recovery_point_id),providerId:D(e.provider_id),name:String(e.name),status:String(e.status),sizeBytes:e.size_bytes==null?void 0:Number(e.size_bytes),encrypted:He(e.encrypted),checksum:D(e.checksum),metadata:de(e.metadata,{}),createdAt:String(e.created_at),updatedAt:String(e.updated_at),deletedAt:D(e.deleted_at)}}class mt{controlPlane;now;id;constructor(e,t=()=>new Date,r=()=>crypto.randomUUID()){this.controlPlane=e;this.now=t;this.id=r}get(e){let t=this.controlPlane.database.query("SELECT * FROM persistent_volumes WHERE id=?").get(e);return t?Kt(t):void 0}list(e){let t=["project_id=?"],r=[e.projectId];if(e.environmentId)t.push("environment_id=?"),r.push(e.environmentId);if(!e.includeDeleted)t.push("deleted_at IS NULL");return this.controlPlane.database.query(`SELECT * FROM persistent_volumes WHERE ${t.join(" AND ")} ORDER BY name`).all(...r).map(Kt)}create(e){let t=H(this.now),r=e.id??this.id();return this.controlPlane.database.run("INSERT INTO persistent_volumes (id,organization_id,project_id,environment_id,resource_id,name,provider,provider_id,type,status,capacity_bytes,used_bytes,filesystem,encrypted,capabilities,desired_state,observed_state,backup_policy_id,last_backup_at,orphaned_at,adopted_at,created_at,updated_at,deleted_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[r,e.organizationId,e.projectId,e.environmentId??null,e.resourceId??null,e.name,e.provider,e.providerId??null,e.type,e.status,e.capacityBytes??null,e.usedBytes??null,e.filesystem??null,e.encrypted?1:0,JSON.stringify(e.capabilities),JSON.stringify(e.desiredState),JSON.stringify(e.observedState),e.backupPolicyId??null,e.lastBackupAt??null,e.orphanedAt??null,e.adoptedAt??null,t,t,e.deletedAt??null]),this.get(r)}update(e,t,r){let n=this.get(e);if(!n||n.version!==t)throw Error("Volume changed before this operation could be applied.");let o={...n,...r,updatedAt:H(this.now)};if(this.controlPlane.database.run("UPDATE persistent_volumes SET environment_id=?,resource_id=?,name=?,provider=?,provider_id=?,type=?,status=?,capacity_bytes=?,used_bytes=?,filesystem=?,encrypted=?,capabilities=?,desired_state=?,observed_state=?,backup_policy_id=?,last_backup_at=?,orphaned_at=?,adopted_at=?,deleted_at=?,version=version+1,updated_at=? WHERE id=? AND version=?",[o.environmentId??null,o.resourceId??null,o.name,o.provider,o.providerId??null,o.type,o.status,o.capacityBytes??null,o.usedBytes??null,o.filesystem??null,o.encrypted?1:0,JSON.stringify(o.capabilities),JSON.stringify(o.desiredState),JSON.stringify(o.observedState),o.backupPolicyId??null,o.lastBackupAt??null,o.orphanedAt??null,o.adoptedAt??null,o.deletedAt??null,o.updatedAt,e,t]).changes!==1)throw Error("Volume changed before this operation could be applied.");return this.get(e)}attachments(e){return this.controlPlane.database.query("SELECT * FROM volume_attachments WHERE volume_id=? ORDER BY target_path").all(e).map(Fe)}attachment(e){let t=this.controlPlane.database.query("SELECT * FROM volume_attachments WHERE id=?").get(e);return t?Fe(t):void 0}upsertAttachment(e){let t=this.controlPlane.database.query("SELECT * FROM volume_attachments WHERE volume_id=? AND resource_id=? AND target_path=?").get(e.volumeId,e.resourceId,e.targetPath),r=H(this.now);if(t){let o=Fe(t);return this.controlPlane.database.run("UPDATE volume_attachments SET read_only=?,uid=?,gid=?,mode=?,propagation=?,driver_options=?,desired_state=?,observed_state=?,operation_id=?,last_error=?,version=version+1,updated_at=? WHERE id=?",[e.readOnly?1:0,e.uid??null,e.gid??null,e.mode??null,e.propagation,JSON.stringify(e.driverOptions),e.desiredState,e.observedState,e.operationId??null,e.lastError??null,r,o.id]),this.attachment(o.id)}let n=e.id??this.id();return this.controlPlane.database.run("INSERT INTO volume_attachments (id,volume_id,resource_id,target_path,read_only,uid,gid,mode,propagation,driver_options,desired_state,observed_state,operation_id,last_error,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[n,e.volumeId,e.resourceId,e.targetPath,e.readOnly?1:0,e.uid??null,e.gid??null,e.mode??null,e.propagation,JSON.stringify(e.driverOptions),e.desiredState,e.observedState,e.operationId??null,e.lastError??null,r,r]),this.attachment(n)}updateAttachment(e,t){let r=this.attachment(e);if(!r)throw Error("Volume attachment was not found.");let n={...r,...t};return this.controlPlane.database.run("UPDATE volume_attachments SET desired_state=?,observed_state=?,operation_id=?,last_error=?,version=version+1,updated_at=? WHERE id=?",[n.desiredState,n.observedState,n.operationId??null,n.lastError??null,H(this.now),e]),this.attachment(e)}snapshots(e){return this.controlPlane.database.query("SELECT * FROM volume_snapshots WHERE volume_id=? AND deleted_at IS NULL ORDER BY created_at DESC").all(e).map(Gt)}snapshot(e){let t=this.controlPlane.database.query("SELECT * FROM volume_snapshots WHERE id=?").get(e);return t?Gt(t):void 0}createSnapshot(e){let t=e.id??this.id(),r=H(this.now);return this.controlPlane.database.run("INSERT INTO volume_snapshots (id,volume_id,recovery_point_id,provider_id,name,status,size_bytes,encrypted,checksum,metadata,created_at,updated_at,deleted_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.volumeId,e.recoveryPointId??null,e.providerId??null,e.name,e.status,e.sizeBytes??null,e.encrypted?1:0,e.checksum??null,JSON.stringify(e.metadata),r,r,e.deletedAt??null]),this.snapshot(t)}updateSnapshot(e,t){let r=this.snapshot(e);if(!r)throw Error("Volume snapshot was not found.");let n={...r,...t};return this.controlPlane.database.run("UPDATE volume_snapshots SET recovery_point_id=?,provider_id=?,name=?,status=?,size_bytes=?,encrypted=?,checksum=?,metadata=?,deleted_at=?,updated_at=? WHERE id=?",[n.recoveryPointId??null,n.providerId??null,n.name,n.status,n.sizeBytes??null,n.encrypted?1:0,n.checksum??null,JSON.stringify(n.metadata),n.deletedAt??null,H(this.now),e]),this.snapshot(e)}inventory(e,t){return this.list({projectId:e,environmentId:t}).map((r)=>{let n=this.attachments(r.id),o=this.snapshots(r.id),i=r.lastBackupAt?Date.now()-new Date(r.lastBackupAt).getTime():1/0;return{...r,attachments:n,snapshots:o,orphaned:r.status==="orphaned",usagePercent:r.capacityBytes&&r.usedBytes!=null?Math.round(r.usedBytes/r.capacityBytes*1000)/10:void 0,backupState:r.backupPolicyId?i<=86400000?"protected":"stale":"unprotected"}})}audit(e){this.controlPlane.appendEvent({organizationId:e.organizationId,projectId:e.projectId,resourceId:this.get(e.volumeId)?.resourceId,actorId:e.actorId,type:e.type,level:"warning",payload:{volumeId:e.volumeId,environmentId:e.environmentId??null,...e.payload}})}}function We(e,t){let r=e.getProject(t.projectId);if(!r?.organizationId)return;let n=new mt(e),o=new $t,i=new Set(t.manifest.spec.volumes),s=new Set;for(let a of i){let d=`${t.slug}-${a}`.toLowerCase().replace(/[^a-z0-9_.-]/g,"-").slice(0,63),c=n.list({projectId:t.projectId,environmentId:t.environmentId,includeDeleted:!0}).find((f)=>f.name===d);if(c?.deletedAt)throw Error(`Compose volume ${d} was permanently deleted; rename it before redeploying.`);let u=c?.resourceId?e.getResource(c.resourceId):e.createResource({projectId:t.projectId,environmentId:t.environmentId,kind:"volume",slug:d,name:d,provider:"docker",providerId:d,desiredState:{composeApplicationId:t.id,composeVolume:a}}),p=c??n.create({organizationId:r.organizationId,projectId:t.projectId,environmentId:t.environmentId,resourceId:u?.id,name:d,provider:"docker",providerId:d,type:"docker",status:"available",encrypted:!1,capabilities:o.capabilities(),desiredState:{composeApplicationId:t.id,composeVolume:a,nativeName:d},observedState:{}});s.add(p.id);let l=new Map;for(let f of Object.values(t.manifest.spec.services))for(let g of f.volumes.filter((y)=>y.source===a)){let y=l.get(g.target)??[];y.push(f.name),l.set(g.target,y),n.upsertAttachment({volumeId:p.id,resourceId:t.resourceId,targetPath:g.target,readOnly:g.readOnly,propagation:"private",driverOptions:{composeServices:y},desiredState:"attached",observedState:"pending"})}}for(let a of n.list({projectId:t.projectId,environmentId:t.environmentId}).filter((d)=>d.desiredState.composeApplicationId===t.id&&!s.has(d.id)))for(let d of n.attachments(a.id))n.updateAttachment(d.id,{desiredState:"detached"})}function Yt(e,t,r){let n=new mt(e);for(let o of n.list({projectId:t.projectId,environmentId:t.environmentId}).filter((i)=>i.desiredState.composeApplicationId===t.id)){for(let i of n.attachments(o.id))n.updateAttachment(i.id,{desiredState:"detached",observedState:"detached"});n.update(o.id,o.version,{status:r?"deleted":"available",deletedAt:r?new Date().toISOString():void 0})}}function Q(e){return typeof e==="string"&&e?e:void 0}function Ke(e,t){try{return JSON.parse(String(e))}catch{return t}}function Ie(e){return{id:String(e.id),resourceId:String(e.resource_id),projectId:String(e.project_id),environmentId:String(e.environment_id),name:String(e.name),slug:String(e.slug),status:String(e.status),sourceKind:String(e.source_kind),sourceHash:String(e.source_hash),redactedSource:String(e.redacted_source),manifest:Ke(e.manifest,{}),diagnostics:Ke(e.diagnostics,[]),templateId:Q(e.template_id),templateVersion:Q(e.template_version),latestOperationId:Q(e.latest_operation_id),createdByActorId:Q(e.created_by_actor_id),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),deletedAt:Q(e.deleted_at)}}function Un(e){return{applicationId:String(e.application_id),serviceName:String(e.service_name),status:String(e.status),replicas:Number(e.replicas),healthyReplicas:Number(e.healthy_replicas),latestOperationId:Q(e.latest_operation_id),observedState:Ke(e.observed_state,{}),updatedAt:String(e.updated_at)}}class gt{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}persist(e,t){if(!e.valid)throw Error(`Compose definition contains ${e.diagnostics.filter((g)=>g.severity==="error").length} blocking diagnostic(s)`);let{projectId:r,environmentId:n,name:o,slug:i}=e.manifest.metadata;if(!this.controlPlane.listEnvironments(r).find((g)=>g.id===n))throw Error("Compose project and environment scope was not found");let a=this.getBySlug(r,n,i),d=this.now().toISOString(),c=JSON.stringify(e.manifest),u=JSON.stringify(h(e.diagnostics));if(a){if(a.status==="deleted")throw Error("A deleted Compose application cannot be overwritten; choose another slug");let g=this.controlPlane.getResource(a.resourceId);if(!g)throw Error("Compose application resource was not found");this.controlPlane.updateResource(g.id,g.version,{name:o,provider:g.provider,providerId:g.providerId,desiredState:e.manifest,discoveredState:g.discoveredState,metadata:{sourceKind:t.sourceKind,templateId:t.templateId??null,templateVersion:t.templateVersion??null,sourceHash:e.sourceHash}}),this.controlPlane.database.run("UPDATE compose_applications SET name=?, status='ready', source_kind=?, source_hash=?, redacted_source=?, manifest=?, diagnostics=?, template_id=?, template_version=?, version=version+1, updated_at=? WHERE id=?",[o,t.sourceKind,e.sourceHash,e.redactedSource,c,u,t.templateId??null,t.templateVersion??null,d,a.id]);let y=Object.keys(e.manifest.spec.services);if(y.length)this.controlPlane.database.run(`DELETE FROM compose_service_states WHERE application_id=? AND service_name NOT IN (${y.map(()=>"?").join(",")})`,[a.id,...y]);for(let b of Object.values(e.manifest.spec.services))this.controlPlane.database.run("INSERT INTO compose_service_states (application_id, service_name, status, replicas, healthy_replicas, observed_state, updated_at) VALUES (?, ?, 'pending', ?, 0, '{}', ?) ON CONFLICT(application_id, service_name) DO UPDATE SET replicas=excluded.replicas, updated_at=excluded.updated_at",[a.id,b.name,b.replicas,d]);this.controlPlane.appendEvent({projectId:r,resourceId:a.resourceId,actorId:t.createdByActorId,type:"compose.application.updated",payload:{applicationId:a.id,sourceHash:e.sourceHash,diagnosticCount:e.diagnostics.length,templateId:t.templateId??null,templateVersion:t.templateVersion??null}});let v=this.get(a.id);return We(this.controlPlane,v),v}let p=this.controlPlane.createResource({projectId:r,environmentId:n,kind:"compose_application",slug:i,name:o,desiredState:e.manifest,metadata:{sourceKind:t.sourceKind,templateId:t.templateId??null,templateVersion:t.templateVersion??null,sourceHash:e.sourceHash}}),l=this.id();this.controlPlane.database.run("INSERT INTO compose_applications (id, resource_id, project_id, environment_id, name, slug, status, source_kind, source_hash, redacted_source, manifest, diagnostics, template_id, template_version, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, 'ready', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[l,p.id,r,n,o,i,t.sourceKind,e.sourceHash,e.redactedSource,c,u,t.templateId??null,t.templateVersion??null,t.createdByActorId??null,d,d]);for(let g of Object.values(e.manifest.spec.services))this.controlPlane.database.run("INSERT INTO compose_service_states (application_id, service_name, status, replicas, healthy_replicas, observed_state, updated_at) VALUES (?, ?, 'pending', ?, 0, '{}', ?)",[l,g.name,g.replicas,d]);this.controlPlane.appendEvent({projectId:r,resourceId:p.id,actorId:t.createdByActorId,type:"compose.application.created",payload:{applicationId:l,sourceHash:e.sourceHash,serviceNames:Object.keys(e.manifest.spec.services),templateId:t.templateId??null}});let f=this.get(l);return We(this.controlPlane,f),f}import(e,t){let r=Ot(e,t);return{application:this.persist(r,{sourceKind:"compose",createdByActorId:t.createdByActorId}),parsed:r}}fromTemplate(e,t,r){let n=Jt(e,t,r,r.version);return{application:this.persist(n,{sourceKind:"template",templateId:e,templateVersion:r.version??"1.0.0",createdByActorId:r.createdByActorId}),parsed:n}}preview(e,t){return Ot(e,t)}get(e){let t=this.controlPlane.database.query("SELECT * FROM compose_applications WHERE id=?").get(e);return t?Ie(t):void 0}getByResource(e){let t=this.controlPlane.database.query("SELECT * FROM compose_applications WHERE resource_id=?").get(e);return t?Ie(t):void 0}getBySlug(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM compose_applications WHERE project_id=? AND environment_id=? AND slug=?").get(e,t,r);return n?Ie(n):void 0}list(e={}){return this.controlPlane.database.query("SELECT * FROM compose_applications ORDER BY updated_at DESC").all().map(Ie).filter((t)=>(!e.projectId||t.projectId===e.projectId)&&(!e.environmentId||t.environmentId===e.environmentId)&&(e.includeDeleted||t.status!=="deleted"))}services(e){return this.controlPlane.database.query("SELECT * FROM compose_service_states WHERE application_id=? ORDER BY service_name").all(e).map(Un)}transition(e,t,r={}){let n=this.get(e);if(!n)throw Error(`Compose application ${e} was not found`);let o=this.now().toISOString(),i=t==="deleted"?o:null;this.controlPlane.database.run("UPDATE compose_applications SET status=?, latest_operation_id=COALESCE(?, latest_operation_id), version=version+1, updated_at=?, deleted_at=? WHERE id=?",[t,r.operationId??null,o,i,e]);for(let s of r.services??[])if(n.manifest.spec.services[s.name])this.controlPlane.database.run("INSERT INTO compose_service_states (application_id, service_name, status, replicas, healthy_replicas, latest_operation_id, observed_state, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(application_id, service_name) DO UPDATE SET status=excluded.status, replicas=excluded.replicas, healthy_replicas=excluded.healthy_replicas, latest_operation_id=excluded.latest_operation_id, observed_state=excluded.observed_state, updated_at=excluded.updated_at",[e,s.name,s.status,s.replicas??n.manifest.spec.services[s.name].replicas,s.healthyReplicas??0,r.operationId??null,JSON.stringify(h(s.observedState??{})),o]);return this.controlPlane.appendEvent({projectId:n.projectId,resourceId:n.resourceId,operationId:r.operationId,type:`compose.application.${t}`,level:t==="failed"||t==="degraded"?"error":"info",payload:{applicationId:e,error:r.error??null}}),this.get(e)}}class Je{controlPlane;applications;queue;constructor(e){this.controlPlane=e;this.applications=new gt(e),this.queue=new S(e)}enqueue(e,t,r={}){if(e.status==="deleted")throw Error("Deleted Compose applications cannot be operated");if(r.service&&!e.manifest.spec.services[r.service])throw Error(`Compose service ${r.service} was not found`);if(t==="delete"){let o=r.removeVolumes?`${e.slug} delete volumes`:e.slug;if(r.confirmation!==o)throw Error(`Type ${o} to confirm ${r.removeVolumes?"persistent data removal":"stack deletion"}`)}if(t==="scale"&&(!r.service||!Number.isInteger(r.replicas)||r.replicas<0||r.replicas>100))throw Error("Scale requires a service and 0-100 replicas");let n=this.queue.enqueue({projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:r.actorId,kind:`compose.${t}`,idempotencyKey:`compose:${e.id}:${t}:${r.service??"stack"}:${r.replicas??""}:${e.version}`,correlationId:`compose:${e.id}`,input:{applicationId:e.id,service:r.service??null,replicas:r.replicas??null,removeVolumes:!!r.removeVolumes},lockKey:`compose:${e.id}`,providerKey:this.controlPlane.getResource(e.resourceId)?.provider??"default",buildSlot:t==="deploy"||t==="redeploy",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.applications.transition(e.id,t==="delete"?"deleting":t==="stop"?"stopped":t==="start"?"deploying":t==="scale"?e.status:"deploying",{operationId:n.id}),n}}import{createHash as Fn}from"node:crypto";var Hn=/^[a-f0-9]{40,64}$/i,Qn=/^[A-Z][A-Z0-9_]{1,127}$/;function L(e){return typeof e==="string"&&e?e:void 0}function J(e){try{return JSON.parse(String(e))}catch{return{}}}function Jn(e){let t=J(e);return Array.isArray(t)?t.map(String):[]}function Ge(e){return{id:String(e.id),projectId:String(e.project_id),resourceId:String(e.resource_id),baseEnvironmentId:String(e.base_environment_id),enabled:Number(e.enabled)===1,branchRule:L(e.branch_rule),domainPattern:String(e.domain_pattern),ttlHours:Number(e.ttl_hours),keepCount:Number(e.keep_count),publicAccess:Number(e.public_access)===1,authenticationRequired:Number(e.authentication_required)===1,allowForks:Number(e.allow_forks)===1,inheritedSecrets:Jn(e.inherited_secrets),resourceOverrides:J(e.resource_overrides),databaseStrategy:String(e.database_strategy),maxMonthlyCost:Number(e.max_monthly_cost),maxCpu:Number(e.max_cpu),maxMemoryMb:Number(e.max_memory_mb),cleanupOnClose:Number(e.cleanup_on_close)===1,version:Number(e.version),createdByActorId:L(e.created_by_actor_id),createdAt:String(e.created_at),updatedAt:String(e.updated_at)}}function ce(e){return{id:String(e.id),definitionId:String(e.definition_id),projectId:String(e.project_id),resourceId:String(e.resource_id),baseEnvironmentId:String(e.base_environment_id),identityKey:String(e.identity_key),sourceProvider:L(e.source_provider),repository:L(e.repository),branch:String(e.branch),pullRequestNumber:e.pull_request_number==null?void 0:Number(e.pull_request_number),fork:Number(e.fork)===1,commitSha:String(e.commit_sha),name:String(e.name),stackName:String(e.stack_name),url:L(e.url),status:String(e.status),expiresAt:String(e.expires_at),latestOperationId:L(e.latest_operation_id),createdByActorId:L(e.created_by_actor_id),costEstimate:e.cost_estimate==null?void 0:Number(e.cost_estimate),desiredState:J(e.desired_state),observedState:J(e.observed_state),teardownError:L(e.teardown_error),version:Number(e.version),createdAt:String(e.created_at),updatedAt:String(e.updated_at),destroyedAt:L(e.destroyed_at)}}function Zt(e){return{id:String(e.id),previewId:String(e.preview_id),provider:String(e.provider),providerResourceId:String(e.provider_resource_id),kind:String(e.kind),tags:J(e.tags),observedState:J(e.observed_state),discoveredAt:String(e.discovered_at),deletedAt:L(e.deleted_at)}}function q(e,t,r,n){return Number.isFinite(e)?Math.min(n,Math.max(r,Math.floor(e))):t}function _e(e,t,r,n){return Number.isFinite(e)?Math.min(n,Math.max(r,e)):t}function Ze(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,28)||"preview"}class Me{controlPlane;now;id;constructor(e,t={}){this.controlPlane=e;this.now=t.now??(()=>new Date),this.id=t.id??(()=>crypto.randomUUID())}createDefinition(e){let t=this.controlPlane.getResource(e.resourceId),r=this.controlPlane.listEnvironments(e.projectId).find((c)=>c.id===e.baseEnvironmentId);if(!t||t.projectId!==e.projectId||t.environmentId!==r?.id)throw Error("Preview resource and base environment must belong to the same project scope");if(t.kind!=="application")throw Error("Preview environments currently support application resources only");if(!/^https:\/\//.test(e.domainPattern)||!e.domainPattern.includes("{name}"))throw Error("Preview domainPattern must be HTTPS and include {name}");let n=this.getDefinitionForResource(e.resourceId),o=e.publicAccess??n?.publicAccess??!1,i=e.authenticationRequired??n?.authenticationRequired??!0;if(o&&!i)throw Error("Public preview environments require an authentication policy");let s=[...new Set(e.inheritedSecrets??[])];if(s.some((c)=>!Qn.test(c)))throw Error("Inherited preview secret names must use uppercase environment-variable identifiers");let a=this.now().toISOString();if(n)return this.controlPlane.database.run("UPDATE preview_definitions SET base_environment_id=?, enabled=1, branch_rule=?, domain_pattern=?, ttl_hours=?, keep_count=?, public_access=?, authentication_required=?, allow_forks=?, inherited_secrets=?, resource_overrides=?, database_strategy=?, max_monthly_cost=?, max_cpu=?, max_memory_mb=?, cleanup_on_close=?, version=version+1, updated_at=? WHERE id=?",[e.baseEnvironmentId,e.branchRule??null,e.domainPattern,q(e.ttlHours,n.ttlHours,1,720),q(e.keepCount,n.keepCount,1,100),o?1:0,i?1:0,e.allowForks??n.allowForks?1:0,JSON.stringify(e.inheritedSecrets===void 0?n.inheritedSecrets:s),JSON.stringify(h(e.resourceOverrides??n.resourceOverrides)),e.databaseStrategy??n.databaseStrategy,_e(e.maxMonthlyCost,n.maxMonthlyCost,0,1e4),_e(e.maxCpu,n.maxCpu,0.1,64),q(e.maxMemoryMb,n.maxMemoryMb,128,131072),e.cleanupOnClose??n.cleanupOnClose?1:0,a,n.id]),this.controlPlane.appendEvent({projectId:e.projectId,resourceId:e.resourceId,actorId:e.createdByActorId,type:"preview.definition.updated",payload:{definitionId:n.id,baseEnvironmentId:e.baseEnvironmentId,version:n.version+1}}),this.getDefinition(n.id);let d=this.id();return this.controlPlane.database.run("INSERT INTO preview_definitions (id, project_id, resource_id, base_environment_id, enabled, branch_rule, domain_pattern, ttl_hours, keep_count, public_access, authentication_required, allow_forks, inherited_secrets, resource_overrides, database_strategy, max_monthly_cost, max_cpu, max_memory_mb, cleanup_on_close, created_by_actor_id, created_at, updated_at) VALUES (?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[d,e.projectId,e.resourceId,e.baseEnvironmentId,e.branchRule??null,e.domainPattern,q(e.ttlHours,24,1,720),q(e.keepCount,10,1,100),e.publicAccess?1:0,e.authenticationRequired===!1?0:1,e.allowForks?1:0,JSON.stringify(s),JSON.stringify(h(e.resourceOverrides??{})),e.databaseStrategy??"disabled",_e(e.maxMonthlyCost,25,0,1e4),_e(e.maxCpu,1,0.1,64),q(e.maxMemoryMb,1024,128,131072),e.cleanupOnClose===!1?0:1,e.createdByActorId??null,a,a]),this.controlPlane.appendEvent({projectId:e.projectId,resourceId:e.resourceId,actorId:e.createdByActorId,type:"preview.definition.created",payload:{definitionId:d,baseEnvironmentId:e.baseEnvironmentId,ttlHours:q(e.ttlHours,24,1,720),inheritedSecretNames:s}}),this.getDefinition(d)}getDefinition(e){let t=this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE id=?").get(e);return t?Ge(t):void 0}getDefinitionForResource(e){let t=this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE resource_id=?").get(e);return t?Ge(t):void 0}listDefinitions(e){return this.controlPlane.database.query("SELECT * FROM preview_definitions WHERE project_id=? ORDER BY updated_at DESC").all(e).map(Ge)}listInstances(e={}){return this.controlPlane.database.query("SELECT * FROM preview_instances ORDER BY created_at DESC").all().map(ce).filter((r)=>(!e.projectId||r.projectId===e.projectId)&&(!e.definitionId||r.definitionId===e.definitionId)&&(!e.status||r.status===e.status))}getInstance(e){let t=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE id=?").get(e);return t?ce(t):void 0}findForPullRequest(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(e,`pr:${t}:${r}`);return n?ce(n):void 0}findForBranch(e,t,r){let n=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(e,`branch:${t}:${r}`);return n?ce(n):void 0}upsert(e){let t=this.getDefinition(e.definitionId);if(!t?.enabled)throw Error("Preview environments are not enabled for this application");if(!Hn.test(e.commitSha))throw Error("Preview deployment requires an immutable 40-64 character commit SHA");if(e.fork&&!t.allowForks)throw Error("Untrusted fork previews are disabled");let r=e.pullRequestNumber?`pr:${e.repository??"unknown"}:${e.pullRequestNumber}`:`branch:${e.repository??"local"}:${e.branch}`,n=Fn("sha256").update(`${t.id}:${r}`).digest("hex").slice(0,8),i=`${(e.pullRequestNumber?`pr-${e.pullRequestNumber}`:Ze(e.branch)).slice(0,28)}-${n}`,s=`preview-${i}`.slice(0,63),a=t.domainPattern.replaceAll("{name}",i).replaceAll("{project}",Ze(t.projectId)).replaceAll("{branch}",Ze(e.branch)).replaceAll("{pr}",String(e.pullRequestNumber??"branch")),d=e.now??this.now(),c=d.toISOString(),u=new Date(d.getTime()+t.ttlHours*60*60*1000).toISOString(),p=this.controlPlane.database.query("SELECT * FROM preview_instances WHERE definition_id=? AND identity_key=?").get(t.id,r);if(p){let g=ce(p),y=g.commitSha!==e.commitSha||g.status==="destroyed";if(y)this.controlPlane.database.run("UPDATE preview_instances SET commit_sha=?, branch=?, fork=?, status='queued', expires_at=?, url=?, teardown_error=NULL, destroyed_at=NULL, version=version+1, updated_at=? WHERE id=?",[e.commitSha,e.branch,e.fork?1:0,u,a,c,g.id]);return{preview:this.getInstance(g.id),created:!1,changed:y,inheritedSecrets:e.fork?[]:t.inheritedSecrets}}let l=this.id(),f=h({source:{provider:e.sourceProvider??null,repository:e.repository??null,branch:e.branch,commitSha:e.commitSha,pullRequestNumber:e.pullRequestNumber??null,fork:!!e.fork},policy:{databaseStrategy:t.databaseStrategy,resourceOverrides:t.resourceOverrides,maxMonthlyCost:t.maxMonthlyCost,maxCpu:t.maxCpu,maxMemoryMb:t.maxMemoryMb,publicAccess:t.publicAccess,authenticationRequired:t.authenticationRequired},inheritedSecretNames:e.fork?[]:t.inheritedSecrets});return this.controlPlane.database.run("INSERT INTO preview_instances (id, definition_id, project_id, resource_id, base_environment_id, identity_key, source_provider, repository, branch, pull_request_number, fork, commit_sha, name, stack_name, url, status, expires_at, created_by_actor_id, desired_state, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'queued', ?, ?, ?, ?, ?)",[l,t.id,t.projectId,t.resourceId,t.baseEnvironmentId,r,e.sourceProvider??null,e.repository??null,e.branch,e.pullRequestNumber??null,e.fork?1:0,e.commitSha,i,s,a,u,e.createdByActorId??null,JSON.stringify(f),c,c]),this.controlPlane.appendEvent({projectId:t.projectId,resourceId:t.resourceId,actorId:e.createdByActorId,type:"preview.created",payload:{previewId:l,identityKey:r,commitSha:e.commitSha,expiresAt:u,fork:!!e.fork}}),{preview:this.getInstance(l),created:!0,changed:!0,inheritedSecrets:e.fork?[]:t.inheritedSecrets}}transition(e,t,r={}){let n=this.getInstance(e);if(!n)throw Error(`Preview ${e} was not found`);let o=this.now().toISOString(),i=t==="destroyed"?o:null;return this.controlPlane.database.run("UPDATE preview_instances SET status=?, latest_operation_id=COALESCE(?, latest_operation_id), observed_state=?, teardown_error=?, cost_estimate=COALESCE(?, cost_estimate), destroyed_at=?, version=version+1, updated_at=? WHERE id=?",[t,r.operationId??null,JSON.stringify(h(r.observedState??n.observedState)),r.teardownError??null,r.costEstimate??null,i,o,e]),this.controlPlane.appendEvent({projectId:n.projectId,resourceId:n.resourceId,operationId:r.operationId,type:`preview.${t}`,level:t==="failed"||t==="cleanup_failed"?"error":"info",payload:{previewId:e,commitSha:n.commitSha,teardownError:r.teardownError??null}}),this.getInstance(e)}extend(e,t){let r=this.getInstance(e),n=r?this.getDefinition(r.definitionId):void 0;if(!r||!n)throw Error(`Preview ${e} was not found`);let o=this.now(),i=q(t,n.ttlHours,1,720),s=new Date(Math.max(o.getTime(),new Date(r.expiresAt).getTime())+i*3600000).toISOString();return this.controlPlane.database.run("UPDATE preview_instances SET expires_at=?, version=version+1, updated_at=? WHERE id=?",[s,o.toISOString(),e]),this.getInstance(e)}expired(e=this.now()){return this.listInstances().filter((t)=>["queued","deploying","active","updating","failed","cleanup_failed"].includes(t.status)&&new Date(t.expiresAt)<=e)}recordResource(e){let t=this.getInstance(e.previewId);if(!t)throw Error(`Preview ${e.previewId} was not found`);let r={"ts-cloud:preview":t.id,"ts-cloud:project":t.projectId,"ts-cloud:expires-at":t.expiresAt};for(let[s,a]of Object.entries(r))if(e.tags[s]!==a)throw Error(`Preview resource is missing immutable tag ${s}`);let n=this.id(),o=this.now().toISOString();this.controlPlane.database.run("INSERT INTO preview_resources (id, preview_id, provider, provider_resource_id, kind, tags, observed_state, discovered_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(preview_id, provider, provider_resource_id) DO UPDATE SET kind=excluded.kind, tags=excluded.tags, observed_state=excluded.observed_state, deleted_at=NULL",[n,t.id,e.provider,e.providerResourceId,e.kind,JSON.stringify(e.tags),JSON.stringify(h(e.observedState??{})),o]);let i=this.controlPlane.database.query("SELECT * FROM preview_resources WHERE preview_id=? AND provider=? AND provider_resource_id=?").get(t.id,e.provider,e.providerResourceId);return Zt(i)}listResources(e){return this.controlPlane.database.query("SELECT * FROM preview_resources WHERE preview_id=? ORDER BY kind, provider_resource_id").all(e).map(Zt)}markResourcesDeleted(e){if(!this.getInstance(e))throw Error(`Preview ${e} was not found`);return this.controlPlane.database.run("UPDATE preview_resources SET deleted_at=? WHERE preview_id=? AND deleted_at IS NULL",[this.now().toISOString(),e]).changes}}class Xe{controlPlane;previews;queue;constructor(e){this.controlPlane=e;this.previews=new Me(e),this.queue=new S(e)}enqueueDeploy(e,t={}){let r=t.created?"preview.create":"preview.update",n=t.reason==="manual_rebuild"?`:${crypto.randomUUID()}`:"",o=this.queue.enqueue({projectId:e.projectId,environmentId:e.baseEnvironmentId,resourceId:e.resourceId,actorId:t.actorId,kind:r,correlationId:`preview:${e.id}`,idempotencyKey:`preview:${e.id}:${e.commitSha}${n}`,input:{previewId:e.id,reason:t.reason??(t.created?"create":"commit_update"),source:{repository:e.repository??null,branch:e.branch,commitSha:e.commitSha,pullRequestNumber:e.pullRequestNumber??null,fork:e.fork}},lockKey:`preview:${e.id}`,providerKey:"preview",buildSlot:!0,maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.previews.transition(e.id,"queued",{operationId:o.id}),o}enqueueDestroy(e,t,r){if(e.status==="destroyed")throw Error("Preview is already destroyed");let n=this.queue.enqueue({projectId:e.projectId,environmentId:e.baseEnvironmentId,resourceId:e.resourceId,actorId:r,kind:"preview.destroy",correlationId:`preview:${e.id}`,idempotencyKey:`preview:${e.id}:destroy:${t}`,input:{previewId:e.id,reason:t},lockKey:`preview:${e.id}`,providerKey:"preview",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.previews.transition(e.id,"queued",{operationId:n.id}),n}cleanup(e={}){let t=e.now??new Date,r=new Map,n=this.previews.listInstances().filter((d)=>!["destroyed","destroying"].includes(d.status)),o=(d,c)=>{let u=r.get(d.id)??{preview:d,reasons:[]};if(!u.reasons.includes(c))u.reasons.push(c);r.set(d.id,u)};for(let d of n){if(new Date(d.expiresAt)<=t)o(d,"ttl_expired");if(e.maxAgeHours&&t.getTime()-new Date(d.createdAt).getTime()>=e.maxAgeHours*3600000)o(d,"max_age")}let i=new Map;for(let d of n)i.set(d.definitionId,[...i.get(d.definitionId)??[],d]);for(let[d,c]of i){let u=this.previews.getDefinition(d),p=e.keepCount??u?.keepCount;if(!p)continue;c.sort((l,f)=>f.createdAt.localeCompare(l.createdAt)).slice(p).forEach((l)=>o(l,"keep_count"))}let s=[...r.values()].sort((d,c)=>d.preview.createdAt.localeCompare(c.preview.createdAt)),a=e.dryRun?[]:s.map((d)=>this.enqueueDestroy(d.preview,d.reasons.sort().join("+"),e.actorId));if(s.length)this.controlPlane.appendEvent({actorId:e.actorId,type:e.dryRun?"preview.cleanup.planned":"preview.cleanup.queued",payload:{previewIds:s.map((d)=>d.preview.id),reasons:Object.fromEntries(s.map((d)=>[d.preview.id,d.reasons])),dryRun:!!e.dryRun}});return{candidates:s,operations:a,dryRun:!!e.dryRun}}reconcile(e){let t=[],r=[],n=[];for(let o of e){let i=o.tags["ts-cloud:preview"],s=o.tags["ts-cloud:project"],a=o.tags["ts-cloud:expires-at"];if(!i||!s||!a){n.push(o.providerResourceId);continue}let d=this.previews.getInstance(i);if(!d||d.projectId!==s||d.expiresAt!==a){r.push(o.providerResourceId);continue}if(this.previews.recordResource({...o,previewId:d.id}),o.estimatedMonthlyCost!==void 0)this.previews.transition(d.id,d.status,{costEstimate:o.estimatedMonthlyCost,observedState:{...d.observedState,lastReconciledAt:new Date().toISOString()}});t.push(o.providerResourceId)}if(r.length)this.controlPlane.appendEvent({type:"preview.reconciliation.leaks",level:"error",payload:{providerResourceIds:r}});return{matched:t,unknownPreviewResources:r,ignoredUntagged:n}}}var Wn=["deployment.create","deployment.rollback","application.create","deploy.source","deploy.preview","preview.create","preview.update","preview.destroy","compose.deploy","compose.redeploy","compose.start","compose.stop","compose.delete","compose.scale"];function Ee(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:{}}function Kn(e,t){if(!t.projectId||!t.environmentId)throw Error(`Queued ${t.kind} operation is missing its project or environment scope`);let r=e.listEnvironments(t.projectId).find((s)=>s.id===t.environmentId);if(!r)throw Error(`Environment ${t.environmentId} was not found for queued ${t.kind} operation`);let n=t.resourceId?e.getResource(t.resourceId):void 0;if(t.resourceId&&(!n||n.projectId!==t.projectId||n.environmentId!==t.environmentId))throw Error(`Resource ${t.resourceId} was not found in the queued deployment scope`);let o=Ee(t.input);if(t.kind.startsWith("compose.")){let s=typeof o.applicationId==="string"?o.applicationId:void 0,a=s?new gt(e).get(s):t.resourceId?new gt(e).getByResource(t.resourceId):void 0;if(!a||a.projectId!==t.projectId||a.environmentId!==t.environmentId||a.resourceId!==t.resourceId)throw Error("Queued Compose application does not match the operation scope");let d=t.kind.slice(8),c=["compose:apply",a.id,"--action",d,"--env",r.slug];if(typeof o.service==="string"&&o.service)c.push("--service",o.service);if(typeof o.replicas==="number")c.push("--replicas",String(o.replicas));if(o.removeVolumes===!0)c.push("--remove-volumes");return{id:`queue:${t.id}`,label:`${d[0].toUpperCase()}${d.slice(1)} Compose application`,description:`${d} ${a.name}.`,command:c,mutates:!0,target:{environment:r.slug,resource:n?.slug,composeId:a.id}}}if(t.kind.startsWith("preview.")){let s=typeof o.previewId==="string"?o.previewId:void 0,a=s?new Me(e).getInstance(s):void 0;if(!a)throw Error(`Preview ${s??"(missing)"} was not found for queued ${t.kind}`);if(a.projectId!==t.projectId||a.resourceId!==t.resourceId)throw Error("Queued preview does not match the operation scope");if(t.kind==="preview.destroy")return{id:`queue:${t.id}`,label:"Destroy preview",description:`Destroy ${a.name}.`,command:["stack:delete",a.stackName,"--yes"],mutates:!0,target:{environment:r.slug,resource:n?.slug,previewId:a.id}};return{id:`queue:${t.id}`,label:t.kind==="preview.create"?"Create preview":"Update preview",description:`Deploy ${a.name} at ${a.commitSha}.`,command:["deploy","--stack",a.stackName,"--env",r.slug,"--yes","--skip-dns-verification",...n?["--site",n.slug]:[]],mutates:!0,target:{environment:r.slug,resource:n?.slug,previewId:a.id}}}if(t.kind==="deployment.rollback"){let s=["deploy:rollback"];if(n)s.push(n.slug);if(s.push("--env",r.slug),typeof o.revision==="string"&&o.revision)s.push("--to",o.revision);return{id:`queue:${t.id}`,label:"Rollback deployment",description:`Roll back ${n?.slug??r.slug}.`,command:s,mutates:!0,target:{environment:r.slug,resource:n?.slug}}}let i=["deploy","--env",r.slug,"--yes"];if(n)i.push("--site",n.slug);return{id:`queue:${t.id}`,label:t.kind==="deploy.preview"?"Deploy preview":"Deploy release",description:`Deploy ${n?.slug??r.slug}.`,command:i,mutates:!0,target:{environment:r.slug,resource:n?.slug}}}function Gn(e){let t=e.stderr?.trim()||`Deployment process exited with code ${e.exitCode}`;if(/\b(?:429|rate.?limit|throttl)/i.test(t))return new Le(t,"provider_throttled");if(/\b(?:502|503|504|temporar(?:y|ily)|unavailable|provider.?error)/i.test(t))return new Le(t,"provider_unavailable");if(/\b(?:network|econn|enotfound|socket|timed?\s*out|fetch failed|dns)\b/i.test(t))return new Le(t,"network");return Error(t)}function Cc(e){let t=async(r)=>{r.checkpoint("prepare","Resolving the persisted deployment target.");let n=Kn(e.store,r.operation),o=n.target.previewId?new Me(e.store):void 0,i=n.target.composeId?new gt(e.store):void 0;if(o&&n.target.previewId)o.transition(n.target.previewId,r.operation.kind==="preview.destroy"?"destroying":r.operation.kind==="preview.update"?"updating":"deploying",{operationId:r.operation.id});if(i&&n.target.composeId)i.transition(n.target.composeId,r.operation.kind==="compose.delete"?"deleting":r.operation.kind==="compose.stop"?"stopped":"deploying",{operationId:r.operation.id});r.log(`Target: ${n.target.resource??"all resources"} in ${n.target.environment}.`,{stream:"system"}),r.throwIfCancellationRequested(),r.checkpoint("execute",`Running cloud ${n.command.join(" ")}.`);let s=await e.execute(n,r);if(!s.ok){if(o&&n.target.previewId)o.transition(n.target.previewId,r.operation.kind==="preview.destroy"?"cleanup_failed":"failed",{operationId:r.operation.id,teardownError:r.operation.kind==="preview.destroy"?s.stderr?.trim()||`Process exited with ${s.exitCode}`:void 0});if(i&&n.target.composeId)i.transition(n.target.composeId,r.operation.kind==="compose.delete"?"degraded":"failed",{operationId:r.operation.id,error:s.stderr?.trim()||`Process exited with ${s.exitCode}`});throw Gn(s)}if(r.throwIfCancellationRequested(),o&&n.target.previewId){let a=o.getInstance(n.target.previewId);if(r.operation.kind==="preview.destroy")o.markResourcesDeleted(a.id),o.transition(a.id,"destroyed",{operationId:r.operation.id,observedState:{reconciledResourceIds:o.listResources(a.id).map((d)=>d.providerResourceId),exactCommitSha:a.commitSha}});else{let d=e.store.getResource(a.resourceId)?.provider??"default";o.recordResource({previewId:a.id,provider:d,providerResourceId:a.stackName,kind:"stack",tags:{"ts-cloud:preview":a.id,"ts-cloud:project":a.projectId,"ts-cloud:expires-at":a.expiresAt},observedState:{command:s.command??null,exactCommitSha:a.commitSha}}),o.transition(a.id,"active",{operationId:r.operation.id,observedState:{url:a.url??null,stackName:a.stackName,exactCommitSha:a.commitSha,providerStatus:"deployed"}})}}if(i&&n.target.composeId){let a=i.get(n.target.composeId),d=typeof Ee(r.operation.input).service==="string"?String(Ee(r.operation.input).service):void 0,c=r.operation.kind==="compose.delete"?"deleted":r.operation.kind==="compose.stop"?"stopped":"running",u=i.transition(a.id,c,{operationId:r.operation.id,services:Object.values(a.manifest.spec.services).filter((p)=>!d||p.name===d).map((p)=>({name:p.name,status:c==="stopped"||c==="deleted"?"stopped":"running",replicas:c==="deleted"?0:p.replicas,healthyReplicas:c==="running"?p.replicas:0,observedState:{command:s.command??null,healthGatePassed:c==="running"}}))});if(c==="deleted")Yt(e.store,u,Ee(r.operation.input).removeVolumes===!0)}return r.checkpoint("finalize","Deployment command completed; persisting the terminal result."),{command:s.command??`cloud ${n.command.join(" ")}`,exitCode:s.exitCode,environment:n.target.environment,resource:n.target.resource??null}};return Object.fromEntries(Wn.map((r)=>[r,t]))}class m extends Error{code;status;details;constructor(e,t,r,n){super(t);this.code=e;this.status=r;this.details=n}}function et(e,t){if(e.organizationId!==t.organizationId)return!1;if(e.projectId&&e.projectId!==t.projectId)return!1;if(e.environmentId&&e.environmentId!==t.environmentId)return!1;if(e.resourceId&&e.resourceId!==t.resourceId)return!1;return!0}function Zn(e,t,r){return Yn("sha256").update(`${e.toUpperCase()}
110
110
  ${t}
111
- ${JSON.stringify(r)}`).digest("hex")}class go{controlPlane;identities;queue;spendGate;constructor(e,t){this.controlPlane=e;this.identities=t;this.queue=new S(e),this.spendGate=new Mt(e)}target(e,t){let r=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,t),n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope);if(!r||!n||!et(n,r))throw new m("forbidden","The token does not grant access to this resource.",403);return r}authorize(e,t,r){if(!e.token.capabilities.includes(t))throw new m("forbidden",`The token is missing the ${t} capability.`,403);let n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,r),o=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope),i=t==="project:read"&&!!n&&!!o&&et(n,o);if(!n||!o||!et(o,n)&&!i)throw new m("forbidden","The token does not grant access to this resource.",403);let s=i?o:n;if(!re({membership:e.membership,grants:this.controlPlane.listGrants(e.membership.id),capability:t,target:s}).allowed)throw new m("forbidden","The service account does not have access to this resource.",403);return n}listProjects(e){return this.controlPlane.listProjects().filter((t)=>t.organizationId===e.serviceAccount.organizationId).filter((t)=>{try{return this.authorize(e,"project:read",{type:"project",id:t.id}),!0}catch{return!1}}).map((t)=>({id:t.id,slug:t.slug,name:t.name,description:t.description,version:t.version,createdAt:t.createdAt,updatedAt:t.updatedAt}))}listEnvironments(e,t){let r=this.controlPlane.getProject(t);if(!r||r.organizationId!==e.serviceAccount.organizationId)throw new m("not_found","Project was not found.",404);return this.controlPlane.listEnvironments(t).filter((n)=>{try{return this.authorize(e,"project:read",{type:"environment",id:n.id}),!0}catch{return!1}}).map((n)=>({id:n.id,projectId:n.projectId,slug:n.slug,name:n.name,kind:n.kind,region:n.region,version:n.version,createdAt:n.createdAt,updatedAt:n.updatedAt}))}listServices(e,t,r){let n=new Set(this.listEnvironments(e,t).map((o)=>String(o.id)));if(r&&!n.has(r))throw new m("not_found","Environment was not found.",404);return this.controlPlane.listResources(t,r).filter((o)=>!o.environmentId||n.has(o.environmentId)).filter((o)=>{try{return this.authorize(e,"project:read",{type:"resource",id:o.id}),!0}catch{return!1}}).map((o)=>({id:o.id,projectId:o.projectId,environmentId:o.environmentId,kind:o.kind,slug:o.slug,name:o.name,provider:o.provider,providerId:o.providerId,metadata:h(o.metadata),version:o.version,createdAt:o.createdAt,updatedAt:o.updatedAt}))}listOperations(e,t){return this.controlPlane.listOperations({projectId:t,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.environmentId?{type:"environment",id:n.environmentId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.authorize(e,"deployments:read",o),!0}catch{return!1}}).map((n)=>this.operation(n))}listEvents(e,t,r){if(t)this.authorize(e,"audit:read",{type:"project",id:t});else this.authorize(e,"audit:read",e.token.scope);return this.controlPlane.listEvents({organizationId:e.serviceAccount.organizationId,projectId:t,afterSequence:r,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.target(e,o),!0}catch{return!1}}).map((n)=>({id:n.id,sequence:n.sequence,projectId:n.projectId,operationId:n.operationId,resourceId:n.resourceId,correlationId:n.correlationId,type:n.type,level:n.level,payload:h(n.payload),createdAt:n.createdAt}))}createDeployment(e,t,r){if(!this.controlPlane.listEnvironments(t.projectId).find((u)=>u.id===t.environmentId))throw new m("not_found","Environment was not found in this project.",404);let o=t.serviceId?{type:"resource",id:t.serviceId}:{type:"environment",id:t.environmentId};this.authorize(e,"deployments:create",o);let i=this.spendGate.check("deploy",{organizationId:e.serviceAccount.organizationId,projectId:t.projectId,environmentId:t.environmentId});if(!i.allowed)throw new m("spend_cap_exceeded",i.reason??"A spend cap is blocking deployments.",402,{action:i.action,budgetId:i.budgetId});let s=Zn("POST","/api/v1/deployments",t),a=this.identities.getIdempotency(e.token.id,r);if(a){if(a.requestHash!==s)throw new m("idempotency_conflict","Idempotency-Key was already used for another request.",409);let u=a.operationId?this.controlPlane.getOperation(a.operationId):void 0;if(!u)throw new m("idempotency_unavailable","The original operation is no longer available.",409);return{operation:this.operation(u),replay:!0}}if(t.serviceId){let u=this.controlPlane.getResource(t.serviceId);if(!u||u.projectId!==t.projectId||u.environmentId!==t.environmentId)throw new m("not_found","Service was not found in this environment.",404)}let d=t.serviceId?this.controlPlane.getResource(t.serviceId):void 0,c=this.queue.enqueue({projectId:t.projectId,environmentId:t.environmentId,resourceId:t.serviceId,actorId:e.actor.id,kind:t.action==="rollback"?"deployment.rollback":"deployment.create",idempotencyKey:`api:${e.token.id}:${r}`,input:h({action:t.action??"deploy",revision:t.revision??null}),lockKey:t.serviceId?`resource:${t.serviceId}`:`environment:${t.environmentId}`,providerKey:d?.provider??"default",buildSlot:t.action!=="rollback",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.identities.saveIdempotency({tokenId:e.token.id,key:r,requestHash:s,operationId:c.id,responseStatus:202,responseBody:{operationId:c.id}}),{operation:this.operation(c),replay:!1}}operation(e){return{id:e.id,state:e.state,kind:e.kind,projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:e.actorId,correlationId:e.correlationId,input:h(e.input),output:h(e.output),error:e.error,attempt:e.attempt,createdAt:e.createdAt,updatedAt:e.updatedAt,startedAt:e.startedAt,finishedAt:e.finishedAt}}}function we(e){return e.serviceAccount.organizationId}function Xt(e){if(e==null)return;if(e==="daily"||e==="weekly"||e==="monthly")return e;throw new m("validation_error","period must be daily, weekly, or monthly.",422)}function W(e,t){if(e==null)return;let r=Number(e);if(!Number.isFinite(r)||r<0||!Number.isInteger(r))throw new m("validation_error",`${t} must be a non-negative integer.`,422);return r}function T(e,t,r,n,o){if(o)e.authorization.authorize(t,r,{type:"environment",id:o});else if(n)e.authorization.authorize(t,r,{type:"project",id:n});else e.authorization.authorize(t,r,{type:"organization"});return{organizationId:we(t),projectId:n,environmentId:o}}async function Ps(e,t,r){let{method:n,url:o}=r,i=e.now?.()??new Date,s=o.searchParams.get("projectId")??void 0,a=o.searchParams.get("environmentId")??void 0;if(n==="GET"&&o.pathname==="/api/v1/usage"){let l=T(e,t,"billing:read",s,a);return e.service.usageReport({...l,period:Xt(o.searchParams.get("period")),timezone:o.searchParams.get("timezone")??void 0,now:i})}if(n==="GET"&&o.pathname==="/api/v1/usage/rollups"){let l=T(e,t,"billing:read",s,a),f=o.searchParams.get("from"),g=o.searchParams.get("to");if(!f||!g)throw new m("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(f))||Number.isNaN(Date.parse(g)))throw new m("validation_error","from and to must be ISO-8601 timestamps.",422);let y=o.searchParams.getAll("meter");return{data:e.store.listRollups({...l,from:f,to:g,meters:y.length>0?y:void 0},W(o.searchParams.get("limit"),"limit")??1000)}}if(n==="GET"&&o.pathname==="/api/v1/usage/focus"){let l=T(e,t,"billing:read",s,a),f=o.searchParams.get("from"),g=o.searchParams.get("to");if(!f||!g)throw new m("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(f))||Number.isNaN(Date.parse(g)))throw new m("validation_error","from and to must be ISO-8601 timestamps.",422);if(new Date(g).getTime()-new Date(f).getTime()>31622400000)throw new m("validation_error","The range must not exceed one year.",422);let y=o.searchParams.get("granularity")==="hourly"?"hourly":"daily",v=e.store.listRollups({...l,from:f,to:g},1e4),b=Mc(v,{billingPeriodStart:f,billingPeriodEnd:g,currency:e.store.priceBook.currency,granularity:y});return{contentType:"application/x-ndjson",body:As(b),recordCount:b.length}}if(n==="GET"&&o.pathname==="/api/v1/spend/budgets"){let l=T(e,t,"billing:read",s,a);return{data:e.store.listBudgets({organizationId:l.organizationId,projectId:l.projectId})}}if(n==="POST"&&o.pathname==="/api/v1/spend/budgets"){let l=await r.body?.()??{},g={organizationId:T(e,t,"billing:manage",l.projectId,l.environmentId).organizationId,projectId:l.projectId,environmentId:l.environmentId,name:String(l.name??"").trim(),period:Xt(l.period??"monthly")??"monthly",timezone:l.timezone,currency:l.currency,softLimitCents:W(l.softLimitCents,"softLimitCents"),hardLimitCents:W(l.hardLimitCents,"hardLimitCents"),thresholds:l.thresholds,meters:l.meters,graceSeconds:W(l.graceSeconds,"graceSeconds"),hysteresisPercent:l.hysteresisPercent,dryRun:l.dryRun!==!1,enabled:l.enabled};try{return{data:e.store.createBudget(g)}}catch(y){throw new m("validation_error",y instanceof Error?y.message:String(y),422)}}let d=/^\/api\/v1\/spend\/budgets\/([^/]+)$/.exec(o.pathname);if(d&&(n==="PATCH"||n==="DELETE")){let l=e.store.getBudget(decodeURIComponent(d[1]));if(!l||l.organizationId!==we(t))throw new m("not_found","Budget was not found.",404);if(T(e,t,"billing:manage",l.projectId,l.environmentId),n==="DELETE")return{data:{deleted:e.store.deleteBudget(l.id)}};let f=await r.body?.()??{};try{return{data:e.store.updateBudget(l.id,f,W(f.expectedVersion,"expectedVersion"))}}catch(g){let y=g instanceof Error?g.message:String(g);throw new m(y.includes("concurrently")?"conflict":"validation_error",y,y.includes("concurrently")?409:422)}}if(n==="GET"&&o.pathname==="/api/v1/spend/anomalies"){let l=T(e,t,"billing:read",s,a);return{data:e.store.listAnomalies({organizationId:l.organizationId,projectId:l.projectId,since:o.searchParams.get("since")??void 0,unacknowledgedOnly:o.searchParams.get("unacknowledged")==="true",limit:W(o.searchParams.get("limit"),"limit")})}}let c=/^\/api\/v1\/spend\/anomalies\/([^/]+)\/acknowledge$/.exec(o.pathname);if(c&&n==="POST"){let l=e.store.getAnomaly(decodeURIComponent(c[1]));if(!l||l.organizationId!==we(t))throw new m("not_found","Anomaly was not found.",404);return T(e,t,"billing:manage",l.projectId,l.environmentId),{data:{acknowledged:e.store.acknowledgeAnomaly(l.id)}}}if(n==="GET"&&o.pathname==="/api/v1/spend/signals")return T(e,t,"billing:read",s,a),{data:Lt};if(o.pathname==="/api/v1/spend/anomaly-configs"){if(n==="GET"){let l=T(e,t,"billing:read",s,a);return{data:e.service.anomalyConfigs.list({organizationId:l.organizationId,projectId:l.projectId})}}if(n==="POST"){let l=await r.body?.()??{},f=T(e,t,"billing:manage",l.projectId,l.environmentId);try{return{data:e.service.anomalyConfigs.upsert({organizationId:f.organizationId,projectId:l.projectId,environmentId:l.environmentId,signal:String(l.signal??""),enabled:l.enabled,sensitivity:l.sensitivity,seasonLength:l.seasonLength==null?void 0:Number(l.seasonLength),minAbsoluteDelta:l.minAbsoluteDelta==null?void 0:Number(l.minAbsoluteDelta),detectDrops:l.detectDrops,severity:l.severity})}}catch(g){throw new m("validation_error",g instanceof Error?g.message:String(g),422)}}}let u=/^\/api\/v1\/spend\/anomaly-configs\/([^/]+)$/.exec(o.pathname);if(u&&n==="DELETE"){let l=e.service.anomalyConfigs.get(decodeURIComponent(u[1]));if(!l||l.organizationId!==we(t))throw new m("not_found","Anomaly config was not found.",404);return T(e,t,"billing:manage",l.projectId,l.environmentId),{data:{deleted:e.service.anomalyConfigs.delete(l.id)}}}if(o.pathname==="/api/v1/spend/anomaly-silences"){if(n==="GET"){let l=T(e,t,"billing:read",s,a);return{data:e.service.anomalyConfigs.listSilences({organizationId:l.organizationId,projectId:l.projectId,includeExpired:o.searchParams.get("includeExpired")==="true"})}}if(n==="POST"){let l=await r.body?.()??{},f=T(e,t,"billing:manage",l.projectId);try{return{data:e.service.anomalyConfigs.silence({organizationId:f.organizationId,projectId:l.projectId,signal:l.signal,routePattern:l.routePattern,statusCode:l.statusCode==null?void 0:Number(l.statusCode),reason:String(l.reason??""),expiresAt:l.expiresAt})}}catch(g){throw new m("validation_error",g instanceof Error?g.message:String(g),422)}}}let p=/^\/api\/v1\/spend\/anomaly-silences\/([^/]+)$/.exec(o.pathname);if(p&&n==="DELETE")return T(e,t,"billing:manage",s),{data:{deleted:e.service.anomalyConfigs.removeSilence(decodeURIComponent(p[1]))}};if(n==="GET"&&o.pathname==="/api/v1/spend/enforcement"){let l=T(e,t,"billing:read",s,a);return{data:e.store.listEnforcements({organizationId:l.organizationId,activeOnly:o.searchParams.get("active")!=="false"})}}if(n==="GET"&&o.pathname==="/api/v1/spend/allowance"){let l=T(e,t,"billing:read",s,a),f=o.searchParams.get("operation")??"deploy";if(!["build","deploy","function_invoke","request"].includes(f))throw new m("validation_error","operation must be build, deploy, function_invoke, or request.",422);let y=e.store.listEnforcements({organizationId:l.organizationId,activeOnly:!0}).filter((_)=>(!_.projectId||_.projectId===l.projectId)&&(!_.environmentId||_.environmentId===l.environmentId)),v=Oc(f,y),I=e.store.budgetsForScope(l.organizationId,l.projectId,l.environmentId).map((_)=>e.service.status(_,i));return{operation:f,allowed:v.allowed,blockedBy:v.blockedBy??null,reason:v.reason??null,budgets:I.map((_)=>({id:_.budget.id,name:_.budget.name,usedPercent:_.decision.usedPercent,projectedPercent:_.decision.projectedPercent,level:_.decision.level,timeToCap:_.timeToCap}))}}return}function Ds(){let e=[{name:"projectId",in:"query",schema:{type:"string"}},{name:"environmentId",in:"query",schema:{type:"string"}}];return{"/api/v1/usage":{get:{summary:"Current usage, cost, and every budget governing the scope.",parameters:[...e,{name:"period",in:"query",schema:{type:"string",enum:["daily","weekly","monthly"]}},{name:"timezone",in:"query",schema:{type:"string"}}],responses:{"200":{description:"Usage totals, per-meter breakdown, hourly series, and budget status."}}}},"/api/v1/usage/rollups":{get:{summary:"Itemized hourly usage rollups.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"meter",in:"query",schema:{type:"array",items:{type:"string"}}},{name:"limit",in:"query",schema:{type:"integer"}}],responses:{"200":{description:"Hourly rollups, newest first."}}}},"/api/v1/usage/focus":{get:{summary:"Usage and cost in FOCUS v1.3 format, newline-delimited JSON.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"granularity",in:"query",schema:{type:"string",enum:["daily","hourly"]}}],responses:{"200":{description:"FOCUS records, one JSON object per line."}}}},"/api/v1/spend/budgets":{get:{summary:"Budgets governing a scope.",parameters:e,responses:{"200":{description:"Budgets."}}},post:{summary:"Create a budget. Starts in dry run unless dryRun is explicitly false.",responses:{"201":{description:"The created budget."},"422":{description:"Validation error."}}}},"/api/v1/spend/budgets/{budgetId}":{patch:{summary:"Update a budget. Pass expectedVersion for optimistic concurrency.",responses:{"200":{description:"The updated budget."},"409":{description:"Version conflict."}}},delete:{summary:"Delete a budget.",responses:{"200":{description:"Deletion result."}}}},"/api/v1/spend/anomalies":{get:{summary:"Detected spend anomalies.",parameters:[...e,{name:"since",in:"query",schema:{type:"string",format:"date-time"}},{name:"unacknowledged",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Anomalies, newest first."}}}},"/api/v1/spend/anomalies/{anomalyId}/acknowledge":{post:{summary:"Acknowledge an anomaly.",responses:{"200":{description:"Acknowledgement result."}}}},"/api/v1/spend/signals":{get:{summary:"Signals anomaly detection can run on, with their gap and sample rules.",responses:{"200":{description:"Signal catalog."}}}},"/api/v1/spend/anomaly-configs":{get:{summary:"Anomaly detection configuration.",parameters:e,responses:{"200":{description:"Configs."}}},post:{summary:"Create or update the config for a signal.",responses:{"200":{description:"The config."}}}},"/api/v1/spend/anomaly-configs/{configId}":{delete:{summary:"Delete an anomaly config, returning the signal to its default.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/anomaly-silences":{get:{summary:"Active anomaly silences.",parameters:e,responses:{"200":{description:"Silences."}}},post:{summary:"Silence a signal, route, or status code. A reason is required.",responses:{"200":{description:"The silence."}}}},"/api/v1/spend/anomaly-silences/{silenceId}":{delete:{summary:"Remove a silence.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/enforcement":{get:{summary:"Enforcement actions in force.",parameters:[...e,{name:"active",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Enforcement records."}}}},"/api/v1/spend/allowance":{get:{summary:"Whether an operation is allowed under current spend enforcement.",parameters:[...e,{name:"operation",in:"query",schema:{type:"string",enum:["build","deploy","function_invoke","request"]}}],responses:{"200":{description:"Allowance verdict and the budgets behind it."}}}}}}export{Le,S,gs,Ot,pi,fs,hr,yc,bc,Sc,mi,gi,mt,nn,vc,$t,on,gt,Je,Me,Xe,Cc,ft,yr,Ue,Qe,fi,hi,io,oo,Ye,sn,Gp,an,so,se,qp,Tc,Rd,hs,Wp,Kp,Jp,Ec,ao,ys,wc,cn,br,Xp,yi,Qp,Ac,Id,Pd,bs,Rc,Ic,Sr,co,vr,Pc,Ss,bi,Dd,lo,Dc,kc,uo,kd,Nc,xc,_c,Oc,vs,Nd,xd,Yp,_d,$c,po,Od,$d,Cs,Lt,Ts,Es,ws,Lc,Ld,Mc,As,Zp,ht,em,Uc,Mt,Bc,tm,Fc,Md,rm,ee,Ud,Rs,nm,mo,Si,vi,Is,Bd,Fd,im,m,go,Ps,Ds};
111
+ ${JSON.stringify(r)}`).digest("hex")}class go{controlPlane;identities;queue;spendGate;constructor(e,t){this.controlPlane=e;this.identities=t;this.queue=new S(e),this.spendGate=new Mt(e)}target(e,t){let r=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,t),n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope);if(!r||!n||!et(n,r))throw new m("forbidden","The token does not grant access to this resource.",403);return r}authorize(e,t,r){if(!e.token.capabilities.includes(t))throw new m("forbidden",`The token is missing the ${t} capability.`,403);let n=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,r),o=this.controlPlane.resolveAuthorizationTarget(e.serviceAccount.organizationId,e.token.scope),i=t==="project:read"&&!!n&&!!o&&et(n,o);if(!n||!o||!et(o,n)&&!i)throw new m("forbidden","The token does not grant access to this resource.",403);let s=i?o:n;if(!re({membership:e.membership,grants:this.controlPlane.listGrants(e.membership.id),capability:t,target:s}).allowed)throw new m("forbidden","The service account does not have access to this resource.",403);return n}listProjects(e){return this.controlPlane.listProjects().filter((t)=>t.organizationId===e.serviceAccount.organizationId).filter((t)=>{try{return this.authorize(e,"project:read",{type:"project",id:t.id}),!0}catch{return!1}}).map((t)=>({id:t.id,slug:t.slug,name:t.name,description:t.description,version:t.version,createdAt:t.createdAt,updatedAt:t.updatedAt}))}listEnvironments(e,t){let r=this.controlPlane.getProject(t);if(!r||r.organizationId!==e.serviceAccount.organizationId)throw new m("not_found","Project was not found.",404);return this.controlPlane.listEnvironments(t).filter((n)=>{try{return this.authorize(e,"project:read",{type:"environment",id:n.id}),!0}catch{return!1}}).map((n)=>({id:n.id,projectId:n.projectId,slug:n.slug,name:n.name,kind:n.kind,region:n.region,version:n.version,createdAt:n.createdAt,updatedAt:n.updatedAt}))}listServices(e,t,r){let n=new Set(this.listEnvironments(e,t).map((o)=>String(o.id)));if(r&&!n.has(r))throw new m("not_found","Environment was not found.",404);return this.controlPlane.listResources(t,r).filter((o)=>!o.environmentId||n.has(o.environmentId)).filter((o)=>{try{return this.authorize(e,"project:read",{type:"resource",id:o.id}),!0}catch{return!1}}).map((o)=>({id:o.id,projectId:o.projectId,environmentId:o.environmentId,kind:o.kind,slug:o.slug,name:o.name,provider:o.provider,providerId:o.providerId,metadata:h(o.metadata),version:o.version,createdAt:o.createdAt,updatedAt:o.updatedAt}))}listOperations(e,t){return this.controlPlane.listOperations({projectId:t,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.environmentId?{type:"environment",id:n.environmentId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.authorize(e,"deployments:read",o),!0}catch{return!1}}).map((n)=>this.operation(n))}listEvents(e,t,r){if(t)this.authorize(e,"audit:read",{type:"project",id:t});else this.authorize(e,"audit:read",e.token.scope);return this.controlPlane.listEvents({organizationId:e.serviceAccount.organizationId,projectId:t,afterSequence:r,limit:500}).filter((n)=>{let o=n.resourceId?{type:"resource",id:n.resourceId}:n.projectId?{type:"project",id:n.projectId}:{type:"organization"};try{return this.target(e,o),!0}catch{return!1}}).map((n)=>({id:n.id,sequence:n.sequence,projectId:n.projectId,operationId:n.operationId,resourceId:n.resourceId,correlationId:n.correlationId,type:n.type,level:n.level,payload:h(n.payload),createdAt:n.createdAt}))}createDeployment(e,t,r){if(!this.controlPlane.listEnvironments(t.projectId).find((u)=>u.id===t.environmentId))throw new m("not_found","Environment was not found in this project.",404);let o=t.serviceId?{type:"resource",id:t.serviceId}:{type:"environment",id:t.environmentId};this.authorize(e,"deployments:create",o);let i=this.spendGate.check("deploy",{organizationId:e.serviceAccount.organizationId,projectId:t.projectId,environmentId:t.environmentId});if(!i.allowed)throw new m("spend_cap_exceeded",i.reason??"A spend cap is blocking deployments.",402,{action:i.action,budgetId:i.budgetId});let s=Zn("POST","/api/v1/deployments",t),a=this.identities.getIdempotency(e.token.id,r);if(a){if(a.requestHash!==s)throw new m("idempotency_conflict","Idempotency-Key was already used for another request.",409);let u=a.operationId?this.controlPlane.getOperation(a.operationId):void 0;if(!u)throw new m("idempotency_unavailable","The original operation is no longer available.",409);return{operation:this.operation(u),replay:!0}}if(t.serviceId){let u=this.controlPlane.getResource(t.serviceId);if(!u||u.projectId!==t.projectId||u.environmentId!==t.environmentId)throw new m("not_found","Service was not found in this environment.",404)}let d=t.serviceId?this.controlPlane.getResource(t.serviceId):void 0,c=this.queue.enqueue({projectId:t.projectId,environmentId:t.environmentId,resourceId:t.serviceId,actorId:e.actor.id,kind:t.action==="rollback"?"deployment.rollback":"deployment.create",idempotencyKey:`api:${e.token.id}:${r}`,input:h({action:t.action??"deploy",revision:t.revision??null}),lockKey:t.serviceId?`resource:${t.serviceId}`:`environment:${t.environmentId}`,providerKey:d?.provider??"default",buildSlot:t.action!=="rollback",maxAttempts:3,retryClasses:["network","provider_throttled","provider_unavailable"],resumePolicy:"fail",cancellationMode:"provider_non_cancellable",retentionDays:90}).operation;return this.identities.saveIdempotency({tokenId:e.token.id,key:r,requestHash:s,operationId:c.id,responseStatus:202,responseBody:{operationId:c.id}}),{operation:this.operation(c),replay:!1}}operation(e){return{id:e.id,state:e.state,kind:e.kind,projectId:e.projectId,environmentId:e.environmentId,resourceId:e.resourceId,actorId:e.actorId,correlationId:e.correlationId,input:h(e.input),output:h(e.output),error:e.error,attempt:e.attempt,createdAt:e.createdAt,updatedAt:e.updatedAt,startedAt:e.startedAt,finishedAt:e.finishedAt}}}function we(e){return e.serviceAccount.organizationId}function Xt(e){if(e==null)return;if(e==="daily"||e==="weekly"||e==="monthly")return e;throw new m("validation_error","period must be daily, weekly, or monthly.",422)}function W(e,t){if(e==null)return;let r=Number(e);if(!Number.isFinite(r)||r<0||!Number.isInteger(r))throw new m("validation_error",`${t} must be a non-negative integer.`,422);return r}function T(e,t,r,n,o){if(o)e.authorization.authorize(t,r,{type:"environment",id:o});else if(n)e.authorization.authorize(t,r,{type:"project",id:n});else e.authorization.authorize(t,r,{type:"organization"});return{organizationId:we(t),projectId:n,environmentId:o}}async function Ps(e,t,r){let{method:n,url:o}=r,i=e.now?.()??new Date,s=o.searchParams.get("projectId")??void 0,a=o.searchParams.get("environmentId")??void 0;if(n==="GET"&&o.pathname==="/api/v1/usage"){let l=T(e,t,"billing:read",s,a);return e.service.usageReport({...l,period:Xt(o.searchParams.get("period")),timezone:o.searchParams.get("timezone")??void 0,now:i})}if(n==="GET"&&o.pathname==="/api/v1/usage/rollups"){let l=T(e,t,"billing:read",s,a),f=o.searchParams.get("from"),g=o.searchParams.get("to");if(!f||!g)throw new m("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(f))||Number.isNaN(Date.parse(g)))throw new m("validation_error","from and to must be ISO-8601 timestamps.",422);let y=o.searchParams.getAll("meter");return{data:e.store.listRollups({...l,from:f,to:g,meters:y.length>0?y:void 0},W(o.searchParams.get("limit"),"limit")??1000)}}if(n==="GET"&&o.pathname==="/api/v1/usage/focus"){let l=T(e,t,"billing:read",s,a),f=o.searchParams.get("from"),g=o.searchParams.get("to");if(!f||!g)throw new m("validation_error","from and to are required.",422);if(Number.isNaN(Date.parse(f))||Number.isNaN(Date.parse(g)))throw new m("validation_error","from and to must be ISO-8601 timestamps.",422);if(new Date(g).getTime()-new Date(f).getTime()>31622400000)throw new m("validation_error","The range must not exceed one year.",422);let y=o.searchParams.get("granularity")==="hourly"?"hourly":"daily",v=e.store.listRollups({...l,from:f,to:g},1e4),b=Mc(v,{billingPeriodStart:f,billingPeriodEnd:g,currency:e.store.priceBook.currency,granularity:y});return{contentType:"application/x-ndjson",body:As(b),recordCount:b.length}}if(n==="GET"&&o.pathname==="/api/v1/spend/budgets"){let l=T(e,t,"billing:read",s,a);return{data:e.store.listBudgets({organizationId:l.organizationId,projectId:l.projectId})}}if(n==="POST"&&o.pathname==="/api/v1/spend/budgets"){let l=await r.body?.()??{},g={organizationId:T(e,t,"billing:manage",l.projectId,l.environmentId).organizationId,projectId:l.projectId,environmentId:l.environmentId,name:String(l.name??"").trim(),period:Xt(l.period??"monthly")??"monthly",timezone:l.timezone,currency:l.currency,softLimitCents:W(l.softLimitCents,"softLimitCents"),hardLimitCents:W(l.hardLimitCents,"hardLimitCents"),thresholds:l.thresholds,meters:l.meters,graceSeconds:W(l.graceSeconds,"graceSeconds"),hysteresisPercent:l.hysteresisPercent,dryRun:l.dryRun!==!1,enabled:l.enabled};try{return{data:e.store.createBudget(g)}}catch(y){throw new m("validation_error",y instanceof Error?y.message:String(y),422)}}let d=/^\/api\/v1\/spend\/budgets\/([^/]+)$/.exec(o.pathname);if(d&&(n==="PATCH"||n==="DELETE")){let l=e.store.getBudget(decodeURIComponent(d[1]));if(!l||l.organizationId!==we(t))throw new m("not_found","Budget was not found.",404);if(T(e,t,"billing:manage",l.projectId,l.environmentId),n==="DELETE")return{data:{deleted:e.store.deleteBudget(l.id)}};let f=await r.body?.()??{};try{return{data:e.store.updateBudget(l.id,f,W(f.expectedVersion,"expectedVersion"))}}catch(g){let y=g instanceof Error?g.message:String(g);throw new m(y.includes("concurrently")?"conflict":"validation_error",y,y.includes("concurrently")?409:422)}}if(n==="GET"&&o.pathname==="/api/v1/spend/anomalies"){let l=T(e,t,"billing:read",s,a);return{data:e.store.listAnomalies({organizationId:l.organizationId,projectId:l.projectId,since:o.searchParams.get("since")??void 0,unacknowledgedOnly:o.searchParams.get("unacknowledged")==="true",limit:W(o.searchParams.get("limit"),"limit")})}}let c=/^\/api\/v1\/spend\/anomalies\/([^/]+)\/acknowledge$/.exec(o.pathname);if(c&&n==="POST"){let l=e.store.getAnomaly(decodeURIComponent(c[1]));if(!l||l.organizationId!==we(t))throw new m("not_found","Anomaly was not found.",404);return T(e,t,"billing:manage",l.projectId,l.environmentId),{data:{acknowledged:e.store.acknowledgeAnomaly(l.id)}}}if(n==="GET"&&o.pathname==="/api/v1/spend/signals")return T(e,t,"billing:read",s,a),{data:Lt};if(o.pathname==="/api/v1/spend/anomaly-configs"){if(n==="GET"){let l=T(e,t,"billing:read",s,a);return{data:e.service.anomalyConfigs.list({organizationId:l.organizationId,projectId:l.projectId})}}if(n==="POST"){let l=await r.body?.()??{},f=T(e,t,"billing:manage",l.projectId,l.environmentId);try{return{data:e.service.anomalyConfigs.upsert({organizationId:f.organizationId,projectId:l.projectId,environmentId:l.environmentId,signal:String(l.signal??""),enabled:l.enabled,sensitivity:l.sensitivity,seasonLength:l.seasonLength==null?void 0:Number(l.seasonLength),minAbsoluteDelta:l.minAbsoluteDelta==null?void 0:Number(l.minAbsoluteDelta),detectDrops:l.detectDrops,severity:l.severity})}}catch(g){throw new m("validation_error",g instanceof Error?g.message:String(g),422)}}}let u=/^\/api\/v1\/spend\/anomaly-configs\/([^/]+)$/.exec(o.pathname);if(u&&n==="DELETE"){let l=e.service.anomalyConfigs.get(decodeURIComponent(u[1]));if(!l||l.organizationId!==we(t))throw new m("not_found","Anomaly config was not found.",404);return T(e,t,"billing:manage",l.projectId,l.environmentId),{data:{deleted:e.service.anomalyConfigs.delete(l.id)}}}if(o.pathname==="/api/v1/spend/anomaly-silences"){if(n==="GET"){let l=T(e,t,"billing:read",s,a);return{data:e.service.anomalyConfigs.listSilences({organizationId:l.organizationId,projectId:l.projectId,includeExpired:o.searchParams.get("includeExpired")==="true"})}}if(n==="POST"){let l=await r.body?.()??{},f=T(e,t,"billing:manage",l.projectId);try{return{data:e.service.anomalyConfigs.silence({organizationId:f.organizationId,projectId:l.projectId,signal:l.signal,routePattern:l.routePattern,statusCode:l.statusCode==null?void 0:Number(l.statusCode),reason:String(l.reason??""),expiresAt:l.expiresAt})}}catch(g){throw new m("validation_error",g instanceof Error?g.message:String(g),422)}}}let p=/^\/api\/v1\/spend\/anomaly-silences\/([^/]+)$/.exec(o.pathname);if(p&&n==="DELETE")return T(e,t,"billing:manage",s),{data:{deleted:e.service.anomalyConfigs.removeSilence(decodeURIComponent(p[1]))}};if(n==="GET"&&o.pathname==="/api/v1/spend/enforcement"){let l=T(e,t,"billing:read",s,a);return{data:e.store.listEnforcements({organizationId:l.organizationId,activeOnly:o.searchParams.get("active")!=="false"})}}if(n==="GET"&&o.pathname==="/api/v1/spend/allowance"){let l=T(e,t,"billing:read",s,a),f=o.searchParams.get("operation")??"deploy";if(!["build","deploy","function_invoke","request"].includes(f))throw new m("validation_error","operation must be build, deploy, function_invoke, or request.",422);let y=e.store.listEnforcements({organizationId:l.organizationId,activeOnly:!0}).filter((_)=>(!_.projectId||_.projectId===l.projectId)&&(!_.environmentId||_.environmentId===l.environmentId)),v=Oc(f,y),I=e.store.budgetsForScope(l.organizationId,l.projectId,l.environmentId).map((_)=>e.service.status(_,i));return{operation:f,allowed:v.allowed,blockedBy:v.blockedBy??null,reason:v.reason??null,budgets:I.map((_)=>({id:_.budget.id,name:_.budget.name,usedPercent:_.decision.usedPercent,projectedPercent:_.decision.projectedPercent,level:_.decision.level,timeToCap:_.timeToCap}))}}return}function Ds(){let e=[{name:"projectId",in:"query",schema:{type:"string"}},{name:"environmentId",in:"query",schema:{type:"string"}}];return{"/api/v1/usage":{get:{summary:"Current usage, cost, and every budget governing the scope.",parameters:[...e,{name:"period",in:"query",schema:{type:"string",enum:["daily","weekly","monthly"]}},{name:"timezone",in:"query",schema:{type:"string"}}],responses:{"200":{description:"Usage totals, per-meter breakdown, hourly series, and budget status."}}}},"/api/v1/usage/rollups":{get:{summary:"Itemized hourly usage rollups.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"meter",in:"query",schema:{type:"array",items:{type:"string"}}},{name:"limit",in:"query",schema:{type:"integer"}}],responses:{"200":{description:"Hourly rollups, newest first."}}}},"/api/v1/usage/focus":{get:{summary:"Usage and cost in FOCUS v1.3 format, newline-delimited JSON.",parameters:[...e,{name:"from",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"to",in:"query",required:!0,schema:{type:"string",format:"date-time"}},{name:"granularity",in:"query",schema:{type:"string",enum:["daily","hourly"]}}],responses:{"200":{description:"FOCUS records, one JSON object per line."}}}},"/api/v1/spend/budgets":{get:{summary:"Budgets governing a scope.",parameters:e,responses:{"200":{description:"Budgets."}}},post:{summary:"Create a budget. Starts in dry run unless dryRun is explicitly false.",responses:{"201":{description:"The created budget."},"422":{description:"Validation error."}}}},"/api/v1/spend/budgets/{budgetId}":{patch:{summary:"Update a budget. Pass expectedVersion for optimistic concurrency.",responses:{"200":{description:"The updated budget."},"409":{description:"Version conflict."}}},delete:{summary:"Delete a budget.",responses:{"200":{description:"Deletion result."}}}},"/api/v1/spend/anomalies":{get:{summary:"Detected spend anomalies.",parameters:[...e,{name:"since",in:"query",schema:{type:"string",format:"date-time"}},{name:"unacknowledged",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Anomalies, newest first."}}}},"/api/v1/spend/anomalies/{anomalyId}/acknowledge":{post:{summary:"Acknowledge an anomaly.",responses:{"200":{description:"Acknowledgement result."}}}},"/api/v1/spend/signals":{get:{summary:"Signals anomaly detection can run on, with their gap and sample rules.",responses:{"200":{description:"Signal catalog."}}}},"/api/v1/spend/anomaly-configs":{get:{summary:"Anomaly detection configuration.",parameters:e,responses:{"200":{description:"Configs."}}},post:{summary:"Create or update the config for a signal.",responses:{"200":{description:"The config."}}}},"/api/v1/spend/anomaly-configs/{configId}":{delete:{summary:"Delete an anomaly config, returning the signal to its default.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/anomaly-silences":{get:{summary:"Active anomaly silences.",parameters:e,responses:{"200":{description:"Silences."}}},post:{summary:"Silence a signal, route, or status code. A reason is required.",responses:{"200":{description:"The silence."}}}},"/api/v1/spend/anomaly-silences/{silenceId}":{delete:{summary:"Remove a silence.",responses:{"200":{description:"Result."}}}},"/api/v1/spend/enforcement":{get:{summary:"Enforcement actions in force.",parameters:[...e,{name:"active",in:"query",schema:{type:"boolean"}}],responses:{"200":{description:"Enforcement records."}}}},"/api/v1/spend/allowance":{get:{summary:"Whether an operation is allowed under current spend enforcement.",parameters:[...e,{name:"operation",in:"query",schema:{type:"string",enum:["build","deploy","function_invoke","request"]}}],responses:{"200":{description:"Allowance verdict and the budgets behind it."}}}}}}export{Le,S,gs,Ot,pi,fs,hr,yc,bc,Sc,mi,gi,mt,nn,vc,$t,on,gt,Je,Me,Xe,Cc,ft,yr,Ue,Qe,fi,hi,io,oo,Ye,sn,qp,an,so,se,Gp,Tc,Rd,hs,Wp,Kp,Jp,Ec,ao,ys,wc,cn,br,Xp,yi,Qp,Ac,Id,Pd,bs,Rc,Ic,Sr,co,vr,Pc,Ss,bi,Dd,lo,Dc,kc,uo,kd,Nc,xc,_c,Oc,vs,Nd,xd,Yp,_d,$c,po,Od,$d,Cs,Lt,Ts,Es,ws,Lc,Ld,Mc,As,Zp,ht,em,Uc,Mt,Bc,tm,Fc,Md,rm,ee,Ud,Rs,nm,mo,Si,vi,Is,Bd,Fd,im,m,go,Ps,Ds};
@@ -1 +1 @@
1
- import{Kc,mm}from"./chunk-5wx26yjy.js";import"./chunk-f64jvh96.js";import"./chunk-nmqjmx30.js";import"./chunk-dkf2kcsc.js";export{Kc as EmailClient,mm as email};
1
+ import{Kc,mm}from"./chunk-kdsgbvep.js";import"./chunk-f64jvh96.js";import"./chunk-nmqjmx30.js";import"./chunk-dkf2kcsc.js";export{Kc as EmailClient,mm as email};
@@ -1,6 +1,6 @@
1
- import{Be,A,Wt,Lr,Li}from"./chunk-1jwmkbzx.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 qd="dashboard";function jc(){return Be("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=jc(),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{Be,A,Wt,Lr,Li}from"./chunk-tf8qxy9k.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 Gd="dashboard";function jc(){return Be("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=jc(),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 Be("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 wo(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 Ao(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(Wt(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=Li(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=wo(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=Li(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 ${jc()})`;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 Ro(e){return Object.keys(e.sites??{}).filter(Lr)}function xs(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??qd}-${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{qd,jc,Wd,wo,Ao,Ro,xs};
5
+ `),J()}catch(n){return t.warn(`Management dashboard: could not stage the live release (${n?.message??n}) — skipping.`),null}}function wo(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 Ao(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(Wt(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=Li(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=wo(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=Li(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 ${jc()})`;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 Ro(e){return Object.keys(e.sites??{}).filter(Lr)}function xs(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??Gd}-${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{Gd,jc,Wd,wo,Ao,Ro,xs};