everyapp 0.3.0-rc.2 → 0.3.0-rc.4
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 +1 -1
- package/dist/access-YWM4BSBD.js +1 -0
- package/dist/activity-RTCAUMQS.js +14 -0
- package/dist/ai-UOYQFTAX.js +5 -0
- package/dist/apps-PEOBCDNU.js +14 -0
- package/dist/chunk-26KS6TD6.js +1 -0
- package/dist/chunk-3EADVHFN.js +15 -0
- package/dist/chunk-4LKLQOM7.js +7 -0
- package/dist/{chunk-PNLU5U3P.js → chunk-5IC3ZN52.js} +1 -1
- package/dist/{chunk-H7PDL3X5.js → chunk-AMCNAKYU.js} +1 -1
- package/dist/{chunk-23HJ5I2A.js → chunk-ASCNE7GS.js} +1 -1
- package/dist/{chunk-6OGVO7QK.js → chunk-BCTEWNN4.js} +1 -1
- package/dist/{chunk-W3JCQHHU.js → chunk-BK4NK34C.js} +1 -1
- package/dist/chunk-BWNZ6F4F.js +2 -0
- package/dist/chunk-DCFHBCCW.js +9 -0
- package/dist/{chunk-2Y5Q6A5K.js → chunk-DWTJ4OLZ.js} +1 -1
- package/dist/chunk-EP3IQ354.js +20 -0
- package/dist/{chunk-OP4DYXYI.js → chunk-EP4HRYXP.js} +1 -1
- package/dist/{chunk-HOUHG236.js → chunk-EQLY5I46.js} +1 -1
- package/dist/{chunk-YHJZMJYZ.js → chunk-F5XK23HV.js} +1 -1
- package/dist/{chunk-5PTNYZK6.js → chunk-FB2OC32C.js} +3 -3
- package/dist/chunk-FQ2A7YAP.js +57 -0
- package/dist/{chunk-OM2HDWVP.js → chunk-GAPQSINH.js} +1 -1
- package/dist/chunk-GJK6GAWO.js +1 -0
- package/dist/chunk-H4EZTXIK.js +1 -0
- package/dist/chunk-HJGZGZFE.js +32 -0
- package/dist/{chunk-CCWBPAKH.js → chunk-I7FNTTUY.js} +3 -3
- package/dist/chunk-KOBKGQ27.js +91 -0
- package/dist/{chunk-PS7S74DG.js → chunk-KQM6ZUX5.js} +1 -1
- package/dist/chunk-KVCL64LI.js +1 -0
- package/dist/{chunk-4JRIS6S6.js → chunk-LEEUODYR.js} +1 -1
- package/dist/{chunk-6PGUCTJ6.js → chunk-LI3YLKLC.js} +1 -1
- package/dist/chunk-MEIWV7FJ.js +20 -0
- package/dist/{configure-F7UZCJUG.js → chunk-MLTNW3AM.js} +2 -2
- package/dist/chunk-NDOEON54.js +4 -0
- package/dist/chunk-NW7SJPSP.js +37 -0
- package/dist/chunk-O64FPLGX.js +1 -0
- package/dist/chunk-ORGV2NNT.js +8 -0
- package/dist/chunk-PDPUGYJW.js +47 -0
- package/dist/chunk-QFTBDXLF.js +146 -0
- package/dist/{chunk-E3EPK27P.js → chunk-QJRZFIYC.js} +2 -2
- package/dist/chunk-QKHLRLK3.js +15 -0
- package/dist/{chunk-CZXHKPRZ.js → chunk-R2DF3ENZ.js} +1 -1
- package/dist/{chunk-IUOBIB5M.js → chunk-R7JOHK7Y.js} +2 -2
- package/dist/chunk-RL72BUT4.js +1 -0
- package/dist/chunk-RQBSTNL7.js +1 -0
- package/dist/{chunk-H6QQMY7B.js → chunk-S2G4G73L.js} +1 -1
- package/dist/{chunk-LXYMDZER.js → chunk-SGRGD7L4.js} +1 -1
- package/dist/{chunk-T2GD7RHS.js → chunk-TIYSZWP5.js} +1 -1
- package/dist/chunk-TUXKBLLJ.js +10 -0
- package/dist/chunk-U4ATZJEU.js +6 -0
- package/dist/chunk-V7BWZOSZ.js +26 -0
- package/dist/{chunk-J35DDCNU.js → chunk-VVKQJSF3.js} +1 -1
- package/dist/chunk-WVHJIYQ3.js +14 -0
- package/dist/{chunk-ZEXVHB22.js → chunk-XBD7PQN5.js} +1 -1
- package/dist/{chunk-N5GQLGEC.js → chunk-YAZHTVUV.js} +1 -1
- package/dist/configure-CAWCTPYY.js +1 -0
- package/dist/{create-2E5HVWYK.js → create-3ZWJQXPK.js} +2 -2
- package/dist/{db-HEQVTDTM.js → db-B7KO37SV.js} +1 -1
- package/dist/delete-CB3EPOU4.js +3 -0
- package/dist/deploy-5O7LV5OX.js +1 -0
- package/dist/dev-4JYCVVOZ.js +86 -0
- package/dist/{email-RLZFUFUN.js → email-SWJQXEUR.js} +1 -1
- package/dist/{events-2V5VRBWP.js → events-GJV2KVIU.js} +13 -13
- package/dist/{groups-HDG5DVFY.js → groups-NNTLSXMK.js} +1 -1
- package/dist/index.js +104 -95
- package/dist/install-UAG3CNYW.js +1 -0
- package/dist/{login-KHJBC64Z.js → login-QEKMLMUB.js} +1 -1
- package/dist/mcp-AFGVOM5D.js +1 -0
- package/dist/provider-622VM7UZ.js +29 -0
- package/dist/release-CXEX6O7F.js +1 -0
- package/dist/{restore-FFGYV7NO.js → restore-PGIVEA5P.js} +1 -1
- package/dist/secret-3LUDEDUW.js +1 -0
- package/dist/setup-PUD375AM.js +1 -0
- package/dist/{signin-AP3D4XM4.js → signin-EP5JLAT5.js} +2 -2
- package/dist/status-LK6DNLCI.js +5 -0
- package/dist/teardown-6RURRSME.js +22 -0
- package/dist/update-YJFTOZEV.js +1 -0
- package/dist/{workspace-CJC5I66L.js → workspace-VW7ZZRFP.js} +3 -3
- package/package.json +5 -5
- package/skills/build-every-app/SKILL.md +22 -13
- package/skills/build-every-app/patterns.md +16 -3
- package/skills/everyapp/SKILL.md +33 -18
- package/skills/everyapp/mcp.md +22 -8
- package/skills/everyapp/security-review.md +1 -1
- package/skills/everyapp/setup/README.md +18 -1
- package/skills/everyapp/setup/access.md +11 -7
- package/skills/everyapp/setup/ai-gateway.md +117 -0
- package/skills/everyapp/setup/ai.md +139 -0
- package/skills/everyapp/setup/context.md +2 -2
- package/skills/everyapp/setup/dataforseo.md +3 -3
- package/skills/everyapp/setup/email.md +1 -1
- package/skills/everyapp/setup/gateway.md +3 -3
- package/skills/everyapp/setup/google.md +8 -6
- package/skills/everyapp/setup/microsoft-365.md +4 -2
- package/skills/everyapp/setup/providers.md +27 -9
- package/skills/everyapp/setup/remote-mcp.md +1 -1
- package/skills/everyapp/setup/signin-apple.md +3 -3
- package/skills/everyapp/setup/signin-cloudflare.md +1 -1
- package/skills/everyapp/setup/signin-github.md +1 -1
- package/skills/everyapp/setup/signin-google.md +2 -2
- package/skills/everyapp/setup/signin-microsoft.md +1 -1
- package/skills/everyapp/setup/slack.md +2 -0
- package/dist/access-LGEN3ABJ.js +0 -1
- package/dist/activity-RSD4D66F.js +0 -12
- package/dist/apps-4RCFXT74.js +0 -13
- package/dist/chunk-AGTCKFRB.js +0 -22
- package/dist/chunk-BHMRY53V.js +0 -2
- package/dist/chunk-CB4U7H2G.js +0 -4
- package/dist/chunk-CZTEDWZ2.js +0 -22
- package/dist/chunk-EGEWRFVY.js +0 -1
- package/dist/chunk-ELK7QZ2M.js +0 -1
- package/dist/chunk-FJJSSVET.js +0 -33
- package/dist/chunk-GKBPYVP3.js +0 -25
- package/dist/chunk-IFCPALVC.js +0 -46
- package/dist/chunk-J455FAEN.js +0 -7
- package/dist/chunk-JYKRUS5C.js +0 -1
- package/dist/chunk-LYNBZ7RV.js +0 -57
- package/dist/chunk-M2QQ2UD7.js +0 -132
- package/dist/chunk-NFU4YFXB.js +0 -1
- package/dist/chunk-ONLNJXVQ.js +0 -32
- package/dist/chunk-RMF4YGD6.js +0 -98
- package/dist/chunk-TLRM3P7V.js +0 -15
- package/dist/chunk-WOVS3GV5.js +0 -10
- package/dist/chunk-ZECBN24L.js +0 -15
- package/dist/chunk-ZFCUH5PK.js +0 -7
- package/dist/delete-XCSIQIRS.js +0 -3
- package/dist/deploy-3QOZEZHC.js +0 -1
- package/dist/dev-JL3ZP5BT.js +0 -86
- package/dist/install-Z5FYXUYM.js +0 -1
- package/dist/mcp-EFDUKJ5V.js +0 -1
- package/dist/provider-EOI5PTFH.js +0 -13
- package/dist/release-74J5ZIL3.js +0 -1
- package/dist/secret-7FKKTLHB.js +0 -1
- package/dist/setup-PAKRCAFO.js +0 -1
- package/dist/status-RMWNHOEK.js +0 -4
- package/dist/teardown-E4JNKAZJ.js +0 -22
- package/dist/update-DWVZFNPS.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{e as A,h as d}from"./chunk-
|
|
1
|
+
import{e as A,h as d}from"./chunk-I7FNTTUY.js";import{b as L}from"./chunk-RQBSTNL7.js";import{Dc as p,Fc as E,bc as u,c,cc as s,d as g,fc as h,jc as C}from"./chunk-FQ2A7YAP.js";import f from"chalk";var O=null;async function _(o){let t=await p(o,{plane:"account",args:["auth","whoami"]},L);return O=t.authenticated&&!process.env.CLOUDFLARE_API_TOKEN?t.email??null:null,t}function x(){return O}var m=5*60*1e3;function F(o,t){return i=>o.emit({type:"action_required",action:"cloudflare_login",step:t,message:"Log in to Cloudflare: open this link and enter the code",data:{url:i.url,code:i.code,expiresAt:new Date(Date.now()+m).toISOString(),waiting:!0,waitingFor:"Cloudflare login"}})}async function S(o){let t=await _(o.cf);return t.authenticated?t:w(o)}async function w({cf:o,interactive:t,onDeviceLogin:i}){if(process.env.CLOUDFLARE_API_TOKEN)throw new u("CLOUDFLARE_TOKEN_REJECTED",`Cloudflare didn't accept CLOUDFLARE_API_TOKEN
|
|
2
2
|
It may be mistyped, expired or revoked.
|
|
3
3
|
A token needs Account \u203A Workers Scripts \u203A Edit, Account \u203A D1 \u203A Edit, Account \u203A Workers KV Storage \u203A Edit, Zone \u203A Zone \u203A Read and Zone \u203A DNS \u203A Read: https://dash.cloudflare.com/profile/api-tokens`,{fix:`set a valid token, or unset CLOUDFLARE_API_TOKEN and run ${c} login`});if(t)d(`${f.cyan("\u2192")} Log in to Cloudflare to continue
|
|
4
4
|
${f.dim(" Starting Cloudflare's login. Open its link and enter the code.")}`),await o.run({plane:"account",mode:"interactive",args:["auth","login"]});else if(i)await D(o,i);else throw new s("cloudflare_login",`Log in to Cloudflare with ${c} login
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{K as Y,L,M as z,O as J,Q,e as R,h as W,l as P,m as B,n as F,o as V,q as K,r as v,s as j,t as k,u as q,v as O,w as D}from"./chunk-QKHLRLK3.js";import{c as H,e as U}from"./chunk-EQLY5I46.js";import{bc as N,c as M,f as I,fc as C,hc as T,k as b}from"./chunk-FQ2A7YAP.js";var Z="Every App gateway members",X="Every App gateway",ee="Every App apps",te="720h",ae=6e4;async function $(o,p,t,e){let{step:a}=e;if(!t){p.emit({type:"progress",step:a,message:`Creating the Access application "${e.name}"`});let n=L(null,e.allowedIdps);return{application:await B(o,{name:e.name,type:"self_hosted",destinations:e.destinations,policies:e.policyId?[e.policyId]:[],session_duration:e.session,http_only_cookie_attribute:!0,enable_binding_cookie:!0,...n.allowedIdps.length>0?{allowed_idps:n.allowedIdps}:{},auto_redirect_to_identity:n.autoRedirect,app_launcher_visible:e.appLauncherVisible}),outcome:"created",signInAdded:n.allowedIdps}}let y=t.destinations??[],h=[...k(y,e.scope).foreign,...e.destinations],c=[...t.policies??[]].sort((n,f)=>(n.precedence??0)-(f.precedence??0)),s=c.filter(n=>n.reusable===!1);if(s.length>0)return p.emit({type:"warning",code:"ACCESS_INLINE_POLICIES",step:a,message:`The Access application "${t.name??t.id}" has ${s.length===1?"a policy":"policies"} of its own: ${b(s.map(n=>n.name??n.id))}
|
|
2
|
+
It is left as it is: Access takes either application policies or reusable ones, not both, so the policy "${Z}" can't be attached and its paths aren't managed here. Make its policies reusable in the dashboard, or manage it there.`,data:{application:t.id,policies:s.map(n=>n.id)}}),{application:t,outcome:"skipped",signInAdded:[]};let r=c.map(n=>n.id),u=e.policyId===null||r.includes(e.policyId)?r:[...r,e.policyId],l=D(t)?t.enable_binding_cookie??!1:!0,A=L(t,e.allowedIdps),i=A.allowedIdps.filter(n=>!(t.allowed_idps??[]).includes(n)),d={destinations:h,policies:u,http_only_cookie_attribute:!0,enable_binding_cookie:l,allowed_idps:A.allowedIdps,auto_redirect_to_identity:A.autoRedirect,...e.sessionGiven?{session_duration:e.session}:{}};return q(y,h)&&u.join(",")===r.join(",")&&t.http_only_cookie_attribute===!0&&(t.enable_binding_cookie??!1)===l&&z(t,e.allowedIdps)&&(!e.sessionGiven||t.session_duration===e.session)?{application:t,outcome:"unchanged",signInAdded:[]}:(p.emit({type:"progress",step:a,message:`Updating the Access application "${t.name??e.name}"`}),{application:await V(o,t.id,F(t,d)),outcome:"updated",signInAdded:i})}async function se(o,p,t,{scope:e,found:a,policyId:y,session:h,sessionGiven:c,allowedIdps:s,create:r,step:u}){let{gatewayHost:l,appBaseDomain:A}=e,i=D(a.gateway),d=j(A,await J(t),{managedOAuth:i}),g=a.gateway!==null&&a.apps!==null&&a.gateway.id===a.apps.id,m=[],n=w=>{if(!w)return;let G=k(w.destinations??[],e).foreign;G.length>0&&m.push({application:w.name??w.id,uris:G.map(x=>x.uri??"(private)")})},f={scope:e,policyId:y,session:h,sessionGiven:c,allowedIdps:s,step:u},S,E;if(g){p.emit({type:"warning",code:"ACCESS_ONE_APPLICATION",step:u,message:`One Access application covers ${l} and *.${A}
|
|
3
|
+
It is kept and updated. The runbook recommends two, so an app host's Access cookie is never a Gateway login.`}),n(a.gateway);let w=await $(o,p,a.gateway,{...f,name:a.gateway.name??X,destinations:[v(l,i),...d.destinations],appLauncherVisible:!0});S=w,E=w}else n(a.apps),n(a.gateway),S=a.apps||r?await $(o,p,a.apps,{...f,name:ee,destinations:d.destinations,appLauncherVisible:!1}):null,E=a.gateway||r?await $(o,p,a.gateway,{...f,name:X,destinations:[v(l,i)],appLauncherVisible:!0}):null;return{apps:S,gateway:E,combined:g,leftovers:{dropped:d.dropped,outsideBase:d.outsideBase,foreign:m},plan:d}}function ne(o){return{appsWithRoutes:o.destinations.filter(p=>p.overrides.some(t=>!K.includes(t.path_pattern))).length,appsWithMcp:o.destinations.filter(p=>p.overrides.some(t=>t.path_pattern==="/mcp")).length}}var _="gateway.access";async function Ae({cf:o,db:p,scope:t,out:e}){let a=`${M} access on`,y;try{y=await P(o)}catch(c){if(c instanceof N&&c.code==="ACCESS_PERMISSION_MISSING"||T(c,"access_not_enabled"))return;e.emit({type:"warning",code:"ACCESS_NOT_CHECKED",step:_,message:`Couldn't check Cloudflare Access after the Gateway deploy
|
|
4
|
+
${C(c).split(`
|
|
5
|
+
`)[0]}
|
|
6
|
+
If the Gateway is behind Access, the paths it lets through may be out of step with this release until it is updated.`,data:{rerun:a,rerunNote:"if the Gateway is behind Access"}});return}let h=O(y,t);if(!(!h.gateway&&!h.apps))try{let c=await H({db:p,id:U,purpose:"access.sync",out:e,step:"gateway.lease",waitMs:ae}),s;try{let i=O(await P(o),t);if(!i.gateway&&!i.apps)return;let[d,g]=await Promise.all([R(o),W(o)]);await c.check(),s=await se(o,e,p,{scope:t,found:i,policyId:g.find(m=>m.name===Z)?.id??null,session:te,sessionGiven:!1,allowedIdps:Y(d).map(m=>m.id),create:!1,step:_})}finally{await c.release()}Q(e,s.leftovers);let r=[s.gateway,s.apps].filter(i=>i!==null&&i.outcome==="updated").filter((i,d,g)=>g.findIndex(m=>m.application.id===i.application.id)===d),u=[...s.gateway?[]:[t.gatewayHost],...s.apps?[]:[`*.${t.appBaseDomain}`]];u.length>0&&e.emit({type:"warning",code:"ACCESS_APPLICATION_MISSING",step:_,message:`Cloudflare Access has no application in front of ${b(u)}
|
|
7
|
+
The Gateway requires an Access login, and nothing there asks for one: run access on to put it back.`,data:{hosts:u,rerun:a}});let l=ne(s.plan),A=l.appsWithRoutes>0?`public routes of ${I(l.appsWithRoutes,"app")}${l.appsWithMcp>0?`, /mcp on ${I(l.appsWithMcp,"app host")}`:""}`:l.appsWithMcp>0?`/mcp on ${I(l.appsWithMcp,"app host")}`:"no app public routes";e.emit({type:"step",step:_,status:r.length>0?"ok":"skip",message:r.length>0?`Cloudflare Access brought in step with this Gateway: ${b(r.map(i=>i.application.name??i.application.id))} updated (${A} let through).`:"Cloudflare Access already matches this Gateway.",data:{changed:r.map(i=>i.application.id),gateway:s.gateway?{id:s.gateway.application.id,outcome:s.gateway.outcome}:null,apps:s.apps?{id:s.apps.application.id,outcome:s.apps.outcome}:null,combined:s.combined,missing:u,...l}})}catch(c){e.emit({type:"warning",code:"ACCESS_RECONCILE_FAILED",step:_,message:`Couldn't bring Cloudflare Access in step with this Gateway
|
|
8
|
+
${C(c).split(`
|
|
9
|
+
`)[0]}
|
|
10
|
+
Until it is updated, the paths Access lets through are the previous release's.`,data:{rerun:a}})}}export{Z as a,X as b,ee as c,te as d,se as e,ne as f,Ae as g};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import t from"node:fs";import s from"node:path";function m(o,n){let i=s.join(o,".gitignore");if(!t.existsSync(i)){t.writeFileSync(i,n+`
|
|
2
|
+
`);return}let e=t.readFileSync(i,"utf-8");e.split(`
|
|
3
|
+
`).some(r=>r.trim()===n||r.trim()===n.replace(/\/$/,""))||t.appendFileSync(i,(e.endsWith(`
|
|
4
|
+
`)?"":`
|
|
5
|
+
`)+n+`
|
|
6
|
+
`)}export{m as a};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import{b as _,c as $e,d as Ee,e as Re,f as Pe}from"./chunk-N4E5YE4X.js";import{d as ge}from"./chunk-MEIWV7FJ.js";import{e as ce}from"./chunk-QJRZFIYC.js";import{g as ie}from"./chunk-TUXKBLLJ.js";import{A as fe}from"./chunk-PDPUGYJW.js";import{a as be,b as De,c as I,d as Ae,e as Ce}from"./chunk-DWTJ4OLZ.js";import{c as ye,j as he,k as ve,n as j,o as ke}from"./chunk-S2G4G73L.js";import{c as P,i as M}from"./chunk-BCTEWNN4.js";import{e as G,g as Se,h as N,i as O}from"./chunk-YAZHTVUV.js";import{a as T}from"./chunk-BK4NK34C.js";import{b as q}from"./chunk-QKHLRLK3.js";import{c as we}from"./chunk-ORGV2NNT.js";import{a as J}from"./chunk-LEEUODYR.js";import{a as ue,b as me}from"./chunk-DCFHBCCW.js";import{a as R,j as le,s as pe}from"./chunk-KOBKGQ27.js";import{c as se,d as oe,f as re}from"./chunk-TIYSZWP5.js";import{b as X,c as Q,e as ee,f as te,g as ae}from"./chunk-I7FNTTUY.js";import{Cc as K,Dc as Y,Fc as U,Hb as V,Hc as ne,Sc as de,b as E,bc as S,c as b,cc as D,d as W,dc as Z,e as B,fc as x,tc as L}from"./chunk-FQ2A7YAP.js";import{z as A}from"zod";var Ue=A.array(A.looseObject({state:A.string().nullish(),rate_plan:A.looseObject({id:A.string().nullish(),public_name:A.string().nullish()}).nullish(),product:A.looseObject({name:A.string().nullish()}).nullish()}));var Me=/cancel|expired|failed/i;async function Te(t){let n;try{n=await Y(t,{plane:"account",args:["accounts","subscriptions","get"]},Ue)}catch{return"unreadable"}let a=n.filter(e=>!Me.test(e.state??"")).map(e=>[e.rate_plan?.id,e.rate_plan?.public_name,e.product?.name].filter(Boolean).join(" ")).filter(e=>/workers/i.test(e));return a.some(e=>/paid|standard|bundled|unbound/i.test(e))?"paid":a.some(e=>/free/i.test(e))?"free":"unknown"}import{setTimeout as je}from"node:timers/promises";var He=6e5,ze=3e3,Be=15e3;function Ve(t){let n=r=>[...t].filter(([,c])=>c===r).map(([c])=>c),a=[],e=n("tls");e.length>0&&a.push(`Waiting for ${e.length===1?"a certificate":"certificates"}: ${e.join(", ")}`);let s=n("dns");s.length>0&&a.push(`Waiting for DNS: ${s.join(", ")} ${s.length===1?"has":"have"} no record at the zone's nameservers yet`);let o=n("other");return o.length>0&&a.push(`Waiting for ${o.map(r=>`https://${r}`).join(", ")} to answer`),a.join("; ")}async function F({hosts:t,out:n,step:a,maxWaitMs:e=He,pollMs:s=ze,progressEveryMs:o=Be,probe:r,localDns:c=r?void 0:Ae,sleep:m=je,now:u=Date.now}){let l=u(),d=[],p=[],i=[...new Set(t)],h=null,y=r??(f=>I(f));for(;i.length>0;){let f=await Promise.all(i.map(v=>y(`https://${v}/`))),g=new Map;for(let[v,k]of i.entries()){let $=f[v];if(!$.answered){g.set(k,$.kind);continue}d.push(k),n.emit({type:"progress",step:a,message:`https://${k} has its certificate.`,data:{host:k}}),c&&await Ce({host:k,lead:`https://${k} has its certificate and the gateway serves it`,out:n,step:a,localDns:c})&&p.push(k)}if(i=[...g.keys()],i.length===0)break;let w=u()-l;if(w>=e){n.emit({type:"warning",code:"CERT_PENDING",step:a,message:`${i.map(v=>`https://${v}`).join(", ")} ${i.length===1?"has":"have"} no certificate after ${ne(w)}. It usually comes within five minutes; the gateway serves ${i.length===1?"it":"them"} as soon as it does. If it never comes, check the zone's CAA records allow Cloudflare's certificate authorities. Check later with \`${b} status\`.`,data:{hosts:i}});break}(h===null||u()-h>=o)&&(n.emit({type:"progress",step:a,message:`${Ve(g)} (usually under five minutes)...`,data:{hosts:i,waitedMs:w,waitingFor:Object.fromEntries(g)}}),h=u()),await m(s)}return{ready:d,pending:i,staleLocally:p}}async function Ie({cf:t,accountId:n,install:a,domain:e,out:s}){if(a&&(a.liveVersionId!==null||a.gatewayHost===e)){if(a.gatewayHost!==e)throw new S("DOMAIN_CHANGE_UNSUPPORTED",`The Gateway can't move to ${e}
|
|
2
|
+
It's installed at ${a.gatewayHost}, and moving an installed Gateway isn't supported.`,{rerun:B("--domain"),rerunNote:"(without --domain) to update it where it is"});return{domain:e,zone:{id:a.zoneId,name:a.zoneName},appBaseDomain:a.appBaseDomain}}let o=await Ze(t,e,n);return Ke(e,o,s),{domain:e,zone:o,appBaseDomain:e}}async function Ze(t,n,a){let e=await Se(t,n,a);if(!e){let s=(await O(t,a)).filter(o=>!o.status||o.status==="active").map(o=>o.name);throw new S("ZONE_NOT_FOUND",`${n} isn't under a domain in this Cloudflare account${s.length>0?`
|
|
3
|
+
This account's domains: ${s.join(", ")}`:""}`,{fix:s.length>0?`use a name under one of them, or add ${n}'s domain to Cloudflare`:`add ${n}'s domain to Cloudflare`,data:{url:G(a),zones:s}})}if(e.status&&e.status!=="active")throw new D("add_domain",`Finish activating ${e.name} on Cloudflare
|
|
4
|
+
Its nameservers don't point at Cloudflare yet.`,N(a,e.name),{data:{zone:e.name,status:e.status}});return{id:e.id,name:e.name}}async function Ge({cf:t,out:n,reason:a,release:e,accountId:s,target:o,interactive:r,...c}){let{certificates:m,...u}=c,l=await pe(t);n.emit({type:"step",step:"gateway.resources",status:"ok",message:l.created.length?`Created ${l.created.join(", ")}`:"The Gateway's database and KV namespace are there"});let d=R(t,l.d1Id),p=await ke({cf:t,out:n,reason:a,release:e,accountId:s,gatewayHost:o.domain,zone:o.zone,appBaseDomain:o.appBaseDomain,resources:l,db:d,interactive:r,cliVersion:E,...u});return await F({hosts:p.newHosts,out:n,step:"gateway.tls",...m}),{result:p,db:d}}function Ke(t,n,a){t===n.name&&a.emit({type:"warning",code:"GATEWAY_AT_ZONE_APEX",message:`The Gateway's sign-in cookie will cover every subdomain of ${n.name}
|
|
5
|
+
Apps take names directly below it too. Unless the domain is only for EveryApp,
|
|
6
|
+
install on a subdomain instead, e.g. --domain apps.${n.name}`,data:{suggestedDomain:`apps.${n.name}`}})}function ra({gateway:t,interactive:n}){return{createCf:a=>K({accountId:a}),openRelease:t.openRelease,source:t.source,interactive:n,prompts:it,openBrowser:Pe,cliVersion:E}}async function ia(t,n,a){let e=_e(t.domain);xe(n);let{whoami:s,discovery:o}=await Oe(t,n,a,{host:e,hostFlag:"--domain"});return Fe({whoami:s,discovery:o,flags:t,out:n,deps:a})}async function ca(t,n,a){xe(n);let{whoami:e,discovery:s}=await Oe(t,n,a);if(!me(s,e).install?.liveVersionId)throw le();return Fe({whoami:e,discovery:s,flags:t,out:n,deps:a,offerAccess:!1})}async function Oe(t,n,a,e){let s=await oe({cf:a.createCf(),interactive:a.interactive,onDeviceLogin:t.json?se(n,"setup.auth"):void 0});n.emit({type:"step",step:"setup.auth",status:"ok",message:`Logged in to Cloudflare${s.email?` as ${s.email}`:""}`,data:{email:s.email??null}});let o=await ue({whoami:s,createCf:a.createCf,accountId:t["account-id"],...e,interactive:a.interactive});return{whoami:s,discovery:o}}function _e(t){try{return T(t)}catch(n){throw n instanceof S?new S(n.code,`--domain ${t} isn't a full hostname`,{fix:n.fix}):n}}async function Fe({whoami:t,discovery:n,flags:a,out:e,deps:s,offerAccess:o=!0}){let r=n.gateway,c=r?.account??await re({whoami:t,flag:a["account-id"],interactive:s.interactive}),m=c.name??c.id,u=r?.cf??s.createCf(c.id),l=r?.install??null,d=l?.liveVersionId?l:null;e.emit({type:"step",step:"setup.account",status:"ok",message:`Setting up EveryApp in ${m}`,data:{id:c.id,name:c.name,email:t.email??null,gateway:d!==null}});let p=await s.source();p.minCli&&M({version:p.version,minCli:p.minCli},s.cliVersion),d||await Xe(u,c.id,e);let i=await Ie({cf:u,accountId:c.id,install:l,domain:_e(a.domain)??l?.gatewayHost??await et(u,c.id,s),out:e}),h=!d?.liveDomains.includes(i.domain);h&&await ye({cf:u,out:e,step:"gateway.domains",zone:i.zone,domains:[i.domain],liveDomains:[],forceDns:a["force-dns"],cfAsks:s.interactive&&e.verbose}),e.emit({type:"step",step:"setup.domain",status:"ok",message:`Apps will live one level below ${i.appBaseDomain}`,data:{gatewayHost:i.domain,appBaseDomain:i.appBaseDomain,zone:i.zone.name}});let y=`https://${i.domain}`,f=await tt({cf:u,accountId:c.id,accountName:m,install:l,databaseId:r?.databaseId??null,target:i,source:p,checkedDomains:h?[i.domain]:[],flags:a,out:e,deps:s}),g=d?.deploymentMode??"self_hosted";d&&g==="self_hosted"&&await ie({cf:u,db:f.db,scope:{gatewayHost:i.domain.toLowerCase(),appBaseDomain:i.appBaseDomain.toLowerCase()},out:e});let{owner:w,created:v}=await nt({db:f.db,gatewayUrl:y,flags:a,out:e,deps:s}),k=s.interactive&&!a.yes&&g==="self_hosted",$=o&&w!==null&&g==="self_hosted"&&!a["no-access"],H=k||$?await J(u,V):[];if(k&&!H.includes("CF_DEPLOY_TOKEN")){let C=await s.prompts.browserDeploymentToken();C!==null&&await fe({flags:{json:a.json,"account-id":c.id,gateway:y},out:e,names:["CF_DEPLOY_TOKEN"],readValue:async()=>C,createCf:()=>u})}let z=null;if($&&!ce.every(C=>H.includes(C))){let C={cf:u,db:f.db,accountId:c.id,gatewayUrl:y,zoneName:i.zone.name,owner:w.email,cloudflareEmail:t.email??null,flags:a,out:e,deps:s};z=k?await Ye(C):await qe(C)}return{gatewayUrl:y,account:m,owner:w?.email??null,organizationName:w?.organizationName||null,release:f.release,releaseName:P(p),gateway:f.outcome,ownerCreated:v,mode:g,accessOn:z}}async function Ye(t){let{owner:n,cloudflareEmail:a,deps:e}=t;return await e.prompts.accessInFront({owner:n,cloudflareEmail:a})?We(t,{interactive:!0}):!1}async function qe(t){let{cf:n,db:a,zoneName:e,cloudflareEmail:s,out:o}=t,r=e.split(".")[0].toLowerCase().replace(/[^a-z0-9-]/g,"")||"every-app",c=(l,d=`${b} access on`,p="to turn it on")=>(o.emit({type:"warning",code:"ACCESS_SETUP_SKIPPED",step:"setup.access",message:`Cloudflare Access wasn't turned on
|
|
7
|
+
${l}
|
|
8
|
+
The Gateway works without it: passwords sign people in. ${b} access on turns it on.`,data:{rerun:d,rerunNote:p}}),!1),m;try{m=await q(n)}catch(l){return c(x(l).split(`
|
|
9
|
+
`)[0],`${b} access on`,"with a login that can manage Access")}return m?s===null?c("This Cloudflare login has no email address (an API token), so nobody is known to get past Access."):(await Je(a)).includes(s.toLowerCase())?We(t,{interactive:!1}):c(`Sign in with Cloudflare would sign you in as ${s}, which isn't an owner or admin of this Gateway.`,`${b} access on`,`once ${s} is an owner or admin, or at a terminal`):c("This Cloudflare account has no Zero Trust team yet, and a team's name is permanent: it is never picked for you.",`${b} access on --team ${r}`,"or another name: its sign-in page becomes <name>.cloudflareaccess.com")}async function Je(t){let[n=[]]=await t.run([{sql:`SELECT DISTINCT u.email FROM members m JOIN users u ON u.id = m.user_id
|
|
10
|
+
WHERE m.role IN ('owner', 'admin') AND (u.banned IS NULL OR u.banned = 0 OR (u.ban_expires IS NOT NULL AND u.ban_expires <= ?1))`,params:[Date.now()]}]);return n.map(a=>String(a.email).toLowerCase())}async function We({cf:t,accountId:n,gatewayUrl:a,flags:e,out:s,deps:o},{interactive:r}){try{return await ge({flags:{json:e.json,"account-id":n,gateway:a},out:de(s,"setup.access"),interactive:r,createCf:()=>t,askTeam:o.askTeam}),!0}catch(c){if(c instanceof Z)throw c;return s.emit({type:"warning",code:"ACCESS_SETUP_SKIPPED",step:"setup.access",message:`Cloudflare Access wasn't turned on
|
|
11
|
+
${x(c).split(`
|
|
12
|
+
`)[0]}
|
|
13
|
+
The Gateway works without it: passwords sign people in.`,data:{rerun:`${b} access on`,rerunNote:"to try again"}}),!1}}function xe(t){t.emit({type:"step",step:"setup.toolchain",status:"ok",message:`Node ${process.versions.node}, cf ${L}`,data:{node:process.versions.node,cf:L}})}async function Xe(t,n,a){let e=await Te(t),s=we(n);switch(e){case"paid":a.emit({type:"step",step:"setup.plan",status:"ok",message:"Account is on Workers Paid",data:{plan:e}});return;case"free":throw new D("upgrade_workers_paid",`Subscribe this account to Workers Paid
|
|
14
|
+
It's on the Free plan. EveryApp needs Workers Paid ($5 a month, then usage): on Free, the Gateway stops once D1 hits its daily limit.`,s,{data:{plan:e}});case"unknown":a.emit({type:"warning",code:"WORKERS_PAID_UNVERIFIED",step:"setup.plan",message:`Couldn't confirm this account is on Workers Paid
|
|
15
|
+
EveryApp needs it ($5 a month, then usage). On Free, the Gateway stops once D1 hits its daily limit.`,data:{url:s,plan:e}});return;case"unreadable":a.emit({type:"step",step:"setup.plan",status:"skip",message:"Couldn't read this account's plan; Cloudflare refuses the upload if it's on Free",data:{url:s,plan:e}});return}}async function Qe(t,n){let a=await O(t,n),e=a.filter(o=>!o.status||o.status==="active");if(e.length>0)return e.map(o=>o.name);let[s]=a;throw s?new D("add_domain",`Finish activating ${a.map(o=>o.name).join(", ")} on Cloudflare
|
|
16
|
+
${a.length===1?"Its nameservers don't":"Their nameservers don't"} point at Cloudflare yet.`,N(n,s.name)):new D("add_domain",`Add a domain to this Cloudflare account
|
|
17
|
+
EveryApp needs one. Buy one in the dashboard (about $10 a year for a .com, ready in minutes),
|
|
18
|
+
or point a domain you own at Cloudflare's nameservers.`,G(n))}async function et(t,n,a){let e=await Qe(t,n);if(!a.interactive){let s=r=>W(["--domain",`apps.${r}`]),[o]=e;throw new S("DOMAIN_REQUIRED",`Choose the Gateway's address with --domain
|
|
19
|
+
It must be under one of this account's domains: ${e.join(", ")}. A subdomain works best.`,e.length===1?{fix:`add --domain apps.${o}, or another name under ${o}`,rerun:s(o),rerunNote:`or another name under ${o}`,data:{zones:e}}:{fix:`add --domain apps.${o}, or another name under ${Le(e)}`,data:{zones:e,choices:e.map(r=>({label:r,rerun:s(r)}))}})}return T(await a.prompts.gatewayAddress(e))}function Le(t){return t.length<=1?t[0]??"":`${t.slice(0,-1).join(", ")} or ${t.at(-1)}`}async function tt({cf:t,accountId:n,accountName:a,install:e,databaseId:s,target:o,source:r,checkedDomains:c,flags:m,out:u,deps:l}){let d=`https://${o.domain}`,p=e?.liveVersionId?e:null,i=m["allow-downgrade"]??!1,h=w=>at({cf:t,accountId:n,accountName:a,install:p,databaseId:s,openRelease:w,source:r,flags:m,out:u,deps:l});if(p&&s){if(r.treeSha256&&r.treeSha256===p.sourceTreeSha256||r.sha256&&r.sha256===p.releaseSha256)return h(l.openRelease);i||j(r,p,{allowDowngradeFlag:!0})}let y=P(r),f=p?"upgrade":e?.gatewayHost===o.domain?"resume":"install";u.emit({type:"step",step:"setup.gateway",status:"start",message:p?`Upgrading the Gateway to ${y}`:`Installing the Gateway at ${o.domain} (${y})`,data:{change:f,release:r.version,releaseName:y,from:p?.releaseVersion??null,gatewayUrl:d,account:a,...f==="install"?{expectedMinutes:st}:{}}});let g=await l.openRelease();try{let w=g.manifest;if(M(w,l.cliVersion),p&&s){if(ve(g,p))return await h(async()=>g);i||j(he(g),p,{allowDowngradeFlag:!0})}let{result:v,db:k}=await Ge({cf:t,out:u,reason:p?"upgrade":"deploy",release:g,accountId:n,target:o,interactive:l.interactive,forceDns:m["force-dns"],checkedDomains:c,allowDowngrade:i,allowDowngradeFlag:!0,sleep:l.seams?.sleep,leaseWaitMs:l.seams?.leaseWaitMs,certificates:l.seams?.certificates});return u.emit({type:"step",step:"setup.gateway",status:"ok",message:`The Gateway (${y}) is live at ${d}`,data:{versionId:v.versionId,release:w.version,releaseName:y}}),{db:k,release:w.version,outcome:p?"upgraded":"installed"}}finally{await g.cleanup()}}async function at({cf:t,accountId:n,accountName:a,install:e,databaseId:s,openRelease:o,source:r,flags:c,out:m,deps:u}){let l=R(t,s),d=`https://${e.gatewayHost}`,p=e.releaseVersion,i=P(r),{inSync:h,desired:y}=await De(t,l,e);if(h&&!c.redeploy)return m.emit({type:"step",step:"setup.gateway",status:"skip",message:`The Gateway is up to date with ${i}`,data:{release:p,releaseName:i,gatewayUrl:d,upToDate:!0,account:a,apps:y.appWorkers.length}}),{db:l,release:p,outcome:"up-to-date"};let f=!e.liveDomains.includes(e.gatewayHost),g=[...new Set(y.apps.filter(v=>!e.liveAppWorkers.includes(v.workerName)).map(v=>v.appId))].sort();m.emit({type:"step",step:"setup.gateway",status:"start",message:h?`Redeploying the Gateway (${i}) for --redeploy`:f?`Finishing the Gateway's first publication at ${e.gatewayHost} (${i})`:`Repairing the Gateway (${i}): ${y.appWorkers.length} apps, was ${e.liveAppWorkers.length}`,data:{change:h?"redeploy":f?"resume":"repair",release:p,releaseName:i,from:p,gatewayUrl:d,account:a,apps:y.appWorkers.length,was:e.liveAppWorkers.length,redeploy:h}});let w=await be({cf:t,out:m,accountId:n,databaseId:s,openRelease:o,interactive:u.interactive,cliVersion:u.cliVersion,force:!0,forceDns:c["force-dns"],sleep:u.seams?.sleep,leaseWaitMs:u.seams?.leaseWaitMs});return await F({hosts:w.newHosts,out:m,step:"gateway.tls",...u.seams?.certificates}),m.emit({type:"step",step:"setup.gateway",status:"ok",message:h?`The Gateway (${i}) is redeployed`:f?`The Gateway (${i}) is live at ${d}`:`The Gateway (${i}) routes ${w.appWorkers.length} apps`,data:{versionId:w.versionId,release:p,releaseName:i,appWorkers:w.appWorkers,...h||f?{}:{repaired:!0,added:g,apps:w.appWorkers.length,was:e.liveAppWorkers.length}}}),{db:l,release:p,outcome:f?"installed":"repaired"}}async function nt({db:t,gatewayUrl:n,flags:a,out:e,deps:s}){let o=await _(t);if(o)return e.emit({type:"step",step:"setup.owner",status:"skip",message:`Owner account is ${o.email}`,data:{...o}}),{owner:o,created:!1};if(!Re({terminal:s.interactive,relayed:a.json}))return e.emit({type:"warning",code:"OWNER_NOT_CLAIMED",step:"setup.owner",message:`The Gateway has no owner yet
|
|
20
|
+
Apps deploy without one. To create it, run setup at a terminal with this Cloudflare login.`,data:{rerun:`${b} setup`,rerunNote:"at a terminal",needsTerminal:!0}}),{owner:null,created:!1};await rt(n,e,s.seams?.fetch);let r=await $e({db:t,gatewayUrl:n}),c=()=>U(r.expiresAt.getTime()-Date.now());e.emit({type:"action_required",action:"claim_owner",step:"setup.owner",message:r.replaced?`Open this new link to create the owner account
|
|
21
|
+
The link shown before no longer works. This one works once and expires in ${c()}. Treat it like a password.`:`Open this link to create the owner account
|
|
22
|
+
Works once and expires in ${c()}. Treat it like a password.`,data:{url:r.url,expiresAt:r.expiresAt.toISOString(),replaced:r.replaced,waiting:!0,waitingFor:"the owner account (up to 15 minutes)"}}),s.interactive&&await s.openBrowser(r.url);let m=Date.now(),u=await Ee({db:t,id:r.id,...s.seams?.owner}),l=u.status==="claimed"?u.owner??await _(t):u.status==="gone"?await _(t):null;if(l)return e.emit({type:"step",step:"setup.owner",status:"ok",message:`Owner account created for ${l.email}`,data:{...l}}),{owner:l,created:!0};throw u.status==="waiting"?new D("claim_owner",`Open the setup link above to create the owner account
|
|
23
|
+
Nobody opened it within ${U(Date.now()-m)}. It still works for ${c()}; running setup before it's opened replaces it.`,void 0,{rerun:Ne(a),rerunNote:"to finish",data:{setupUrl:r.url,expiresAt:r.expiresAt.toISOString()}}):new D("claim_owner",`Use the newer setup link, or get a new one
|
|
24
|
+
This link stopped working before anyone used it: setup ran again on another machine, or it expired.`,void 0,{rerun:Ne(a),rerunNote:"for a new link"})}function Ne(t){return W([],{argv:t.json?["setup","--json"]:["setup"]})}var st={min:5,max:10},ot={tls:()=>"Its certificate is probably still on the way (TLS handshake failed).",dns:t=>`DNS has no address for ${t} yet.`,other:(t,n)=>`It didn't answer (${n}).`};async function rt(t,n,a){let e=new URL(t).host,s=await I(`${t}/`,a);s.answered?s.access&&n.emit({type:"warning",code:"ACCESS_IN_FRONT",step:"setup.owner",message:`Cloudflare Access protects ${e}
|
|
25
|
+
Whoever opens the setup link signs in to Access first.`}):n.emit({type:"warning",code:"GATEWAY_UNREACHABLE",step:"setup.owner",message:`${e} doesn't answer over HTTPS yet
|
|
26
|
+
${ot[s.kind](e,s.reason)} The link below works as soon as it does.`,data:{kind:s.kind,reason:s.reason}})}var it={accessInFront:({owner:t,cloudflareEmail:n})=>Q("Put Cloudflare Access in front of your Gateway?",["One command: people sign in at Cloudflare's edge before they reach your Gateway or its apps,","with their Cloudflare account (members of your Cloudflare account) or a code sent by email.",`Cloudflare's free Zero Trust plan covers 50 people. Turn it off any time: ${b} access off.`,...n&&n.toLowerCase()!==t.toLowerCase()?[`Your Cloudflare account is ${n}; your Gateway account is ${t}:`,`sign in with the code emailed to ${t}, or invite ${n} later.`]:[]]),browserDeploymentToken:async()=>await X("Configure browser app installs?",["Install apps on this Gateway through your browser, without running deployment commands."])?(await ae("Cloudflare API token",{context:["1. Open https://dash.cloudflare.com/profile/api-tokens"," Select Create Token, then Custom token > Get started.","2. Add permissions:"," Account > Workers Scripts > Edit; Account > D1 > Edit; Zone > DNS > Read."," Limit account resources to this account and zone resources to the Gateway's zone.","3. Continue to summary, create the token, then paste it below (input is hidden).","The token is stored as a secret on your Gateway."]})).trim():null,pickZone:t=>ee("Which of your domains should EveryApp live under?",t.map(n=>({label:n,value:n}))),gatewayAddress:t=>te("Gateway address",{context:[t.length===1?`Apps get addresses one level below the Gateway, e.g. todo.apps.${t[0]}`:`Your domains: ${t.join(", ")}. Apps live one level below the Gateway.`],initial:`apps.${t[0]}`,validate:n=>{let a;try{a=T(n)}catch{return`Enter a hostname like apps.${t[0]}`}return t.some(e=>a===e||a.endsWith(`.${e}`))?null:`Use a name under ${Le(t)}`}})};export{ra as a,ia as b,ca as c,Fe as d,Qe as e};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{xc as e}from"./chunk-FQ2A7YAP.js";import t from"node:path";var n=".cloudflare/types/index.d.ts";async function p(r,o){await r.run({args:["workers","types"],plane:"project",cwd:o,mode:"text"})}async function a(r){return e(t.join(r,n))}export{p as a,a as b};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import{A as P,Y as h,_ as F,ma as N,w as S}from"./chunk-KOBKGQ27.js";import{D as _,E as A,Ea as C,Pa as I,Qa as $,bc as s,c as m,d as D,k as w,rb as k,sb as L,tb as U,ub as x}from"./chunk-FQ2A7YAP.js";var M=new WeakMap;function q(e,t){let r=M.get(e);r||(r=new Map,M.set(e,r));let i=r.get(t);return i||(i=e.run([{sql:"SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?",params:[t]}]).then(([n=[]])=>n.length>0),r.set(t,i)),i}function T(e){return q(e,"providers")}function y(e){return q(e,"provider_connections")}async function R(e){if(!await T(e))return[];let[t=[]]=await e.run([{sql:"SELECT id, spec, added_by, added_at, bound_to FROM providers ORDER BY added_at, id"}]);return t.map(r=>({id:String(r.id),spec:String(r.spec),addedBy:h(r.added_by),addedAt:r.added_at==null?null:Number(r.added_at),boundTo:h(r.bound_to)}))}function z(e){return t=>L(t,{gatewayHost:e.gatewayHost,appBaseDomain:e.appBaseDomain})}function O(e,t){return x(e,{refuseHost:z(t)})}async function ne(e,t){return O(await R(e),t)}function V(e,t){return e.rows().filter(r=>_(r.capability).some(i=>t.includes(i)))}function H(){return new s("GATEWAY_OUTDATED",`This Gateway predates the provider registry
|
|
2
|
+
Its database has no providers table until the Gateway is updated. Nothing was changed.`,{rerun:`${m} update`,rerunNote:"then run this again"})}function W(e){return e==="everyapp"||A.includes(e)}async function ie(e,t){let r=I(t.spec);if(!r.ok)throw new s("PROVIDER_SPEC_INVALID",`The spec isn't one this Gateway takes
|
|
3
|
+
${$(r.problems)}`,{fix:"fix each field named above, then add it again"});let{id:i,capability:n}=r;if(!await T(e))throw H();let o=await R(e),a=O(o.filter(l=>l.id!==i),t.install),d=U(i,n,{rowSettings:new Set(a.rows().flatMap(l=>_(l.capability))),refuseHost:z(t.install)});if(d)switch(d.code){case"PROVIDER_BUILTIN":throw new s("PROVIDER_BUILTIN",`${i} is built in
|
|
4
|
+
A registered provider can't take a built-in provider's id.`,{fix:`give the provider another id in its spec; ${m} provider show ${i} prints the built-in one`});case"PROVIDER_SECRET_TAKEN":throw new s("PROVIDER_SECRET_TAKEN",`${i} can't use that setting: ${d.message}`,{fix:`name the provider's settings after its id, ${i.toUpperCase().replace(/-/g,"_")}_\u2026, and none another provider or the Gateway reads`});case"PROVIDER_HOST_REFUSED":throw new s("PROVIDER_HOST_REFUSED",`${i}'s key can't be sent there: ${d.message}`,{fix:"list only the provider's own public API hosts under hosts"});default:throw new s("PROVIDER_SPEC_INVALID",`The spec isn't one this Gateway takes
|
|
5
|
+
${d.message}`,{fix:"fix the spec, then add it again"})}let p=_(n);for(let l of await N(e)){if(!l.manifest)continue;let B=C(l.manifest).map(b=>b.toUpperCase()),v=p.filter(b=>B.includes(b));if(v.length>0)throw new s("PROVIDER_SECRET_TAKEN",`${w(v)} ${v.length===1?"is":"are"} ${l.appSlug}'s own secret
|
|
6
|
+
${l.appSlug}'s deployed manifest lists ${v.length===1?"it":"them"} under secrets, so a provider can't read ${v.length===1?"it":"them"} from the Gateway.`,{fix:`name the provider's settings otherwise, or drop ${w(v)} from ${l.appSlug}'s secrets and deploy it again`})}let c=o.find(l=>l.id===i);if(c&&!t.replace)throw new s("PROVIDER_EXISTS",`${i} is registered on this Gateway already
|
|
7
|
+
Replacing it writes the new spec; its key must then be set again before the Gateway sends it.`,{rerun:D(["--replace"]),rerunNote:"replaces it",authorize:!0});let g=t.now??Date.now(),E=JSON.stringify(t.spec),f=await G(e,"provider.added",{id:i,name:n.label,kind:n.mode==="oauth_client"?"oauth":"api_key"},t.deployer,g,{sql:"EXISTS (SELECT 1 FROM providers WHERE id = ? AND spec = ? AND updated_at = ?)",params:[i,E,g]}),[u=[]]=await e.run([c?{sql:"UPDATE providers SET spec = ?, updated_at = ?, bound_to = NULL, bound_at = NULL WHERE id = ? RETURNING id",params:[E,g,i]}:{sql:`INSERT INTO providers (id, spec, added_by, added_at, updated_at, bound_to, bound_at)
|
|
8
|
+
VALUES (?1, ?2, ?3, ?4, ?4, NULL, NULL) ON CONFLICT(id) DO NOTHING RETURNING id`,params:[i,E,t.deployer.actor,g]},...f]);if(u.length===0)throw new s("PROVIDER_EXISTS",`${i} changed on this Gateway while this ran`,{rerun:`${m} provider list`,rerunNote:"shows it as it is now"});return{id:i,capability:n,replaced:!!c}}async function ae(e,t,r,{force:i=!1,now:n=Date.now()}={}){if(W(t))throw new s("PROVIDER_BUILTIN",`${t} is built in
|
|
9
|
+
Only a provider registered with ${m} provider add can be removed.`,{rerun:`${m} provider list`,rerunNote:"shows which are registered"});if(!await T(e))throw H();let o=(await R(e)).find(u=>u.id===t);if(!o)throw new s("PROVIDER_NOT_FOUND",`No provider ${t} is registered on this Gateway`,{rerun:`${m} provider list`,rerunNote:"shows which are"});let a=I(J(o.spec)),d=(await N(e)).filter(u=>u.manifest?.capabilities&&Object.hasOwn(u.manifest.capabilities,t)).map(u=>u.appSlug);if(d.length>0&&!i)throw new s("PROVIDER_IN_USE",`${w(d)} ${d.length===1?"lists":"list"} ${t} under capabilities
|
|
10
|
+
Removing it stops ${d.length===1?"its":"their"} calls to it at once: the Gateway answers that it doesn't offer ${t}.`,{rerun:D(["--force"]),rerunNote:"removes it anyway",authorize:!0});let p=a.ok?a.capability.label:t,c=await G(e,"provider.removed",{id:t,name:p,kind:a.ok&&a.capability.mode==="oauth_client"?"oauth":"api_key"},r,n,{sql:"EXISTS (SELECT 1 FROM providers WHERE id = ?)",params:[t]}),g=await y(e),E=await e.run([...c,...g?[{sql:"DELETE FROM provider_connections WHERE provider_id = ? RETURNING id",params:[t]},{sql:"DELETE FROM oauth_clients WHERE provider_id = ? RETURNING provider_id",params:[t]}]:[],{sql:"DELETE FROM providers WHERE id = ?",params:[t]}]),f=g?E.slice(c.length,c.length+2):[];return{id:t,name:p,settings:a.ok?[..._(a.capability)]:[],apps:d,connections:f[0]?.length??0,client:(f[1]?.length??0)>0}}async function G(e,t,r,i,n,o){let a=await F(e);return a?P(e,{organizationId:a.organization.id,type:t,actor:S(i),data:{provider:{id:r.id,name:r.name,...r.kind?{kind:r.kind}:{}}},onlyIf:o,now:n}):[]}function J(e){try{return JSON.parse(e)}catch{return null}}async function se(e,t,r,i=Date.now()){let n=await R(e);if(n.length===0)return[];let o=O(n,t),a=V(o,r);return a.length===0?[]:(await e.run(a.map(p=>({sql:"UPDATE providers SET bound_to = ?, bound_at = ? WHERE id = ? AND spec = ? RETURNING id",params:[k(p.capability),i,p.id,n.find(c=>c.id===p.id).spec]})))).flatMap(p=>p.map(c=>String(c.id)))}async function oe(e){if(!await y(e))return new Map;let[t=[]]=await e.run([{sql:"SELECT provider_id, client_id, client_secret_enc IS NOT NULL AS has_secret, added_by, added_at FROM oauth_clients"}]);return new Map(t.map(r=>[String(r.provider_id),{providerId:String(r.provider_id),clientId:String(r.client_id),hasSecret:!!Number(r.has_secret),addedBy:h(r.added_by),addedAt:r.added_at==null?null:Number(r.added_at)}]))}function X(e){let t=[],r=[];return e.organizationId&&(t.push("c.organization_id = ?"),r.push(e.organizationId)),e.providerId&&(t.push("c.provider_id = ?"),r.push(e.providerId)),e.userEmail&&(t.push("lower(u.email) = ?"),r.push(e.userEmail.trim().toLowerCase())),e.organization&&t.push("c.account_kind = 'organization'"),{sql:t.length?`WHERE ${t.join(" AND ")}`:"",params:r}}function Y(e){try{let t=JSON.parse(String(e??"[]"));return Array.isArray(t)?t.map(String):[]}catch{return[]}}async function K(e,t={}){if(!await y(e))return[];let r=X(t),[i=[]]=await e.run([{sql:`SELECT c.id, c.organization_id, c.provider_id, c.account_kind, c.user_id, u.email AS user_email, c.label,
|
|
11
|
+
c.scope_sets, c.status, c.created_at, c.last_used_at, c.expires_at
|
|
12
|
+
FROM provider_connections c LEFT JOIN users u ON u.id = c.user_id
|
|
13
|
+
${r.sql}
|
|
14
|
+
ORDER BY c.created_at DESC, c.id`,params:r.params}]);return i.map(n=>({id:String(n.id),organizationId:String(n.organization_id),providerId:String(n.provider_id),account:n.account_kind==="organization"?"organization":"user",userId:h(n.user_id),userEmail:h(n.user_email),label:h(n.label),scopeSets:Y(n.scope_sets),status:String(n.status??"active"),createdAt:Number(n.created_at),lastUsedAt:n.last_used_at==null?null:Number(n.last_used_at),expiresAt:n.expires_at==null?null:Number(n.expires_at)}))}async function de(e){if(!await y(e))return new Map;let[t=[]]=await e.run([{sql:"SELECT provider_id, count(*) AS n FROM provider_connections GROUP BY provider_id"}]);return new Map(t.map(r=>[String(r.provider_id),Number(r.n)]))}async function ce(e,t,r,i=Date.now()){let n=await K(e,t);if(n.length===0)return[];let o=[];for(let a of n)o.push(...await P(e,{organizationId:a.organizationId,type:"provider.disconnected",actor:S(r),data:{provider:{id:t.providerId,name:t.providerName},account:{kind:a.account,...a.userId?{user:{id:a.userId,...a.userEmail?{email:a.userEmail}:{}}}:{},...a.label?{label:a.label}:{}},revoked:!1},onlyIf:{sql:"EXISTS (SELECT 1 FROM provider_connections WHERE id = ?)",params:[a.id]},now:i}),{sql:"DELETE FROM provider_connections WHERE id = ?",params:[a.id]});return await e.run(o),n}export{ne as a,V as b,ie as c,ae as d,se as e,oe as f,K as g,de as h,ce as i};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as E,b as v}from"./chunk-
|
|
1
|
+
import{a as E,b as v}from"./chunk-V7BWZOSZ.js";import{a as A}from"./chunk-S2G4G73L.js";import{a as y}from"./chunk-I7FNTTUY.js";import{Gc as f,Qc as w,Yc as g,c as a}from"./chunk-FQ2A7YAP.js";import I from"chalk";async function N(t){await S(t,(e,o)=>v(t,e,o))}async function S(t,e){let o=Date.now();await g(t,async n=>{let r=A({out:n,verbose:t.verbose}),i=await e(n,E({gateway:{openRelease:r.open,source:r.describe},interactive:y(t.json??!1)}));_(n,i,o)})}function _(t,e,o){let{gatewayUrl:n,organizationName:r,release:i,releaseName:p,owner:c,mode:d}=e,l=`${n}/admin`,s={gatewayUrl:n,adminUrl:l,organizationName:r,owner:c,release:i,mode:d,gateway:e.gateway,accessOn:e.accessOn},m={label:"Gateway",value:n},u=e.accessOn?[{label:"Access",value:"on",note:"everyone signs in through Cloudflare Access first"}]:[];if(e.gateway==="upgraded"&&!e.ownerCreated){t.emit({type:"done",message:`Upgraded to ${p}`,data:s,display:[...w([{label:"Gateway",value:I.cyan(n)}]),I.dim(`Upgraded to ${p} in ${f(Date.now()-o)}`)].join(`
|
|
2
2
|
`)});return}if(!c){t.emit({type:"done",data:{...s,facts:[m]}});return}if(e.gateway==="installed"||e.ownerCreated){t.emit({type:"done",data:{...s,facts:[m,{label:"Admin",value:l,note:"invite people, choose who opens which app"},...u],next:O(d,e.accessOn===!0)}});return}t.emit({type:"done",data:{...s,facts:[m,...u],...e.gateway==="up-to-date"?{next:[{command:`${a} status`,note:"see apps, domains and certificates"}]}:{}}})}function O(t,e){return t==="hosted"?[{command:`${a} create my-app`,note:"start your first app"},{command:`${a} secret set OPENAI_API_KEY`,note:"turn on AI for apps"},{command:`${a} secret set EMAIL_FROM EMAIL_FROM_NAME`,note:"email invites; needs Cloudflare Email Sending"}]:[{command:`${a} create my-app`,note:"start your first app"},...e?[]:[{command:`${a} access on`,note:"put Cloudflare Access in front of your Gateway (recommended)"}],{command:`${a} secret set OPENAI_API_KEY`,note:"AI for apps (or OPENROUTER_API_KEY, WORKERS_AI_API_TOKEN)"},{command:`${a} secret set EMAIL_FROM EMAIL_FROM_NAME`,note:"email invites and password resets; needs Cloudflare Email Sending"}]}export{N as a,S as b,_ as c};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{d}from"./chunk-
|
|
1
|
+
import{d}from"./chunk-BK4NK34C.js";import{o as u,p as f}from"./chunk-RQBSTNL7.js";import{Dc as i,Ec as l,bc as a,d as c}from"./chunk-FQ2A7YAP.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
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 @@
|
|
|
1
|
+
import{a,b,c}from"./chunk-MLTNW3AM.js";import"./chunk-PDPUGYJW.js";import"./chunk-WVHJIYQ3.js";import"./chunk-GAPQSINH.js";import"./chunk-ORGV2NNT.js";import"./chunk-KVCL64LI.js";import"./chunk-LEEUODYR.js";import"./chunk-3EADVHFN.js";import"./chunk-EQLY5I46.js";import"./chunk-DCFHBCCW.js";import"./chunk-KOBKGQ27.js";import"./chunk-RL72BUT4.js";import"./chunk-TIYSZWP5.js";import"./chunk-AMCNAKYU.js";import"./chunk-I7FNTTUY.js";import"./chunk-RQBSTNL7.js";import"./chunk-FQ2A7YAP.js";export{a as configure,b as configureApp,c as parsePipedLines};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as X}from"./chunk-
|
|
1
|
+
import{a as X}from"./chunk-VVKQJSF3.js";import{b as H}from"./chunk-R2DF3ENZ.js";import{b as Q,c as j,d as h}from"./chunk-ASCNE7GS.js";import"./chunk-HJGZGZFE.js";import{a as q}from"./chunk-AMCNAKYU.js";import{a as B,f as Y}from"./chunk-I7FNTTUY.js";import"./chunk-RQBSTNL7.js";import{Ac as U,Bb as O,Bc as G,Cc as z,Gb as R,Hb as _,Yc as V,bc as m,c as x,fc as M,h as I,l as C,vc as W,wc as J,xc as K}from"./chunk-FQ2A7YAP.js";import $ from"node:path";import w from"node:fs/promises";import E from"node:path";var ue=[".claude/skills",".agents/skills"],D={everyapp:"- Before running everyapp, read the everyapp skill: `.agents/skills/everyapp/SKILL.md` (also in `.claude/skills/`).","build-every-app":"- To build or change this app, read the build-every-app skill: `.agents/skills/build-every-app/SKILL.md` (patterns in patterns.md beside it)."};function N(e){return E.join(e,"packages","cli","skills")}async function he(e){let t=[];for(let r of await w.readdir(N(e),{withFileTypes:!0}))if(r.isDirectory())try{await w.access(E.join(N(e),r.name,"SKILL.md")),t.push(r.name)}catch{}let i=Object.keys(D).filter(r=>t.includes(r)),n=t.filter(r=>!(r in D)).sort();return[...i,...n]}function Z(e){return D[e]??`- Read the ${e} skill: \`.agents/skills/${e}/SKILL.md\` (also in \`.claude/skills/\`).`}async function ee({root:e,appDir:t}){let i=await he(e),n=[];for(let r of i)for(let a of ue){let o=`${a}/${r}`,l=E.join(t,o);await w.rm(l,{recursive:!0,force:!0}),await w.cp(E.join(N(e),r),l,{recursive:!0}),n.push(o)}return{skills:i,paths:n,agentsMd:await ye(t,i)}}async function ye(e,t){let i=E.join(e,"AGENTS.md"),n;try{n=await w.readFile(i,"utf8")}catch{return await w.writeFile(i,`# Agent instructions
|
|
2
2
|
|
|
3
3
|
${t.map(Z).join(`
|
|
4
4
|
`)}
|
|
@@ -13,7 +13,7 @@ ${r.map(Z).join(`
|
|
|
13
13
|
`;async function oe({root:e,targetDir:t,appId:i}){await W($e(e),t,{exclude:Ae}),h(t,e)||await ke.writeFile(A.join(t,"pnpm-workspace.yaml"),ve),await te({targetDir:t,appId:i,root:e}),await ne({targetDir:t,appId:i}),await re({targetDir:t,appId:i})}async function pe({targetDir:e,verbose:t=!1}){let i=n=>U("git",n,{cwd:e,echo:t,what:"Initializing the app's git repository",code:"GIT_FAILED"});await i(["init"]),await i(["add","."]),await i(["commit","-m","Starter template"])}import Ie from"node:os";import b from"node:path";var ce=/^[a-z]([a-z0-9-]*[a-z0-9])?$/,Ee="my-app";function L(e){let t=`"${e}" isn't a valid app name`;if(e.length>64)return{headline:t,fix:"use 64 characters or fewer"};if(e.includes("--"))return{headline:t,fix:`don't put two dashes in a row, e.g. ${e.replace(/-{2,}/g,"-")}`};if(!ce.test(e)){let i=le(e);return{headline:t,fix:`use lowercase letters, digits and dashes${i?`, e.g. ${i}`:", starting with a letter"}`}}return O(e)||R(e)===_?{headline:`"${e}" is reserved for the platform`,fix:"pick another name",reserved:!0}:null}function le(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^[^a-z]+|-+$/g,"");return t&&t.length<=64&&ce.test(t)?t:null}function be(e){return e.includes("/")||e.startsWith(".")||e.startsWith("~")||b.isAbsolute(e)}function Pe(e,{cwd:t,home:i}){return e==="~"||e.startsWith("~/")?b.resolve(i,e.slice(2)):b.resolve(t,e)}async function de(e,{interactive:t,yes:i,cwd:n,home:r=Ie.homedir()}){if(e!==void 0&&be(e)){let o=Pe(e,{cwd:n,home:r}),l=b.basename(o),p=L(l);if(p)throw new m("INVALID_APP_ID",`${p.headline}
|
|
14
14
|
An app is named after the last part of its path, ${e}.`,{fix:p.fix});return{appId:l,dir:o,absolute:b.isAbsolute(e)||e.startsWith("~")}}if(e!==void 0){let o=L(e);if(o)throw new m("INVALID_APP_ID",o.headline,{fix:o.fix});return{appId:e,dir:null,absolute:!1}}if(!t)throw new m("APP_ID_REQUIRED",`No app name given
|
|
15
15
|
${i?"--yes means nothing is asked.":"There's no terminal to ask for one."}`,{rerun:`${x} create <name>${i?" --yes":""}`});return{appId:await Y("App name",{context:["Lowercase letters, digits and dashes. It becomes part of the app's URL."],initial:Ee,validate:o=>{let l=L(o);if(!l)return null;if(l.reserved)return`${o} is reserved for the platform. Pick another name.`;let p=le(o);return`Use lowercase letters, digits and dashes.${p&&!L(p)?` Try ${p}`:""}`}}),dir:null,absolute:!1}}async function xe(e,t){await V(e,i=>Le({flags:e,appIdArg:t,out:i}))}async function Le({flags:e,appIdArg:t,out:i,cwd:n=process.cwd(),root:r=Q(),cf:a=z(),install:o=G,git:l=pe,home:p}){let k=e.verbose??!1;if(await K($.join(n,"everyapp.config.ts")))throw new m("NESTED_APP",`This directory is already an app
|
|
16
|
-
It has an everyapp.config.ts. New apps go next to it, not inside it.`,{fix:"run create from the directory that holds your apps"});let d=await de(t,{interactive:!e.yes&&B(e.json??!1),yes:e.yes??!1,cwd:n,...p===void 0?{}:{home:p}}),{appId:f}=d,c=d.dir??ae({appId:f,cwd:n,root:r}),P=$.relative(n,c),S=d.absolute?c:P,y=d.absolute||P.startsWith("..")?S:`./${P}`;if(d.dir!==null&&se(d.dir,r)==="inside"){let s=v=>d.absolute?v:$.relative(n,v);throw new m("APP_DIR_IN_CHECKOUT",`${y} is inside your
|
|
16
|
+
It has an everyapp.config.ts. New apps go next to it, not inside it.`,{fix:"run create from the directory that holds your apps"});let d=await de(t,{interactive:!e.yes&&B(e.json??!1),yes:e.yes??!1,cwd:n,...p===void 0?{}:{home:p}}),{appId:f}=d,c=d.dir??ae({appId:f,cwd:n,root:r}),P=$.relative(n,c),S=d.absolute?c:P,y=d.absolute||P.startsWith("..")?S:`./${P}`;if(d.dir!==null&&se(d.dir,r)==="inside"){let s=v=>d.absolute?v:$.relative(n,v);throw new m("APP_DIR_IN_CHECKOUT",`${y} is inside your EveryApp checkout but not in its apps/ folder
|
|
17
17
|
An app inside the checkout goes in apps/<name>; one anywhere else is its own git repository.`,{fix:`use ${s($.join(r,"apps",f))} (inside the checkout) or ${s($.join($.dirname(r),f))} (beside it)`})}if(await J(c))throw new m("APP_DIR_EXISTS",`${y} already exists`,{fix:`pick another name, or move ${y} away`});i.emit({type:"step",step:"create.copy",status:"start",message:"Copying the starter template",data:{appId:f,shown:y,elsewhere:d.dir===null&&P.startsWith("..")}}),await oe({root:r,targetDir:c,appId:f}),i.emit({type:"step",step:"create.copy",status:"ok",message:"Copied the starter template",data:{appId:f,dir:c}});let T=await ee({root:r,appDir:c});i.emit({type:"step",step:"create.skill",status:"ok",message:`Added the ${T.skills.join(" and ")} ${T.skills.length===1?"skill":"skills"} for coding agents`,data:T}),await F(i,"create.install",["Installing dependencies","Installed dependencies"],async()=>{try{await o({cwd:c,description:"Installing dependencies",verbose:k})}catch(s){throw Te(s,{shown:y,cdTo:S})}});let fe=await q(c);try{await F(i,"create.types",["Generating types","Generated types"],()=>X(a,c))}catch(s){i.emit({type:"warning",code:"WORKER_TYPES_FAILED",step:"create.types",message:`Couldn't generate types
|
|
18
18
|
${me(s)}. pnpm dev tries again.`})}try{i.emit({type:"step",step:"migrations.local",status:"start",message:"Setting up the local database"});let s=await H({cwd:c,manifest:fe,cf:a});i.emit({type:"step",step:"migrations.local",status:s.status==="applied"?"ok":"skip",message:"Set up the local database",data:s.status==="applied"?{database:s.database,applied:s.applied}:{reason:s.reason}})}catch(s){i.emit({type:"step",step:"migrations.local",status:"fail"}),i.emit({type:"warning",code:"MIGRATIONS_FAILED",step:"migrations.local",message:`Couldn't set up the local database
|
|
19
19
|
${me(s)}. pnpm dev tries again.`,data:{rerun:`${x} db migrate`}})}if(!h(c,r))try{await F(i,"create.git",["Starting a git repository","Started a git repository"],()=>l({targetDir:c,verbose:k}))}catch(s){if(!(s instanceof m)||s.code!=="GIT_FAILED")throw s;let v=I(s.data?.command)?.startsWith("git commit")??!1;i.emit({type:"warning",code:"GIT_FAILED",step:"create.git",message:`${v?"Couldn't make the first git commit":"Couldn't start a git repository"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as Y,b as K}from"./chunk-
|
|
1
|
+
import{a as Y,b as K}from"./chunk-SGRGD7L4.js";import{b as B,d as W,e as J}from"./chunk-R2DF3ENZ.js";import{b as _}from"./chunk-3EADVHFN.js";import{j as G}from"./chunk-HJGZGZFE.js";import{c as q,e as T}from"./chunk-DCFHBCCW.js";import{b as C,c as F,ga as P}from"./chunk-KOBKGQ27.js";import"./chunk-RL72BUT4.js";import"./chunk-TIYSZWP5.js";import{a as E,e as U,f as A}from"./chunk-AMCNAKYU.js";import{a as Q,i as x}from"./chunk-I7FNTTUY.js";import{t as k}from"./chunk-RQBSTNL7.js";import{Cc as $,Dc as S,Gb as M,Rc as j,Yc as R,bc as s,c as D,d as L,f as w,fc as N,gc as v,yc as O}from"./chunk-FQ2A7YAP.js";import ot from"node:fs/promises";import it from"node:path";import{text as at}from"node:stream/consumers";import u from"chalk";function V(t,e){let n=nt(t.reduce((r,o)=>r+o.duration,0));if(t.length===1){let[r]=t;if(z(r))return`${w(r.changes,"row")} changed ${u.green("\u2713")} ${u.dim(`${e} \xB7 ${n}`)}`;let o=u.dim(`${w(r.rows.length,"row")} \xB7 ${e} \xB7 ${n}`);return r.rows.length===0?o:[...H(r),"",o].join(`
|
|
2
2
|
`)}return[...t.flatMap(r=>[...z(r)?[`${w(r.changes,"row")} changed`]:H(r),""]),u.dim(`${w(t.length,"statement")} \xB7 ${e} \xB7 ${n}`)].join(`
|
|
3
3
|
`)}var z=t=>t.rows.length===0&&t.changes>0;function H({rows:t}){let e=Object.keys(t[0]??{});return e.length===0?[u.dim("0 rows")]:j(e,t.map(n=>e.map(r=>et(n[r]))))}function et(t){return t==null?u.dim("NULL"):typeof t=="string"?t.replaceAll(`
|
|
4
4
|
`,"\\n"):typeof t=="object"?JSON.stringify(t):String(t)}var nt=t=>t<1?"<1ms":`${Math.round(t)}ms`,rt=[/^(select|explain|values)\b/i,/^with\b(?![\s\S]*\b(insert|update|delete|replace)\b)/i,/^pragma\b[^=]*$/i];function X(t){let e=t.split(";").map(n=>n.trim()).filter(Boolean);return e.length>0&&e.every(n=>rt.some(r=>r.test(n)))}var I="db.migrate";async function jt(t){await R(t,async e=>{await st({cwd:process.cwd(),out:e}),e.emit({type:"done"})})}async function st({cwd:t,out:e,cf:n=$()}){let r=await E(t);await Y(t,e);let o;try{o=await B({cwd:t,manifest:r,cf:n,onApply:()=>e.emit({type:"step",step:I,status:"start",message:"Applying migrations to the local database..."})})}catch(a){throw await ct({cwd:t,manifest:r,cf:n,error:a})}if(o.status==="skipped"){e.emit({type:"step",step:I,status:"skip",message:o.reason==="no_d1"?`${r.id} declares no D1 database, so there's nothing to migrate.`:`No migrations in ${A(r)}/ yet, so there's nothing to migrate.`,data:{reason:o.reason}});return}K(e,I,o)}async function ct({cwd:t,manifest:e,cf:n,error:r}){let{problem:o,sqliteCode:a}=C(N(r)),[i]=await W({cwd:t,manifest:e,cf:n}).catch(()=>[]);return new s("MIGRATIONS_FAILED",[i?`Migration ${i} failed`:"A local migration failed",a?`${o} (${a})`:o].join(`
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{f as de}from"./chunk-EP4HRYXP.js";import{a as ee}from"./chunk-4LKLQOM7.js";import{A as ue,e as re,h as W,k as ne,l as se,r as ae,s as ie,v as me,z as ce}from"./chunk-GJK6GAWO.js";import{h as oe}from"./chunk-26KS6TD6.js";import{a as Z}from"./chunk-DWTJ4OLZ.js";import{m as X}from"./chunk-S2G4G73L.js";import"./chunk-BCTEWNN4.js";import{e as te}from"./chunk-KQM6ZUX5.js";import"./chunk-F5XK23HV.js";import"./chunk-YAZHTVUV.js";import{b as J}from"./chunk-BK4NK34C.js";import{O as _,R as j}from"./chunk-QKHLRLK3.js";import"./chunk-ORGV2NNT.js";import{c as D,d as C}from"./chunk-KVCL64LI.js";import"./chunk-LEEUODYR.js";import"./chunk-ASCNE7GS.js";import{a as R,b as U,g as H,h as $}from"./chunk-3EADVHFN.js";import"./chunk-HJGZGZFE.js";import"./chunk-LI3YLKLC.js";import"./chunk-EQLY5I46.js";import{c as M,e as B}from"./chunk-DCFHBCCW.js";import{k as F,m as G,o as T,oa as O,q as Q,r as V}from"./chunk-KOBKGQ27.js";import"./chunk-RL72BUT4.js";import"./chunk-TIYSZWP5.js";import{c as Y}from"./chunk-AMCNAKYU.js";import{a as E,f as P,i as x}from"./chunk-I7FNTTUY.js";import"./chunk-RQBSTNL7.js";import{Rb as q,Ub as K,Yc as L,b as A,c as b,dc as z,f as I,hc as h,k as N}from"./chunk-FQ2A7YAP.js";import we from"node:path";import le from"chalk";async function et(e,r){await L(e,async i=>{let o=r??(await Y(we.join(process.cwd(),"everyapp.config.ts"),{message:"Which app? There's no everyapp.config.ts here",fix:`run this from the app's directory, or name it: ${b} delete <id>`})).id,a=E(e.json??!1);await Re({appId:o,flags:e,interactive:a});let u=await ke({appId:o,gateway:M(e.gateway),accountId:e["account-id"],out:i,json:e.json,interactive:a,purge:e.purge??!1});i.emit({type:"done",...ge(o,u)})})}async function ke({appId:e,gateway:r,accountId:i,out:o,json:a,interactive:u,purge:l,createCf:n,reconcile:m}){let d=await B({gateway:r,accountId:i,interactive:u,login:{json:a,out:o,step:"app.login"},createCf:n}),{cf:p,db:f}=d,g=ee(m,o);await X(d.install,g.source),o.emit({type:"step",step:"app.delete",status:"start",message:`Removing ${e} from the Gateway...`,data:{appId:e}});let k=(await _(f)).find(fe=>fe.appId===e),y={publicRoutes:(k?.publicPaths.length??0)>0,mcp:k?.mcp??!1},c=await O(f,e,d.deployer,Date.now(),{purge:l}),v=d.install,t=v.liveAppWorkers.includes(c.workerName)||v.liveDomains.includes(c.hostname);(!c.alreadyDeleted||t)&&await Z({cf:p,out:o,accountId:d.accountId,databaseId:d.databaseId,interactive:u,cliVersion:A,...m,openRelease:g.openRelease}),await j({cf:p,db:f,install:d.install,out:o},{appId:e,surface:y,removing:!0}),o.emit({type:"step",step:"app.delete",status:"ok",message:`${e} is deleted on the gateway; ${c.hostname} stops serving it.`,data:{appId:e,hostname:c.hostname,workerName:c.workerName,alreadyDeleted:c.alreadyDeleted&&!t}});let s=await F(f);if(s&&J(c.hostname,s.appBaseDomain)&&!s.liveDomains.includes(c.hostname)&&await de({cf:p,out:o,zoneId:s.zoneId,hostname:c.hostname}),!l)return c;let w=await ye(p,f,d.accountId,o,e,c);return{...c,purged:w}}function ge(e,{workerName:r,alreadyDeleted:i,purged:o}){let a=`${b} delete ${e} --purge`,u=o?o.kept.length>0?`Deleted ${e}${o.removed.length>0?` and ${o.removed.join(", ")}`:""}; kept ${o.kept.join(", ")}.`:o.removed.length>0?`Deleted ${e} and ${o.removed.join(", ")}.`:`Deleted ${e}; nothing of it was left in Cloudflare.`:`${i?`${e} was already deleted`:`Deleted ${e}`}; its Worker and data are kept, and any cron triggers, Workflows and mail routes keep running.`,l=o?"":i?le.dim(`Its Worker and data are kept. To delete them: ${a}`):["Its Worker and data are kept, and any cron triggers, Workflows and mail routes keep running.",`To delete those too: ${a}`].map(n=>le.dim(n)).join(`
|
|
2
|
+
`);return{message:u,display:l,data:{appId:e,workerName:r,alreadyDeleted:i,purged:o?o.kept.length===0:!1,removed:o?.removed??[],kept:o?.kept??[]}}}var he=["Worker","Workflow","D1 database","KV namespace","Hyperdrive config","Queue","Vectorize index","AI Gateway","Secrets Store secret","mail route"],S={worker:"Compute (Workers) \u2192 Workers & Pages",d1:"Storage & Databases \u2192 D1",kv:"Storage & Databases \u2192 KV",workflow:"Compute (Workers) \u2192 Workflows",queue:"Compute (Workers) \u2192 Queues",vectorize:"AI \u2192 Vectorize"};async function ye(e,r,i,o,a,u){o.emit({type:"step",step:"app.purge",status:"start",message:`Deleting ${a}'s Worker and data...`,data:{appId:a}});let l=new Map,n=t=>l.set(t,(l.get(t)??0)+1),m=await U(r,u.workerName),d=await te({cf:e,gatewayDb:r,accountId:i,workerName:u.workerName,routes:m.filter(t=>t.kind==="email-route")});d.length>0&&l.set("mail route",d.length);let p=m.filter(t=>t.kind!=="email-route"),f=[],g=[],k=new Set(p.flatMap(t=>t.kind==="worker"&&t.resourceId?[t.resourceId]:[]));if(k.size>0)for(let t of await ce(e,u.workerName)){if(!k.has(t.script_name??"")){if(t.name.startsWith(`${u.workerName}--`)){let s=t.script_name??"unknown";f.push({described:`Workflow "${t.name}" (Worker ${s}'s)`,shown:`the Workflow ${t.name}, which Worker ${s} runs`,place:S.workflow})}continue}await ue(e,t.name)&&(d.push(`Workflow "${t.name}"`),n("Workflow"))}p.some(t=>t.kind==="queue"&&t.resourceId)&&await pe(e,k);let y=t=>t.kind!=="worker"?2:t.binding===""?0:1;for(let t of p.sort((s,w)=>y(s)-y(w)))if(t.resourceId)try{if(t.kind==="worker"){if(!await D(e,t.resourceId))continue;let s=t.resourceId;await C(e,s).catch(async w=>{if(!h(w,"queue_consumer_worker"))throw w;await pe(e,new Set([s])),await C(e,s)})}else if(t.kind==="d1")await Q(e,t.resourceId);else if(t.kind==="hyperdrive")await re(e,t.resourceId);else if(t.kind==="queue")await ne(e,t.resourceId);else if(t.kind==="vectorize")await me(e,t.resourceId);else if(t.kind==="ai-gateway")await oe(e,t.resourceId);else if(t.kind==="secrets-store-secret"){let[s="",w=""]=t.resourceId.split("/");await ae(e,s,w)}else await V(e,t.resourceId);d.push($(t)),n(R[t.kind])}catch(s){if(t.kind==="queue"&&h(s,"queue_in_use")){g.push({described:`${$(t)} (a Worker that isn't ${a}'s binds it)`,shown:`the Queue ${t.name}, which a Worker that isn't ${a}'s binds`,place:S.queue});continue}if(!h(s,"not_found"))throw s}await H(r,u.workerName);let c=[...await ve(e,u,p),...f,...g],v=he.flatMap(t=>{let s=l.get(t)??0;return s===0?[]:[s===1?t:I(s,t)]});if(o.emit({type:"step",step:"app.purge",status:"ok",message:d.length?`Deleted ${d.join(", ")}.`:"Nothing deleted in Cloudflare.",data:{appId:a,removed:d,kinds:v}}),c.length>0){let t=c.length===1;o.emit({type:"warning",code:"RESOURCES_KEPT",step:"app.purge",message:[`Kept ${N(c.map(s=>s.shown))}`,t?`It has ${a}'s name, but no deploy recorded creating it, so it may belong to something else.`:`They have ${a}'s names, but no deploy recorded creating them, so they may belong to something else.`].join(`
|
|
3
|
+
`),data:{kept:c.map(s=>s.described),fix:t?`if it is ${a}'s, delete it in the Cloudflare dashboard (${c[0].place})`:`if they are ${a}'s, delete them in the Cloudflare dashboard`}})}return{removed:d,kept:c.map(t=>t.described)}}async function ve(e,r,i){let o=new Set(i.filter(n=>n.resourceId).map(n=>`${n.kind}:${n.name}`)),a=[],u=(n,m)=>a.push({described:$({kind:n,name:m}),shown:`the ${R[n]} ${m}`,place:S[n]});!o.has(`worker:${r.workerName}`)&&await D(e,r.workerName)&&u("worker",r.workerName);for(let n of["d1","kv"])for(let m of new Set(Object.values(r.resources[n])))o.has(`${n}:${m}`)||await(n==="d1"?G:T)(e,m)&&u(n,m);let l=$e(r.manifest).map(n=>q(r.workerName,n)).filter(n=>!o.has(`queue:${n}`));if(l.length>0){let n=new Set((await W(e)).map(m=>m.queue_name));for(let m of l)n.has(m)&&u("queue",m)}for(let n of be(r.manifest)){let m=K(r.workerName,n);o.has(`vectorize:${m}`)||await ie(e,m)&&u("vectorize",m)}return a}async function pe(e,r){for(let i of await W(e))for(let o of i.consumers??[])if(!(!o.consumer_id||!r.has(o.script??"")))try{await se(e,i.queue_id,o.consumer_id)}catch(a){if(!h(a,"not_found"))throw a}}function $e(e){let r=e?.resources?.queues;return Array.isArray(r)?r.flatMap(i=>{let o=i?.name;return typeof o=="string"?[o]:[]}):[]}function be(e){let r=e?.resources;return(Array.isArray(r?.vectorize)?r.vectorize:[]).flatMap(o=>{let a=o?.name;return typeof a=="string"?[a]:[]})}async function Re({appId:e,flags:r,interactive:i}){if(r.purge&&i&&!r.yes){let o=(await P(`Type ${e} to confirm`,{context:[`This deletes ${e}'s Worker and all its data for good.`]})).trim();if(o!==e)throw new z(o?`"${o}" doesn't match ${e}. Nothing deleted.`:"Cancelled. Nothing deleted.");return}await x({yes:r.yes,interactive:i,question:`Delete ${e} from the Gateway?`,unattended:"Deleting an app needs confirmation at a terminal, or --yes",context:["Its Worker and data stay; --purge deletes them too."],cancelled:"Cancelled. Nothing deleted."})}export{et as deleteApp,ge as deletionSummary,ke as removeApp};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as a,c as b}from"./chunk-NW7SJPSP.js";import"./chunk-EP3IQ354.js";import"./chunk-O64FPLGX.js";import"./chunk-U4ATZJEU.js";import"./chunk-5IC3ZN52.js";import"./chunk-V7BWZOSZ.js";import"./chunk-N4E5YE4X.js";import"./chunk-BWNZ6F4F.js";import"./chunk-MEIWV7FJ.js";import"./chunk-QJRZFIYC.js";import"./chunk-TUXKBLLJ.js";import"./chunk-PDPUGYJW.js";import"./chunk-WVHJIYQ3.js";import"./chunk-GAPQSINH.js";import"./chunk-4LKLQOM7.js";import"./chunk-GJK6GAWO.js";import"./chunk-26KS6TD6.js";import"./chunk-DWTJ4OLZ.js";import"./chunk-S2G4G73L.js";import"./chunk-BCTEWNN4.js";import"./chunk-KQM6ZUX5.js";import"./chunk-F5XK23HV.js";import"./chunk-YAZHTVUV.js";import"./chunk-BK4NK34C.js";import"./chunk-QKHLRLK3.js";import"./chunk-ORGV2NNT.js";import"./chunk-KVCL64LI.js";import"./chunk-LEEUODYR.js";import"./chunk-ASCNE7GS.js";import"./chunk-3EADVHFN.js";import"./chunk-HJGZGZFE.js";import"./chunk-LI3YLKLC.js";import"./chunk-EQLY5I46.js";import"./chunk-DCFHBCCW.js";import"./chunk-KOBKGQ27.js";import"./chunk-RL72BUT4.js";import"./chunk-TIYSZWP5.js";import"./chunk-AMCNAKYU.js";import"./chunk-I7FNTTUY.js";import"./chunk-RQBSTNL7.js";import"./chunk-FQ2A7YAP.js";export{a as deploy,b as deployDone};
|