everyapp 0.2.2 → 0.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -77
- package/bin/everyapp.js +235 -0
- package/dist/access-F3GKBKAW.js +1 -0
- package/dist/activity-4MFMH5JP.js +12 -0
- package/dist/apps-63K2DGVT.js +9 -0
- package/dist/chunk-2UFJRKEE.js +4 -0
- package/dist/chunk-3AAHHUJC.js +11 -0
- package/dist/chunk-3Z53CH4F.js +6 -0
- package/dist/chunk-5ZTFC6DK.js +1 -0
- package/dist/chunk-6O3GJS5H.js +15 -0
- package/dist/chunk-74EST4VW.js +2 -0
- package/dist/chunk-7LG3F4FF.js +10 -0
- package/dist/chunk-AUDGOIHE.js +1 -0
- package/dist/chunk-BHMRY53V.js +2 -0
- package/dist/chunk-DQWOXSL3.js +32 -0
- package/dist/chunk-E3EPK27P.js +10 -0
- package/dist/chunk-E7EUXUVD.js +1 -0
- package/dist/chunk-ECLJ5IAL.js +126 -0
- package/dist/chunk-EQX4GKJ2.js +4 -0
- package/dist/chunk-EUNGJMJ6.js +20 -0
- package/dist/chunk-F6IH47GT.js +4 -0
- package/dist/chunk-G64S77GC.js +33 -0
- package/dist/chunk-GD2JZMD3.js +1 -0
- package/dist/chunk-GRFPP4UW.js +7 -0
- package/dist/chunk-IA534DGW.js +10 -0
- package/dist/chunk-IG26HYRR.js +45 -0
- package/dist/chunk-IZEOAOKL.js +6 -0
- package/dist/chunk-JYKRUS5C.js +1 -0
- package/dist/chunk-KMAOZRV4.js +18 -0
- package/dist/chunk-MC56CUQI.js +7 -0
- package/dist/chunk-MDORVBPD.js +1 -0
- package/dist/chunk-N4E5YE4X.js +5 -0
- package/dist/chunk-NJFWEYX7.js +1 -0
- package/dist/chunk-OEOVNJAN.js +1 -0
- package/dist/chunk-OVKVV6MK.js +2 -0
- package/dist/chunk-PL6EORDJ.js +15 -0
- package/dist/chunk-PMPIMHKG.js +6 -0
- package/dist/chunk-QZWSSWMP.js +22 -0
- package/dist/chunk-R4CGF622.js +2 -0
- package/dist/chunk-RFVMR32Y.js +1 -0
- package/dist/chunk-RQFHVU3Y.js +25 -0
- package/dist/chunk-SAT3PGZU.js +57 -0
- package/dist/chunk-SPPR6WCI.js +1 -0
- package/dist/chunk-TPWSGRNT.js +30 -0
- package/dist/chunk-VVQRET35.js +2 -0
- package/dist/chunk-VXJQGJ7Y.js +2 -0
- package/dist/chunk-WEM3WLOC.js +1 -0
- package/dist/chunk-Y3VIFPN5.js +1 -0
- package/dist/chunk-YJBYZWSP.js +22 -0
- package/dist/chunk-ZYL2ZHCF.js +98 -0
- package/dist/configure-2KMHM22T.js +8 -0
- package/dist/create-ELEJMZBS.js +22 -0
- package/dist/db-MZIAKGBN.js +9 -0
- package/dist/delete-H47KPJSB.js +3 -0
- package/dist/deploy-HGFJLLUO.js +1 -0
- package/dist/dev-62VA7UEM.js +86 -0
- package/dist/email-NNFD3VVB.js +10 -0
- package/dist/events-JDY76EG6.js +15 -0
- package/dist/groups-NQFXDZZP.js +8 -0
- package/dist/index.js +92 -1
- package/dist/install-JTZWRZIL.js +1 -0
- package/dist/login-P6LYQQWP.js +1 -0
- package/dist/mcp-NCFWEBMD.js +1 -0
- package/dist/provider-WVBI2VED.js +13 -0
- package/dist/release-6FYSPXXA.js +1 -0
- package/dist/restore-XBU7DOJV.js +3 -0
- package/dist/secret-ML5EXS3O.js +1 -0
- package/dist/setup-IEXCISLP.js +1 -0
- package/dist/status-OPLPKJ4U.js +4 -0
- package/dist/teardown-3JMMLK6O.js +22 -0
- package/dist/update-37ZDATLR.js +1 -0
- package/dist/workspace-DAFZVYQ2.js +21 -0
- package/package.json +30 -27
- package/skills/build-every-app/SKILL.md +199 -0
- package/skills/build-every-app/patterns.md +134 -0
- package/skills/everyapp/SKILL.md +292 -0
- package/skills/everyapp/mcp.md +336 -0
- package/skills/everyapp/security-review.md +61 -0
- package/skills/everyapp/setup/README.md +263 -0
- package/skills/everyapp/setup/access.md +178 -0
- package/skills/everyapp/setup/context.md +117 -0
- package/skills/everyapp/setup/dataforseo.md +287 -0
- package/skills/everyapp/setup/email.md +366 -0
- package/skills/everyapp/setup/gateway.md +243 -0
- package/skills/everyapp/setup/google.md +360 -0
- package/skills/everyapp/setup/microsoft-365.md +281 -0
- package/skills/everyapp/setup/openai.md +318 -0
- package/skills/everyapp/setup/openrouter.md +309 -0
- package/skills/everyapp/setup/providers.md +353 -0
- package/skills/everyapp/setup/remote-mcp.md +199 -0
- package/skills/everyapp/setup/slack.md +344 -0
- package/skills/everyapp/setup/workers-ai.md +138 -0
- package/bin/__everyapp_bash_complete.js +0 -12
- package/dist/bash-complete.js +0 -3
- package/dist/chunk-7BOQJFI5.js +0 -8
- package/dist/chunk-7YVJFS4A.js +0 -1
- package/dist/chunk-BIXKPCDH.js +0 -2
- package/dist/chunk-DLGPLHBH.js +0 -47
- package/dist/chunk-FD6K2YA7.js +0 -9
- package/dist/chunk-GAJEQYJH.js +0 -39
- package/dist/chunk-O2KDOP5R.js +0 -13
- package/dist/chunk-OI2MBGBG.js +0 -4
- package/dist/chunk-POSDLD3G.js +0 -8
- package/dist/chunk-RB5D2R45.js +0 -1
- package/dist/chunk-U4LIQ5VR.js +0 -1
- package/dist/chunk-VEYSNPDH.js +0 -3
- package/dist/chunk-VP6SKW44.js +0 -7
- package/dist/chunk-WO3NE7ZU.js +0 -7
- package/dist/chunk-XTO2VTPY.js +0 -6
- package/dist/chunk-YJ2DKIZS.js +0 -1
- package/dist/create-DYQ3NBWJ.js +0 -22
- package/dist/deploy-PYTCMDGV.js +0 -7
- package/dist/deploy-RMAHOA4Z.js +0 -55
- package/dist/dev-SAE237FS.js +0 -0
- package/dist/generateConfig-46Z3ERF3.js +0 -1
- package/dist/login-B6EF3SMX.js +0 -1
- package/dist/logout-XMKZBLNV.js +0 -1
- package/dist/remoteD1Shell-A67JMO3H.js +0 -6
- package/dist/setupLocal-TZJUW5ES.js +0 -6
- package/gateway/every-app-gateway-build.tar.gz +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import{a as ue,d as fe,f as we,h as G,j as ge,k as he,p as ve,q as be}from"./chunk-PMPIMHKG.js";import{a as ke,c as De,d as M}from"./chunk-OVKVV6MK.js";import{b as ye,c as T}from"./chunk-RFVMR32Y.js";import{b as C,c as P,e as ie,f as le}from"./chunk-GRFPP4UW.js";import{b as ce}from"./chunk-R4CGF622.js";import{a as pe,c as de,e as me}from"./chunk-3AAHHUJC.js";import{h as Q}from"./chunk-EUNGJMJ6.js";import{V as se,d as ee,f as te,g as ae,h as re,i as oe,k as ne,l as _}from"./chunk-ZYL2ZHCF.js";import{a as X}from"./chunk-7LG3F4FF.js";import{Ib as Z,Pb as A,Rb as q,Sb as J,c as R,d as S,f as O,ib as D,nb as j,tb as h,wb as F,xb as V,yb as K,zb as Y}from"./chunk-SAT3PGZU.js";import{execFile as x}from"node:child_process";import y from"node:fs/promises";import k from"node:path";import{promisify as L}from"node:util";var N=["apps/every-app-gateway","packages/sdk","packages/perimeter","packages/toolbus","pnpm-workspace.yaml","pnpm-lock.yaml"],_e=3;function gt({out:e,verbose:t}){let a=ce();return{describe:()=>Me(a),open:()=>Le({root:a,out:e,verbose:t})}}function Ge(e){return k.join(e,"node_modules",".cache","everyapp")}async function W(e){let t;try{({stdout:t}=await L(x)("git",["ls-files","-z","--cached","--others","--exclude-standard","--",...N],{cwd:e,maxBuffer:64*1024*1024}))}catch{return null}let a=[...new Set(t.split("\0").filter(Boolean))];return a.length>0?we(e,a):null}async function Re(e){try{let{stdout:t}=await L(x)("git",["log","-1","--format=%ct","--",...N],{cwd:e}),a=Number.parseInt(t.trim(),10);return Number.isFinite(a)?a*1e3:null}catch{return null}}async function Te(e,t){let a=r=>L(x)("git",r,{cwd:e}),o=()=>a(["diff","--quiet",`gateway-v${t}`,"HEAD","--",...N]).then(()=>!1,()=>!0);try{let[r,l]=await Promise.all([a(["rev-parse","--short","HEAD"]),a(["status","--porcelain","--",...N])]),n=l.stdout.trim()!=="";return!n&&!await o()?null:{hash:r.stdout.trim(),uncommittedChanges:n}}catch{return null}}async function Me(e){let t=k.join(e,"apps","every-app-gateway"),a=async c=>JSON.parse(await y.readFile(k.join(t,c),"utf8")),[o,r,l,n]=await Promise.all([W(e),Re(e),a("drizzle/meta/_journal.json"),a("package.json")]),s=String(n.version??"unknown"),i=await Te(e,s);return{treeSha256:o,origin:{kind:"checkout"},...i?{commit:i}:{},version:s,order:{schema:ge(l.entries??[]),committedAt:r??Date.now()}}}async function We({root:e,out:t,build:a,keep:o=_e}){let[r,l]=await Promise.all([W(e),Re(e)]),n=Ge(e),s=r?k.join(n,`${r}.tar.gz`):null,i={origin:{kind:"checkout"},treeSha256:r,committedAt:l};if(s&&await A(s))try{let m=await G(s,i),d=new Date;return await y.utimes(s,d,d),t.emit({type:"step",step:"gateway.release",status:"ok",message:`Using the Gateway ${m.manifest.version} built from this checkout before (${r.slice(0,12)}).`,data:{cached:!0,treeSha256:r,release:m.manifest.version}}),m}catch{await y.rm(s,{force:!0})}let c=await a();s&&await W(e)===r&&await xe(c,s,o);let p=await G(c,{origin:{kind:"checkout"},treeSha256:s&&await A(s)?r:null,committedAt:l});return t.emit({type:"step",step:"gateway.release",status:"ok",message:`Built the Gateway ${p.manifest.version} from this checkout.`,data:{cached:!1,treeSha256:p.source.treeSha256,release:p.manifest.version}}),p}async function xe(e,t,a){let o=k.dirname(t);await y.mkdir(o,{recursive:!0});let r=`${t}.${process.pid}.partial`;await y.copyFile(e,r),await y.rename(r,t);let l=await Promise.all((await y.readdir(o)).filter(n=>n.endsWith(".tar.gz")).map(async n=>({file:k.join(o,n),usedAt:(await y.stat(k.join(o,n))).mtimeMs})));for(let{file:n}of l.sort((s,i)=>i.usedAt-s.usedAt).slice(a))n!==t&&await y.rm(n,{force:!0})}function Le({root:e,out:t,verbose:a}){return We({root:e,out:t,build:()=>ze(e,t,a??!1)})}async function ze(e,t,a,o=process.env){let r=k.join(e,"apps","every-app-gateway");t.emit({type:"step",step:"gateway.release",status:"start",message:"Building the Gateway from this checkout (usually 1\u20132m)",data:{dir:r}});let l=(n,s)=>J("pnpm",n,{cwd:s,env:{...o,NODE_OPTIONS:Z(o.NODE_OPTIONS)},echo:a,what:"Building the Gateway",code:"GATEWAY_BUILD_FAILED",fix:"fix the build error above, then run this again",logName:"gateway-build"});return await l(["--filter","@every-app/sdk","build"],e),await l(["run","build:release"],r),k.join(r,ue)}var Be=`SELECT apps.app_slug, apps.worker_name, apps.hostname, apps.status,
|
|
2
|
+
organization_keys.org_key
|
|
3
|
+
FROM apps LEFT JOIN organization_keys
|
|
4
|
+
ON organization_keys.organization_id = apps.organization_id
|
|
5
|
+
WHERE apps.status IN ('binding', 'active', 'disabled')
|
|
6
|
+
AND apps.worker_name IS NOT NULL AND apps.hostname IS NOT NULL
|
|
7
|
+
ORDER BY apps.worker_name`;function Se(e){let t=new Map;return a=>{let o=t.get(a);return o||(o=P(e,a).then(r=>r!==null),t.set(a,o)),o}}var Ie=4;async function z(e,t){let[a=[]]=await e.run([{sql:Be}]),o=[],r=[];for(let c of a){let p={appId:String(c.app_slug),workerName:String(c.worker_name),hostname:String(c.hostname),status:String(c.status)};j({appId:p.appId,workerName:p.workerName,orgKey:typeof c.org_key=="string"?c.org_key:null})?o.push(p):r.push({appId:p.appId,workerName:p.workerName})}let l=[];for(let c=0;c<o.length;c+=Ie){let p=o.slice(c,c+Ie);l.push(...await Promise.all(p.map(m=>t(m.workerName))))}let n=o.filter((c,p)=>l[p]),s=o.filter((c,p)=>!l[p]).map(({appId:c,workerName:p})=>({appId:c,workerName:p})),i=[...new Set(n.map(c=>c.workerName))].sort();return{apps:n,appWorkers:i,appHosts:[...new Set(n.map(c=>c.hostname.toLowerCase()))].sort(),skipped:r,missing:s}}import Ze from"node:fs/promises";import qe from"node:os";import Je from"node:path";var He=new Set(["A","AAAA","CNAME","NS"]),E=100,Ue=95;async function B(e){let t=new Set(e.liveDomains),a=[...new Set(e.domains)].filter(c=>!t.has(c));if(a.length===0)return[];let{out:o,step:r,zone:l}=e,n=new Set(e.domains).size;if(n>E)throw new h("ZONE_CUSTOM_DOMAIN_LIMIT",`${l.name} would go over Cloudflare's ${E} Custom Domains per zone
|
|
8
|
+
The Gateway alone needs ${n} there, before other Workers' domains.`,{fix:`delete apps you no longer use (${R} delete <app>), or install a second Gateway on another domain`,data:{total:n,limit:E}});n>=Ue&&o.emit({type:"warning",code:"ZONE_CUSTOM_DOMAIN_LIMIT_NEAR",step:r,message:`${l.name} is close to Cloudflare's ${E} Custom Domains per zone
|
|
9
|
+
It will hold at least ${n}, and other Workers' domains there count too.`,data:{total:n,limit:E}});let s=await Fe(e,a),i=a.filter(c=>!s.includes(c));return!e.cfAsks&&i.length>0&&o.emit({type:"warning",code:"CUSTOM_DOMAIN_OWNER_UNCHECKED",step:r,message:`If another Worker already serves ${i.length===1?i[0]:`any of ${i.join(", ")}`}, it will be replaced by this deployment.`,data:{hosts:i}}),a}function je(e){let t;return()=>t??=C(e,D).then(a=>new Set(a)).catch(a=>{if(a instanceof K)return new Set;throw a})}async function Ae({cf:e,zone:t,forceDns:a},o){try{return await ke(e,t.id,o)}catch(r){if(!Y(r,"auth"))throw r;if(a)return[];throw new h("DNS_UNREADABLE",`Can't read ${t.name}'s DNS records with this Cloudflare login
|
|
10
|
+
So it can't tell whether publishing ${o} would replace one.`,{fix:"give the API token Zone \u2192 DNS \u2192 Read",rerun:S(["--force-dns"]),authorize:!0})}}async function Fe(e,t){let{cf:a,out:o,step:r,zone:l,forceDns:n}=e,s=[],i=[],c=je(a),p=!1,m=f=>f.filter(u=>He.has(u.type.toUpperCase())),d=new Map;for(let f of t){let u=await Ae(e,f),$=m(u);if($.length>0&&(await c()).has(f)){o.emit({type:"progress",step:r,message:`${f} is already this Gateway's Custom Domain (an earlier run published it, then stopped)`,data:{host:f}}),i.push(f);continue}if($.length>0&&s.push({host:f,records:$.map(M).join(", ")}),u.length===0&&f!==l.name){let I=De(f);d.has(I)||d.set(I,Ae(e,I));let U=m(await d.get(I));U.length>0&&(s.push({host:f,records:`${U.map(M).join(", ")}, through ${I}`}),p=!0)}}if(s.length===0)return i;let w=s.length===1,v=w?`${s[0].host} already points somewhere else`:`${s.length} hostnames already point somewhere else`,b=w?`Its DNS record: ${s[0].records}.`:`${s.map(f=>`${f.host} (${f.records})`).join("; ")}.`,g=p?" A wildcard record stays, and keeps answering every other name.":"";if(n)return o.emit({type:"warning",code:"DNS_RECORD_REPLACED",step:r,message:w?`Replacing ${s[0].host}'s DNS record (${s[0].records})${g?`
|
|
11
|
+
${g.trim()}`:""}`:`Replacing the DNS records of ${s.length} hostnames
|
|
12
|
+
${b}${g}`,data:{conflicts:s}}),i;throw new h("DNS_RECORD_CONFLICT",`${v}
|
|
13
|
+
${b} Publishing ${w?"it replaces the record":"them replaces those records"}.${g}`,{fix:`delete ${w?"the record":"the records"} in Cloudflare (${l.name} \u2192 DNS), or use another name`})}async function Ct({cf:e,out:t,install:a,hostname:o,forceDns:r,cfAsks:l}){let n=!ye(o,a.appBaseDomain),s=!n&&!a.liveDomains.includes(o);return s&&await B({cf:e,out:t,step:"app.domain",zone:{id:a.zoneId,name:a.zoneName},domains:[...a.liveDomains,o],liveDomains:a.liveDomains,forceDns:r,cfAsks:l}),{outsideBase:n,newHost:s}}import Ve from"node:fs/promises";import Ke from"node:path";async function Ee({cf:e,databaseId:t,accountId:a,dir:o,registry:r,target:l,restoreCommand:n}){let{nested:s,count:i}=await Ye(o),c=await ae({cf:e,databaseId:t,dir:o,nested:s});if(c.length===0)return{applied:[],fresh:!1,rollback:null};let p=c.length===i,m=null;if(p)await me(r,l);else{let d=await ee(e,t),{email:w}=await X(e);await de(r,{target:l,databaseId:t,bookmark:d,migrations:c,createdAt:Date.now(),createdBy:se(w,a).actor}),m={restoreCommand:n,rollbackCommand:te(t,d,a)}}try{return{applied:await re({cf:e,databaseId:t,dir:o,nested:s}),fresh:p,rollback:m}}catch(d){throw new h("MIGRATION_FAILED",["Database migration failed",V(d),"Nothing was uploaded; the version that's serving keeps running.",...m?[`To roll the database back to before this run: ${m.restoreCommand}`]:[]].join(`
|
|
14
|
+
`),{data:{fix:"correct the migration",...m?{rollbackCommand:m.rollbackCommand}:{}}})}}async function Ye(e){let t=await Ve.readdir(e,{withFileTypes:!0}).catch(()=>[]),a=t.filter(r=>r.isDirectory()&&r.name!=="meta"),o=(await Promise.all(a.map(r=>A(Ke.join(e,r.name,"migration.sql"))))).filter(Boolean).length;return o>0?{nested:!0,count:o}:{nested:!1,count:t.filter(r=>r.isFile()&&r.name.endsWith(".sql")).length}}function Ce(e){return e?` Restore point saved; to undo: ${e.restoreCommand}`:""}function Pe(e){return{applied:e.applied,fresh:e.fresh,...e.rollback}}var Xe={deploy:"gateway.deploy",upgrade:"gateway.upgrade",reconcile:"gateway.reconcile"};function Qe(e){return{...e.source,version:e.manifest.version,sha256:e.manifest.sha256,minCli:e.manifest.minCli}}function et(e,t){return t.liveVersionId===null?!1:e.manifest.sha256===t.releaseSha256||e.source.treeSha256!==null&&e.source.treeSha256===t.sourceTreeSha256}function tt(e,t){return e.sha256&&e.sha256===t.releaseSha256||e.treeSha256&&e.treeSha256===t.sourceTreeSha256?!1:he(e.order,t.releaseOrder)<0}async function sa(e,t){Ne(await t(),e)}function Ne(e,t,a={}){if(tt(e,t))throw at(e,t,a)}function at(e,t,{allowDowngradeFlag:a=!1}={}){let o=e.version===t.releaseVersion,r=c=>new Date(c.committedAt).toLocaleDateString("en-US",{month:"short",day:"numeric",timeZone:"UTC"}),l=e.origin.kind==="checkout",n=l?"This checkout's Gateway":`The Gateway from ${fe(e.origin)}`,s=o?`${n} (${e.version} from ${r(e.order)}) is older than the live one (from ${r(t.releaseOrder)})`:`${n} (${e.version}) is older than the live one (${t.releaseVersion})`,i={live:t.releaseVersion,candidate:e.version};return a?new h("DOWNGRADE_REFUSED",s,{fix:l?"git pull, then run setup again":"pass --release a newer Gateway release",rerun:S(["--allow-downgrade"]),authorize:!0,data:i}):new h("DOWNGRADE_REFUSED",s,{fix:l?"git pull":"run everyapp from a checkout at least as new",rerun:S(),rerunNote:"after that",data:i})}var H=class{constructor(t,a){this.options=t;this.liveDomains=a;this.checked=new Set(t.checkedDomains)}checked;warned=new Set;domainsFor(t){let{appBaseDomain:a,gatewayHost:o,out:r}=this.options,l=T(t,a),s=t.filter(i=>!l.includes(i)).filter(i=>!this.warned.has(i));if(s.length>0){r.emit({type:"warning",code:"APP_HOST_OUTSIDE_BASE",message:`Skipping ${s.join(", ")}: ${s.length===1?"it isn't":"they aren't"} under ${a}
|
|
15
|
+
Apps live one level below the Gateway's domain (<name>.${a}).`,data:{hosts:s}});for(let i of s)this.warned.add(i)}return ve({gatewayHost:o,appHosts:l})}async check(t){await B({cf:this.options.cf,out:this.options.out,step:"gateway.domains",zone:this.options.zone,domains:t,liveDomains:[...this.liveDomains,...this.checked],forceDns:this.options.forceDns,cfAsks:this.options.interactive&&this.options.out.verbose});for(let a of t)this.checked.add(a)}};async function ia(e){let{cf:t,reason:a,release:o,db:r}=e,l=e.heldLease?null:await Q(e,Xe[a]),n=e.heldLease??l,s=null;try{let i=await ne(r);i&&!e.allowDowngrade&&Ne(Qe(o),i,{allowDowngradeFlag:e.allowDowngradeFlag});let c=i!==null&&i.liveVersionId===null&&(await C(t,D)).includes(i.gatewayHost.toLowerCase());(!i||i.liveVersionId===null)&&await _(r,Oe(e,{liveVersionId:null,liveDomains:[],liveAppWorkers:[],jwtPublicKey:null,deploymentMode:null}));let p=new H(e,i?.liveDomains??[]),m=Se(t),d=i!==null&&et(o,i);if(a!=="reconcile"||!d){await $e(e,{appWorkers:[],appHosts:[]},async()=>{});let v=await z(r,m).catch(()=>null);await p.check(p.domainsFor(v?.appHosts??[])),c?e.out.emit({type:"step",step:"gateway.resume",status:"ok",message:`Replacing the Gateway an earlier run uploaded at ${i.gatewayHost}
|
|
16
|
+
That run stopped before it could finish; nothing uses that upload yet.`,data:{gatewayHost:i.gatewayHost}}):await le({cf:t,workerName:D,shownAs:"the Gateway",recordedVersionIds:[i?.liveVersionId],interactive:e.interactive,confirm:e.confirm,change:{question:`Replace it with ${o.manifest.version}?`,effect:"If it runs a newer release (an upgrade that stopped before recording itself), this puts an older one back."}}),await n.check(),s=await rt(e)}let w=i?.deploymentMode??e.deploymentMode;return await ot({...e,deploymentMode:w},p,m,{liveDomains:i?.liveDomains??[],liveVersionId:i?.liveVersionId??null},n)}catch(i){throw F(i,s)}finally{await l?.release()}}async function rt({cf:e,out:t,resources:a,release:o,accountId:r,db:l}){t.emit({type:"step",step:"gateway.migrations",status:"start",message:"Migrating the Gateway's database"});let n=await Ee({cf:e,databaseId:a.d1Id,accountId:r,dir:Je.join(o.dir,"drizzle"),registry:l,target:pe,restoreCommand:`${R} db restore --gateway`});return t.emit({type:"step",step:"gateway.migrations",status:"ok",message:n.fresh?"Database created":n.applied.length>0?`Applied ${O(n.applied.length,"migration")}.${Ce(n.rollback)}`:"Database up to date",data:Pe(n)}),n.rollback}async function ot(e,t,a,o,r){let{cf:l,out:n,release:s,db:i,gatewayHost:c}=e,p=await P(l,D)===null,m=p||o.liveVersionId===null,d=await z(i,a);for(let u of d.skipped)n.emit({type:"warning",code:"APP_NOT_BOUND",message:`Skipping ${u.appId}: its Worker isn't the one everyapp registered
|
|
17
|
+
So the Gateway won't route to it.`,data:{appId:u.appId,workerName:u.workerName,fix:`deploy ${u.appId} again, or remove it with ${R} delete ${u.appId}`}});for(let u of d.missing)n.emit({type:"warning",code:"APP_WORKER_MISSING",message:`Skipping ${u.appId}: its Worker is missing
|
|
18
|
+
It was deleted by hand or never uploaded, so the Gateway won't route to it.`,data:{appId:u.appId,workerName:u.workerName,fix:`deploy ${u.appId} again, or remove it with ${R} delete ${u.appId}`}});let w=t.domainsFor(d.appHosts);await t.check(w),await r.check(),n.emit({type:"step",step:"gateway.deploy",status:"start",message:`Uploading Gateway ${s.manifest.version} with ${O(d.appWorkers.length,"app")}`,data:{appWorkers:d.appWorkers,domains:w}});let v=e.deploymentMode??"self_hosted",b=m?oe({gatewayUrl:`https://${c}`,accountId:e.accountId,deploymentMode:v}):null,g=await nt(e,d,w,{before:o,secrets:{...b?.secrets,...e.stagedSecrets},jwtPublicKey:b?.jwtPublicKey??null,deploymentMode:b?v:null}),f=w.filter(u=>!t.liveDomains.includes(u));return n.emit({type:"step",step:"gateway.deploy",status:"ok",message:g.versionId?`Uploaded version ${g.versionId}`:"Uploaded",data:{versionId:g.versionId}}),{versionId:g.versionId,firstDeploy:p,appWorkers:d.appWorkers,domains:w,newHosts:f}}function nt(e,t,a,{before:o,secrets:r,jwtPublicKey:l,deploymentMode:n}){return $e(e,t,s=>ie({cf:e.cf,cwd:s,workerName:D,accountId:e.accountId,message:`everyapp ${e.cliVersion} gateway ${e.release.manifest.version} (${e.reason})`,secrets:r,interactive:e.interactive,attach:e.out.verbose,cliCf:!0,out:e.out,step:"gateway.deploy",onUploaded:(i,c)=>st(e,t,i,c?{liveDomains:a}:o,{jwtPublicKey:l,deploymentMode:n})}))}async function $e(e,t,a){let{dir:o,cleanup:r}=await q("gateway-deploy-");try{return await Ze.cp(e.release.dir,o,{recursive:!0}),await be(o,{d1Id:e.resources.d1Id,oauthKvId:e.resources.oauthKvId,release:{version:e.release.manifest.version,sha256:e.release.manifest.sha256},gatewayHost:e.gatewayHost,appBaseDomain:e.appBaseDomain,appWorkers:t.appWorkers,appHosts:T(t.appHosts,e.appBaseDomain)}),await a(o)}finally{await r()}}function st(e,t,a,o,r){return _(e.db,Oe(e,{liveVersionId:a,liveDomains:o.liveDomains,liveAppWorkers:t.appWorkers,...r}))}function Oe(e,t){return{accountId:e.accountId,zoneId:e.zone.id,zoneName:e.zone.name,gatewayHost:e.gatewayHost,appBaseDomain:e.appBaseDomain,oauthKvId:e.resources.oauthKvId,releaseVersion:e.release.manifest.version,releaseSha256:e.release.manifest.sha256,releaseOrder:e.release.source.order,sourceTreeSha256:e.release.source.treeSha256,...t,updatedAt:Date.now(),updatedBy:`everyapp ${e.cliVersion} on ${qe.hostname()}`}}export{gt as a,Me as b,B as c,Ct as d,Ee as e,Ce as f,Pe as g,Se as h,z as i,Qe as j,et as k,tt as l,sa as m,Ne as n,ia as o};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{a as I,c as N,d as T,e as C}from"./chunk-IZEOAOKL.js";import{a as W}from"./chunk-KMAOZRV4.js";import{ba as _,fa as k,k as A}from"./chunk-ZYL2ZHCF.js";import{e as P}from"./chunk-SPPR6WCI.js";import{b as R,c as $,dc as D,sb as b,tb as f}from"./chunk-SAT3PGZU.js";var g="app.live",M=6e5,F=3e3,B=15e3;var V={["deploy"]:"uploaded and bound"};async function G({db:i,appRowId:a,appId:t,hostname:e,out:r,verb:l,fetch:c,localDns:m=c?void 0:T,sleep:v=o=>new Promise(n=>setTimeout(n,o)),maxWaitMs:y=M,intervalMs:d=F,now:u=Date.now}){let o=`https://${e}/`,n=u(),p=!1,s=null,E,h=async()=>(p&&m&&await C({host:e,lead:`${t} is live at https://${e}`,out:r,step:g,localDns:m}),{outcome:"live",waited:E});for(;;){let S=await x(i,a,t);if(S==="active")return h();if(S==="disabled")return r.emit({type:"warning",code:"APP_DISABLED",step:g,message:`${t} is switched off in Admin \u2192 Apps
|
|
2
|
+
It's ${V[l]}; the Gateway serves it once an admin turns it on.`}),{outcome:"disabled"};let L=await N(o,c);if(L.answered){if(p=!0,L.access)return r.emit({type:"warning",code:"ACCESS_IN_FRONT",step:g,message:`Cloudflare Access answers before the Gateway, so this run can't confirm ${t} is live
|
|
3
|
+
It goes live on its first visit, once someone signs in through Access.`,data:{hostname:e}}),{outcome:"first_visit"};if(await x(i,a,t)==="active")return h()}let w=u()-n;if(w>=y){if(!p)return r.emit({type:"warning",code:"CERT_PENDING",step:g,message:`No certificate for ${e} after ${D(w)}
|
|
4
|
+
It usually comes within 5 minutes; ${t} goes live on its first visit once it has one.`,data:{hostname:e,fix:"if it never comes, check the zone's CAA records allow Cloudflare's certificate authorities"}}),{outcome:"first_visit"};throw new f("APP_NOT_LIVE",`${t} isn't live after ${D(w)}: the Gateway can't reach its Worker yet
|
|
5
|
+
${t} stays ${V[l]}.`,{retryable:!0,rerun:`${$} status`,rerunNote:`then ${l} again`})}(s===null||u()-s>=B)&&(E=p?"live":"certificate",r.emit({type:"progress",step:g,message:p?`Waiting for ${t} to go live`:`Waiting for the certificate for ${e} (usually under 5m)`,data:{hostname:e,waitedMs:w,answered:p}}),s=u()),await v(d)}}async function x(i,a,t){let e=await k(i,a);if(!e||e.status===P)throw new f("APP_NOT_FOUND",`${t} was deleted during this run
|
|
6
|
+
Someone removed it from the Gateway while this run waited for it to go live.`,{retryable:!0,rerunNote:"to put it back"});return e.status}function oe(i,a,t){let e=W({out:a,verbose:t});return{openRelease:i?.openRelease??e.open,source:i?.source??e.describe}}function ne(i,{manifest:a,install:t,deployer:e,accountName:r}){return _(i,{appSlug:a.id,name:a.name??a.id,description:a.description??a.id,manifest:a,appBaseDomain:t.appBaseDomain,deployer:e,organizationName:r??""})}var O={["deploy"]:"This app's upload is kept; deploying again binds it and makes it live."};async function pe({cf:i,db:a,databaseId:t,out:e,accountId:r,appId:l,workerName:c,publishHost:m,interactive:v,forceDns:y,seams:d,verb:u}){let o=await A(a);if(o?.liveAppWorkers.includes(c)&&!m)return;e.emit({type:"step",step:"app.bind",status:"start",message:`Binding ${b(c)} on the gateway${m?" and publishing its hostname":""}...`,data:{appId:l}});let n=(await d.source?.())?.version,p=n!==void 0&&o!==null&&n!==o.releaseVersion;p&&e.emit({type:"step",step:"gateway.upgrade",status:"start",message:`Upgrading the Gateway ${o.releaseVersion} \u2192 ${n}...`,data:{from:o.releaseVersion,to:n}});try{let s=await I({cf:i,out:e,accountId:r,databaseId:t,interactive:v,cliVersion:R,force:!0,forceDns:y,...d});p&&e.emit({type:"step",step:"gateway.upgrade",status:"ok",data:{to:n}}),e.emit({type:"step",step:"app.bind",status:"ok",message:`The gateway binds ${b(c)} (gateway version ${s.versionId??"unknown"}).`,data:{versionId:s.versionId,newHosts:s.newHosts}})}catch(s){throw s instanceof f&&s.code==="LEASE_HELD"?new f("LEASE_HELD",`${s.message}
|
|
7
|
+
${O[u]}`,{retryable:!0,rerunNote:"once the other deploy finishes",data:s.data}):s}}async function le({wait:i,db:a,appRowId:t,appId:e,hostname:r,out:l,seams:c,message:m,verb:v}){if(!i)return!1;let{outcome:y,waited:d}=await G({db:a,appRowId:t,appId:e,hostname:r,out:l,verb:v,...c});return y!=="live"?!1:(l.emit({type:"step",step:"app.live",status:"ok",message:m,data:{hostname:r,url:`https://${r}`,...d?{waited:d}:{}}}),!0)}function ce(i){return{url:i.liveUrl,workerName:i.workerName,versionId:i.versionId,live:i.live}}export{oe as a,ne as b,pe as c,le as d,ce as e};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as d}from"./chunk-Y3VIFPN5.js";import{G as p,V as f,c as l,hc as c,ib as m,sa as u,ta as g,ua as S}from"./chunk-SAT3PGZU.js";import a from"chalk";function $(e){return d(e,m)}async function C(e,n){return(await d(e,n)).filter(t=>!f(t))}function w(e,n=p){let t=n.unboundSettings?.();return t&&t.size>0?e.filter(r=>!t.has(r)):[...e]}function I(e){let n=e.lookup??p,t=e.gatewayNames===null?null:w(e.gatewayNames,n),r=g(u(e.manifest,n),(o,i)=>{let s=o==="gateway"?t:e.secretNames;return s===null?null:s.includes(i)});return{report:r,setup:S(r,{cli:l,appId:e.appId})}}function M(e,n=p){return u(e,n).some(t=>t.names.length>0)}function P(e,n=p){let t=new Set;for(let r of u(e,n))if(r.holder==="gateway")for(let o of[...r.names,...r.alsoReads])t.add(o);return[...t]}function O(e,n){let t=new Map,r=(o,i)=>{let s=t.get(o);s?s.required||=i:t.set(o,{name:o,required:i,set:n.includes(o)})};for(let o of e)if(o.holder==="gateway"){for(let i of o.names)r(i,o.need.kind!=="optional");for(let i of o.alsoReads)r(i,!1)}return[...t.values()]}function W(e,n){return e.filter(t=>t.holder==="gateway"&&t.blocking).flatMap(t=>t.names).filter((t,r,o)=>!n.includes(t)&&o.indexOf(t)===r)}var y=`${a.yellow("!")} not set`;function k(e){if(e.set===!0)return`${a.green("\u2713")} set`;if(e.set===null)return e.holder==="app"?`${a.yellow("!")} not recorded`:`${a.yellow("!")} couldn't check`;switch(e.need.kind){case"required":return y;case"optional":return a.dim("not set (optional)");case"anyOf":return e.blocking?y:a.dim(`not set (one of: ${e.need.group})`)}}function h(e){return e.names.join("+")}function A(e,n){return n.filter(t=>t.names.length>0).map(t=>({app:e,setting:h(t),where:t.holder==="gateway"?"Gateway":e,status:k(t)}))}function U(e,n,t){return A(e,t.filter(r=>r.holder==="app")).map(r=>({...r,where:`${n} helper`}))}function _(e,{app:n=!0}={}){return n?c(["APP","SETTING","WHERE","STATUS"],e.map(t=>[t.app,t.setting,t.where,t.status])):c(["SETTING","WHERE","STATUS"],e.map(t=>[t.setting,t.where,t.status]))}function b(e){let n=e.names.join(" and "),t=e.why??(e.label===n?void 0:n);return[t?`${e.label}: ${t}`:e.label,...e.hint?[e.hint]:[],...e.docs?[`Get it at ${e.docs}`]:[]]}var R=".claude/skills/everyapp";function N(e){return e.setup?`Guide: ${R}/${e.setup}`:e.kind==="capability"||e.kind==="provider"?`Guide: ${l} provider show ${e.id}`:null}function q(e){let n=new Set;return e.flatMap(t=>{let r=b(t),o=N(t);return!o||n.has(o)?r:(n.add(o),[...r,o])})}function j(e){let n=[],t=r=>{for(let o of r.names)n.includes(o)||n.push(o)};for(let r of e.unmet)r.need.kind==="required"&&t(r);for(let r of e.groups){if(r.met)continue;let o=e.unmet.find(i=>i.id===r.members[0]);o&&t(o)}return n}export{$ as a,C as b,w as c,I as d,M as e,P as f,O as g,W as h,k as i,A as j,U as k,_ as l,b as m,N as n,q as o,j as p};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{createHash as c,randomBytes as d,randomUUID as l}from"node:crypto";import{setTimeout as p}from"node:timers/promises";import{execa as g}from"execa";var w=24*60*60*1e3,_=e=>c("sha256").update(e).digest("hex"),u=`SELECT users.email AS email, organizations.name AS organization_name, organizations.id AS organization_id
|
|
2
|
+
FROM members
|
|
3
|
+
JOIN users ON users.id = members.user_id
|
|
4
|
+
JOIN organizations ON organizations.id = members.organization_id
|
|
5
|
+
WHERE members.role = 'owner'`;function m(e){return!e||typeof e.email!="string"?null:{email:e.email,organizationName:String(e.organization_name??"")}}async function S(e){let[n=[]]=await e.run([{sql:`${u} ORDER BY organizations.created_at, organizations.id, members.created_at LIMIT 1`}]),t=m(n[0]);return t?{owner:t,organizationId:String(n[0].organization_id)}:null}async function O(e){return(await S(e))?.owner??null}async function x({db:e,gatewayUrl:n,now:t=Date.now()}){let r=`est_${d(32).toString("base64url")}`,i=l(),a=t+w,[s=[]]=await e.run([{sql:"SELECT id FROM owner_setup_tokens WHERE kind = 'claim' AND consumed_at IS NULL AND expires_at > ?1",params:[t]},{sql:"UPDATE owner_setup_tokens SET expires_at = ?1 WHERE kind = 'claim' AND consumed_at IS NULL AND expires_at > ?1",params:[t]},{sql:"INSERT INTO owner_setup_tokens (id, kind, token_hash, expires_at) VALUES (?, 'claim', ?, ?)",params:[i,_(r),a]}]);return{id:i,url:`${n.replace(/\/$/,"")}/setup#token=${r}`,expiresAt:new Date(a),replaced:s.length>0}}async function f(e,n,t=Date.now()){let[r=[],i=[]]=await e.run([{sql:"SELECT consumed_at, expires_at FROM owner_setup_tokens WHERE id = ?",params:[n]},{sql:`${u} AND members.user_id = (SELECT consumed_by FROM owner_setup_tokens WHERE id = ?) LIMIT 1`,params:[n]}]),a=r[0];return a&&a.consumed_at!==null&&a.consumed_at!==void 0?{status:"claimed",owner:m(i[0])}:!a||Number(a.expires_at)<=t?{status:"gone"}:{status:"waiting"}}var b=15*60*1e3,E=5e3;async function y({db:e,id:n,timeoutMs:t=b,intervalMs:r=E,sleep:i=p,now:a=Date.now}){let s=a()+t;for(;;){let o=await f(e,n,a());if(o.status!=="waiting"||a()>=s)return o;await i(r)}}function N({terminal:e=!!process.stdout.isTTY,relayed:n=!1}={}){return process.env.CI?!1:e||n}async function I(e){let[n,t]=process.platform==="darwin"?["open",[e]]:process.platform==="win32"?["cmd",["/c","start","",e]]:["xdg-open",[e]];try{await g(n,t,{stdio:"ignore"})}catch{}}export{S as a,O as b,x as c,y as d,N as e,I as f};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as p,s as u,u as f,v as d}from"./chunk-JYKRUS5C.js";import{Vb as i,Wb as c,zb as a}from"./chunk-SAT3PGZU.js";var l=20,g=10;async function y(n){let r=new Map;for(let e=1;e<=g;e+=1){let o=await i(n,{plane:"account",args:["hyperdrive","list","--per-page",String(l),"--page",String(e)]},d),t=r.size;for(let s of o)r.set(s.id,s);if(o.length<l||r.size===t)break}return[...r.values()]}async function H(n,r){return(await y(n)).find(e=>e.name===r)??null}async function b(n,r,e,o="off"){return(await i(n,{plane:"account",files:{"hyperdrive.json":{name:r,origin:e,...o==="off"?{caching:{disabled:!0}}:{}}},args:s=>["hyperdrive","create","--body",`@${s["hyperdrive.json"]}`]},f)).id}async function P(n,r,e){let o={...e.origin?{origin:e.origin}:{},...e.caching?{caching:{disabled:e.caching==="off"}}:{}};await i(n,{plane:"account",files:{"hyperdrive.json":o},args:t=>["hyperdrive","update",r,"--body",`@${t["hyperdrive.json"]}`]},f)}async function k(n,r){await n.run({plane:"account",mode:"json",args:["hyperdrive","delete",r,"--force"]})}function x(n,r){return n.caching?.disabled===!0==(r==="off")}function R(n,r){let e=n.origin;return e?.host===r.host&&(e.port??null)===r.port&&e.database===r.database&&e.user===r.user}var v=100,w=50;async function S(n,r){try{return await i(n,{plane:"account",args:["workflows","get",r]},p)}catch(e){if(a(e,"not_found"))return null;throw e}}function j(n,r){return c(n,["workflows","list","--search",r],u,{perPage:v,maxPages:w})}async function C(n,r){await n.run({plane:"account",mode:"json",args:["workflows","delete",r,"--force"]})}async function _(n,r){try{return await C(n,r),!0}catch(e){if(a(e,"not_found"))return!1;throw e}}export{y as a,H as b,b as c,P as d,k as e,x as f,R as g,S as h,j as i,_ as j};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{e as m,f as d}from"./chunk-ECLJ5IAL.js";import{qa as l,sa as p}from"./chunk-ZYL2ZHCF.js";import{a as i}from"./chunk-F6IH47GT.js";import{tb as o}from"./chunk-SAT3PGZU.js";import s from"chalk";async function b(e){let{flags:t,out:r,createCf:n}=e,a=await p({gateway:l(t.gateway),accountId:t["account-id"],interactive:i(t.json??!1),login:{json:t.json,out:r,step:"login"},createCf:n}),g=await m(a.db,a.deployer,{org:t.org,now:e.now?.()});return{gateway:a,ws:g,gatewayUrl:a.gatewayUrl}}function x(e){return e.interactive??i(e.flags.json??!1)}async function W(e,t){try{let r=await d(e,t);return{id:r.id,email:r.email,member:!0}}catch(r){if(!(r instanceof o)||r.code!=="USER_NOT_FOUND"||t.includes("@"))throw r;return{id:t.trim(),email:null,member:!1}}}var v=e=>e.member?e.email??e.id:`${e.id} (no longer a member)`;function F(e){return e===null?s.dim("never"):new Date(e).toISOString().slice(0,16).replace("T"," ")}var c=e=>e===null?null:new Date(e).toISOString();function C(e){return e.deactivated?s.yellow("deactivated"):s.green("active")}function h(e){return{id:e.id,email:e.email,name:e.name,role:e.primaryRole??e.role,deactivated:e.deactivated,createdAt:c(e.createdAt)}}function O(e){return{id:e.id,email:e.email,role:e.role,status:e.status,expiresAt:c(e.expiresAt),expired:!e.live&&e.status==="pending",createdAt:c(e.createdAt)}}function A(e){let{add:t,remove:r,set:n}=e;if(n&&(t||r))throw new o("FLAGS_CONFLICT","--set replaces the whole list: give it alone, or --add and --remove without it");return!t&&!r&&!n?{change:null}:{change:{add:t,remove:r,set:n}}}export{b as a,x as b,W as c,v as d,F as e,c as f,C as g,h,O as i,A as j};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d}from"./chunk-RFVMR32Y.js";import{o as u,p as f}from"./chunk-JYKRUS5C.js";import{Vb as i,Wb as l,d as c,tb as a}from"./chunk-SAT3PGZU.js";function $(n,t,r){return i(n,{plane:"account",args:["dns","records","list","-z",t,"--name-exact",r,"--per-page","100"]},f)}async function v(n,t,r){await n.run({plane:"account",mode:"json",args:["dns","records","delete",r,"-z",t,"--force"]})}function y(n){return`*.${n.slice(n.indexOf(".")+1)}`}function z(n){return`${n.type}${n.content?` ${n.content}`:""}`}var p=50,g=20;function C(n){return`https://dash.cloudflare.com/${n}/domains/overview`}async function _(n,t,r){let o=d(t),e=await w(n,t,r);if(!e)throw new a("ZONE_NOT_FOUND",`No zone in this Cloudflare account holds ${t}
|
|
2
|
+
Looked for ${o.join(", ")}. Buy a domain in the dashboard (Domains, ${C(r)}), or add one you own and point its nameservers at Cloudflare.`,{fix:"use a domain that is on Cloudflare in this account"});if(e.status&&e.status!=="active")throw new a("ZONE_NOT_ACTIVE",`The Cloudflare zone ${e.name} is ${e.status}, not active`,{fix:`finish its nameserver setup (Cloudflare dashboard \u2192 ${e.name} \u2192 Overview)`,rerun:c()});return{id:e.id,name:e.name}}async function w(n,t,r){let e=(await Promise.all(d(t).map(async s=>(await i(n,{plane:"account",args:["zones","list","--name",s,"--account-id",r]},u)).find(m=>m.name.toLowerCase()===s)??null))).find(s=>s!==null);return e?{id:e.id,name:e.name.toLowerCase(),status:e.status??null}:null}function A(n,t){return`https://dash.cloudflare.com/${n}/${t}`}async function D(n,t){return(await l(n,["zones","list","--account-id",t],u,{perPage:p,maxPages:g})).map(o=>({id:o.id,name:o.name.toLowerCase(),status:o.status??null}))}export{$ as a,v as b,y as c,z as d,C as e,_ as f,w as g,A as h,D as i};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import{tb as o}from"./chunk-SAT3PGZU.js";var a=[{sql:`CREATE TABLE IF NOT EXISTS _everyapp_app_resources (
|
|
2
|
+
worker_name TEXT NOT NULL,
|
|
3
|
+
kind TEXT NOT NULL,
|
|
4
|
+
binding TEXT NOT NULL,
|
|
5
|
+
name TEXT NOT NULL,
|
|
6
|
+
resource_id TEXT,
|
|
7
|
+
created_at INTEGER NOT NULL,
|
|
8
|
+
-- The Worker's row: the last version a deploy uploaded.
|
|
9
|
+
version_id TEXT,
|
|
10
|
+
PRIMARY KEY (worker_name, kind, binding)
|
|
11
|
+
)`},{sql:"CREATE UNIQUE INDEX IF NOT EXISTS _everyapp_app_resources_id ON _everyapp_app_resources (kind, resource_id)"},{sql:"CREATE UNIQUE INDEX IF NOT EXISTS _everyapp_app_resources_name ON _everyapp_app_resources (kind, name)"}],t={worker:"Worker",d1:"D1 database",kv:"KV namespace",hyperdrive:"Hyperdrive config",r2:"R2 bucket","email-route":"Email Routing route for"};async function u(e,r){return((await e.run([...a,{sql:"SELECT kind, binding, name, resource_id, version_id FROM _everyapp_app_resources WHERE worker_name = ? ORDER BY kind, binding",params:[r]}])).at(-1)??[]).map(i=>({...s(i),versionId:i.version_id==null?null:String(i.version_id)}))}function s(e){return{kind:String(e.kind),binding:String(e.binding),name:String(e.name),resourceId:e.resource_id===null?null:String(e.resource_id)}}async function _(e,r){return((await e.run([...a,{sql:"SELECT worker_name, binding, name, resource_id FROM _everyapp_app_resources WHERE kind = ? ORDER BY worker_name, binding",params:[r]}])).at(-1)??[]).map(i=>({workerName:String(i.worker_name),...s({...i,kind:r})}))}async function E(e){let[r=[]]=await e.run([{sql:"SELECT name FROM sqlite_master WHERE type = 'table' AND name = '_everyapp_app_resources'"}]);if(r.length===0)return[];let[n=[]]=await e.run([{sql:"SELECT worker_name, kind, binding, name, resource_id FROM _everyapp_app_resources ORDER BY worker_name, kind, binding"}]);return n.map(i=>({workerName:String(i.worker_name),...s(i)}))}async function m(e,r,n,i=""){await e.run([...a,{sql:"UPDATE _everyapp_app_resources SET version_id = ? WHERE worker_name = ? AND kind = 'worker' AND binding = ?",params:[n,r,i]}])}async function R(e,r,n){try{await e.run([...a,{sql:`INSERT INTO _everyapp_app_resources (worker_name, kind, binding, name, resource_id, created_at)
|
|
12
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
|
13
|
+
ON CONFLICT (worker_name, kind, binding) DO UPDATE SET name = excluded.name,
|
|
14
|
+
resource_id = excluded.resource_id`,params:[r,n.kind,n.binding,n.name,n.resourceId,Date.now()]}])}catch(i){throw c(i)?new o("RESOURCE_OWNED",`${d(n)} is recorded as another app's
|
|
15
|
+
${r} can't use it.`,{fix:"rename the binding in everyapp.config.ts"}):i}}async function g(e,r,n){await e.run([...a,n?{sql:"DELETE FROM _everyapp_app_resources WHERE worker_name = ? AND kind = ? AND binding = ?",params:[r,n.kind,n.binding]}:{sql:"DELETE FROM _everyapp_app_resources WHERE worker_name = ?",params:[r]}])}function d({kind:e,name:r}){return`${t[e]} "${r}"`}function c(e){let r=e instanceof Error?e.message:"";return/UNIQUE constraint failed/i.test(r)}export{t as a,u as b,_ as c,E as d,m as e,R as f,g,d as h};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{b as v}from"./chunk-RFVMR32Y.js";import{f as _}from"./chunk-DQWOXSL3.js";import{Qb as h,Rb as S,rb as k,sb as O,tb as c}from"./chunk-SAT3PGZU.js";import E from"node:fs/promises";import d from"node:path";import{OutputWorkerSchema as b}from"@cloudflare/config";import R from"node:fs/promises";import g from"node:path";var L=g.join(".cloudflare","output","v0"),A=g.join(L,"workers"),D="default";async function*ie(e){let t=g.join(e,A);for(let n of await R.readdir(t,{withFileTypes:!0})){if(!n.isDirectory())continue;let r=g.join(t,n.name),i=g.join(r,"worker.config.json"),o=JSON.parse(await R.readFile(i,"utf8"));yield{name:n.name,directory:r,file:i,config:o}}}async function oe(e){let t=JSON.parse(await R.readFile(g.join(e,"config.json"),"utf8"));return t.buildContext?.mode==="production"&&!t.buildContext.isPreview}var I=d.join(A,D),j=d.join(I,"worker.config.json"),C=d.join(I,"bundle"),N="__EVERYAPP_PATCH__",B="every-app-gateway";function U(e){return[e.gatewayHost,...[...new Set(e.appHosts)].filter(t=>t!==e.gatewayHost).sort()]}async function ge(e,t){let n=d.join(e,j),r=JSON.parse(await E.readFile(n,"utf8")),i={...r.env??{}};for(let a of Object.keys(i))a.startsWith(k)&&delete i[a];delete i.KV,i.DB={type:"d1",name:B,id:t.d1Id},i.OAUTH_KV={type:"kv",id:t.oauthKvId},i.EVERYAPP_RELEASE={type:"json",value:t.release},i.CF_VERSION_METADATA={type:"version-metadata"};for(let a of[...new Set(t.appWorkers)].sort())i[O(a)]={type:"worker",worker:a};if(r.env=i,t.gatewayHost!==t.appBaseDomain)throw new c("INVALID_APP_BASE_DOMAIN",`Apps live one label below the gateway host ${t.gatewayHost}, so APP_BASE_DOMAIN must be ${t.gatewayHost}, not ${t.appBaseDomain}.`);let o=t.appHosts.filter(a=>!v(a,t.appBaseDomain));if(o.length>0)throw new c("INVALID_APP_HOST",`Refusing to publish ${o.join(", ")} on the gateway: app hosts are one label below ${t.appBaseDomain}.`);i.APP_BASE_DOMAIN={type:"text",value:t.appBaseDomain},r.domains=U(t);let s=(r.triggers??[]).filter(a=>a.type!=="fetch");if(s.length>0?r.triggers=s:delete r.triggers,r.workersDev=!1,r.previewUrls=!1,r.observability??=structuredClone(_),r.manifest){let a={...r.manifest.modules??{}};for(let w of await F(d.join(e,C)))a[w]={type:"sourcemap"};r.manifest={...r.manifest,modules:a}}return V(r,{requireDomain:!0}),await E.writeFile(n,`${JSON.stringify(r,null,2)}
|
|
2
|
+
`),r}function V(e,{requireDomain:t=!1}={}){let n=b.safeParse(e);if(!n.success)throw new c("INVALID_BUILD_OUTPUT",`The patched Worker config isn't valid Build Output: ${n.error.issues.map(r=>`${r.path.join(".")||"(root)"}: ${r.message}`).join("; ")}`);if(JSON.stringify(e).includes(N))throw new c("INVALID_BUILD_OUTPUT","The Worker config still has a deploy-time placeholder.");if(t&&!n.data.domains?.length)throw new c("INVALID_BUILD_OUTPUT","The gateway has no domain to deploy to.")}async function F(e){let t;try{t=await E.readdir(e,{recursive:!0,withFileTypes:!0})}catch{return[]}return t.filter(n=>n.isFile()&&n.name.endsWith(".map")).map(n=>d.relative(e,d.join(n.parentPath,n.name)).split(d.sep).join("/")).sort()}import{spawn as W}from"node:child_process";import{createHash as $}from"node:crypto";import m from"node:fs/promises";import p from"node:path";import{z as l}from"zod";var Se="every-app-gateway-release.tar.gz",x="v0",M={gateway:new Set([".cloudflare","drizzle","release.json"]),app:new Set([".cloudflare","migrations","release.json"])},H=l.looseObject({schema:l.literal(1),kind:l.string().optional(),version:l.string(),gitSha:l.string(),builtAt:l.string(),cfVersion:l.string(),buildOutputVersion:l.string(),sha256:l.string().regex(/^[0-9a-f]{64}$/),migrations:l.array(l.object({tag:l.string(),when:l.number()})),minCli:l.string(),minSdk:l.string()}),G=H.extend({committedAt:l.string().optional(),pluginVersion:l.string(),configVersion:l.string()});function _e({version:e,commit:t}){return t?`commit ${t.hash}${t.uncommittedChanges?" with uncommitted changes":""}`:e}function ve(e){switch(e.kind){case"checkout":return"this checkout";case"github":return`${e.repo} release ${e.tag}`;case"url":return e.url;case"file":return e.path}}async function K(e){let t=(await m.readdir(e,{recursive:!0,withFileTypes:!0})).filter(n=>n.isFile()).map(n=>p.relative(e,p.join(n.parentPath,n.name)).split(p.sep).join("/")).filter(n=>n!=="release.json");return z(e,t)}async function z(e,t){let n=$("sha256");for(let r of[...t].sort()){let i;try{i=await m.readFile(p.join(e,r))}catch(o){if(!h(o))throw o;n.update(`${r}\0-
|
|
3
|
+
`);continue}n.update(`${r}\0${$("sha256").update(i).digest("hex")}
|
|
4
|
+
`)}return n.digest("hex")}function J(e,t){return new Promise((n,r)=>{let i=W("tar",["-xzf",e,"-C",t],{stdio:"ignore"});i.once("error",r),i.once("close",o=>o===0?n():r(new Error(`tar couldn't extract ${e} (exit ${o})`)))})}async function Y(e,t,n){let r=await m.readdir(e,{recursive:!0,withFileTypes:!0});for(let i of r){let o=p.join(i.parentPath,i.name),s=p.relative(e,o).split(p.sep).join("/");if(i.isSymbolicLink()||!(i.isFile()||i.isDirectory()))throw new c("RELEASE_INVALID",`${t} isn't ${n}: ${s} is a link or a special file, not a regular file.`);if(i.isFile()&&(await m.lstat(o)).nlink>1)throw new c("RELEASE_INVALID",`${t} isn't ${n}: ${s} is a hard link, not a regular file.`)}}function q(e){return typeof e=="string"&&e.length>0&&!p.isAbsolute(e)&&!/[\\\0-\x1f]/.test(e)&&e.split("/").every(t=>t!==""&&t!=="."&&t!=="..")}async function X(e,t,n){let r=p.join(e,".cloudflare","output","v0","workers"),i;try{i=await m.readdir(r)}catch(o){if(h(o))return;throw o}for(let o of i){let s;try{s=JSON.parse(await m.readFile(p.join(r,o,"worker.config.json"),"utf8"))}catch(u){if(h(u))continue;throw u}let a=s?.manifest,f=[a?.mainModule,...Object.keys(a?.modules&&typeof a.modules=="object"?a.modules:{})].filter(u=>u!==void 0).find(u=>!q(u));if(f!==void 0)throw new c("RELEASE_INVALID",`${t} isn't ${n}: its ${o} Worker lists a module outside its bundle: ${String(f)}.`)}}var T={gateway:{a:"a gateway release",the:"Gateway release"},app:{a:"an app release",the:"App release"}};async function Z(e,t,n){let r=T[t],{dir:i,cleanup:o}=await S(`${t}-release-`);try{await J(e,i),await Y(i,e,r.a),await X(i,e,r.a);let s=JSON.parse(await m.readFile(p.join(i,"release.json"),"utf8")),a=s?.kind??"gateway";if(a!==t){let y=a==="app"||a==="gateway"?T[a].a:`a ${String(a)} release`;throw new c("RELEASE_INVALID",`${e} is ${y}, not ${t==="gateway"?"a Gateway release":r.a}.`)}let w=(await m.readdir(i)).filter(y=>!M[t].has(y));if(w.length>0)throw new c("RELEASE_INVALID",`${e} holds more than ${r.a}: ${w.join(", ")}.`);let f=n.safeParse(s);if(!f.success)throw new c("RELEASE_INVALID",`${e} isn't a valid ${r.the.toLowerCase()}
|
|
5
|
+
Its release.json is malformed: ${f.error.issues[0]?.message}`);let u=f.data;if(u.buildOutputVersion!==x)throw new c("RELEASE_UNSUPPORTED",`${r.the} ${u.version} needs a newer everyapp`,{fix:"update everyapp (in a checkout: git pull), then run this again",data:{buildOutputVersion:u.buildOutputVersion,supported:x}});let P=await K(i);if(P!==u.sha256)throw new c("RELEASE_CORRUPT",`${r.the} ${u.version} doesn't match its checksum
|
|
6
|
+
The download may be damaged. Download it again.`,{data:{expected:u.sha256,actual:P}});return{dir:i,manifest:u,cleanup:o}}catch(s){throw await o(),s instanceof SyntaxError||h(s)?new c("RELEASE_INVALID",`${e} isn't ${r.a}: ${s.message}`):s}}async function De(e,t={origin:{kind:"file",path:e}}){let{dir:n,manifest:r,cleanup:i}=await Z(e,"gateway",G),o=Q(r),s={treeSha256:t.treeSha256??null,order:{...o,committedAt:t.committedAt??o.committedAt},origin:t.origin};return{dir:n,tarball:e,manifest:r,source:s,cleanup:i}}function Q(e){return{schema:ee(e.migrations),committedAt:Date.parse(e.committedAt??"")||Date.parse(e.builtAt)||0}}function Ie(e,t,n=`Gateway ${e.version}`){if(te(e.minCli,t)>0)throw new c("CLI_TOO_OLD",`${n} needs everyapp ${e.minCli} or newer (this is ${t})`,{fix:"update everyapp (in a checkout: git pull), then run this again",data:{minCli:e.minCli,cliVersion:t}})}function ee(e){return Math.max(0,...e.map(t=>t.when))}function $e(e,t){return e.schema-t.schema||e.committedAt-t.committedAt}function te(e,t){let n=o=>o.replace(/^v/,"").split("-")[0].split(".").map(s=>Number.parseInt(s,10)||0),[r,i]=[n(e),n(t)];for(let o=0;o<Math.max(r.length,i.length);o+=1){let s=(r[o]??0)-(i[o]??0);if(s!==0)return s}return 0}export{Se as a,H as b,_e as c,ve as d,K as e,z as f,Z as g,De as h,Ie as i,ee as j,$e as k,L as l,D as m,ie as n,oe as o,U as p,ge as q,V as r,F as s};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import{a as Te,b as tt,c as nt,d as Le,e as q}from"./chunk-E3EPK27P.js";import{z as Me}from"./chunk-IG26HYRR.js";import{A as Q,B as Z,C as Xe,D as Ke,E as Qe,F as Ce,G as Ee,H as ve,I as De,J as Oe,K as ke,L as et,M as Pe,N as me,O as ct,b as Ae,c as We,d as je,e as we,f as Be,g as He,h as $e,i as Ve,k as Ye,l as ie,m as Ze,n as be,o as Se,p as qe,q as xe,r as ce,s as Ie,t as K,u as le,v as re,w as Y,x as de,y as Je,z as _e}from"./chunk-6O3GJS5H.js";import{a as oe}from"./chunk-Y3VIFPN5.js";import{c as it,e as ot}from"./chunk-EUNGJMJ6.js";import{$ as dt,B as rt,qa as pt,sa as mt,y as lt}from"./chunk-ZYL2ZHCF.js";import{a as pe,f as st,i as at}from"./chunk-F6IH47GT.js";import{c as H,f as V,gc as Re,ib as ae,jc as ne,k as A,oc as ue,tb as z,yb as Fe}from"./chunk-SAT3PGZU.js";import u from"chalk";var x="Every App gateway members",ut="Every App gateway",It="Every App apps",_t="720h",tn=24*3600,D="access.update";async function nn(t){await ue(t,e=>Dt({flags:t,out:e,emails:t.email,emailDomains:t["email-domain"],team:t.team,session:t.session,teamSession:t["team-session"],writeSettings:t["write-settings"]}))}async function sn(t){await ue(t,e=>Tt({flags:t,out:e,keepApplications:t["keep-applications"]}))}async function an(t){await ue(t,e=>Lt({flags:t,out:e}))}var Ct=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,Et=/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9-]{2,63}$/,ht=/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;function Ge({flags:t,out:e,createCf:s}){return mt({gateway:pt(t.gateway),accountId:t["account-id"],interactive:pe(t.json??!1),login:{json:t.json,out:e,step:"login"},createCf:s})}function ft(t){if(t.deploymentMode==="hosted")throw new z("ACCESS_HOSTED",`This Gateway can't be put behind Cloudflare Access
|
|
2
|
+
Hosted Gateways ignore the Access settings.`)}function gt(t,e){let s=e.trim(),n=et(s);if(n===null||n<=0)throw new z("ACCESS_SESSION_INVALID",`${t} ${e} isn't a duration Access takes
|
|
3
|
+
Use hours and minutes, like 720h or 2h30m.`);return s}async function yt(t,e){let s="(u.banned IS NULL OR u.banned = 0 OR (u.ban_expires IS NOT NULL AND u.ban_expires <= ?1))",[n=[],m=[],f=[]]=await t.run([{sql:`SELECT u.email FROM users u WHERE ${s} ORDER BY u.email`,params:[e]},{sql:"SELECT DISTINCT email FROM invitations WHERE status = 'pending' AND expires_at > ?1 ORDER BY email",params:[e]},{sql:`SELECT u.email FROM users u
|
|
4
|
+
WHERE ${s}
|
|
5
|
+
AND EXISTS (SELECT 1 FROM accounts a WHERE a.user_id = u.id AND a.provider_id = 'credential')
|
|
6
|
+
AND NOT EXISTS (SELECT 1 FROM accounts a WHERE a.user_id = u.id AND a.provider_id = 'cloudflare-access')
|
|
7
|
+
ORDER BY u.email`,params:[e]}]),y=g=>[...new Set(g.map(l=>String(l.email).toLowerCase()))];return{members:y(n),invited:y(m),toLink:y(f)}}function vt(t,e){let s=[],n=[],m=[];for(let f of t){let y=f.trim().toLowerCase();if(!Ct.test(y))throw new z("ACCESS_EMAIL_INVALID",`--email ${f} isn't an email address`);s.push(de(y)),n.push(y)}for(let f of e){let y=f.trim().toLowerCase().replace(/^@/,"");if(!Et.test(y))throw new z("ACCESS_DOMAIN_INVALID",`--email-domain ${f} isn't a domain
|
|
8
|
+
Use the part after the @, like example.com.`);s.push(Je(y)),m.push(y)}return{rules:s,emails:n,domains:m}}async function Dt(t){let{out:e}=t,s=t.now??Date.now,n=t.session===void 0?_t:gt("--session",t.session),m=t.teamSession===void 0?null:gt("--team-session",t.teamSession),f=vt(t.emails??[],t.emailDomains??[]),y=t.interactive??pe(t.flags.json??!1);e.emit({type:"step",step:D,status:"start",message:"Checking Cloudflare Access..."});let g=await Ge(t),{cf:l,db:I,install:w}=g;ft(w);let r=me(w),{gatewayHost:_,appBaseDomain:C}=r,b=await yt(I,s()),h=[...b.members.map(de),...b.invited.map(de),...f.rules],c=await Ae(l),$=c?(await $e(l)).find(o=>o.name===x)??null:null;if(h.length===0&&!$)throw new z("ACCESS_NOBODY_ALLOWED",`Nobody to let in yet
|
|
9
|
+
The Gateway has no members or invitations, and no --email was given, so the Access policy would let nobody in. Claim the Gateway first, or name who will (the setup link is then behind Access too).`,{rerun:`${H} access on --email <your address>`});let O=f.emails.filter(o=>!b.members.includes(o)&&!b.invited.includes(o));O.length>0&&e.emit({type:"warning",code:"ACCESS_EMAIL_NOT_INVITED",step:D,message:`${A(O)} ${O.length===1?"has":"have"} no account on this Gateway
|
|
10
|
+
Access will let ${O.length===1,"them"} through, but the Gateway refuses anyone it doesn't know. Invite ${O.length===1,"them"} in Manage workspace \u2192 Users.`,data:{emails:O}});let S=!1,a=null;if(c)m!==null&&c.session_duration!==m&&(e.emit({type:"progress",step:D,message:`Setting the team's global session to ${m}`}),c=await je(l,c,m),a=m);else{let o=w.zoneName.split(".")[0].toLowerCase().replace(/[^a-z0-9-]/g,"")||"every-app",E=t.team;if(E===void 0){if(!y)throw new z("ACCESS_TEAM_REQUIRED",`Choose a name for the Zero Trust team with --team
|
|
11
|
+
This Cloudflare account has none yet. Its sign-in page becomes https://<name>.cloudflareaccess.com and can't be changed later.`,{fix:`add --team ${o}, or another name`,data:{suggested:o}});E=await(t.askTeam??Ot)(o)}if(!ht.test(E))throw new z("ACCESS_TEAM_INVALID",`${t.team===void 0?"":"--team "}${E} can't be a team name
|
|
12
|
+
Use lowercase letters, digits and dashes: it becomes <name>.cloudflareaccess.com.`);e.emit({type:"progress",step:D,message:`Creating the Zero Trust team ${E}.cloudflareaccess.com`});try{c=await We(l,{name:E,auth_domain:`${E}.cloudflareaccess.com`,session_duration:m??n})}catch(B){throw!(B instanceof Fe)||B.kind==="auth"?B:new z("ACCESS_TEAM_CREATE_FAILED",`Cloudflare didn't create the Zero Trust team ${E}
|
|
13
|
+
${B.message.split(`
|
|
14
|
+
`)[0]}`,{fix:"pick another name with --team: team names are shared across Cloudflare",data:{team:E}})}S=!0,a=m??n}let v=c.auth_domain.toLowerCase(),i=await we(l),d=Ce(i),T=!1,W=!1;d.cloudflare&&(e.emit({type:"progress",step:D,message:"Adding Sign in with Cloudflare (members of this Cloudflare account)"}),i=[...i,await He(l)],T=!0),d.pin&&(e.emit({type:"progress",step:D,message:"Adding the one-time PIN identity provider"}),i=[...i,await Be(l)],W=!0);let ee=De(i),j=i.filter(o=>Qe.includes(o.type));j.length>0&&e.emit({type:"warning",code:"ACCESS_IDP_UNVERIFIED_EMAILS",step:D,message:`${A(j.map(o=>`${o.name??o.id} (${o.type})`))} ${j.length===1?"is a generic provider, left off the Every App applications":"are generic providers, left off the Every App applications"}
|
|
15
|
+
The Gateway signs people in as the email Access asserts. A provider that lets people choose their own address would let them choose someone else's; allow only providers that verify addresses (runbook: "Verified emails").`,data:{providers:j.map(o=>({id:o.id,type:o.type,name:o.name??null}))}}),wt(e,i);let L=g.deployer.email?.toLowerCase()??null;L!==null&&!b.members.includes(L)&&!b.invited.includes(L)&&!f.emails.includes(L)&&e.emit({type:"warning",code:"ACCESS_LOGIN_NOT_MEMBER",step:D,message:`Sign in with Cloudflare signs you in as ${L}, which has no account on this Gateway
|
|
16
|
+
Access asserts your Cloudflare login's address, and the Gateway refuses anyone it doesn't know. Sign in with the code Access emails to your Gateway account's address instead, or invite ${L} in Manage workspace \u2192 Users.`,data:{email:L}});let k,M=!1,P=[];if($){let o=_e($.include??[],h);o.added.length>0?(e.emit({type:"progress",step:D,message:`Adding ${V(o.added.length,"rule")} to the Access policy`}),k=await Ye(l,$,o.include),P=o.added):k=$}else{let o=_e([],h);e.emit({type:"progress",step:D,message:`Creating the Access policy "${x}"`}),k=await Ve(l,{name:x,decision:"allow",include:o.include}),M=!0,P=o.include}let J=await it({db:I,id:ot,purpose:"access.sync",out:e,step:"gateway.lease"}),R,F,X,te,N;try{let o=re(await ie(l),r),E=Y(o.gateway);N=Ie(C,await Pe(I),{managedOAuth:E}),X=o.gateway!==null&&o.apps!==null&&o.gateway.id===o.apps.id;let B=[],fe=U=>{if(!U)return;let ze=K(U.destinations??[],r).foreign;ze.length>0&&B.push({application:U.name??U.id,uris:ze.map(St=>St.uri??"(private)")})},ye={scope:r,policyId:k.id,session:n,sessionGiven:t.session!==void 0,allowedIdps:ee.map(U=>U.id)};if(X){e.emit({type:"warning",code:"ACCESS_ONE_APPLICATION",step:D,message:`One Access application covers ${_} and *.${C}
|
|
17
|
+
It is kept and updated. The runbook recommends two, so an app host's Access cookie is never a Gateway login.`}),fe(o.gateway);let U=await Ne(l,e,o.gateway,{...ye,name:o.gateway.name??ut,destinations:[ce(_,E),...N.destinations],appLauncherVisible:!0});R=U,F=U}else fe(o.apps),fe(o.gateway),R=await Ne(l,e,o.apps,{...ye,name:It,destinations:N.destinations,appLauncherVisible:!1}),F=await Ne(l,e,o.gateway,{...ye,name:ut,destinations:[ce(_,E)],appLauncherVisible:!0});te={dropped:N.dropped,outsideBase:N.outsideBase,foreign:B}}finally{await J.release()}ct(e,te);let he=await oe(l,ae),p=q.filter(o=>!he.includes(o)),G={teamDomain:v,gatewayAud:F.application.aud,appsAud:R.application.aud},Ue=await Te(I),bt=R.outcome==="created"||F.outcome==="created",se=p.length>0?"missing":bt?"created":Ue===null?"unrecorded":Le(Ue,G)?t.writeSettings?"asked":null:"changed";if(se){await Me(g,{CLOUDFLARE_ACCESS_TEAM_DOMAIN:G.teamDomain,CLOUDFLARE_ACCESS_APPS_AUD:G.appsAud,CLOUDFLARE_ACCESS_AUD:G.gatewayAud},{flags:t.flags,out:e});let o=se==="asked"?[]:await At(I,g.deployer,{access:"on",teamDomain:v,...Z(k.include??[]).length>0?{emailDomains:Z(k.include??[])}:{}});await tt(I,{...G,writtenAt:s()},o)}e.emit({type:"step",step:D,status:"ok"}),kt(e,{teamDomain:v,organization:{created:S,sessionSet:a,globalSession:c.session_duration??null},signInMethods:i,allowedMethods:ee,cloudflareAdded:T,pinAdded:W,policy:{id:k.id,name:k.name,created:M,added:[...Q(P),...Z(P).map(o=>`@${o}`)],emails:Q(k.include??[]),domains:Z(k.include??[])},gateway:F,apps:R,combined:X,settings:se?{outcome:"set",reason:se}:{outcome:"kept",reason:null},toLink:b.toLink,emailDomains:f.domains},{gatewayHost:_,base:C,session:n,appsWithRoutes:N.destinations.filter(o=>o.overrides.some(E=>!xe.includes(E.path_pattern))).length,appsWithMcp:N.destinations.filter(o=>o.overrides.some(E=>E.path_pattern==="/mcp")).length})}async function At(t,e,s){let n=await dt(t);return n?rt(t,{organizationId:n.organization.id,type:"access.changed",actor:lt(e),data:s}):[]}function wt(t,e){let s=Ee(e);s.length!==0&&t.emit({type:"warning",code:"ACCESS_IDP_ANY_CLOUDFLARE_ACCOUNT",step:D,message:`${A(s.map(n=>`${n.name??n.id} (${n.type})`))} ${s.length===1?"is":"are"} open to any Cloudflare account, so left off the Every App applications
|
|
18
|
+
Restrict to account members is off, so anyone with a Cloudflare account could sign in there, and Cloudflare doesn't promise the address it asserts is verified: someone who registers a Cloudflare account under a member's address could sign in as that member. Turn Restrict to account members on (Zero Trust \u2192 Settings \u2192 Authentication \u2192 the provider), then run access on again; an application that allowed it before keeps it.`,data:{providers:s.map(n=>({id:n.id,type:n.type,name:n.name??null}))}})}function Ot(t){return st("Zero Trust team name",{initial:t,context:["This Cloudflare account has no Zero Trust team yet. People will sign in at","https://<name>.cloudflareaccess.com; the name can't be changed later."],validate:e=>ht.test(e.trim())?null:"Lowercase letters, digits and dashes only."})}async function Ne(t,e,s,n){if(!s){e.emit({type:"progress",step:D,message:`Creating the Access application "${n.name}"`});let c=Oe(null,n.allowedIdps);return{application:await Ze(t,{name:n.name,type:"self_hosted",destinations:n.destinations,policies:[n.policyId],session_duration:n.session,http_only_cookie_attribute:!0,enable_binding_cookie:!0,...c.allowedIdps.length>0?{allowed_idps:c.allowedIdps}:{},auto_redirect_to_identity:c.autoRedirect,app_launcher_visible:n.appLauncherVisible}),outcome:"created",signInAdded:c.allowedIdps}}let m=s.destinations??[],f=[...K(m,n.scope).foreign,...n.destinations],y=[...s.policies??[]].sort((c,$)=>(c.precedence??0)-($.precedence??0)),g=y.filter(c=>c.reusable===!1);if(g.length>0)return e.emit({type:"warning",code:"ACCESS_INLINE_POLICIES",step:D,message:`The Access application "${s.name??s.id}" has ${g.length===1?"a policy":"policies"} of its own: ${A(g.map(c=>c.name??c.id))}
|
|
19
|
+
It is left as it is: Access takes either application policies or reusable ones, not both, so the policy "${x}" can't be attached and its paths aren't managed here. Make its policies reusable in the dashboard, or manage it there.`,data:{application:s.id,policies:g.map(c=>c.id)}}),{application:s,outcome:"skipped",signInAdded:[]};let l=y.map(c=>c.id),I=l.includes(n.policyId)?l:[...l,n.policyId],w=Y(s)?s.enable_binding_cookie??!1:!0,r=Oe(s,n.allowedIdps),_=r.allowedIdps.filter(c=>!(s.allowed_idps??[]).includes(c)),C={destinations:f,policies:I,http_only_cookie_attribute:!0,enable_binding_cookie:w,allowed_idps:r.allowedIdps,auto_redirect_to_identity:r.autoRedirect,...n.sessionGiven?{session_duration:n.session}:{}};return le(m,f)&&I.join(",")===l.join(",")&&s.http_only_cookie_attribute===!0&&(s.enable_binding_cookie??!1)===w&&ke(s,n.allowedIdps)&&(!n.sessionGiven||s.session_duration===n.session)?{application:s,outcome:"unchanged",signInAdded:[]}:(e.emit({type:"progress",step:D,message:`Updating the Access application "${s.name??n.name}"`}),{application:await Se(t,s.id,be(s,C)),outcome:"updated",signInAdded:_})}function kt(t,e,s){let{gatewayHost:n,base:m}=s,f=[],y=[],g=(d,T)=>{f.push(ne(d,T)),y.push(`${d}${T?` (${T})`:""}.`)},l=d=>{f.push(u.dim(d)),y.push(d)},I=ve(e.allowedMethods);e.organization.created?g(`Zero Trust team ${e.teamDomain}`,`created \xB7 sign-in with ${I}`):e.organization.sessionSet?g(`Zero Trust team ${e.teamDomain}`,`global session now ${e.organization.sessionSet}, for every Access application in the account`):l(`Zero Trust team ${e.teamDomain} \xB7 sign-in with ${I}.`),e.cloudflareAdded&&g("Sign in with Cloudflare","added: members of this Cloudflare account sign in with their Cloudflare account"),e.pinAdded&&g("One-time PIN sign-in","added: Access emails everyone else a code");let{policy:w}=e,r=[...w.emails,...w.domains.map(d=>`@${d}`)];w.created?g(`Access policy "${w.name}"`,`lets in ${A(r)}`):w.added.length>0?g(`Access policy "${w.name}"`,`now also lets in ${A(w.added)}`):l(`Access policy "${w.name}" lets in ${A(r)}.`);let _=s.appsWithRoutes>0?`public routes of ${V(s.appsWithRoutes,"app")} let through${s.appsWithMcp>0?`, /mcp on ${V(s.appsWithMcp,"app host")}`:""}`:s.appsWithMcp>0?`/mcp on ${V(s.appsWithMcp,"app host")} let through`:"no app has public routes or /mcp",C="MCP, the OAuth endpoints and /health let through",b=d=>d.outcome==="updated"&&d.signInAdded.length>0?" \xB7 sign-in methods added":"",h=d=>l(`Access in front of ${d} left as it is (see the warning above).`);if(e.combined){let d=`${n} and *.${m}`;e.gateway.outcome==="skipped"?h(d):e.gateway.outcome==="unchanged"?l(`Access in front of ${d} is as it should be.`):g(`Access in front of ${d}`,`${e.gateway.outcome}${b(e.gateway)} \xB7 ${C} \xB7 ${_}`)}else e.gateway.outcome==="skipped"?h(n):e.gateway.outcome==="unchanged"?l(`Access in front of ${n} is as it should be.`):g(`Access in front of ${n}`,`${e.gateway.outcome}${b(e.gateway)} \xB7 ${C}`),e.apps.outcome==="skipped"?h(`*.${m}`):e.apps.outcome==="unchanged"?l(`Access in front of *.${m} is as it should be (${_}).`):g(`Access in front of *.${m}`,`${e.apps.outcome}${b(e.apps)} \xB7 ${_}`);if(e.settings.outcome==="set"){let d=e.settings.reason==="changed"?" \xB7 an application's AUD tag had changed":e.settings.reason==="unrecorded"?" \xB7 recorded, so a rerun can tell when they go stale":"";g("Gateway settings",`${q.join(", ")} \xB7 one new version${d}`)}else l("Gateway settings kept: they name these applications already (--write-settings writes them again).");let c=e.allowedMethods.every(d=>d.type===Ke),$=e.allowedMethods.length>1,O=$?"Access asks them to sign in first, with their Cloudflare account if they are a member of this Cloudflare account, otherwise with a code emailed to them":c?"Access emails them a code first":"Access asks them to sign in first",S=e.toLink.length>0?`${A(e.toLink)} ${e.toLink.length===1?"signs":"sign"} in once with ${e.toLink.length===1?"their":"their own"} password; ${O}. After that Access alone signs them in.`:null,a=[],v=[];e.emailDomains.length>0&&(a.push(`People at ${A(e.emailDomains)} pass Access, but still need an invitation here, unless they may join on their first sign-in: ${H} secret set CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS (${e.emailDomains.join(", ")}).`),v.push({command:`${H} secret set CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS`,note:`${e.emailDomains.join(", ")}: people there join as members on their first sign-in`}));let i=e.signInMethods.filter(d=>!e.allowedMethods.includes(d));i.length>0&&a.push(`${A(i.map(d=>`${d.name??d.id} (${d.type})`))} ${i.length===1?"is":"are"} on the team but not allowed on the Every App applications: access on allows only the one-time PIN and a Cloudflare provider restricted to this account's members. Allow another on both applications in the dashboard (Zero Trust \u2192 Access controls \u2192 Applications); access on never takes a method off.`),a.push("MCP clients and personal access tokens keep working: the Gateway's /mcp, the OAuth endpoints, /health and each app's public routes are let through without a login (an app host's /mcp only where its manifest asks for it)."),a.push(`Once everyone has signed in through Access, passwords can go: ${H} secret set EMAIL_PASSWORD_SIGN_IN (false).`),v.push({command:`${H} secret set EMAIL_PASSWORD_SIGN_IN`,note:"false, once everyone has linked Access"}),t.emit({type:"done",message:[...y,...S?[`Sign in at https://${n}: ${S}`]:[],...a].join(" "),display:[...f,"",...Re([{label:"Sign in",value:u.cyan(`https://${n}`)}]),...S?[`${" ".repeat(7+2)}${S}`]:[],...a.map(d=>u.dim(d))].join(`
|
|
20
|
+
`),data:{team:{domain:e.teamDomain,created:e.organization.created,sessionSet:e.organization.sessionSet,globalSession:e.organization.globalSession},signInMethods:e.signInMethods.map(d=>$t(d,e.allowedMethods)),identityProviders:{oneTimePinAdded:e.pinAdded,cloudflareAdded:e.cloudflareAdded},policy:w,applications:{gateway:ge(e.gateway),apps:ge(e.apps),combined:e.combined},settings:{names:[...q],...e.settings},signIn:{url:`https://${n}`,pending:e.toLink,first:$?"both":c?"pin":"idp"},next:v}})}function $t(t,e){return{id:t.id,type:t.type,name:t.name??null,allowed:e.some(s=>s.id===t.id),...t.type===Xe?{restrictToAccountMembers:t.config?.restrict_to_account_members===!0}:{}}}function ge({application:t,outcome:e,signInAdded:s}){return{id:t.id,aud:t.aud,name:t.name??null,outcome:e,destinations:(t.destinations??[]).map(n=>({uri:n.uri??null,public:(n.overrides??[]).map(m=>m.path_pattern)})),allowedIdps:t.allowed_idps??[],signInAdded:s}}async function Tt(t){let{out:e}=t,s=t.interactive??pe(t.flags.json??!1),n=await Ge(t),{cf:m,db:f,install:y}=n;ft(y);let g=me(y),{gatewayHost:l,appBaseDomain:I}=g,w=await oe(m,ae),r=q.filter(i=>w.includes(i)),_=re(await ie(m),g),C=t.keepApplications?[]:[...new Map([_.gateway,_.apps].filter(i=>i!==null).map(i=>[i.id,i])).values()],b=C.filter(i=>K(i.destinations??[],g).foreign.length===0),h=C.filter(i=>!b.includes(i));if(r.length===0&&C.length===0){let i=`Cloudflare Access isn't in front of ${l}. Nothing changed.`;e.emit({type:"done",message:i,display:u.dim(i),data:{removed:!1}});return}let c=i=>i.name??i.id;await at({yes:t.flags.yes,interactive:s,confirm:t.confirm,question:`Turn Cloudflare Access off for ${l}?`,unattended:"Turning Access off needs confirmation at a terminal, or --yes",context:[...r.length>0?[`Removes ${A(r)} from the Gateway: passwords sign people in again at once.`]:[],...b.length>0?[`Deletes ${V(b.length,"Access application")}: ${A(b.map(c))}.`]:[],...h.length>0?[`Takes ${l} and *.${I} out of ${A(h.map(c))}, which also covers something else.`]:[],...t.keepApplications&&(_.gateway||_.apps)?["The Access applications stay: Access still asks people to sign in there."]:[],...b.some(Y)?["The Gateway's application has Managed OAuth on: AI apps connected through it stop."]:[],"The team, its identity providers and the policy stay."],cancelled:"Cancelled. Access stays on."}),e.emit({type:"step",step:"access.off",status:"start",message:"Turning Cloudflare Access off..."}),r.length>0&&await Me(n,Object.fromEntries(r.map(i=>[i,null])),{flags:t.flags,out:e}),await nt(f,await At(f,n.deployer,{access:"off"}));let $=[];for(let i of b)await qe(m,i.id)&&$.push(c(i));let O=[];for(let i of h){let d=K(i.destinations??[],g).foreign;await Se(m,i.id,be(i,{destinations:d})),O.push(c(i))}e.emit({type:"step",step:"access.off",status:"ok"});let S=[],a=[];if(r.length>0&&(S.push(ne("Gateway settings removed",A(r))),a.push(`Removed ${A(r)} from the Gateway.`)),$.length>0&&(S.push(ne(`${V($.length,"Access application")} deleted`,A($))),a.push(`Deleted ${A($)}.`)),O.length>0&&(S.push(ne(`${l} and *.${I} taken out of ${A(O)}`)),a.push(`Took ${l} and *.${I} out of ${A(O)}.`)),t.keepApplications&&(_.gateway||_.apps)){let i="The Access applications stay: Access still asks people to sign in there, and the Gateway no longer requires it.";S.push(u.dim(i)),a.push(i)}let v=`Passwords sign people in as before. The Zero Trust team, its identity providers and the policy "${x}" are left as they were.`;e.emit({type:"done",message:[...a,v].join(" "),display:[...S,u.dim(v)].join(`
|
|
21
|
+
`),data:{removed:!0,settings:r,applications:{deleted:b.filter(i=>$.includes(c(i))).map(i=>i.id),trimmed:h.map(i=>i.id),kept:t.keepApplications??!1}}})}async function Lt(t){let{out:e}=t,s=t.now??Date.now,n=await Ge(t),{cf:m,db:f,install:y}=n,g=me(y),{gatewayHost:l,appBaseDomain:I}=g,w=y.deploymentMode==="hosted",r=w?null:await Ae(m),_=await oe(m,ae),C=q.filter(p=>_.includes(p)),b=w?null:await Te(f),h=r?(await $e(m)).find(p=>p.name===x)??null:null,c=r?await we(m):[],$=De(c),O=$.map(p=>p.id),S=Ce(c),a=r?re(await ie(m),g):{gateway:null,apps:null},v=await yt(f,s()),i=Y(a.gateway),d=Ie(I,await Pe(f),{managedOAuth:i});r&&wt(e,c);let T=C.length===q.length&&a.gateway!==null,W=T&&b&&r&&a.apps?Le(b,{teamDomain:r.auth_domain.toLowerCase(),gatewayAud:a.gateway.aud,appsAud:a.apps.aud}):null,ee=p=>K(p.destinations??[],g).owned,j=a.gateway!==null&&a.gateway.id===a.apps?.id,L=a.apps?le(ee(a.apps).filter(p=>!j||(p.uri??"").toLowerCase()!==l),d.destinations):!1,k=a.gateway?le(ee(a.gateway).filter(p=>(p.uri??"").toLowerCase()===l),[ce(l,i)]):!1,M=p=>p===null?null:ke(p,O),P=p=>p===null||h===null||(p.policies??[]).some(G=>G.id===h.id),J=h?[...v.members,...v.invited].filter(p=>!Q(h.include??[]).includes(p)):[],R=[];!w&&(!T||W===!1||!L||!k||!P(a.gateway)||!P(a.apps)||J.length>0||r!==null&&(S.cloudflare||S.pin)||M(a.gateway)===!1||M(a.apps)===!1)&&R.push(`${H} access on`);let F=[...S.cloudflare?["a Cloudflare account"]:[],...S.pin?["a one-time PIN"]:[]],X=Ee(c),te=c.filter(p=>!$.includes(p)),N=h?[...Q(h.include??[]),...Z(h.include??[]).map(p=>`@${p}`)]:[],he=[{label:"Access",value:w?u.dim("not available on a hosted Gateway"):T?u.green("on"):a.gateway?u.yellow("applications exist, Gateway settings missing"):u.dim("off")},{label:"Team",value:r?`${r.auth_domain}${r.session_duration?u.dim(` \xB7 global session ${r.session_duration}`):""}`:u.dim(w?"":"none in this Cloudflare account")},{label:"Lets in",value:h?`${A(N)}${J.length>0?u.yellow(` \xB7 not yet: ${A(J)}`):""}${u.dim(` (policy "${h.name}")`)}`:u.dim(`no policy "${x}" yet`)},...r?[{label:"Sign in",value:`${$.length>0?`with ${ve($)}`:u.dim("no sign-in method yet")}${F.length>0?u.yellow(` \xB7 access on adds ${A(F)}`):""}${X.length>0?u.yellow(" \xB7 open to any Cloudflare account (see the warning)"):""}${te.length>0?u.dim(` \xB7 on the team, not allowed here: ${A(te.map(p=>p.name??p.id))}`):""}`}]:[],{label:l,value:a.gateway?`${a.gateway.name??a.gateway.id} \xB7 ${k?"paths as they should be":u.yellow("paths differ")}${M(a.gateway)===!1?u.yellow(" \xB7 sign-in methods differ"):""}${Y(a.gateway)?" \xB7 Managed OAuth":""}${P(a.gateway)?"":u.yellow(" \xB7 policy not attached")}`:u.dim("no Access application")},{label:`*.${I}`,value:a.apps?`${a.apps.name??a.apps.id} \xB7 ${L?"public routes as they should be":u.yellow("public routes differ")}${M(a.apps)===!1?u.yellow(" \xB7 sign-in methods differ"):""}${P(a.apps)?"":u.yellow(" \xB7 policy not attached")}`:u.dim("no Access application")},{label:"Settings",value:C.length>0?`${A(C)}${W===!1?u.yellow(" \xB7 name an application that no longer exists: nobody can sign in"):W===!0?u.dim(" \xB7 name the applications above"):u.dim(" (values can't be read back)")}`:u.dim("none")},...v.toLink.length>0&&T?[{label:"To link",value:`${A(v.toLink)} (sign in once with the password through Access)`}]:[]];e.emit({type:"done",message:`Cloudflare Access is ${T?"on":"off"} for ${l}.`,display:[...Re(he),...R.length>0?["",u.dim("To fix: ")+u.bold(R.join(", "))]:[]].join(`
|
|
22
|
+
`),data:{on:T,hosted:w,team:r?{domain:r.auth_domain,sessionDuration:r.session_duration??null}:null,policy:h?{id:h.id,name:h.name,emails:Q(h.include??[]),domains:Z(h.include??[]),notYet:J}:null,signIn:r?{methods:c.map(p=>$t(p,$)),cloudflare:!S.cloudflare,pin:!S.pin,openToAnyCloudflareAccount:X.map(p=>p.id)}:null,applications:{gateway:a.gateway?{...ge({application:a.gateway,outcome:"unchanged",signInAdded:[]}),inSync:k,signInInSync:M(a.gateway),managedOAuth:Y(a.gateway),policyAttached:P(a.gateway)}:null,apps:a.apps?{...ge({application:a.apps,outcome:"unchanged",signInAdded:[]}),inSync:L,signInInSync:M(a.apps),policyAttached:P(a.apps)}:null,combined:j},desired:{apps:d.destinations.map(p=>({uri:p.uri,public:p.overrides.map(G=>G.path_pattern)}))},settings:{names:C,current:W},linkPending:v.toLink,...R.length>0?{fixes:R}:{}}})}export{x as a,ut as b,It as c,nn as d,sn as e,an as f,Dt as g,Tt as h,Lt as i};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{tb as o}from"./chunk-SAT3PGZU.js";import i from"node:fs";import t from"node:path";import{fileURLToPath as a}from"node:url";function p(e=import.meta.url){let r=t.dirname(a(e));for(let n=r;;n=t.dirname(n)){if(i.existsSync(t.join(n,"apps","every-app-gateway","scripts","build-release.ts"))&&i.existsSync(t.join(n,"packages","cli","package.json")))return n;if(t.dirname(n)===n)return null}}function c(e=import.meta.url){let r=p(e);if(r)return r;throw new o("CHECKOUT_MISSING",`everyapp has to run from a checkout of the Every App repository
|
|
2
|
+
This copy is installed in ${u(t.dirname(a(e)))}, outside any checkout.`,{fix:`in your checkout, run pnpm everyapp ${process.argv.slice(2).join(" ")}`.trimEnd()})}function u(e){for(let r=e;t.dirname(r)!==r;r=t.dirname(r))if(i.existsSync(t.join(r,"package.json")))return r;return e}function s(e){try{return i.realpathSync(e)}catch{return t.resolve(e)}}function h(e,r=c()){let n=t.relative(s(r),s(e));return n===""||n!==".."&&!n.startsWith(`..${t.sep}`)&&!t.isAbsolute(n)}export{p as a,c as b,s as c,h as d};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tb as r}from"./chunk-SAT3PGZU.js";var s="[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?",a=new RegExp(`^(?=.{1,253}$)(?:${s}\\.)+${s}$`);function o(n){return a.test(n)}function f(n){if(n===void 0)return;let e=n.trim().toLowerCase().replace(/^https?:\/\//,"").replace(/[/?#].*$/,"").replace(/\.$/,"");if(!o(e))throw new r("INVALID_DOMAIN",`${n} isn't a full hostname`,{fix:"use a name like apps.example.com"});return e}function l(n,e){if(!n.endsWith(`.${e}`))return!1;let t=n.slice(0,-(e.length+1));return t.length>0&&!t.includes(".")&&o(n)}function c(n,e){return n.filter(t=>l(t,e))}function d(n){let e=n.split("."),t=[];for(let i=0;i<=e.length-2;i+=1)t.push(e.slice(i).join("."));return t}export{f as a,l as b,c,d};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import{b as ne,e as ie,g as se,i as oe,l as ae,m as D,n as pe,o as I,r as ce,s as le}from"./chunk-PMPIMHKG.js";import{d as te,e as re,f as W}from"./chunk-GD2JZMD3.js";import{Hb as J,Ib as X,Kb as Q,Qb as Z,Rb as _,Sb as ee,b as N,c as C,db as Y,fb as H,ib as K,j as G,lb as $,tb as c,yb as q}from"./chunk-SAT3PGZU.js";import{spawn as We,spawnSync as Ue}from"node:child_process";import F from"node:fs";import b from"node:fs/promises";import{createRequire as Be}from"node:module";import m from"node:path";import{z as v}from"zod";import Ne from"node:fs";import Ce from"node:path";import Ie from"node:fs/promises";import ue from"node:path";var Le=200*1024*1024,Pe=5*6e4,Te=5,je=new Set([301,302,303,307,308]);function L(e){let t=/^([\w.-]+)\/([\w.-]+)$/.exec(e.trim());if(t)return`${t[1]}/${t[2].replace(/\.git$/,"")}`;let r;try{r=new URL(e.trim())}catch{return null}if(r.protocol!=="https:"||r.hostname!=="github.com")return null;let[n,i]=r.pathname.split("/").filter(Boolean);return!n||!i?null:`${n}/${i.replace(/\.git$/,"")}`}async function he({repo:e,asset:t,tag:r,...n}){let i=L(e);if(!i)throw new c("RELEASE_NOT_FOUND",`${e} isn't a GitHub repository (https://github.com/<owner>/<repo>).`);let s=r?`https://github.com/${i}/releases/download/${encodeURIComponent(r)}/${encodeURIComponent(t)}`:`https://github.com/${i}/releases/latest/download/${encodeURIComponent(t)}`,o=await U(s,{...n,notFound:`${i} has no ${r?`release ${r}`:"published release"} with ${t} that can be downloaded without signing in (https://github.com/${i}/releases).`});if(!o.tag)throw await o.cleanup(),new c("RELEASE_DOWNLOAD_FAILED",`GitHub didn't say which release of ${i} ${s} is.`);return{...o,tag:o.tag,repo:i}}async function U(e,{fetch:t=fetch,timeoutMs:r=Pe,maxBytes:n=Le,notFound:i}={}){let s=AbortSignal.timeout(r),{response:o,current:a,tag:p}=await xe(e,t,s).catch(f=>{throw me(f,e)});if(o.status===404)throw await o.body?.cancel(),new c("RELEASE_NOT_FOUND",i??`${e} doesn't exist (404).`);if(!o.ok||!o.body)throw await o.body?.cancel(),new c("RELEASE_DOWNLOAD_FAILED",`Couldn't download ${e}: HTTP ${o.status}.`,{retryable:o.status>=500});if(Number(o.headers.get("content-length"))>n)throw await o.body.cancel(),ge(e,n);let{dir:l,cleanup:u}=await _("release-download-"),d=ue.join(l,ue.posix.basename(a.pathname)||"release.tar.gz");try{let f=await Ie.open(d,"wx",384);try{let k=0;for await(let w of o.body){if(k+=w.byteLength,k>n)throw ge(e,n);await f.write(w)}}finally{await f.close()}}catch(f){throw await o.body.cancel().catch(()=>{}),await u(),me(f,e)}return{tarball:d,tag:p,url:e,cleanup:u}}async function xe(e,t,r){let n=de(e,e),i=fe(n);for(let s=0;;s+=1){let o=await t(n.href,{redirect:"manual",credentials:"omit",signal:r,headers:{accept:"application/octet-stream"}});if(!je.has(o.status))return{response:o,current:n,tag:i};let a=o.headers.get("location");if(await o.body?.cancel(),!a||s>=Te)throw new c("RELEASE_DOWNLOAD_FAILED",`${e} redirects ${a?"too many times":"nowhere"}.`);n=de(new URL(a,n).href,e),i??=fe(n)}}function de(e,t){let r;try{r=new URL(e)}catch{throw new c("RELEASE_DOWNLOAD_FAILED",`${e} isn't a URL.`)}if(r.protocol!=="https:")throw new c("RELEASE_DOWNLOAD_FAILED",`${t} ${e===t?"isn't":`redirects to ${e}, which isn't`} an HTTPS URL.`);return r}function fe(e){if(e.hostname!=="github.com")return null;let t=/^\/[^/]+\/[^/]+\/releases\/download\/([^/]+)\/[^/]+$/.exec(e.pathname);return t?decodeURIComponent(t[1]):null}function ge(e,t){return new c("RELEASE_TOO_LARGE",`${e} is over ${Math.round(t/1024/1024)} MB, too big for a release
|
|
2
|
+
A release is a few MB. Check the URL.`)}function me(e,t){if(e instanceof c)return e;let r=e.name;return new c("RELEASE_DOWNLOAD_FAILED",r==="TimeoutError"||r==="AbortError"?`Downloading ${t} timed out.`:`Couldn't download ${t}: ${e.message}`,{retryable:!0})}function P(e){return/^[a-z][a-z0-9+.-]*:\/\//i.test(e)}async function we(e,{asset:t,what:r,step:n,missing:i,out:s,fetch:o}){if(!P(e)){let l=Ce.resolve(e);if(!Ne.existsSync(l))throw new c("RELEASE_NOT_FOUND",i);return{tarball:l,origin:{kind:"file",path:l},cleanup:async()=>{}}}let a=B(e);s.emit({type:"progress",step:n,message:`Downloading ${r} from ${a?`${a.repo}${a.tag?` release ${a.tag}`:"'s latest release"}`:e}...`,data:{url:e}});let p,g;if(a){let l=await he({repo:a.repo,asset:t,tag:a.tag,fetch:o});p=l,g={kind:"github",repo:l.repo,tag:l.tag}}else{p=await U(e,{fetch:o});let l=p.tag?L(e):null;g=l&&p.tag?{kind:"github",repo:l,tag:p.tag}:{kind:"url",url:e}}return{tarball:p.tarball,origin:g,cleanup:p.cleanup}}function B(e){let t=L(e);if(!t||!P(e))return null;let r=new URL(e).pathname.split("/").filter(Boolean).slice(2);return r.length===0||r.length===1&&r[0]==="releases"?{repo:t}:r.length===3&&r[0]==="releases"&&r[1]==="tag"?{repo:t,tag:decodeURIComponent(r[2])}:r.length===2&&r[0]==="releases"&&r[1]==="latest"?{repo:t}:null}var M="everyapp-release.tar.gz",O="migrations",ye=m.join(".cloudflare","output"),S="v0",Fe="0.3.0",Me="0.3.0",Ee=/^(\.DS_Store|\._.*)$/;function ze(e){try{return Be(m.join(e,"package.json"))("@every-app/sdk/package.json").version??null}catch{return null}}var Ve=ne.extend({kind:v.literal("app"),appId:v.string().min(1),cliVersion:v.string(),sdkVersion:v.string().nullable(),manifest:v.record(v.string(),v.unknown())});function xt(e){switch(e.kind){case"github":return`github.com/${e.repo} (release ${e.tag})`;case"url":return e.url;case"file":return e.path;case"checkout":return"this checkout"}}function Ge(e){if(e.migrations?.engine==="prisma")throw new c("RELEASE_MIGRATIONS_UNSUPPORTED",`${e.id} migrates with Prisma, which a release can't carry
|
|
3
|
+
Prisma migrations (migrations.engine "prisma") need the app's source and its Prisma CLI.`,{rerun:`${C} deploy`,rerunNote:"from the app's checkout"});if(e.migrations?.dialect==="postgresql")return W(e);let t=e.resources?.d1??[];return t.length===0?null:(re(t,e.migrations),W(e))}async function Ye(e){return(await b.readdir(e,{recursive:!0,withFileTypes:!0})).filter(t=>!t.isDirectory()).map(t=>m.relative(e,m.join(t.parentPath,t.name)).split(m.sep).join("/")).sort()}async function He(e){let t=(await Ye(e)).filter(r=>{let n=m.posix.basename(r);return n.startsWith(".dev.vars")||n.startsWith(".env")||n.endsWith(".pem")||/(^|\/)\.cloudflare\/(state|types)(\/|$)/.test(r)||/(^|\/)\.(wrangler|everyapp)(\/|$)/.test(r)});if(t.length>0)throw new c("RELEASE_LOCAL_STATE",`Refusing to pack local state or secrets into the release:
|
|
4
|
+
${t.join(`
|
|
5
|
+
`)}`)}async function Ke(e){let t;try{t=await b.readFile(m.join(e,"meta","_journal.json"),"utf8")}catch(n){if(Z(n))return[];throw n}return(JSON.parse(t).entries??[]).map(({tag:n,when:i})=>({tag:n,when:i}))}function be(e,t){let r=Ue("git",t,{cwd:e,encoding:"utf8"});return r.status===0?r.stdout.trim():null}function qe(e){return new Promise((t,r)=>{let n=We("tar",e,{stdio:["ignore","ignore","pipe"],env:{...process.env,COPYFILE_DISABLE:"1"}}),i="";n.stderr.on("data",s=>i+=s.toString()),n.once("error",r),n.once("close",s=>s===0?t():r(new c("RELEASE_PACK_FAILED",`tar couldn't pack the release (exit ${s}): ${i.trim()}`)))})}async function Nt({cwd:e,manifest:t,outFile:r,cfVersion:n,builtAt:i=new Date}){let s=m.join(e,ye),o=F.existsSync(s)?(await b.readdir(s)).filter(u=>!Ee.test(u)):[];if(o.length!==1||o[0]!==S)throw new c("RELEASE_PACK_FAILED",`Expected the Build Output ${S} alone in ${s}, found ${o.length?o.join(", "):"none"}.`);let a=m.join(s,S);if(!await I(a))throw new c("RELEASE_PACK_FAILED",`The app's Build Output isn't a production build
|
|
6
|
+
A release ships only one.`,{fix:"build with `cf build` (production by default)"});let p=Ge(t),{dir:g,cleanup:l}=await _("app-release-stage-");try{let u=(y,x)=>b.cp(y,m.join(g,x),{recursive:!0,dereference:!0,filter:R=>!Ee.test(m.basename(R))});await u(a,m.join(ye,S));let d=p?m.resolve(e,p):null,f=d!==null&&F.existsSync(d)&&F.statSync(d).isDirectory();f&&await u(d,O),await He(g);let k=JSON.parse(await b.readFile(m.join(e,"package.json"),"utf8").catch(()=>"{}")),w=be(e,["rev-parse","HEAD"]),A=w!==null&&!!be(e,["status","--porcelain","--","."]),j={schema:1,kind:"app",appId:t.id,version:k.version??"0.0.0",gitSha:w?`${w}${A?"-dirty":""}`:"unknown",builtAt:i.toISOString(),cfVersion:n,cliVersion:N,sdkVersion:ze(e),buildOutputVersion:S,sha256:await ie(g),migrations:f?await Ke(m.join(g,O)):[],minCli:Fe,minSdk:Me,manifest:t.migrations||f?{...t,migrations:{engine:"drizzle",...t.migrations,dir:O}}:t};return await b.writeFile(m.join(g,"release.json"),`${JSON.stringify(j,null,2)}
|
|
7
|
+
`),await b.mkdir(m.dirname(r),{recursive:!0}),await b.rm(r,{force:!0}),await qe(["-czf",r,"-C",g,"."]),j}finally{await l()}}async function Je(e,{origin:t={kind:"file",path:e},version:r=N}={}){let{dir:n,manifest:i,cleanup:s}=await se(e,"app",Ve);try{oe(i,r,`${i.appId} ${i.version}`);let o;try{o=H(i.manifest,te)}catch(p){throw p instanceof Y?new c("RELEASE_INVALID",`${e} carries a manifest this everyapp refuses: ${p.message}`):p}if(o.id!==i.appId)throw new c("RELEASE_INVALID",`${e} says it is ${i.appId}, but its manifest is ${o.id}'s.`);let a=o.migrations?.dir;if(a!==void 0&&a!==O)throw new c("RELEASE_INVALID",`${e}'s manifest keeps its migrations in ${a}; a release keeps them in ${O}/.`);return{dir:n,release:i,manifest:o,origin:t,cleanup:s}}catch(o){throw await s(),o}}async function Ct(e,{out:t,fetch:r,version:n}){let i=P(e)?B(e):null,s;try{s=await we(e,{asset:M,what:"the app",step:"app.release",missing:`${e} is neither a URL nor a file
|
|
8
|
+
Pass a GitHub repository URL (https://github.com/<owner>/<repo>), a release tarball's URL, or a downloaded ${M}.`,out:t,fetch:r})}catch(o){throw i&&o instanceof c&&o.code==="RELEASE_NOT_FOUND"?new c("NO_RELEASE",`${i.repo} publishes no everyapp release${i.tag?` ${i.tag}`:""}
|
|
9
|
+
Its GitHub releases have no ${M}.`,{fix:`clone it, then run pnpm install in it and this checkout's ${C} deploy from its directory`}):o}try{let o=await Je(s.tarball,{origin:s.origin,version:n});return{...o,cleanup:async()=>{await o.cleanup(),await s.cleanup()}}}catch(o){throw await s.cleanup(),o}}import{rmSync as Qe}from"node:fs";import E from"node:fs/promises";import h from"node:path";import{execa as Ze}from"execa";import T from"node:fs";import Xe from"node:path";function ke(e,t){let r=Xe.join(e,".gitignore");if(!T.existsSync(r)){T.writeFileSync(r,t+`
|
|
10
|
+
`);return}let n=T.readFileSync(r,"utf-8");n.split(`
|
|
11
|
+
`).some(s=>s.trim()===t||s.trim()===t.replace(/\/$/,""))||T.appendFileSync(r,(n.endsWith(`
|
|
12
|
+
`)?"":`
|
|
13
|
+
`)+t+`
|
|
14
|
+
`)}var et=["drizzle.config.ts","drizzle.config.js"],ve=12e4;async function Jt({cwd:e,manifest:t,out:r}){let n=t.migrations?.engine??"drizzle",i=t.migrations?.dialect==="postgresql",s=(d,f={})=>r.emit({type:"warning",code:"SCHEMA_CHECK_SKIPPED",step:"app.schema",message:`Can't check the schema against the migrations: ${d}${f.detail?`
|
|
15
|
+
${f.detail}`:""}`,...f.fix?{data:{fix:f.fix}}:{}});if(n==="prisma"){r.emit({type:"progress",step:"app.schema",message:"To check a Prisma schema against its migrations: prisma migrate diff --from-migrations <dir> --to-schema <schema> --exit-code, with datasource.shadowDatabaseUrl set in prisma.config.ts."}),r.emit({type:"step",step:"app.schema",status:"skip",message:"Schema not checked against migrations (Prisma needs a shadow database; --verbose shows how)",data:{engine:n}});return}if(!i&&!t.resources?.d1?.length||n!=="drizzle")return;let o;try{o=(await Q(e,"drizzle-kit","drizzle-kit")).binPath}catch{s("drizzle-kit isn't installed",{fix:"add drizzle-kit to devDependencies"});return}let a=t.migrations?.config,p=await tt(e,a?[a]:et);if(!p){s(a?`no ${a} (migrations.config)`:"no drizzle.config.ts",a?{}:{detail:'An app whose drizzle config lives elsewhere sets migrations.config to its path; an app that writes its SQL by hand sets migrations.engine to "d1-sql".'});return}r.emit({type:"step",step:"app.schema",status:"start",message:"Checking the schema..."});let g=h.resolve(e,t.migrations?.dir??"drizzle");ke(e,".everyapp/"),await E.mkdir(h.join(e,".everyapp"),{recursive:!0});let l=await E.mkdtemp(h.join(e,".everyapp","schema-check-")),u=J({sync:()=>Qe(l,{recursive:!0,force:!0})});try{let d=h.join(l,"migrations");await E.cp(g,d,{recursive:!0}).catch(async y=>{if(y.code!=="ENOENT")throw y;await E.mkdir(d)});let f=new Set(await Ae(d)),k=h.join(l,"drizzle.config.ts");await E.writeFile(k,[`import config from ${JSON.stringify(p)};`,`export default { ...config, out: ${JSON.stringify(h.relative(e,d).split(h.sep).join("/"))} };`,""].join(`
|
|
16
|
+
`));let w=h.join(l,"report-failure.cjs");await E.writeFile(w,["const report = console.error;","console.error = (...args) => {"," if (args.some((arg) => arg instanceof Error)) process.exitCode = 1;"," report(...args);","};",""].join(`
|
|
17
|
+
`));let A=await Ze(process.execPath,["--require",w,o,"generate","--config",k],{cwd:e,stdin:"ignore",reject:!1,timeout:ve,env:{NODE_NO_WARNINGS:"1"}});if((await Ae(d)).filter(y=>!f.has(y)).length>0)throw new c("SCHEMA_DRIFT",`The schema has changes no migration covers
|
|
18
|
+
drizzle-kit would write a new migration for them. Nothing was migrated or uploaded.`,{rerun:"pnpm db:generate",rerunNote:"then run this again"});if(A.failed){let y=A.stderr.split(`
|
|
19
|
+
`).map(R=>R.trim()).filter(Boolean),x=y.find(R=>/^\w*Error\b/.test(R))??y.at(-1)??(A.timedOut?`no answer in ${ve/1e3} s`:`exit ${A.exitCode}`);throw new c("SCHEMA_CHECK_FAILED",`drizzle-kit couldn't compare the schema with the migrations
|
|
20
|
+
${x}. Nothing was migrated or uploaded.`,{rerun:"pnpm db:generate",rerunNote:"in a terminal; it asks about renamed columns and tables"})}r.emit({type:"step",step:"app.schema",status:"ok",message:"The schema matches the migrations."})}finally{await E.rm(l,{recursive:!0,force:!0}),u()}}async function tt(e,t){for(let r of t){let n=h.join(e,r);try{if((await E.stat(n)).isFile())return n}catch{}}return null}async function Ae(e){return(await E.readdir(e,{recursive:!0,withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".sql")).map(r=>h.relative(e,h.join(r.parentPath,r.name)))}var rt=6e5,Re={EVERYAPP_BUILD:"1"};async function nr({cwd:e,cf:t,buildCommand:r,verbose:n}){if(r){await ee(r,[],{cwd:e,env:{...process.env,...Re,NODE_OPTIONS:X(process.env.NODE_OPTIONS)},shell:!0,echo:n,what:"Build",code:"BUILD_FAILED"});return}await t.run({args:["build"],plane:"project",cwd:e,mode:"text",env:Re,timeoutMs:rt,...n?{onOutput:i=>void process.stderr.write(i)}:{}}).catch(i=>{throw i instanceof q?new c("BUILD_FAILED",["Build failed","cf build's last lines:",...G(i.stdout,i.stderr).map(s=>` ${s}`)].join(`
|
|
21
|
+
`)):i})}import nt from"node:fs/promises";import z from"node:path";var it=new Set(["text","json","secret","version-metadata","assets","d1","kv","r2","durable-object","workflow","worker","hyperdrive"]);function Se(e,t){return e==="EVERY_APP_GATEWAY"&&t.worker===K&&t.exportName==="AppGateway"}function V(e,t){return e===t||e.startsWith(`${t}${$}`)}function st(e,t){let{workerName:r,helperWorkers:n=[]}=t,i=[];e.name!==r&&i.push(`its name is "${e.name}", not "${r}"`),i.push(...Oe(e));let s=e.env??{};for(let a of["EVERYAPP_IDENTITY_PUBLIC_KEYS","EVERYAPP_IDENTITY_ISSUER"])s[a]?.type!=="text"&&i.push(`${a} isn't built in`);let o=s.EVERYAPP_AUDIENCE;return(o?.type!=="text"||o.value!==r)&&i.push(`EVERYAPP_AUDIENCE isn't the Worker's name ("${r}")`),i.push(..._e(s,t,(a,p)=>Se(a,p)||n.includes(String(p.worker))),...De(e.exports??{},t.deletedDurableObjects??[],r)),i}function ot(e,t,r){let n=[];return e.name!==t&&n.push(`its name is "${e.name}", not "${t}"`),n.push(...Oe(e),..._e(e.env??{},r,Se),...De(e.exports??{},[],r.workerName)),n}function Oe(e){let t=[];e.workersDev!==!1&&t.push("workersDev isn't false"),e.previewUrls!==!1&&t.push("previewUrls isn't false"),e.domains?.length&&t.push("it declares domains (apps are served through the gateway)");for(let r of e.triggers??[])r.type!=="scheduled"&&t.push(r.type==="fetch"?"it declares routes (apps are served through the gateway)":`it declares a trigger of type "${String(r.type)}" (apps may only declare cron schedules)`);return e.env?.EVERYAPP_DEV&&t.push("EVERYAPP_DEV is set, which only `everyapp dev` may do"),t}function _e(e,{workerName:t,resources:r,helperWorkers:n=[]},i){let s=[],o=new Set([t,...n]),a=new Set(Object.values(r.d1??{}).map(u=>u.id)),p=new Set(Object.values(r.kv??{}).map(u=>u.id)),g=new Set(Object.values(r.hyperdrive??{}).map(u=>u.id)),l=Object.values(r.r2??{}).map(u=>u.name);for(let[u,d]of Object.entries(e)){if(!it.has(String(d.type))){s.push(`${u} is a ${String(d.type)} binding, which Every App apps can't use`);continue}switch(d.type){case"worker":i(u,d)||s.push(`${u} binds Worker "${String(d.worker)}"; apps may only bind the gateway's AppGateway and, from the app's own Worker, its helper Workers`);break;case"durable-object":o.has(String(d.worker))||s.push(`${u} binds another Worker's Durable Object ("${String(d.worker)}")`);break;case"d1":a.has(String(d.id))||s.push(`${u} isn't a D1 database the deploy provisioned`);break;case"kv":p.has(String(d.id))||s.push(`${u} isn't a KV namespace the deploy provisioned`);break;case"hyperdrive":g.has(String(d.id))||s.push(`${u} isn't a Hyperdrive config the deploy provisioned`);break;case"r2":{let f=String(d.name??"");l.length>0?l.includes(f)||s.push(`${u} is bucket "${f}", which isn't one of the app's buckets in resources.r2 (${l.join(", ")})`):V(f,t)||s.push(`${u} is bucket "${f}"; an app's buckets are named after its Worker (${t} or ${t}${$}<name>)`);break}case"workflow":{let f=String(d.name??"");(!o.has(String(d.worker))||!V(f,t))&&s.push(`${u} binds Workflow "${f}" of Worker "${String(d.worker)}"; an app binds only its own Workflows, named after its Worker (${t}${$}<name>)`);break}}}return s}function De(e,t,r){let n=[];for(let[i,s]of Object.entries(e))if(s.type!=="worker"){if(s.type==="workflow"){let o=String(s.name??"");V(o,r)||n.push(`Workflow ${i} is named "${o}"; an app's Workflows are named after its Worker (${r}${$}<name>)`);continue}if(s.type!=="durable-object"){n.push(`export ${i} is a ${String(s.type)}, which Every App apps can't declare`);continue}switch(s.container!==void 0&&n.push(`Durable Object class ${i} is backed by a container, which Every App apps can't run`),s.state??"created"){case"created":case"renamed":break;case"deleted":t.includes(i)||n.push(`Durable Object class ${i} is marked deleted, which deletes its data; remove it from everyapp.config.ts and deploy with --allow-delete-durable-object-data instead`);break;case"transferred":n.push(`Durable Object class ${i} would move its data to Worker "${String(s.transferredTo)}"`);break;case"expecting-transfer":n.push(`Durable Object class ${i} would take the data of Worker "${String(s.transferFrom)}"'s class`);break;default:n.push(`Durable Object class ${i} has state "${s.state}", which everyapp doesn't deploy`)}}return n}async function ur({cwd:e,inputs:t}){if(!await I(z.join(e,ae)))throw new c("APP_POLICY","The app's Build Output isn't a production build. The manifest's build command must run `cf build` (production by default).");let r=await pt(e),n=t.helperWorkers??[],i=[],s=r.get(D);if(!s)throw new c("APP_POLICY","The app's Build Output has no default Worker. Build it from everyAppWorker() in cloudflare.config.ts.");i.push(...st(s.config,t));for(let[a,{config:p}]of r){if(a===D)continue;let g=String(p.name);if(!n.includes(g)){i.push(`the build has a Worker "${g}" that everyapp.config.ts doesn't declare in workers`);continue}i.push(...ot(p,g,t).map(l=>`${g}: ${l}`))}for(let a of n)[...r.values()].some(({config:p})=>p.name===a)||i.push(`the build has no Worker ${a}, which everyapp.config.ts declares; add it to the Vite plugin's auxiliaryWorkers with everyAppAuxiliaryWorker()`);if(i.length>0)throw new c("APP_POLICY",`The built Worker can't be deployed as an Every App app:
|
|
22
|
+
- ${i.join(`
|
|
23
|
+
- `)}
|
|
24
|
+
Build it from everyAppWorker() in cloudflare.config.ts.`);let o={};for(let[a,{config:p,directory:g}]of r){if(a!==D){let l=String(p.name);o[l]=$e(p,l)}if(p.manifest){let l={...p.manifest.modules??{}};for(let u of await le(z.join(g,"bundle")))l[u]={type:"sourcemap"};p.manifest={...p.manifest,modules:l}}ce(p),await nt.writeFile(z.join(g,"worker.config.json"),`${JSON.stringify(p,null,2)}
|
|
25
|
+
`)}return{workflows:$e(s.config,t.workerName),helperWorkflows:o,r2Buckets:[...new Set([...r.values()].flatMap(({config:a})=>at(a)))].sort()}}function at(e){let t=e.env??{};return Object.values(t).filter(r=>r?.type==="r2"&&typeof r.name=="string").map(r=>r.name)}function $e(e,t){let r=[...Object.values(e.exports??{}).filter(n=>n.type==="workflow").map(n=>String(n.name)),...Object.values(e.env??{}).filter(n=>n.type==="workflow"&&n.worker===t).map(n=>String(n.name))];return[...new Set(r)]}async function pt(e){let t=new Map;for await(let{name:r,config:n,directory:i}of pe(e))t.set(r,{config:n,directory:i});return t}export{ke as a,Jt as b,nr as c,ur as d,M as e,xt as f,Nt as g,Ct as h};
|