everyapp 0.2.2 → 0.3.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -77
  3. package/bin/everyapp.js +235 -0
  4. package/dist/access-LGEN3ABJ.js +1 -0
  5. package/dist/activity-RSD4D66F.js +12 -0
  6. package/dist/apps-4RCFXT74.js +13 -0
  7. package/dist/chunk-23HJ5I2A.js +2 -0
  8. package/dist/chunk-2Y5Q6A5K.js +6 -0
  9. package/dist/chunk-4JRIS6S6.js +1 -0
  10. package/dist/chunk-5PTNYZK6.js +4 -0
  11. package/dist/chunk-6OGVO7QK.js +6 -0
  12. package/dist/chunk-6PGUCTJ6.js +11 -0
  13. package/dist/chunk-AGTCKFRB.js +22 -0
  14. package/dist/chunk-BHMRY53V.js +2 -0
  15. package/dist/chunk-CB4U7H2G.js +4 -0
  16. package/dist/chunk-CCWBPAKH.js +4 -0
  17. package/dist/chunk-CZTEDWZ2.js +22 -0
  18. package/dist/chunk-CZXHKPRZ.js +2 -0
  19. package/dist/chunk-E3EPK27P.js +10 -0
  20. package/dist/chunk-EGEWRFVY.js +1 -0
  21. package/dist/chunk-ELK7QZ2M.js +1 -0
  22. package/dist/chunk-FJJSSVET.js +33 -0
  23. package/dist/chunk-GKBPYVP3.js +25 -0
  24. package/dist/chunk-H6QQMY7B.js +18 -0
  25. package/dist/chunk-H7PDL3X5.js +1 -0
  26. package/dist/chunk-HOUHG236.js +20 -0
  27. package/dist/chunk-IFCPALVC.js +46 -0
  28. package/dist/chunk-IUOBIB5M.js +30 -0
  29. package/dist/chunk-J35DDCNU.js +1 -0
  30. package/dist/chunk-J455FAEN.js +7 -0
  31. package/dist/chunk-JYKRUS5C.js +1 -0
  32. package/dist/chunk-LXYMDZER.js +1 -0
  33. package/dist/chunk-LYNBZ7RV.js +57 -0
  34. package/dist/chunk-M2QQ2UD7.js +132 -0
  35. package/dist/chunk-N4E5YE4X.js +5 -0
  36. package/dist/chunk-N5GQLGEC.js +2 -0
  37. package/dist/chunk-NFU4YFXB.js +1 -0
  38. package/dist/chunk-OM2HDWVP.js +1 -0
  39. package/dist/chunk-ONLNJXVQ.js +32 -0
  40. package/dist/chunk-OP4DYXYI.js +2 -0
  41. package/dist/chunk-PNLU5U3P.js +1 -0
  42. package/dist/chunk-PS7S74DG.js +6 -0
  43. package/dist/chunk-RMF4YGD6.js +98 -0
  44. package/dist/chunk-T2GD7RHS.js +10 -0
  45. package/dist/chunk-TLRM3P7V.js +15 -0
  46. package/dist/chunk-W3JCQHHU.js +1 -0
  47. package/dist/chunk-WOVS3GV5.js +10 -0
  48. package/dist/chunk-YHJZMJYZ.js +1 -0
  49. package/dist/chunk-ZECBN24L.js +15 -0
  50. package/dist/chunk-ZEXVHB22.js +2 -0
  51. package/dist/chunk-ZFCUH5PK.js +7 -0
  52. package/dist/configure-F7UZCJUG.js +8 -0
  53. package/dist/create-2E5HVWYK.js +22 -0
  54. package/dist/db-HEQVTDTM.js +9 -0
  55. package/dist/delete-XCSIQIRS.js +3 -0
  56. package/dist/deploy-3QOZEZHC.js +1 -0
  57. package/dist/dev-JL3ZP5BT.js +86 -0
  58. package/dist/email-RLZFUFUN.js +10 -0
  59. package/dist/events-2V5VRBWP.js +15 -0
  60. package/dist/groups-HDG5DVFY.js +8 -0
  61. package/dist/index.js +97 -1
  62. package/dist/install-Z5FYXUYM.js +1 -0
  63. package/dist/login-KHJBC64Z.js +1 -0
  64. package/dist/mcp-EFDUKJ5V.js +1 -0
  65. package/dist/provider-EOI5PTFH.js +13 -0
  66. package/dist/release-74J5ZIL3.js +1 -0
  67. package/dist/restore-FFGYV7NO.js +3 -0
  68. package/dist/secret-7FKKTLHB.js +1 -0
  69. package/dist/setup-PAKRCAFO.js +1 -0
  70. package/dist/signin-AP3D4XM4.js +12 -0
  71. package/dist/status-RMWNHOEK.js +4 -0
  72. package/dist/teardown-E4JNKAZJ.js +22 -0
  73. package/dist/update-DWVZFNPS.js +1 -0
  74. package/dist/workspace-CJC5I66L.js +21 -0
  75. package/package.json +19 -16
  76. package/skills/build-every-app/SKILL.md +199 -0
  77. package/skills/build-every-app/patterns.md +140 -0
  78. package/skills/everyapp/SKILL.md +292 -0
  79. package/skills/everyapp/mcp.md +350 -0
  80. package/skills/everyapp/security-review.md +61 -0
  81. package/skills/everyapp/setup/README.md +274 -0
  82. package/skills/everyapp/setup/access.md +178 -0
  83. package/skills/everyapp/setup/context.md +117 -0
  84. package/skills/everyapp/setup/dataforseo.md +287 -0
  85. package/skills/everyapp/setup/email.md +366 -0
  86. package/skills/everyapp/setup/gateway.md +243 -0
  87. package/skills/everyapp/setup/google.md +360 -0
  88. package/skills/everyapp/setup/microsoft-365.md +281 -0
  89. package/skills/everyapp/setup/openai.md +318 -0
  90. package/skills/everyapp/setup/openrouter.md +309 -0
  91. package/skills/everyapp/setup/providers.md +1253 -0
  92. package/skills/everyapp/setup/remote-mcp.md +199 -0
  93. package/skills/everyapp/setup/signin-apple.md +178 -0
  94. package/skills/everyapp/setup/signin-cloudflare.md +148 -0
  95. package/skills/everyapp/setup/signin-github.md +139 -0
  96. package/skills/everyapp/setup/signin-google.md +178 -0
  97. package/skills/everyapp/setup/signin-microsoft.md +183 -0
  98. package/skills/everyapp/setup/signin-oidc.md +163 -0
  99. package/skills/everyapp/setup/slack.md +344 -0
  100. package/skills/everyapp/setup/workers-ai.md +138 -0
  101. package/bin/__everyapp_bash_complete.js +0 -12
  102. package/dist/bash-complete.js +0 -3
  103. package/dist/chunk-7BOQJFI5.js +0 -8
  104. package/dist/chunk-7YVJFS4A.js +0 -1
  105. package/dist/chunk-BIXKPCDH.js +0 -2
  106. package/dist/chunk-DLGPLHBH.js +0 -47
  107. package/dist/chunk-FD6K2YA7.js +0 -9
  108. package/dist/chunk-GAJEQYJH.js +0 -39
  109. package/dist/chunk-O2KDOP5R.js +0 -13
  110. package/dist/chunk-OI2MBGBG.js +0 -4
  111. package/dist/chunk-POSDLD3G.js +0 -8
  112. package/dist/chunk-RB5D2R45.js +0 -1
  113. package/dist/chunk-U4LIQ5VR.js +0 -1
  114. package/dist/chunk-VEYSNPDH.js +0 -3
  115. package/dist/chunk-VP6SKW44.js +0 -7
  116. package/dist/chunk-WO3NE7ZU.js +0 -7
  117. package/dist/chunk-XTO2VTPY.js +0 -6
  118. package/dist/chunk-YJ2DKIZS.js +0 -1
  119. package/dist/create-DYQ3NBWJ.js +0 -22
  120. package/dist/deploy-PYTCMDGV.js +0 -7
  121. package/dist/deploy-RMAHOA4Z.js +0 -55
  122. package/dist/dev-SAE237FS.js +0 -0
  123. package/dist/generateConfig-46Z3ERF3.js +0 -1
  124. package/dist/login-B6EF3SMX.js +0 -1
  125. package/dist/logout-XMKZBLNV.js +0 -1
  126. package/dist/remoteD1Shell-A67JMO3H.js +0 -6
  127. package/dist/setupLocal-TZJUW5ES.js +0 -6
  128. package/gateway/every-app-gateway-build.tar.gz +0 -0
@@ -0,0 +1,10 @@
1
+ import"./chunk-5PTNYZK6.js";import{a as ee,b as ne,d as te,g as O}from"./chunk-PS7S74DG.js";import"./chunk-YHJZMJYZ.js";import"./chunk-N5GQLGEC.js";import"./chunk-W3JCQHHU.js";import{b as Z}from"./chunk-ZECBN24L.js";import{g as q}from"./chunk-HOUHG236.js";import{ha as B,ia as W,ja as z,ka as J,qa as K,sa as Q}from"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import{c as G}from"./chunk-H7PDL3X5.js";import{a as P}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{Bb as h,Ea as k,Fb as H,c as u,d as V,pc as X,rc as Y,wc as D}from"./chunk-LYNBZ7RV.js";import ce from"node:path";import{stripVTControlCharacters as me}from"node:util";import d from"chalk";var se="email.update";async function Me(e){await D(e,n=>pe({flags:e,out:n,senders:e.sender?.length?e.sender:void 0,inbound:e.inbound?.length?e.inbound:void 0,enableRouting:e["enable-email-routing"]}))}async function De(e,...n){await D(e,s=>ue({flags:e,out:s,lists:n}))}async function Oe(e){await D(e,n=>fe({flags:e,out:n}))}function ie(e,n){let s=[...new Set(k(e,n))];if(s.length===0)return;let a=e==="senders"?"--sender":"--inbound",t=e==="senders"?"EMAIL_SENDER_INVALID":"EMAIL_INBOUND_INVALID";if(s.length>1)throw new h(t,[`${s.length} problems with ${a}`,...s.map(l=>`\u2022 ${l}`)].join(`
2
+ `),{data:{problems:s}});let[p,c]=s[0].split(": "),A=k(e,n.map(l=>l.toLowerCase())).length===0;throw new h(t,c?`${p}
3
+ ${c.charAt(0).toUpperCase()}${c.slice(1)}`:p,{...A?{rerun:V([],{argv:process.argv.slice(2).map(l=>n.includes(l)?l.toLowerCase():l)})}:{},data:{problems:s}})}async function pe(e){let{senders:n,inbound:s}=e;if(n===void 0&&s===void 0)throw new h("EMAIL_NOTHING_TO_SET","Name what to set: --sender, --inbound, or both",{rerun:`${u} email set --help`});n!==void 0&&ie("senders",n),s!==void 0&&ie("inbound",s);let a=await F(e),t=O(a),p={rerun:`${u} deploy`,rerunNote:"then this command again"};if(n!==void 0&&!t.sends)throw new h("EMAIL_NOT_DECLARED",`${a.id} can't send mail yet
4
+ everyapp.config.ts doesn't list email in its capabilities.`,{fix:'add capabilities: { email: { access: "write" } } to everyapp.config.ts',...p});if(s!==void 0&&!t.receives)throw new h("EMAIL_INBOUND_NOT_DECLARED",`${a.id} can't receive mail yet
5
+ everyapp.config.ts doesn't declare email: { inbound: true }.`,{fix:"declare email: { inbound: true } and export email() from the app's Worker",...p});await re({...e,manifest:a,change:{...n!==void 0?{senders:[...n]}:{},...s!==void 0?{inbound:[...s]}:{}},spin:n!==void 0&&s!==void 0?"Updating email...":n!==void 0?"Updating senders...":`Routing ${s.join(", ")}...`,hostedCheck:n!==void 0})}async function ue(e){let n=await F(e);await re({...e,manifest:n,change:{...e.lists.includes("senders")?{senders:[]}:{},...e.lists.includes("inbound")?{inbound:[]}:{}},spin:"Clearing email...",hostedCheck:!1})}async function fe(e){let{out:n}=e,s=await F(e),{id:a}=s,t=O(s),{db:p,install:c}=await ae(e),A=t.sends&&c.deploymentMode!=="hosted",l=await W(p,a),C=(i,v)=>n.emit({type:"done",message:me(i),display:i,data:v});if(!l){C(d.dim(`${a} isn't deployed yet. Senders and inbound addresses can be set after its first deploy.`),{app:{id:a,deployed:!1},declares:t,next:[`${u} deploy`]});return}let{workerName:N,status:y}=l,{senders:f,inbound:w}=l.email,S=y==="pending",g=(await Z(p,N)).filter(i=>i.kind==="email-route"&&i.resourceId!==null).map(i=>i.name),o=g.filter(i=>!w.includes(i)),E=!t.receives&&w.length>0,$={app:{id:a,workerName:N,status:y,deployed:!S},declares:t,senders:f,inbound:w,routed:g},x=[...f.map(i=>[i,"sender",t.sends?"allowed":d.yellow("not declared")]),...w.map(i=>[i,"inbound",E?d.yellow("not declared"):g.includes(i)?d.green("routed"):d.yellow("not routed yet")]),...o.map(i=>[i,"inbound",d.yellow("removed, still routed")])],m={command:`${u} email set --sender '*@<domain>'`,note:"send as your own domain"},b={command:`${u} email set --inbound <address>`,note:"receive mail"};if(x.length===0){if(!t.sends&&!t.receives){C([`${a} doesn't send or receive email.`,'To send, add capabilities: { email: { access: "write" } } to everyapp.config.ts.',"To receive, add email: { inbound: true } to everyapp.config.ts."].map(v=>d.dim(v)).join(`
6
+ `),$);return}let i=[...A?[m]:[],...t.receives?[b]:[]];C(d.dim(`${a} ${t.sends?"sends as the Gateway's sender":"doesn't send email"} and ${t.receives?"receives no mail":"doesn't receive email"}.`),{...$,...i.length>0?{next:i}:{}});return}let R=w.some(i=>!g.includes(i)),T=!E&&(R||o.length>0),I=[...E?[{command:`${u} email unset inbound`,note:"clear the stored address"}]:T?[{command:`${u} deploy`,note:"route the list as shown"}]:[],...A&&f.length===0?[m]:[],...t.receives&&w.length===0?[b]:[]];C([...X(["ADDRESS","ROLE","STATUS"],x),...t.sends&&f.length===0?["",d.dim(`${a} sends as the Gateway's sender only.`)]:[],...E?[...t.sends&&f.length===0?[]:[""],d.dim("everyapp.config.ts no longer declares email: { inbound: true }, so this address isn't used.")]:[]].join(`
7
+ `),{...$,...I.length>0?{next:I}:{}})}function F(e){return e.flags.manifest?G(e.flags.manifest):G(ce.join(e.cwd??process.cwd(),"everyapp.config.ts"),{message:"No everyapp.config.ts in this directory",fix:"run this from the app's directory, or pass --manifest <path>"})}function ae({flags:e,out:n,createCf:s}){return Q({gateway:K(e.gateway),accountId:e["account-id"],interactive:P(e.json??!1),login:{json:e.json,out:n,step:"login"},createCf:s})}var oe=(e,n)=>e.length===n.length&&e.every(s=>n.includes(s));async function re(e){let{out:n,manifest:s,change:a}=e,{id:t}=s;n.emit({type:"step",step:se,status:"start",message:e.spin});let{cf:p,db:c,accountId:A,install:l,deployer:C}=await ae(e),N=l.deploymentMode==="hosted";if(e.hostedCheck&&N)throw new h("EMAIL_SENDERS_HOSTED",`This Gateway doesn't take app senders
8
+ Hosted Gateways send all app mail from their own sender for now.`);let y=await B(c,t),{workerName:f}=y,w=y.status==="pending",S=await q({db:c,out:n},{workerName:f,appId:t,purpose:"app.email"});try{let g=await z(c,y.id),o={senders:a.senders??g.senders,inbound:a.inbound??g.inbound},E=a.inbound!==void 0,$=w||!y.declaresInbound&&o.inbound.length>0,x=E&&!$?await ee({cf:p,gatewayDb:c,accountId:A,workerName:f,addresses:o.inbound,interactive:e.interactive??P(e.flags.json??!1),enableRouting:e.enableRouting,confirm:e.confirm}):null;await S.check(),await J(c,t,o,C);let m=[],b=[],R=!1;if(x)try{await S.check(),{routed:m,removed:b,changed:R}=await ne({cf:p,gatewayDb:c,plan:x,onProgress:r=>n.emit({type:"progress",step:"app.email",message:r})})}catch(r){throw new h("EMAIL_ROUTES_PARTIAL",`Inbound addresses saved, but routing them stopped part-way
9
+ ${H(r)}`,{retryable:!0,rerunNote:`again, or ${u} deploy, to finish`,data:{saved:o.inbound,cause:r instanceof h?r.code:null}})}n.emit({type:"step",step:se,status:"ok"});let T=!oe(o.senders,g.senders),I=!oe(o.inbound,g.inbound),i=[],v=[],L=(r,_)=>{i.push(Y(r,_)),v.push(`${r}${_?` (${_})`:""}.`)},U=r=>{i.push(d.dim(`Nothing changed. ${r}`)),v.push(r)};a.senders!==void 0&&(T?o.senders.length>0?L(`${t} sends as ${o.senders.join(", ")}`):L("Senders cleared","sends as the Gateway's sender"):U(o.senders.length>0?`${t} already sends as ${o.senders.join(", ")}.`:`${t} already sends as the Gateway's sender only.`));let j=[];E&&($&&o.inbound.length>0?(L(`Saved ${o.inbound.join(", ")}`),j.push(`It's routed to ${t} on the next deploy.`)):I||R?(m.length>0&&L(`Mail to ${m.join(", ")} goes to ${t}`),b.length>0&&L(`Stopped routing ${b.join(", ")}`),m.length===0&&b.length===0&&L("Inbound addresses cleared")):U(m.length>0?`Mail to ${m.join(", ")} already goes to ${t}.`:`${t} already receives no mail.`)),T&&j.push("The Gateway picks up the change within 30 seconds.");let M=O(s).sends&&!N&&m.length>0&&(I||R)?te(m,o.senders):[],de=M.length>0?["",d.dim(`To reply from ${M.join(", ")}, set ${M.length===1?"it":"them"} up for Email Sending, then:`),` ${d.bold(`${u} email set ${[...o.senders,...M.map(r=>`*@${r}`)].map(r=>`--sender '${r}'`).join(" ")}`)}`]:[],le=$&&o.inbound.length>0;n.emit({type:"done",message:[...v,...j].join(" "),display:[...i,...j.map(r=>d.dim(r)),...de].join(`
10
+ `),data:{app:{id:t,workerName:f,status:y.status},senders:{value:o.senders,changed:T},inbound:{value:o.inbound,changed:I,routed:m,removed:b},...le?{next:[`${u} deploy`]}:{}}})}finally{await S.release()}}export{Me as set,pe as setEmail,Oe as show,fe as showEmail,De as unset,ue as unsetEmail};
@@ -0,0 +1,15 @@
1
+ import{a as g,b as re,c as S,d as O,e as E,f as l,g as L,h as b,j as de,k as me}from"./chunk-CB4U7H2G.js";import"./chunk-M2QQ2UD7.js";import{a as z}from"./chunk-4JRIS6S6.js";import{D as W,E as Y,F as H,G as K,H as Q,I as X,J as B,K as J,L as Z,M as ee,N as te,O as ie,S as ne,T as se,U as ae,x as j,y as q}from"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import{a as V,g as U}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{Bb as y,Ja as I,Ma as P,Sa as G,c,f as $,lc as F,oc as oe,pc as D,qb as M,wc as u}from"./chunk-LYNBZ7RV.js";import{text as ge}from"node:stream/consumers";import he from"chalk";var R="events.add",Ee=/^[a-z][a-z0-9+.-]*:\/\//i;async function be(){return process.stdin.isTTY?null:ge(process.stdin)}async function Te(e){let i=e.flags["secret-from-env"];if(i){let n=(e.env??process.env)[i];if(!n)throw new y("SECRET_EMPTY",`$${i} is empty or not set`,{fix:`export ${i} first, or name another variable with --secret-from-env`});return n}let t=await(e.readStdin??be)();if(t!==null){let n=t.replace(/\r?\n$/,"");if(n)return n}let o=e.interactive??V(e.flags.json??!1);if(t!==null||!o)throw new y("SECRET_VALUE_REQUIRED",`Can't ask for the signing secret without a terminal
2
+ Pipe it in, or name the environment variable holding it with --secret-from-env.`,{fix:"leave --secret out to have one made, or add --secret-from-env <VAR>"});return(e.prompt??(()=>U("Signing secret",{context:["16 to 128 printable characters. Receivers check X-EveryApp-Signature with it."]})))()}async function pe(e,i){let{flags:t,out:o}=e,n=t.secret===!0||t["secret-from-env"]!==void 0;if(n&&i!==void 0&&!Ee.test(i.trim()))throw new y("VALUE_ON_COMMAND_LINE",`--secret takes no value on the command line
3
+ It lands in the shell's history and the process list: rotate it if it was real. Nothing was added.`,{fix:"give --secret alone: it asks at a hidden prompt, or reads the secret piped in or from --secret-from-env <VAR>"});if(i!==void 0&&t.email!==void 0)throw new y("EVENT_SINK_CONFLICT",`Give a webhook URL or --email, not both
4
+ A subscription delivers one way: a signed POST to a URL, or mail to the organization's owners (and admins).`,{fix:"add one subscription for each"});if(t.email!==void 0&&n)throw new y("EVENT_SINK_CONFLICT",`An email subscription has no signing secret
5
+ Only a webhook is signed; mail goes from the Gateway's own sender to the organization's members.`,{fix:"leave --secret out"});if(i===void 0&&t.email===void 0)throw new y("EVENT_SINK_CONFLICT","Name where events go: a webhook URL, or --email owners|admins",{rerun:`${c} events add https://hooks.example.com/everyapp`,rerunNote:"or --email admins"});let d=H(t.events),a=B(t.name),{gateway:s,organization:v}=await g(e),w=await z(s.cf,M),r,h=!1;if(i!==void 0){let T=K(i,{gatewayHost:s.install.gatewayHost,appBaseDomain:s.install.appBaseDomain,allowPrivate:w.includes(G)}),f=n?Q(await Te(e)):X();h=!n,r={sink:"webhook",url:T,secret:f}}else r={sink:"email",recipients:t.email},w.includes("EMAIL_FROM")||o.emit({type:"warning",code:"EVENT_EMAIL_NOT_CONFIGURED",step:R,message:`The Gateway has no sender (EMAIL_FROM), so these mails can't go out yet
6
+ Each one is dead at once with email_not_configured until a sender is set.`,data:{rerun:`${c} secret set EMAIL_FROM EMAIL_FROM_NAME`}});o.emit({type:"step",step:R,status:"start",message:"Adding the subscription..."});let m=await J(s.db,{organization:v,name:a??(r.sink==="webhook"?j(r.url):r.recipients==="owners"?"Email owners":"Email owners and admins"),events:d,target:r,deployer:s.deployer,now:e.now?.()});o.emit({type:"step",step:R,status:"ok",message:`Added ${l(m)}`,data:{id:m.id}});let x=`${c} events test ${m.id}`,A=`Added ${l(m)} for ${v.name}.`,_=oe([{label:"Events",value:O(m.events)},{label:"Target",value:S(m)},...r.sink==="webhook"&&h?[{label:"Secret",value:r.secret}]:[]]),k=[...r.sink==="webhook"?[h?"Copy it now: it isn't shown again. Each delivery is signed with it (X-EveryApp-Signature); the receiver checks it.":"Each delivery is signed with your secret (X-EveryApp-Signature); the receiver checks it."]:[],"The Gateway delivers within a minute of each event."];o.emit({type:"done",message:`${A} ${k.at(-1)}`,display:[A,..._,...k.map(T=>he.dim(T))].join(`
7
+ `),data:{subscription:E(m),organization:b(v),secretGenerated:h,...r.sink==="webhook"&&h?{secret:r.secret}:{},next:[{command:x,note:"sends a test event and waits for the delivery"}]}})}import p from"chalk";function $e(e){if(e.lastDeliveryAt===null)return p.dim("never");let i=e.lastDeliveryStatus??"unknown",t=i==="delivered"?p.green(i):i==="dead"?p.red(i):p.yellow(i),o=e.consecutiveFailures>0?p.yellow(` \xB7 ${$(e.consecutiveFailures,"failure")} in a row`):"";return`${t} ${re(e.lastDeliveryAt)}${o}`}async function ce(e){let{out:i}=e,{gateway:t,organization:o}=await g(e),n=await W(t.db,o.id),d=`${$(n.length,"subscription")} in ${o.name} (at most ${P})`,a=n.length===0?[p.dim(`${o.name} has no event subscriptions.`),p.dim(`Add a webhook: ${c} events add https://hooks.example.com/everyapp --events member.*`),p.dim(`Or mail the owners and admins: ${c} events add --email admins --events cap.*`)]:[...D(["ID","NAME","TARGET","EVENTS","ON","LAST DELIVERY"],n.map(s=>[s.id,`${s.name}${s.builtin?p.dim(" (built-in)"):""}`,S(s),O(s.events),s.enabled?p.green("on"):p.dim("off"),$e(s)])),"",p.dim(d)];i.emit({type:"done",message:d,display:a.join(`
8
+ `),data:{organization:b(o),subscriptions:n.map(E),max:P}})}function le({out:e}){let i=["An app's own events are app.<app id>.<name> (app.crm.invoice.paid): subscribe with app.crm.* or app.*.","--events takes types, prefixes with .* (member.*), or * for everything but test pings (the default)."];e.emit({type:"done",message:`${$(I.length,"event type")}`,display:[...D(["TYPE","V","WHAT"],I.map(t=>[t.type,String(t.version),p.dim(t.description)])),"",...i.map(t=>p.dim(t))].join(`
9
+ `),data:{types:I.map(t=>({type:t.type,version:t.version,group:t.group,description:t.description})),patterns:["*","<group>.*","app.<app id>.*","app.<app id>.<name>"]}})}import{stripVTControlCharacters as Se}from"node:util";import ve from"chalk";async function ue(e,i){let{out:t}=e,{gateway:o,organization:n}=await g(e),{subscription:d,outcome:a}=await Z(o.db,n,i,e.now?.()),s=a==="disabled"?[`${l(d)} is built in, so it was disabled instead of removed.`,`The Gateway won't make it again. Turn it back on: ${c} events enable ${d.id}`]:[`Removed ${l(d)} from ${n.name}.`,"Nothing more is delivered to it; its delivery log stays for 30 days."];t.emit({type:"done",message:s.join(" "),display:[s[0],ve.dim(s[1])].join(`
10
+ `),data:{id:d.id,outcome:a,subscription:E(d),organization:b(n)}})}async function C(e,i,t){let{out:o}=e,{gateway:n,organization:d}=await g(e),{subscription:a,changed:s}=await ee(n.db,d,i,t,e.now?.()),v=s?`${t?"Enabled":"Disabled"} ${l(a)}.`:`${l(a)} is ${t?"enabled":"disabled"} already.`,w=s?t?"New events are queued for it again; what happened while it was off isn't sent.":"No new events are queued for it, and the Gateway drops what is queued.":"Nothing changed.";o.emit({type:"done",message:Se(`${v} ${w}`),display:[v,ve.dim(w)].join(`
11
+ `),data:{id:a.id,enabled:t,changed:s,subscription:E(a),organization:b(d)}})}import N from"chalk";var we="events.test";function fe(e,i,t){let o=i.lastError?.split(`
12
+ `)[0]?.slice(0,200),n=i.lastStatusCode!==null&&i.lastStatusCode>0?i.lastStatusCode:null;return t==="email"?`${e}, ${n!==null?`${$(n,"recipient")} mailed`:o??"no answer"}`:n!==null?`${e} answered HTTP ${n}${o?` (${o})`:""}`:`${e} answered ${o??"no answer"}`}async function ye(e,i){let{out:t,flags:o}=e,{gateway:n,organization:d}=await g(e),a=await Y(n.db,d,i);if(!a.enabled)throw te(a,"a test");t.emit({type:"step",step:we,status:"start",message:`Queuing a test event for ${l(a)}...`});let s=await ne(n.db,{organizationId:d.id,subscription:a,actor:q(n.deployer),now:e.now?.()});t.emit({type:"step",step:we,status:"ok",message:`Queued ping ${s.eventId} as delivery ${s.deliveryId}`,data:s});let v=S(a),w=`${c} events deliveries ${a.id}`;if(o["no-wait"]){let f=`Queued a test event for ${l(a)}. The Gateway sends it to ${v} within a minute.`;t.emit({type:"done",message:f,display:[f,N.dim(`See how it went: ${w}`)].join(`
13
+ `),data:{outcome:"queued",subscriptionId:a.id,...s,next:[{command:w,note:"how it went"}]}});return}let r=e.now??Date.now,h=r();t.emit({type:"step",step:"events.deliver",status:"start",message:"Waiting for the Gateway to send it (it sends queued events every minute)..."});let m=await ae(n.db,d.id,s.deliveryId,{now:r,...e.wait});if(!m){let f=F(e.wait?.timeoutMs??se);throw new y("EVENT_TEST_TIMEOUT",`The Gateway hasn't sent the test event in ${f}
14
+ It stays queued. The Gateway sends queued events every minute; one installed before events were added sends them hourly at best until it is updated.`,{fix:`if the Gateway is older than this CLI, update it (${c} update)`,rerun:w,rerunNote:"shows whether it went since",data:{subscriptionId:a.id,...s}})}let x=ie(m,r()),A=F(r()-h);if(x==="delivered"){t.emit({type:"step",step:"events.deliver",status:"ok",message:`Delivered in ${A}`});let f=`Delivered: ${fe(v,m,a.sink)}.`;t.emit({type:"done",message:f,display:N.green(f),data:{outcome:"delivered",subscriptionId:a.id,delivery:L(m,r())}});return}t.emit({type:"step",step:"events.deliver",status:"fail",message:`Failed after ${A}`});let _=x==="failed",k=`The test event wasn't delivered: ${fe(v,m,a.sink)}.`,T=_?"The Gateway retries it (in a minute, then 5, 30, \u2026). Fix the receiver, then send another test.":"It is dead: the Gateway won't try it again.";t.emit({type:"done",message:`${k} ${T}`,display:[N.yellow(k),N.dim(T)].join(`
15
+ `),data:{outcome:"failed",subscriptionId:a.id,delivery:L(m,r()),next:[{command:`${c} events test ${a.id}`,note:"once the receiver is fixed"}]}})}async function lt(e,i){await u(e,t=>pe({flags:e,out:t},i))}async function vt(e){await u(e,i=>ce({flags:e,out:i}))}async function ut(e,i){await u(e,t=>ue({flags:e,out:t},i))}async function wt(e,i){await u(e,t=>C({flags:e,out:t},i,!0))}async function ft(e,i){await u(e,t=>C({flags:e,out:t},i,!1))}async function yt(e,i){await u(e,t=>ye({flags:e,out:t},i))}async function gt(e,i){await u(e,t=>de({flags:e,out:t},i))}async function ht(e,i){await u(e,t=>me({flags:e,out:t},i))}async function Et(e){await u(e,async i=>le({out:i}))}export{lt as add,gt as deliveries,ft as disable,wt as enable,vt as list,ht as redeliverDelivery,ut as remove,yt as test,Et as types};
@@ -0,0 +1,8 @@
1
+ import{a as h,b as D,e as E,g as M,h as v,j as G}from"./chunk-ELK7QZ2M.js";import{A as j,h as C,t as W,u as I,v as z,w as A,x as O,y as x,z as F}from"./chunk-M2QQ2UD7.js";import"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import{i as P}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{Bb as S,c as y,f as g,pc as f,wc as w}from"./chunk-LYNBZ7RV.js";import u from"chalk";var c="workspace.update";async function ee(e){await w(e,n=>N({flags:e,out:n}))}async function te(e,n){await w(e,o=>U({flags:e,out:o},n))}async function ae(e,n){await w(e,o=>R({flags:e,out:o},n))}async function oe(e,n){await w(e,o=>L({flags:e,out:o},n))}async function ne(e,n){await w(e,o=>q({flags:e,out:o},n))}async function se(e,n){await w(e,o=>_({flags:e,out:o},n))}var $=e=>({id:e.id,name:e.name,description:e.description,members:e.memberCount,apps:e.appCount,createdAt:new Date(e.createdAt).toISOString()});async function N(e){let{out:n}=e,{ws:o}=await h(e),r=await W(o),s=f(["GROUP","MEMBERS","APPS","DESCRIPTION","ID"],r.map(t=>[t.name,String(t.memberCount),String(t.appCount),t.description??u.dim("\u2013"),u.dim(t.id)]));n.emit({type:"done",message:`${g(r.length,"group")} in ${o.organization.name}`,display:r.length>0?s.join(`
2
+ `):u.dim(`No groups in ${o.organization.name} yet: ${y} workspace group create <name>`),data:{organization:o.organization,groups:r.map($)}})}async function U(e,n){let{out:o,flags:r}=e,{ws:s}=await h(e);o.emit({type:"step",step:c,status:"start",message:`Creating the group ${n}...`});let t=await I(s,{name:n,description:r.description});o.emit({type:"step",step:c,status:"ok",message:`Created ${t.name}`,data:{groupId:t.id}}),o.emit({type:"done",message:`Created the group ${t.name} (${t.id}) in ${s.organization.name}.`,data:{organization:s.organization,group:$(t),next:[{command:`${y} workspace group members ${T(t.name)} --add <email>`,note:"who is in it"},{command:`${y} workspace group apps ${T(t.name)} --add <app>`,note:"which apps it opens"}]}})}var T=e=>/^[\w.-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`;async function R(e,n){let{out:o,flags:r}=e;if(r.name===void 0&&r.description===void 0)throw new S("NOTHING_TO_SET","Nothing to set: give --name or --description");let{ws:s}=await h(e);o.emit({type:"step",step:c,status:"start",message:`Updating ${n}...`});let t=await z(s,n,{name:r.name,description:r.description});o.emit({type:"step",step:c,status:"ok",message:`Updated ${t.name}`,data:{groupId:t.id}}),o.emit({type:"done",message:`${t.name} (${t.id}): ${t.description?`"${t.description}"`:"no description"}.`,data:{organization:s.organization,group:$(t)}})}async function L(e,n){let{out:o,flags:r}=e,{ws:s}=await h(e),t=await C(s,n);await P({yes:r.yes,interactive:D(e),confirm:e.confirm,question:`Delete the group ${t.name}?`,unattended:"Deleting a group needs confirmation at a terminal, or --yes",context:[`It has ${g(t.memberCount,"member")} and opens ${g(t.appCount,"app")}; what it granted ends with it.`],cancelled:"Cancelled. Nothing deleted.",data:{groupId:t.id,name:t.name}}),o.emit({type:"step",step:c,status:"start",message:`Deleting ${t.name}...`}),await A(s,t.id),o.emit({type:"step",step:c,status:"ok",message:`Deleted ${t.name}`,data:{groupId:t.id}});let i=[`Deleted the group ${t.name} from ${s.organization.name}.`,`Its ${g(t.memberCount,"member")} keep their direct grants and other groups; the ${g(t.appCount,"app")} it opened are no longer open through it.`];o.emit({type:"done",message:i.join(`
3
+ `),display:[i[0],u.dim(i[1])].join(`
4
+ `),data:{organization:s.organization,group:$(t)}})}async function q(e,n){let{out:o,flags:r}=e,{change:s}=G(r),{ws:t}=await h(e),i=await C(t,n),p=[],m=[],d;s?(o.emit({type:"step",step:c,status:"start",message:`Changing who is in ${i.name}...`}),{added:p,removed:m,members:d}=await x(t,i,s),o.emit({type:"step",step:c,status:"ok",message:`${i.name}: ${g(p.length,"member")} added, ${m.length} removed`,data:{groupId:i.id,added:p.length,removed:m.length}})):d=await O(t,i);let l=d.filter(a=>a.inGroup),b=f(["EMAIL","ROLE","STATUS","IN GROUP"],d.map(a=>[a.email,a.primaryRole??a.role,M(a),a.inGroup?u.green("yes"):u.dim("no")])),k=s?`${i.name}: added ${p.length>0?p.map(a=>a.email).join(", "):"nobody"}, removed ${m.length>0?m.map(a=>a.email).join(", "):"nobody"}; ${g(l.length,"member")} in it now.`:`${g(l.length,"member")} in ${i.name}, of ${d.length} in ${t.organization.name}.`;o.emit({type:"done",message:k,display:[k,b.join(`
5
+ `)].join(`
6
+ `),data:{organization:t.organization,group:$({...i,memberCount:l.length}),members:d.map(a=>({...v(a),inGroup:a.inGroup})),...s?{added:p.map(v),removed:m.map(v)}:{}}})}async function _(e,n){let{out:o,flags:r}=e,{change:s}=G(r),{ws:t}=await h(e),i=await C(t,n),p=[],m=[],d;s?(o.emit({type:"step",step:c,status:"start",message:`Changing which apps ${i.name} opens...`}),{added:p,removed:m,apps:d}=await j(t,i,s),o.emit({type:"step",step:c,status:"ok",message:`${i.name}: ${g(p.length,"app")} granted, ${m.length} revoked`,data:{groupId:i.id,granted:p.length,revoked:m.length}})):d=await F(t,i);let l=d.filter(a=>a.granted),b=f(["APP","NAME","STATUS","OPENS"],d.map(a=>[a.appSlug,a.name,a.status,a.granted?u.green("yes"):u.dim("no")])),k=s?`${i.name}: granted ${p.length>0?p.map(a=>a.appSlug).join(", "):"nothing"}, revoked ${m.length>0?m.map(a=>a.appSlug).join(", "):"nothing"}; it opens ${g(l.length,"app")} now.`:`${i.name} opens ${g(l.length,"app")} of ${t.organization.name}'s ${d.length}.`;o.emit({type:"done",message:k,display:[k,b.join(`
7
+ `),u.dim(`Updated ${E(t.now)} UTC`)].join(`
8
+ `),data:{organization:t.organization,group:$({...i,appCount:l.length}),apps:d.map(a=>({id:a.id,appId:a.appSlug,name:a.name,status:a.status,granted:a.granted})),...s?{added:p.map(a=>({id:a.id,appId:a.appSlug})),removed:m.map(a=>({id:a.id,appId:a.appSlug}))}:{}}})}export{U as createGroup,L as deleteGroup,se as groupApps,_ as groupAppsCommand,te as groupCreate,oe as groupDelete,ne as groupMembers,q as groupMembersCommand,ae as groupSet,ee as groups,N as listGroups,R as updateGroup};
package/dist/index.js CHANGED
@@ -1,2 +1,98 @@
1
1
  #!/usr/bin/env node
2
- import{a as i,b as t}from"./chunk-POSDLD3G.js";import{a as r,b as o}from"./chunk-U4LIQ5VR.js";import"./chunk-RB5D2R45.js";import"./chunk-YJ2DKIZS.js";import{run as e}from"@stricli/core";r();await e(t,process.argv.slice(2),i(process));await o();
2
+ import{a as h,b as d,c as P,d as i,e as I,f as l,g as T,h as N,i as F,j as Se}from"./chunk-5PTNYZK6.js";import{i as $e}from"./chunk-CB4U7H2G.js";import{C as Re,I as Te,L as M,c as Z}from"./chunk-M2QQ2UD7.js";import"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{Fb as ye,Mb as be,N as ue,Rb as ve,Sa as X,Ua as we,a as me,b as B,c as t,ia as fe,ja as ge,k as he,mc as ke,nc as Ae,sc as Ce,tc as Ee,uc as J}from"./chunk-LYNBZ7RV.js";import Co from"chalk";import{run as Eo}from"@stricli/core";function Ge(e){return{process:e}}import v from"chalk";import{buildApplication as wo,buildRouteMap as yo,text_en as bo}from"@stricli/core";import{AliasNotFoundError as _e,ArgumentParseError as bt,EnumValidationError as vt,FlagNotFoundError as xe,InvalidNegatedFlagSyntaxError as kt,UnexpectedFlagError as At,UnexpectedPositionalError as Ct,UnsatisfiedFlagError as Et,UnsatisfiedPositionalError as St}from"@stricli/core";var U=`
3
+ A value never goes on the command line: it lands in the shell's history and the process list. Rotate it if it was real.`,je=new Set(["secret"]);function Rt(e){for(let[o,a]of e.entries()){let n=a.startsWith("--")?a.slice(2):"",r=e[o+1];if(je.has(n)&&r!==void 0&&!r.startsWith("-"))return n}}function De(e){return{code:"VALUE_ON_COMMAND_LINE",message:`--${e} takes no value on the command line${U}`,data:{fix:`give --${e} alone: it asks at a hidden prompt, or reads the value piped in or from --${e}-from-env <VAR>`}}}function Q(e){return e.includes("=")?`${e.split("=")[0]}=\u2026`:e}function ee(e){return e.includes("=")?U:""}function W(e,o){let a=[],n=e;for(let r of o){if(r.startsWith("-")||!("getRoutingTargetForInput"in n))break;let s=n.getRoutingTargetForInput(r);if(!s)break;a.push(r),n=s}return{path:a,target:n}}var x=e=>e.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`);function Tt(e,o){let a=o.parameters.positional,n=a?.kind==="array"?[`<${a.parameter.placeholder??"arg"}>...`]:(a?.parameters??[]).map((s,u)=>{let g=`<${s.placeholder??`arg${u+1}`}>`;return s.optional?`[${g}]`:g}),r=Object.entries(o.parameters.flags??{}).flatMap(([s,u])=>u.kind==="parsed"&&!u.optional&&u.default===void 0?[`--${x(s)} <${u.placeholder??"value"}>`]:[]);return[t,...e,...n,...r,"[flags]"].join(" ")}function te(e,o){let a;for(let n of o){let r=$t(e.toLowerCase(),n.toLowerCase());r<=2&&(!a||r<a.distance)&&(a={candidate:n,distance:r})}return a?.candidate}function $t(e,o){let a=Array.from({length:o.length+1},(n,r)=>r);for(let n=1;n<=e.length;n++){let r=[n];for(let s=1;s<=o.length;s++)r[s]=Math.min(a[s]+1,r[s-1]+1,a[s-1]+(e[n-1]===o[s-1]?0:1));a=r}return a[o.length]}function Oe(e,o,a){let{path:n,target:r}=W(e,o),s="getAllEntries"in r?r.getAllEntries().filter(g=>!g.hidden).map(g=>g.name.original):[],u=te(a,s);return{code:"UNKNOWN_COMMAND",message:[`Unknown command ${[...n,a].join(" ")}`,...n.length>0&&s.length>0?[`${n.join(" ")} has ${he(s)}.`]:[]].join(`
4
+ `),data:{...u?{didYouMean:[t,...n,u].join(" ")}:{},help:[t,...n,"--help"].join(" ")}}}function Le(e,o,a){let{path:n,target:r}=W(e,o),s="parameters"in r?r:void 0,u=n.join(" "),g={help:[t,...n,"--help"].join(" ")},A=s?{usage:Tt(n,s)}:{},y=s?.parameters.flags??{};if(a instanceof xe||a instanceof _e){let p=`${a instanceof _e?"-":"--"}${a.input}`,f=a instanceof xe?te(a.input,Object.keys(y).map(x)):void 0;return{code:"UNKNOWN_FLAG",message:`Unknown flag ${p}${u?` for ${u}`:""}`,data:{...f?{didYouMean:`--${f}`}:{},...g}}}if(a instanceof vt){let p=te(a.input,a.values);return{code:"INVALID_VALUE",message:`--${a.externalFlagName} can't be "${a.input}"
5
+ Use one of: ${a.values.join(", ")}.`,data:p?{didYouMean:p}:{}}}if(a instanceof bt){let p=a.exception instanceof Error?a.exception.message:String(a.exception),f=a.externalFlagNameOrPlaceholder,w=Object.keys(y).map(x).includes(f);return w&&je.has(f)?De(f):w&&y[Object.keys(y).find(_=>x(_)===f)]?.kind==="boolean"?{code:"INVALID_VALUE",message:`--${f} is a switch and takes no value${U}`,data:{fix:`use --${f} or --no-${f}`}}:w?{code:"INVALID_VALUE",message:p.startsWith(`--${f}`)?`${p}, not ${a.input}`:`--${f} can't be "${a.input}"
6
+ ${p}`,data:{}}:{code:"INVALID_VALUE",message:`"${Q(a.input)}" won't do for <${f}>
7
+ ${p}${ee(a.input)}`,data:A}}if(a instanceof St){let p=s?.parameters.positional;if(p?.kind==="array"){let C=p.parameter.brief;return{code:"MISSING_ARGUMENT",message:`Name at least one ${/^[A-Z]{2}/.test(C)?C:`${C.charAt(0).toLowerCase()}${C.slice(1)}`}`,data:A}}let f=s?.parameters.positional?.kind==="tuple"?s.parameters.positional.parameters.find(C=>C.placeholder===a.placeholder):void 0,w=f&&f.brief.length<=30?f.brief.replace(/^the /i,""):void 0;return{code:"MISSING_ARGUMENT",message:`Missing the ${w?/^[A-Z]{2}/.test(w)?w:`${w.charAt(0).toLowerCase()}${w.slice(1)}`:a.placeholder.replaceAll("-"," ")}`,data:A}}if(a instanceof Et){let p=a.externalFlagName,f=o.some(L=>L===`--${p}`||L.startsWith(`--${p}=`)),w=Object.keys(y).find(L=>x(L)===p),_=w?y[w]:void 0,C=_?.kind==="parsed"&&_.placeholder||"value";return{code:"MISSING_FLAG_VALUE",message:f?`--${p} needs a value`:`${u||"everyapp"} needs --${p} <${C}>`,data:{...A,...g}}}if(a instanceof Ct){let p=Rt(o);if(p)return De(p);let f=a.expectedCount===1?"one argument":`${a.expectedCount} arguments`;return{code:"TOO_MANY_ARGUMENTS",message:a.expectedCount===0?`${u||"everyapp"} takes no arguments (got "${Q(a.input)}")${ee(a.input)}`:`${u||"everyapp"} takes ${f}, but got another: "${Q(a.input)}"${ee(a.input)}`,data:A}}return a instanceof kt?{code:"INVALID_VALUE",message:`--no-${a.externalFlagName} is a switch and takes no value${U}`,data:{}}:a instanceof At?{code:"REPEATED_FLAG",message:`--${a.externalFlagName} is given more than once`,data:g}:{code:"COMMAND_FAILED",message:a instanceof Error?a.message:String(a),data:g}}import{buildCommand as ae,buildRouteMap as Gt}from"@stricli/core";var oe={gateway:h,"account-id":d,json:i,verbose:l},_t=ae({loader:async()=>{let{on:e}=await import("./access-LGEN3ABJ.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{email:{kind:"parsed",parse:String,variadic:!0,optional:!0,placeholder:"address",brief:"Also let this email address past Access (repeat for several; an account still takes an invitation)"},"email-domain":{kind:"parsed",parse:String,variadic:!0,optional:!0,placeholder:"domain",brief:"Also let everyone with an email address at this domain past Access (repeat for several)"},team:{kind:"parsed",parse:String,optional:!0,placeholder:"name",brief:"Name for a new Zero Trust team when the account has none: its sign-in page is <name>.cloudflareaccess.com, for good (asked at a terminal; ignored once a team exists)"},session:{kind:"parsed",parse:String,optional:!0,placeholder:"duration",brief:"How long an Access sign-in lasts, like 720h or 24h (default 720h, the most Access allows; an existing application keeps its own unless given)"},"team-session":{kind:"parsed",parse:String,optional:!0,placeholder:"duration",brief:"Set the team's global session too (how often people sign in at the identity provider): it applies to every Access application in the account"},"write-settings":{kind:"boolean",optional:!0,brief:"Write the three Gateway settings even when they are set already (after an Access application was recreated by hand: its AUD tag changed)"},...oe}},docs:{brief:"Turn Cloudflare Access on in front of the Gateway and its apps, or bring it up to date",fullDescription:["Everyone opens the Gateway and its apps through Cloudflare Access first (a one-time PIN to","their email, or your identity provider), then lands signed in. With your Cloudflare login it","finds or creates the Zero Trust team, adds the one-time PIN when people have no other way to","sign in, keeps an allow policy with every member's and invitee's email, puts one Access","application in front of the Gateway's host and one in front of the apps' hosts (MCP, the OAuth","endpoints and each app's public routes stay reachable without a login), and gives the Gateway","the team domain and both AUD tags in one change.","","Run it again any time: after inviting someone, so Access lets them in, or after anything","changed by hand. It changes only what differs, never removes anyone from the policy, and","leaves alone what it didn't set up. Deploys keep an app's public routes in step themselves.","","Afterwards each existing member signs in once with their password through Access, which",`links the two. Then passwords can go: ${t} secret set EMAIL_PASSWORD_SIGN_IN (false).`,"","Examples:",` ${t} access on`,` ${t} access on --email-domain example.com`,` ${t} access on --team acme --json`].join(`
8
+ `)}}),xt=ae({loader:async()=>{let{off:e}=await import("./access-LGEN3ABJ.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{"keep-applications":{kind:"boolean",optional:!0,brief:"Keep the two Access applications: Access still asks people to sign in there, and the Gateway no longer requires it"},yes:{kind:"boolean",optional:!0,brief:"Turn Access off without asking"},...oe},aliases:{y:"yes"}},docs:{brief:"Turn Cloudflare Access off for the Gateway and its apps",fullDescription:["Removes CLOUDFLARE_ACCESS_AUD, CLOUDFLARE_ACCESS_APPS_AUD and CLOUDFLARE_ACCESS_TEAM_DOMAIN","from the Gateway in one change, so passwords sign people in again at once, then deletes the","two Access applications (one that also covers something else only loses Every App's hosts).","The Zero Trust team, its identity providers and the allow policy stay: other applications may","use them. Asks first.","","Example:",` ${t} access off`].join(`
9
+ `)}}),Dt=ae({loader:async()=>{let{show:e}=await import("./access-LGEN3ABJ.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:oe},docs:{brief:"Show how Cloudflare Access fronts the Gateway, and what access on would change",fullDescription:["The Zero Trust team, who the allow policy lets in, the two Access applications and whether","their public paths match the apps' public routes, and which Access settings the Gateway has","(their values can't be read back). Nothing is changed.","","Example:",` ${t} access show`].join(`
10
+ `)}}),Pe=Gt({routes:{on:_t,off:xt,show:Dt},docs:{brief:"Put Cloudflare Access in front of the Gateway and its apps, or take it off"}});import{buildCommand as jt}from"@stricli/core";var Ie=jt({loader:async()=>{let{configure:e}=await import("./configure-F7UZCJUG.js");return e},parameters:{positional:{kind:"tuple",parameters:[{brief:"The app to configure (default: the app in this directory)",parse:String,placeholder:"app",optional:!0}]},flags:{"from-env":{kind:"boolean",brief:"Take each unset setting's value, optional ones too, from the environment variable of its name (DATAFORSEO_API_KEY from $DATAFORSEO_API_KEY); a set name is never replaced; stdin isn't read; the rest are asked for at a terminal",optional:!0},gateway:h,"account-id":d,json:i,verbose:l}},docs:{brief:"Set up an app: asks for each setting it needs, required ones first, then the optional ones",fullDescription:["Reads what the app's everyapp.config.ts declares (AI providers, capabilities, its own","secrets) and what is set, then asks for each required setting that isn't (hidden input,","with where to get it beside each), offers the optional ones (Enter skips them all), and","says whether the app is ready. One member of an any-of group is enough: it asks which.","Run it again any time: it shows what is set (names only, never values) and lets you","change one.","","Where they go: an AI provider's key or a capability's client is a Gateway setting, held","once for every app on the Gateway Worker; the app's own secrets go on its Worker, after","its first deploy. Changes are live at once; no deploy needed.","","For a script or a coding agent, which can't answer a prompt: pipe NAME=value lines in","(one per line; # starts a comment only at the start of a line; a value is taken as it is,","one pair of quotes around it dropped), or export the variables under the settings' own","names and add --from-env (then stdin isn't read). A value never goes on the command line.","","Examples:",` ${t} configure crm`,` ${t} configure (in the app's directory)`,` ${t} configure crm --from-env --json`,` printf 'OPENROUTER_API_KEY=%s\\n' "$OPENROUTER_API_KEY" | ${t} configure crm --json`,"",`One setting at a time, by name: ${t} secret set <NAME> [--app <id>]`].join(`
11
+ `)}});import{buildCommand as Ot}from"@stricli/core";var Ne=Ot({loader:async()=>import("./create-2E5HVWYK.js"),parameters:{positional:{kind:"tuple",parameters:[{brief:"An app name (lowercase letters, digits and dashes, e.g. my-app; asked for when missing), or the path of the folder to make, named after its last part (../my-app)",parse:String,placeholder:"name or path",optional:!0}]},flags:{yes:{kind:"boolean",brief:"Don't ask anything (a name is then required)",optional:!0},json:i,verbose:{kind:"boolean",brief:"Stream install and git output to stderr",optional:!0}},aliases:{y:"yes"}},docs:{brief:"Create a new app from the starter template",fullDescription:["A path (../my-app, ~/apps/my-app) makes the app there, named after its last part:","outside your Every App checkout it is its own git repository, linked to the checkout;","inside it only apps/<name> is allowed. A bare name goes in apps/<name> when run from","the checkout, in ./<name> anywhere else. Dependencies are installed and the local","database is ready, so `pnpm dev` works straight away. Then: cd into it and","`pnpm run deploy`.","","Examples:"," pnpm everyapp create ../my-app beside the checkout, its own repository"," pnpm everyapp create analytics apps/analytics, from the checkout"].join(`
12
+ `)}});import{buildCommand as ne,buildRouteMap as Lt}from"@stricli/core";var Pt=ne({loader:async()=>{let{migrate:e}=await import("./db-HEQVTDTM.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{json:i,verbose:l}},docs:{brief:"Apply migrations to the local database",fullDescription:["Apply the app's migrations to the local database","","Reads migrations from migrations.dir in everyapp.config.ts (default drizzle/).",`\`${t} dev\` runs this on every start. Production migrations run only during`,`\`${t} deploy\`, after a restore point is saved.`].join(`
13
+ `)}}),It=ne({loader:async()=>{let{query:e}=await import("./db-HEQVTDTM.js");return e},parameters:{positional:{kind:"tuple",parameters:[{brief:"SQL to run",parse:String,placeholder:"sql",optional:!0}]},flags:{local:{kind:"boolean",brief:"Query the local database `everyapp dev` uses",optional:!0},file:{kind:"parsed",parse:String,brief:"Read the SQL from a file (- for stdin)",placeholder:"path",optional:!0},binding:{kind:"parsed",parse:String,brief:"D1 binding to query (default: the migrations binding, or the first)",placeholder:"name",optional:!0},gateway:h,"account-id":d,yes:{kind:"boolean",brief:"Run SQL that changes the production database without asking",optional:!0},json:{...I,brief:"Print one NDJSON done event, its rows in data.results, instead of a table"},verbose:{...l,brief:"Show every step"}}},docs:{brief:"Run SQL against the production database (or --local)",fullDescription:["Run SQL against the app's D1 database","","Runs against the production database unless --local is set; SQL that changes it is","confirmed first (--yes skips that). Rows print as a table; with --json they are in the","done event's data.results.","","EXAMPLES",` $ ${t} db query "select * from todos limit 5"`,` $ ${t} db query --local "select count(*) from events"`,` $ ${t} db query --file scripts/backfill.sql`].join(`
14
+ `)}}),Nt=ne({loader:async()=>{let{restore:e}=await import("./restore-FFGYV7NO.js");return e},parameters:{positional:{kind:"tuple",parameters:[{brief:"The app (default: the one in this directory)",parse:String,placeholder:"app",optional:!0}]},flags:{gateway:{kind:"boolean",brief:"Restore the Gateway's database, from its last migrating setup or upgrade",optional:!0},"account-id":d,yes:{kind:"boolean",brief:"Restore without asking",optional:!0},json:i}},docs:{brief:"Put the production database back to before the last migrations",fullDescription:["Put the app's production database back to before its last migrations","","Each deploy that migrates a database with data saves a restore point first (Time Travel).","This restores the last one, after asking: the migrations are undone, and so is anything","written to the database since. --gateway does the same for the Gateway's database.","","EXAMPLES",` $ ${t} db restore`,` $ ${t} db restore --gateway`].join(`
15
+ `)}}),Fe=Lt({routes:{migrate:Pt,query:It,restore:Nt},docs:{brief:"Migrate, query and restore an app's D1 database"}});import{buildCommand as Ft}from"@stricli/core";var Me=Ft({loader:async()=>{let{deleteApp:e}=await import("./delete-XCSIQIRS.js");return e},parameters:{positional:{kind:"tuple",parameters:[{brief:"App id (default: the app in this directory)",parse:String,placeholder:"id",optional:!0}]},flags:{gateway:h,"account-id":d,purge:{kind:"boolean",brief:"Also delete the app's Worker and helper Workers, D1 databases, KV namespaces, Workflows and Email Routing routes",optional:!0},yes:{kind:"boolean",brief:"Delete without asking (with --purge too, without typing the app id)",optional:!0},json:i,verbose:l},aliases:{y:"yes"}},docs:{brief:"Remove an app from the Gateway",fullDescription:["Deletes the app in the Gateway's D1 database (its name stays reserved; deploy it again to","bring it back) and removes its Gateway binding and hostname, with a redeploy of the Gateway","from this checkout.","The app's Worker and data are kept unless --purge, which deletes them for good.","Asks first at a terminal; elsewhere it needs --yes."].join(`
16
+ `)}});import{buildCommand as Mt}from"@stricli/core";var Ue=Mt({loader:async()=>{let{deploy:e}=await import("./deploy-3QOZEZHC.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{gateway:h,"account-id":d,...F,"no-wait":{kind:"boolean",brief:"Don't wait for the app to go live (a new hostname's certificate included); it goes live on its first visit",optional:!0},yes:{kind:"boolean",brief:"With no Gateway yet, install one at apps.<zone> without asking (never cf's questions, or the one before replacing a Worker changed outside everyapp)",optional:!0},json:i,verbose:l},aliases:{y:"yes"}},docs:{brief:"Deploy the app in this directory",fullDescription:["Deploys the app in this directory as a private Cloudflare Worker defined by cloudflare.config.ts,","with cf and your Cloudflare login (or CLOUDFLARE_API_TOKEN), in the Gateway's account:"," 1. Registers the app in the Gateway's database, which names its Worker, resources and hostname"," 2. Creates or links the D1 databases and KV namespaces in everyapp.config.ts"," 3. Installs dependencies and builds (cf build, or the manifest's build command), then checks"," the built Worker against the app policy and the drizzle migrations against the schema"," 4. Bookmarks the production D1 database, then applies its migrations"," 5. Uploads the Worker with its secrets, its helper Workers, its Workflows and the Email"," Routing rules for its inbound addresses (turning routing on for a domain asks first)"," 6. Rebinds the Gateway from this checkout when the app is new (upgrading the Gateway too"," when the checkout is newer), then waits for the app's hostname to go live","","No Gateway in any account the login sees? At a terminal it offers to install one at",`apps.<zone> (what ${t} setup does), then deploys; otherwise it stops with action_required`,"install_gateway and the setup command to run. Nothing else asks first. Install and build","output goes to a log file, never to stdout. Safe to run again: a redeploy of an app the","Gateway already serves never touches the Gateway.","",`Someone else's published app: ${t} install <url>. To publish this one: ${t} release.`,"--gateway <url> (or EVERYAPP_GATEWAY_URL) names the Gateway when your login sees several.","With --json, each step is an NDJSON event."].join(`
17
+ `)}});import{buildCommand as Ut}from"@stricli/core";import{numberParser as Wt}from"@stricli/core";var We=Ut({loader:async()=>import("./dev-JL3ZP5BT.js"),parameters:{flags:{port:{kind:"parsed",parse:Wt,brief:"Gateway port (defaults to $PORT, then 8787)",optional:!0},host:{kind:"parsed",parse:String,brief:"Address the Gateway listens on (default 127.0.0.1; 0.0.0.0 lets other machines in, each as a dev identity)",optional:!0},mode:{kind:"parsed",parse:String,brief:"stub (seeded dev user, default) | mirror (real login through a local Gateway)",optional:!0},gateway:{kind:"parsed",parse:String,brief:"mirror mode: URL of the separately-run local Gateway (default http://localhost:3000)",optional:!0},baseHost:{kind:"parsed",parse:String,brief:"mirror mode: two-label base host for cookie scope (default everyapp.localhost)",optional:!0},"skip-migrations":{kind:"boolean",brief:"Start without applying local database migrations",optional:!0}}},docs:{brief:"Run the app locally behind a dev Gateway",fullDescription:["Runs the app under `cf dev` (or the manifest's dev command) on an internal","port and a gateway-lite in front of it on $PORT (default 8787) \u2014 the REAL","perimeter: public-route policy, header strip/inject, a real RS256 identity","JWT, and a seeded dev user. Open http://<app-id>.localhost:8787 \u2014 the first","Host label selects the app, so portless per-worktree hosts work with no","configuration.","","Identities are signed with the SDK's well-known dev keypair, which the app's","development build trusts on its own: nothing is written into the app. The","key is public, so the gateway listens on 127.0.0.1 unless --host says","otherwise. Before starting, dev generates the Worker's types when",".cloudflare/types is missing and applies local D1 migrations","(cf d1 migrations apply --local) to .cloudflare/state.","","With no Gateway in local runs, the app reads its manifest's secrets and the","keys of its providers and capabilities (OPENROUTER_API_KEY, DATAFORSEO_API_KEY,","...) from .dev.vars in its directory, one NAME=value per line, gitignored. The","ready block names the ones that file is missing and the app can't run without;","until they are set, AI calls and integrations answer that they aren't set up","(email needs none: sendEmail() prints until EMAIL_FROM and a transport are set).","","Every request goes through the real perimeter (identity header, public-route","policy, CSRF). Public routes are auth-optional; to call them anonymously send","the header x-everyapp-dev-anon: 1 (curl) or set the cookie everyapp_dev_anon=1","(browser). Requests straight to the app's internal port get 401, by design.","","An app that declares crons runs one on demand with"," curl -X POST http://<app-id>.localhost:8787/__everyapp/cron -d '<schedule>'","An app that receives mail gets a curl command that delivers message.eml to its","email() handler: a raw message with From, To, Subject and Message-ID headers,","to any address. email() gets no identity.","","--mode stub (default): seeded dev user, zero setup.","--mode mirror: authenticate against a SEPARATELY-running local Gateway"," (run `pnpm dev` in apps/every-app-gateway first). Real login/launcher"," are forwarded to it. Requires a two-label base host (e.g."," everyapp.localhost) so the session cookie crosses the subdomain"," boundary; the CLI prints setup guidance if the host is unusable."," Also settable via EVERYAPP_DEV_MODE; the flag wins.","","Ctrl+C stops the app and exits with 130."].join(`
18
+ `)}});import{buildCommand as b,buildRouteMap as qt}from"@stricli/core";var E={org:P,gateway:h,"account-id":d,json:i,verbose:l},D={placeholder:"id",brief:"The subscription, by its sub_ id (events list names them)",parse:String},zt=b({loader:async()=>{let{add:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[{placeholder:"url",brief:"The webhook's https:// URL (leave it out with --email)",parse:String,optional:!0}]},flags:{events:{kind:"parsed",parse:String,variadic:!0,optional:!0,placeholder:"types",brief:"The events to send, comma separated: types (member.joined), prefixes (cap.*, app.crm.*) or * (repeat to add more; default: every event but test pings)"},name:{kind:"parsed",parse:String,optional:!0,placeholder:"text",brief:"What to call it, like 'Slack #ops' (default: the URL's host, or Email owners and admins)"},email:{kind:"enum",values:we,optional:!0,brief:"Mail each event to the organization's owners, or its owners and admins (admins), instead of a webhook"},secret:{kind:"boolean",optional:!0,brief:"Give the webhook's signing secret yourself, 16 to 128 characters: asked at a hidden prompt, or read piped in, never typed on the command line (default: one is made and shown once)"},"secret-from-env":{kind:"parsed",parse:String,optional:!0,placeholder:"VAR",brief:"Read the signing secret from this environment variable"},...E}},docs:{brief:"Send the organization's events to a URL (a signed POST) or by email to its owners and admins",fullDescription:["A webhook gets each event as a JSON POST, signed with the subscription's secret:","X-EveryApp-Signature: t=<seconds>,v1=<hex>, HMAC-SHA256 over <t>.<body>; the receiver checks","it (/docs/events has the code). Without --secret one is made and shown once: copy it then.","Slack's Workflow Builder, Zapier, n8n, Make and your own endpoint all take one; the body's","top-level summary is a line a person reads.","","The URL must be https:// on a public hostname: not an IP address, not a local or internal","name, not the Gateway or one of its apps. For a receiver on a private network, set",`${X} on the Gateway with the value "true" (self-host only;`,`${t} secret set ${X}): then http://, IP addresses and private names are let through.`,"","--email mails each event to the organization's owners (owners) or owners and admins","(admins), from the Gateway's sender (EMAIL_FROM); it takes no address. An organization has at","most 25 subscriptions. The Gateway sends each event within a minute.","","Examples:",` ${t} events add https://hooks.example.com/everyapp --events cap.*,member.*`,` ${t} events add https://hooks.zapier.com/hooks/catch/1/abc --name Zapier --secret`,` ${t} events add --email admins --events cap.*`,` ${t} events add https://n8n.example.com/webhook/x --secret-from-env N8N_SECRET --json`].join(`
19
+ `)}}),Vt=b({loader:async()=>{let{list:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:E},docs:{brief:"List the organization's subscriptions: where each goes, what it takes, how its last delivery went",fullDescription:["A webhook shows its URL's host and path (never its query or secret); an email one, whom it","mails. Nothing is changed.","","Example:",` ${t} events list`].join(`
20
+ `)}}),Kt=b({loader:async()=>{let{remove:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[D]},flags:E},docs:{brief:"Remove a subscription (a built-in one is disabled instead)",fullDescription:["Nothing more is delivered to it; its delivery log stays for 30 days. The Gateway's built-in","cap alerts are disabled instead of removed, so the Gateway never makes them again.","","Example:",` ${t} events remove sub_0123456789abcdef01234567`].join(`
21
+ `)}}),Yt=b({loader:async()=>{let{enable:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[D]},flags:E},docs:{brief:"Resume a subscription: new events are queued for it again",fullDescription:["What happened while it was disabled isn't sent. Safe to repeat.","","Example:",` ${t} events enable sub_0123456789abcdef01234567`].join(`
22
+ `)}}),Ht=b({loader:async()=>{let{disable:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[D]},flags:E},docs:{brief:"Pause a subscription: no new events are queued for it, and what is queued is dropped",fullDescription:["Turn the built-in cap alerts off this way. Safe to repeat; events enable resumes it.","","Example:",` ${t} events disable sub_0123456789abcdef01234567`].join(`
23
+ `)}}),Bt=b({loader:async()=>{let{test:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[D]},flags:{"no-wait":{kind:"boolean",optional:!0,brief:"Return once the test event is queued; events deliveries shows how it went"},...E}},docs:{brief:"Send a test event (ping) to one subscription and wait to see whether it was delivered",fullDescription:["Queues a ping for that subscription only, then waits up to 90 seconds while the Gateway","sends it (it sends queued events every minute), and says delivered or failed with the","receiver's status code or the error. A failed test is retried like any delivery.","","Examples:",` ${t} events test sub_0123456789abcdef01234567`,` ${t} events test sub_0123456789abcdef01234567 --no-wait --json`].join(`
24
+ `)}}),Xt=b({loader:async()=>{let{deliveries:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[{...D,brief:"Only this subscription's (default: every subscription's)",optional:!0}]},flags:{dead:{kind:"boolean",optional:!0,brief:"Only deliveries that ran out of attempts (dead), to redeliver"},limit:{kind:"parsed",parse:$e,optional:!0,placeholder:"n",brief:"How many to show, newest first: 1 to 200 (default 20)"},...E}},docs:{brief:"List the last deliveries (30 days): the event, its subscription, attempts, status, next attempt, last error",fullDescription:["A delivery is retried after 1, 5 and 30 minutes, then 2, 8 and 24 hours; the seventh failure","is dead. Nothing is changed.","","Examples:",` ${t} events deliveries`,` ${t} events deliveries sub_0123456789abcdef01234567 --limit 50`,` ${t} events deliveries --dead`].join(`
25
+ `)}}),Jt=b({loader:async()=>{let{redeliverDelivery:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[{placeholder:"delivery",brief:"The delivery, by its dlv_ id (events deliveries names them)",parse:String}]},flags:E},docs:{brief:"Send a failing or dead delivery again: the Gateway sends it within a minute, with the full retry schedule",fullDescription:["Its attempts start over at 0. A delivered one is left alone. The receiver may get the same","event id again: receivers deduplicate on it.","","Example:",` ${t} events redeliver dlv_0123456789abcdef01234567`].join(`
26
+ `)}}),Zt=b({loader:async()=>{let{types:e}=await import("./events-2V5VRBWP.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{json:i,verbose:l}},docs:{brief:"List the event types --events takes, with their versions",fullDescription:["The catalogue this CLI knows, and how a pattern names several (member.*, app.crm.*, *). No","Gateway is needed.","","Example:",` ${t} events types`].join(`
27
+ `)}}),qe=qt({routes:{add:zt,list:Vt,remove:Kt,enable:Yt,disable:Ht,test:Bt,deliveries:Xt,redeliver:Jt,types:Zt},aliases:{ls:"list"},docs:{brief:"Send the Gateway's events to Slack, Zapier, n8n or your own endpoint (signed), or by email"}});import{buildCommand as Qt}from"@stricli/core";var ze=Qt({loader:async()=>{let{install:e}=await import("./install-Z5FYXUYM.js");return e},parameters:{positional:{kind:"tuple",parameters:[{brief:"The app release to install: a GitHub repository URL (its latest release), a release tarball's URL, or a downloaded everyapp-release.tar.gz",parse:String,placeholder:"source"}]},flags:{gateway:h,"account-id":d,...F,"no-wait":{kind:"boolean",brief:"Don't wait for the app to go live (a new hostname's certificate included); it goes live on its first visit",optional:!0},yes:{kind:"boolean",brief:"With no Gateway yet, install one at apps.<zone> without asking (never cf's questions, or the one before replacing a Worker changed outside everyapp)",optional:!0},json:i,verbose:l},aliases:{y:"yes"}},docs:{brief:"Install an app someone published, from GitHub or a release file",fullDescription:[`Installs an app release on your Gateway with no checkout of the app, as ${t} deploy`,"would from the app's directory, with nothing to build: <source> is a GitHub repository URL","(the everyapp-release.tar.gz on its latest release; \u2026/releases/tag/<tag> for that one), a","tarball's HTTPS URL, or a downloaded everyapp-release.tar.gz. The release holds the app's","tenant-neutral Build Output, migrations and manifest, checked against its SHA-256. Run it",`again later to update the app. Its settings are set with ${t} configure <id>;`,".everyapp/secrets.env in this directory is the deploy's own file, read only for a Hyperdrive","app's database URL.","","A repository without a release is never built from its URL: clone it, then run pnpm",`install in it and this checkout's ${t} deploy from its directory. Postgres migrations`,"need the app's source, so their releases are refused.","","No Gateway in any account the login sees? At a terminal it offers to install one at",`apps.<zone> (what ${t} setup does, owner link included), then installs the app; otherwise`,"it stops with action_required install_gateway and the setup command to run.","--gateway <url> (or EVERYAPP_GATEWAY_URL) names the Gateway when your login sees several.","With --json, each step is an NDJSON event."].join(`
28
+ `)}});import{buildCommand as ea}from"@stricli/core";var Ve=ea({loader:async()=>{let{login:e}=await import("./login-KHJBC64Z.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{json:i,verbose:l}},docs:{brief:"Log in to Cloudflare",fullDescription:["Log in to Cloudflare","","At a terminal, Cloudflare's own login runs (open its link and enter the code). Piped, or","with --json, the link and code are printed and the run waits for the login to be approved.","Already logged in, it says as whom. Unattended runs can set CLOUDFLARE_API_TOKEN and","CLOUDFLARE_ACCOUNT_ID instead."].join(`
29
+ `)}});import{buildCommand as S,buildRouteMap as ta}from"@stricli/core";var R={gateway:h,"account-id":d,json:i,verbose:l},$={placeholder:"id",brief:"The MCP app (mcp list names them): dataforseo, or the id a server was added as",parse:String},aa=S({loader:async()=>{let{add:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[{placeholder:"url",brief:"The server's MCP address (https://, the one URL the Gateway ever sends its credential to)",parse:String}]},flags:{name:{kind:"parsed",parse:String,brief:"The app's id and tool prefix (default: from the URL's host, https://mcp.treg.to/mcp \u2192 treg)",optional:!0},auth:{kind:"enum",values:fe,brief:"How the Gateway authenticates to the server (default: none; bearer with --secret, header with --header)",optional:!0},header:{kind:"parsed",parse:String,brief:"With --auth header: the header the server reads the credential from (X-Api-Key)",optional:!0},secret:{kind:"parsed",parse:String,brief:"The Gateway setting holding the credential, ending in _MCP_TOKEN (default: <ID>_MCP_TOKEN)",optional:!0},risk:{kind:"enum",values:ge,brief:"How a tool's risk is decided: from the server's hints, unknown as write (annotations, the default), or every tool read or write",optional:!0},description:{kind:"parsed",parse:String,brief:"What the app is for, as Admin \u2192 Apps and everyapp_list_apps say it (default: from the URL)",optional:!0},"from-env":{kind:"parsed",parse:String,brief:"Set the credential from this environment variable once the app is added (as secret set --from-env)",placeholder:"VAR",optional:!0},...R}},docs:{brief:"Add any remote MCP server as an MCP app: its tools reach members' AI clients through the Gateway's /mcp",fullDescription:["The Gateway serves the server's tools on its own /mcp under <id>_<tool> names, holding the","server's credential itself: every call is attributed to the member, audited, counted and","capped like an app's, and read tools are told apart from write tools (a read-only","connection sees only the read ones). You, the owners and the admins get it at once; an","admin grants others in Admin \u2192 Apps \u2192 Manage access. Nothing is deployed.","","The credential is a Gateway setting named <ID>_MCP_TOKEN (--secret picks another name","ending in _MCP_TOKEN), pinned to the URL's origin when it is set: the Gateway never sends","it anywhere else. At a terminal, add offers to set it right away (hidden input, as secret","set asks); --from-env VAR sets it from an environment variable; otherwise, afterwards:",` ${t} secret set TREG_MCP_TOKEN`,"","--auth bearer sends Authorization: Bearer <value>; header sends <header>: <value>; basic","takes user:password; none sends nothing. oauth is recorded but not served yet: the Gateway","doesn't sign in to MCP servers with OAuth this week.","","add looks at the URL once from this machine, without the credential, and says what it","found (MCP, a 401, a redirect, or nothing); that is a warning, never a refusal, since the","Gateway, not this machine, is what fetches it. The Gateway follows no redirects.","","Examples:",` ${t} mcp add https://mcp.deepwiki.com/mcp`,` ${t} mcp add https://treg.to/mcp/ --auth bearer`,` ${t} mcp add https://api.example.org/mcp --name example --auth header --header X-Api-Key --risk read`].join(`
30
+ `)}}),oa=S({loader:async()=>{let{remove:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[$]},flags:R},docs:{brief:"Remove an MCP app: it leaves /mcp and the home page, and everyone's access to it goes",fullDescription:["Like deleting an app: the Gateway stops serving its tools within 30 seconds, and","everyone's access to it, the personal tokens bound to it, its tools snapshot and its","place in AI connections go with it. Adding it again starts fresh. To stop serving it",`and keep all that, turn it off instead: ${t} mcp off <id>.`,"","The Gateway setting holding its key or credential stays, and so does a credential's pin",`to its origin; ${t} secret unset <NAME> removes both.`,"","Example:",` ${t} mcp remove treg`].join(`
31
+ `)}}),na=S({loader:async()=>{let{on:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[$]},flags:R},docs:{brief:"Turn an MCP app on: its tools reach members' AI clients through the Gateway's /mcp",fullDescription:["An MCP app is a data provider (DataForSEO, built in) or any remote MCP server added with",`${t} mcp add <url>, offered as an app of the Gateway's own with no page and nothing to`,"deploy: the Gateway serves its tools on its /mcp under <id>_<tool> names, with its own key,","and counts and audits every call like an app's. It appears in Admin \u2192 Apps and under MCP","apps on the home page.","","A built-in's first on adds it: you, the owners and the admins get it at once, and an","admin grants other members with Manage access. On after off serves it again at once,","with everyone's access kept. The key is a Gateway setting the tools need (mcp list names","it):",` ${t} secret set DATAFORSEO_API_KEY`,"","Safe to repeat: an app that is on stays on, with its access.","","Examples:",` ${t} mcp on dataforseo`,` ${t} mcp on treg --json`].join(`
32
+ `)}}),sa=S({loader:async()=>{let{off:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[$]},flags:R},docs:{brief:"Turn an MCP app off: its tools leave /mcp, and everyone's access is kept for on",fullDescription:["The Gateway stops serving the app's tools within 30 seconds and the home page stops","listing it. Everyone's access, the personal tokens bound to it and its tools snapshot",`are kept, so ${t} mcp on <id> serves it again at once. To remove it for good, with`,`all of that: ${t} mcp remove <id>.`,"","(Until 2026-10-25 off removed the app; that is remove now.)","","Example:",` ${t} mcp off dataforseo`].join(`
33
+ `)}}),ra=S({loader:async()=>{let{list:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:R},docs:{brief:"List the MCP apps: built-in and added, on or off, their tools and whether each key is set",fullDescription:["Nothing is changed. A key's value can't be read back; only whether it is set.","","Example:",` ${t} mcp list`].join(`
34
+ `)}}),ia=S({loader:async()=>{let{show:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[$]},flags:R},docs:{brief:"Show an MCP app: its address, credential, status, last tool listing and every tool with its risk",fullDescription:["For a remote server: the URL, how the Gateway authenticates, the credential's name, whether","it is set and the origin it is pinned to, the risk default, when the tools were last listed","(and the error if that failed), then every tool the server listed: its name on the Gateway,","the server's own name, its risk and where that comes from (the server's hint, the app's","default, your override), and whether it is on. Nothing is changed.","","Examples:",` ${t} mcp show treg`,` ${t} mcp show dataforseo --json`].join(`
35
+ `)}}),pa=S({loader:async()=>{let{refresh:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[$]},flags:R},docs:{brief:"Drop an MCP app's tools snapshot, so the Gateway lists its tools again",fullDescription:["Only the snapshot goes (the Gateway's copy of the tool list); the app, its access and its","settings stay. The Gateway lists the tools again on the next request to its /mcp, or","within the hour. Use it after the server changed its tools.","","Example:",` ${t} mcp refresh treg`].join(`
36
+ `)}}),la=S({loader:async()=>{let{tool:e}=await import("./mcp-EFDUKJ5V.js");return e},parameters:{positional:{kind:"tuple",parameters:[$,{placeholder:"tool",brief:"The tool: the server's name for it, or its name on the Gateway (mcp show lists both)",parse:String}]},flags:{risk:{kind:"enum",values:["read","write","destructive","annotations"],brief:"The tool's risk: read, write or destructive (hidden until approvals exist); annotations drops your override",optional:!0},on:{kind:"boolean",brief:"List the tool (the default)",optional:!0},off:{kind:"boolean",brief:"Leave the tool out: it isn't listed, and a call answers Unknown tool",optional:!0},...R}},docs:{brief:"Override one tool of a remote MCP app: its risk, or whether it is listed at all",fullDescription:["A tool's risk decides who can call it: read tools every connection, write tools only","read & write ones, destructive tools nobody until approvals exist. The server's hints","decide it unless the app's --risk default or this override says otherwise. The Gateway","lists the tools again on first use. A built-in MCP app's tools are its own and can't be","changed here.","","Examples:",` ${t} mcp tool treg delete_everything --risk destructive`,` ${t} mcp tool treg treg_noisy_tool --off`,` ${t} mcp tool treg search --risk annotations`].join(`
37
+ `)}}),Ke=ta({routes:{add:aa,remove:oa,on:na,off:sa,list:ra,show:ia,refresh:pa,tool:la},aliases:{ls:"list"},docs:{brief:"Offer MCP servers to members' AI clients as MCP apps, with the Gateway holding each one's key"}});import{buildCommand as j,buildRouteMap as da}from"@stricli/core";var O={gateway:h,"account-id":d,json:i,verbose:l},se={placeholder:"id",brief:"The provider's id (provider list names them): stripe",parse:String},ca=j({loader:async()=>{let{add:e}=await import("./provider-EOI5PTFH.js");return e},parameters:{positional:{kind:"tuple",parameters:[{placeholder:"spec",brief:"The provider's spec: a JSON file, or an https URL to one (64 KiB at most)",parse:String}]},flags:{replace:{kind:"boolean",brief:"Replace the provider registered under the spec's id; its key must be set again",optional:!0},...O}},docs:{brief:"Register an API provider on the Gateway from its spec, so apps can list it under capabilities",fullDescription:["The spec says what the provider is and where its key goes: its id, name, the page the key","comes from (docs), the only hosts the key is ever sent to, and how it is sent (auth: bearer,","header, query or basic), naming the Gateway setting that holds the key (STRIPE_API_KEY for","stripe). It never holds the key itself. A URL is fetched on this machine.","","The rules a spec must pass: an id that isn't a built-in provider's, settings named after the","id that no other provider, app or the Gateway itself reads, and public hosts that aren't the","Gateway's own or its apps'. The Gateway checks them again every time it reads the row.","","Next, set the key; the Gateway sends it only to the hosts the row had when it was set:",` ${t} secret set STRIPE_API_KEY`,"","Run in an app's directory, it also writes .everyapp/providers/<id>.json, which everyapp dev","reaches the provider from with your key in .dev.vars.","","Examples:",` ${t} provider add stripe.json`,` ${t} provider add https://example.com/providers/stripe.json`,` ${t} provider add stripe.json --replace`].join(`
38
+ `)}}),ma=j({loader:async()=>{let{list:e}=await import("./provider-EOI5PTFH.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:O},docs:{brief:"List the API providers the Gateway offers: built in and registered, each key's state, the apps using each",fullDescription:["Nothing is changed. A key's value can't be read back; only whether it is set, and for a","registered provider whether it was set for the hosts the row names now (bound).","","Example:",` ${t} provider list`].join(`
39
+ `)}}),ha=j({loader:async()=>{let{show:e}=await import("./provider-EOI5PTFH.js");return e},parameters:{positional:{kind:"tuple",parameters:[se]},flags:{save:{kind:"boolean",brief:"Also write the spec to .everyapp/providers/<id>.json in this app's directory, for everyapp dev",optional:!0},...O}},docs:{brief:"Print a provider's spec: its hosts, how its key is sent, its settings, who registered it and which apps use it",fullDescription:["What an agent reads to set up and call a provider without a setup guide. With --save, in an","app's directory, the spec is written where everyapp dev reads it.","","Examples:",` ${t} provider show stripe`,` ${t} provider show stripe --save`].join(`
40
+ `)}}),ua=j({loader:async()=>{let{remove:e}=await import("./provider-EOI5PTFH.js");return e},parameters:{positional:{kind:"tuple",parameters:[se]},flags:{force:{kind:"boolean",brief:"Remove it even though deployed apps list it (their calls to it stop)",optional:!0},...O}},docs:{brief:"Remove a registered provider from the Gateway; its key stays set until secret unset",fullDescription:["The Gateway stops serving it within 30 seconds. A provider a deployed app lists under","capabilities is refused unless --force. The Gateway setting holding its key stays; remove",`it with ${t} secret unset <NAME>. Registering it again needs the key set again too.`,"","Example:",` ${t} provider remove stripe`].join(`
41
+ `)}}),Ye=e=>j({loader:async()=>{let o=await import("./provider-EOI5PTFH.js");return e==="on"?o.on:o.off},parameters:{positional:{kind:"tuple",parameters:[{...se,brief:"The MCP app (mcp list names them): dataforseo"}]},flags:O},docs:{brief:`Same as ${t} mcp ${e}; this alias goes after launch week`}}),He=da({routes:{add:ca,list:ma,show:ha,remove:ua,on:Ye("on"),off:Ye("off")},aliases:{ls:"list",rm:"remove"},docs:{brief:"Register API providers for apps to call with the Gateway's key, beside the built-in ones",hideRoute:{on:!0,off:!0}}});import{buildCommand as fa}from"@stricli/core";var Be=fa({loader:async()=>{let{release:e}=await import("./release-74J5ZIL3.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{out:{kind:"parsed",parse:String,brief:"Where to write the release (default: ./everyapp-release.tar.gz)",placeholder:"file",optional:!0},json:i,verbose:l}},docs:{brief:"Pack the app in this directory as a release others can install",fullDescription:["Builds the app in this directory as a deploy would (tenant-neutral), checks its Build Output","against the app policy and its migrations against its schema, and packs the release","(default ./everyapp-release.tar.gz) without deploying it: no Gateway and no Cloudflare login,","so it runs in CI. Attach the tarball to a GitHub release of the app's repository, and",`${t} install <repository url> installs it on any Gateway.`,"With --json, each step is an NDJSON event; done carries the tarball's path and SHA-256."].join(`
42
+ `)}});import{buildCommand as re,buildRouteMap as ga}from"@stricli/core";var Xe={kind:"array",minimum:1,parameter:{brief:"Secret or Gateway setting",parse:String,placeholder:"name"}},ie={gateway:h,"account-id":d},Je={kind:"parsed",parse:String,brief:"The app whose secret this is (default: the app in this directory)",placeholder:"id",optional:!0},wa=re({loader:async()=>{let{set:e}=await import("./secret-7FKKTLHB.js");return e},parameters:{positional:Xe,flags:{"from-env":{kind:"parsed",parse:String,brief:"Read the value from this environment variable",placeholder:"VAR",optional:!0},app:Je,...ie,json:i,verbose:{kind:"boolean",brief:"Show which Worker each secret goes to and its new version",optional:!0}}},docs:{brief:"Set secrets on your app or your Gateway",fullDescription:["Gateway settings (AI provider keys, EMAIL_FROM, sign-in clients) go to the Gateway, from any","directory. Other names go to the app in this directory, or with --app <id> to that app from","anywhere; the app's everyapp.config.ts must list them under secrets. Values come from a","hidden prompt, --from-env or stdin, never the command line. Changes are live at once; no","deploy needed.","","Examples:",` ${t} secret set OPENAI_API_KEY`,` ${t} secret set GITHUB_TOKEN --from-env GITHUB_TOKEN`,` echo "$STRIPE_KEY" | ${t} secret set STRIPE_KEY`,` ${t} secret set MAIN_SECRET --app analytics`,"",`See what an app needs and what is set: ${t} secret list [<app>]`].join(`
43
+ `)}}),ya=re({loader:async()=>{let{unset:e}=await import("./secret-7FKKTLHB.js");return e},parameters:{positional:Xe,flags:{yes:{kind:"boolean",brief:"Remove without asking",optional:!0},app:Je,...ie,json:{kind:"boolean",brief:"Print NDJSON events on stdout (never asks)",optional:!0},verbose:{kind:"boolean",brief:"Show which Worker each secret is removed from",optional:!0}},aliases:{y:"yes"}},docs:{brief:"Remove secrets from your app or your Gateway",fullDescription:["Names go where `secret set` sends them (--app <id> names the app from anywhere). Asks before","removing; the change is live at once.","","Example:",` ${t} secret unset GITHUB_TOKEN`].join(`
44
+ `)}}),ba=re({loader:async()=>{let{list:e}=await import("./secret-7FKKTLHB.js");return e},parameters:{positional:{kind:"tuple",parameters:[{brief:"An app id (default: the app in this directory; elsewhere, every app)",parse:String,placeholder:"app",optional:!0}]},flags:{...ie,json:I,verbose:{kind:"boolean",brief:"Also list the names everyapp sets itself",optional:!0}}},docs:{brief:"List what an app needs set and what is: its own secrets and the Gateway's settings",fullDescription:["For one app (the app in this directory, or <app> from anywhere): every setting its manifest","declares, where it is held (the Gateway, or the app's Worker), whether it is set, and the one",`command that opens the app when something required is missing (${t} configure <app>).`,"Elsewhere with no app named: the Gateway's names and who set them, then every app's","settings. Names only, never values."].join(`
45
+ `)}}),Ze=ga({routes:{set:wa,unset:ya,list:ba},docs:{brief:"Set, remove and list secrets and Gateway settings"}});import{buildCommand as va}from"@stricli/core";var Qe=va({loader:async()=>{let{setup:e}=await import("./setup-PAKRCAFO.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{domain:{kind:"parsed",parse:String,brief:"Where the Gateway lives: any hostname under one of the account's domains, e.g. apps.example.com (asked at a terminal; remembered after that)",optional:!0},"account-id":{kind:"parsed",parse:String,brief:"The Cloudflare account of the Gateway, or with none yet, the one to install it in (default: CLOUDFLARE_ACCOUNT_ID, or the only one)",optional:!0},"force-dns":N,"allow-downgrade":{kind:"boolean",brief:"Deploy this Gateway even though it is older than the live one (a deliberate rollback)",optional:!0,hidden:!0},redeploy:{kind:"boolean",brief:"Upload the Gateway even when it is up to date (after a change in the dashboard, such as a key rotation)",optional:!0,hidden:!0},yes:T,json:i,verbose:{kind:"boolean",brief:"Show every step and progress line, and stream the Gateway's build output to stderr",optional:!0}},aliases:{y:"yes"}},docs:{brief:"Install or repair the Gateway",fullDescription:["One command from an empty Cloudflare account (Workers Paid) to a working Gateway and its","owner, and the one to run when something is off. Run it again any time: it picks up where it",`stopped, and does nothing once everything is there. After a git pull, ${t} update takes`,"the newer Gateway from this checkout (setup does that too, on its way).","","A fresh install takes 5 to 20 minutes, most of it waiting for you at the owner link: give it a","long timeout, or run it in the background and watch its output.",""," 1. Logs in to Cloudflare (cf auth login, or CLOUDFLARE_API_TOKEN) and finds the Gateway in"," the login's accounts; with none, picks the account to install it in"," 2. Picks where the Gateway lives (--domain, or asked): any hostname under one of the"," account's domains, apps.example.com; apps get one each below it, todo.apps.example.com"," 3. Installs the Gateway from this checkout (apps/every-app-gateway), or repairs it, and"," waits for its certificate"," 4. Opens a one-time link to create the owner account and waits up to 15 minutes for it;"," in CI there is no link, and the run ends with a warning to run setup at a terminal","","The flags people use: --domain, --account-id, and --yes for a script (it answers setup's own","questions; never cf's). With --json each step is an NDJSON event; a run that stops on","something only a person can do exits 2 with action_required.",`Then: ${t} create my-app, cd into it, ${t} dev, ${t} deploy.`,"More: https://everyapp.com/docs/gateway"].join(`
46
+ `)}});import{buildCommand as q,buildRouteMap as ka}from"@stricli/core";var z={gateway:h,"account-id":d,json:i,verbose:l},pe={placeholder:"id",brief:`The sign-in provider: ${ue.join(", ")}`,parse:String},Aa=q({loader:async()=>{let{add:e}=await import("./signin-AP3D4XM4.js");return e},parameters:{positional:{kind:"tuple",parameters:[pe]},flags:{"client-id":{kind:"parsed",parse:String,brief:"The OAuth app's client id (not a secret; for apple, the Services ID)",optional:!0},"client-secret-from-env":{kind:"parsed",parse:String,brief:"Read the client secret from this environment variable (a secret never goes on the command line)",placeholder:"VAR",optional:!0},issuer:{kind:"parsed",parse:String,brief:"oidc: the issuer's https URL, which serves /.well-known/openid-configuration",placeholder:"url",optional:!0},label:{kind:"parsed",parse:String,brief:'oidc: the button text after "Continue with" (default SSO; 40 characters at most)',placeholder:"text",optional:!0},tenant:{kind:"parsed",parse:String,brief:"microsoft: the Directory (tenant) ID that pins sign-in to your own directory (recommended), or common, organizations, consumers",optional:!0},...z}},docs:{brief:'Turn a sign-in provider on: "Continue with Google" (or Microsoft, GitHub, Apple, Cloudflare, your SSO)',fullDescription:["Says where to create the OAuth app and the redirect URL to register with it","(https://<gateway>/api/auth/callback/<id>), then sets the provider's settings on the","Gateway Worker, all in one new version under your Cloudflare login, live on the next","request. At a terminal it asks for each setting: the client id shown as typed, the","client secret hidden, an optional one (microsoft's tenant, oidc's label) left as it is","when you press Enter. Unattended (--json, or no terminal) every required setting comes","from a flag: --client-id, --client-secret-from-env VAR, and for oidc --issuer. The","client secret is never taken from the command line.","","A provider says who someone is; the Gateway still decides who gets in: a member, or","someone with a pending invitation for that exact, verified email. Nobody else.","","Safe to repeat: running it again replaces the values given (a rotated secret, a new",`client). An optional setting not given stays as it is; ${t} secret unset <NAME>`,"removes one. The everyapp skill's setup/signin-<id>.md walks through each provider's","console.","","Examples:",` ${t} signin add google`,` ${t} signin add github --client-id Iv1.0123456789abcdef --client-secret-from-env GITHUB_SECRET --json`,` ${t} signin add microsoft --tenant 72f988bf-86f1-41af-91ab-2d7cd011db47`,` ${t} signin add oidc --issuer https://acme.okta.com --label Okta`].join(`
47
+ `)}}),Ca=q({loader:async()=>{let{list:e}=await import("./signin-AP3D4XM4.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:z},docs:{brief:"List the sign-in providers: on, needs setup (naming what is missing) or off",fullDescription:["Reads which of each provider's settings the Gateway Worker holds (names only: a value","can't be read back) and says whether the provider is on (every required setting set),","needs setup (some set, the rest named; the Gateway keeps it off rather than half","configured) or off. A value that is set but malformed also keeps a provider off; the","Gateway's log says so (signin.config_problem). Nothing is changed.","","Example:",` ${t} signin list`].join(`
48
+ `)}}),Ea=q({loader:async()=>{let{show:e}=await import("./signin-AP3D4XM4.js");return e},parameters:{positional:{kind:"tuple",parameters:[pe]},flags:z},docs:{brief:"Show a sign-in provider: where to make its OAuth app, the redirect URL, its settings and whether each is set",fullDescription:["The provider's console and what the OAuth app is called there, the redirect URL to","register for this Gateway, the scopes asked for (identity only), which claim becomes","the email and when it counts as verified, every setting with what it holds and whether","it is set, the provider's caveats and its setup guide. Nothing is changed.","","Example:",` ${t} signin show apple`].join(`
49
+ `)}}),Sa=q({loader:async()=>{let{remove:e}=await import("./signin-AP3D4XM4.js");return e},parameters:{positional:{kind:"tuple",parameters:[pe]},flags:{yes:T,...z}},docs:{brief:"Turn a sign-in provider off: its settings leave the Gateway; accounts stay",fullDescription:["Asks first (--yes doesn't), then removes every setting of the provider from the Gateway","Worker in one new version: the button leaves the sign-in page on the next request.","People who signed in with it keep their accounts and sign in another way (a password","via Forgot password, another provider, Access). Delete the OAuth app at the provider","too: a client the Gateway no longer holds is still a client.","","Example:",` ${t} signin remove github`].join(`
50
+ `)}}),et=ka({routes:{add:Aa,list:Ca,show:Ea,remove:Sa},aliases:{ls:"list"},docs:{brief:"Let people sign in with Google, Microsoft, GitHub, Apple, Cloudflare or your SSO, beside passwords"}});import{buildCommand as Ra}from"@stricli/core";var tt=Ra({loader:async()=>{let{status:e}=await import("./status-RMWNHOEK.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{"account-id":d,json:i,verbose:l}},docs:{brief:"Show the Gateway, its apps and anything to fix",fullDescription:["One screen, all of it from the Gateway's D1 database and cf, nothing asked of the Gateway:","its URL and release (and whether this checkout builds it), its owner, the apps its registry","lists and whether the live Gateway binds them, each hostname's certificate, any deploy in","progress, and what to run when something is off. With --json, the `done` event's data has","all of it, `fixes` included: the one state query an agent needs."].join(`
51
+ `)}});import{buildCommand as Ta}from"@stricli/core";var at=Ta({loader:async()=>{let{teardown:e}=await import("./teardown-E4JNKAZJ.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{"account-id":{kind:"parsed",parse:String,placeholder:"id",brief:"The dedicated test account to empty (required; 32 hex characters, from the dashboard URL dash.cloudflare.com/<id>/\u2026; never read from CLOUDFLARE_ACCOUNT_ID)"},confirm:{kind:"parsed",parse:String,placeholder:"id",optional:!0,brief:"The same account id again, for a run without a terminal (--json, a script); at a terminal it is typed instead"},"dry-run":{kind:"boolean",optional:!0,brief:"List what would be deleted and stop; nothing is written"},json:i,verbose:l}},docs:{brief:"Delete everything Every App created in a dedicated test Cloudflare account",fullDescription:["For the accounts the onboarding loop installs into, over and over: removes every Worker,","Workflow, D1 database, KV namespace, R2 bucket and Hyperdrive config named every-*, the","Gateway's own included, the two Cloudflare Access applications and the allow policy, the","Email Routing rules that send mail to those Workers (a catch-all drops mail again, and","routing is turned off once no rule and no catch-all of anyone else's needs it), the","certificate packs of the hostnames the Gateway published, and the Custom Domain records","(A, AAAA, CNAME) left at exactly those names. Never the zone, the Workers Paid subscription,","the workers.dev subdomain, the Zero Trust team and its identity providers, any other DNS","record (MX, TXT, CAA...) even at those names, R2 buckets outside the default jurisdiction,","or anything whose name doesn't start with every- and that no app recorded.","","It is destructive and exists for dedicated test accounts only. The account must be on the","allowlist (EVERYAPP_TEST_ACCOUNTS, or one id per line in ~/.config/everyapp/test-accounts),","the run needs CLOUDFLARE_API_TOKEN scoped to that account alone (a token that sees any other","account is refused), and one account is refused by id whatever the lists say. It reads","everything first and shows what it found; then the account id is typed at the terminal, or","passed again with --confirm for a run without one. There is no --yes.","","Examples:"," EVERYAPP_TEST_ACCOUNTS=<id> everyapp teardown --account-id <id> --dry-run"," EVERYAPP_TEST_ACCOUNTS=<id> everyapp teardown --account-id <id>"," EVERYAPP_TEST_ACCOUNTS=<id> everyapp teardown --account-id <id> --confirm <id> --json"].join(`
52
+ `)}});import{buildCommand as $a}from"@stricli/core";var ot=$a({loader:async()=>{let{update:e}=await import("./update-DWVZFNPS.js");return e},parameters:{positional:{kind:"tuple",parameters:[]},flags:{"account-id":d,"force-dns":N,"allow-downgrade":{kind:"boolean",brief:"Deploy this Gateway even though it is older than the live one (a deliberate rollback)",optional:!0,hidden:!0},redeploy:{kind:"boolean",brief:"Upload the Gateway even when it is up to date (after a change in the dashboard, such as a key rotation)",optional:!0,hidden:!0},yes:T,json:i,verbose:l},aliases:{y:"yes"}},docs:{brief:"Update the Gateway to this checkout (after git pull)",fullDescription:["Deploys the Gateway built from this checkout (apps/every-app-gateway) over the one your","Cloudflare login finds, where it is, keeping its data, users and apps. It never installs a",`Gateway: with none, it stops and says to run ${t} setup.`,""," 1. Logs in to Cloudflare (cf auth login, or CLOUDFLARE_API_TOKEN) and finds the Gateway in"," the login's accounts (--account-id when there is one in more than one)"," 2. Upgrades it (migrations first, with a restore point). When it runs this checkout's"," Gateway already, binds and publishes every registered app if the live Gateway doesn't,"," and otherwise says it is up to date. A Gateway newer than this checkout is refused"," (git pull)","","The release is named by its version when this checkout's Gateway is that version's release","(the gateway-v<version> tag), and by the checkout's commit otherwise.","With --json, each step is an NDJSON event."].join(`
53
+ `)}});import{buildCommand as c,buildRouteMap as G}from"@stricli/core";var m={org:P,gateway:h,"account-id":d,json:i,verbose:l},nt={gateway:h,"account-id":d,json:i,verbose:l},Ga=["owner","admin","member"];function _a(e){let o=Ga.find(a=>a===e.trim().toLowerCase());if(!o)throw new Error("Use owner, admin or member.");return o}var st=e=>({kind:"boolean",brief:`${e} without asking (needed where nobody is at a terminal)`,optional:!0}),xa=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function Da(e){let o=e.trim().toLowerCase();if(!xa.test(o))throw new Error(`${e} isn't an email address`);return o}var V={placeholder:"email",brief:"The member, by email or user id (workspace users lists them)",parse:String},le={placeholder:"app",brief:"The app, by id (crm) or row id (workspace apps lists them)",parse:String},K={placeholder:"group",brief:"The group, by name or grp_ id (workspace groups lists them)",parse:String},rt={placeholder:"email|id",brief:"The pending invitation, by invited email or id (workspace users lists them)",parse:String},de=(e,o)=>({add:{kind:"parsed",parse:String,variadic:!0,optional:!0,placeholder:o,brief:`Add ${e} (repeat for several)`},remove:{kind:"parsed",parse:String,variadic:!0,optional:!0,placeholder:o,brief:`Remove ${e} (repeat for several)`},set:{kind:"parsed",parse:String,variadic:!0,optional:!0,placeholder:o,brief:"Replace the whole list with these (repeat for several; alone, with neither --add nor --remove)"}}),ja=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).show,parameters:{positional:{kind:"tuple",parameters:[]},flags:m},docs:{brief:"The organization: its owners, whether it can send mail, and how many members, invitations, groups and apps it has",fullDescription:["Nothing is changed. Email counts as configured when the Gateway settings EMAIL_FROM and a","provider key are set, which is what invitations need to be mailed from the Gateway (this","command prints links instead either way).","",`Example:
54
+ ${t} workspace show --json`].join(`
55
+ `)}}),Oa=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).users,parameters:{positional:{kind:"tuple",parameters:[]},flags:m},docs:{brief:"The members with their role and state, then the pending invitations",fullDescription:["Nothing is changed. A deactivated member is listed as such; a pending invitation with when","it expires.","",`Example:
56
+ ${t} workspace users`].join(`
57
+ `)}}),La=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).invite,parameters:{positional:{kind:"tuple",parameters:[{placeholder:"email",brief:"The address to invite",parse:Da}]},flags:{role:{kind:"enum",values:["member","admin"],default:"member",brief:"The role they join with"},...m}},docs:{brief:"Invite someone by email and print the link to send them (the Gateway mails nothing from here)",fullDescription:["Makes a pending invitation (72 hours, single use, only for an account with that email) in","your name: your Cloudflare login's email must be a member of the organization. Prints","<gateway>/accept-invitation?token=einv_\u2026, which is the invitation's only secret: hand it to","the person yourself. The Gateway mails invitations only from Admin \u2192 Users.","","Examples:",` ${t} workspace invite ann@example.com`,` ${t} workspace invite ann@example.com --role admin --json`].join(`
58
+ `)}}),Pa=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).inviteLink,parameters:{positional:{kind:"tuple",parameters:[rt]},flags:m},docs:{brief:"Print a new link for a pending invitation (earlier links keep working until it is used)",fullDescription:["The link's token is new each time and stored only as its hash. Every link of an invitation","stops working once it is accepted, canceled or expired.","",`Example:
59
+ ${t} workspace invite-link ann@example.com`].join(`
60
+ `)}}),Ia=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).uninvite,parameters:{positional:{kind:"tuple",parameters:[rt]},flags:m},docs:{brief:"Cancel a pending invitation: its links stop working",fullDescription:`Example:
61
+ ${t} workspace uninvite ann@example.com`}}),Na=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).deactivate,parameters:{positional:{kind:"tuple",parameters:[V]},flags:m},docs:{brief:"Lock a member out everywhere: no sign-in, every session ended, their tokens and AI connections revoked",fullDescription:["The account stays, listed as deactivated, and the ban holds in every organization it belongs","to; workspace reactivate lifts it (revoked tokens and connections stay revoked). An","organization always keeps an owner who can act, and the ban is account-wide, so the last","live owner of this organization, or of any other they own, can't be deactivated","(LAST_OWNER, naming the organization): a deactivated owner doesn't count.","",`Example:
62
+ ${t} workspace deactivate ann@example.com`].join(`
63
+ `)}}),Fa=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).reactivate,parameters:{positional:{kind:"tuple",parameters:[V]},flags:m},docs:{brief:"Lift a deactivation: they can sign in again (revoked tokens and connections stay revoked)",fullDescription:`Example:
64
+ ${t} workspace reactivate ann@example.com`}}),Ma=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).remove,parameters:{positional:{kind:"tuple",parameters:[V]},flags:{yes:st("Remove"),...m},aliases:{y:"yes"}},docs:{brief:"Remove a member from the organization, and their account when it belongs to no other",fullDescription:["Deletes the membership, their app grants and places in groups, and revokes their personal","access tokens for the organization and AI connections to it, in one write. The account goes","too when it belongs to no other organization (a hosted Gateway keeps accounts). Someone","Cloudflare Access would let straight back in (the Gateway has CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS","or CLOUDFLARE_ACCESS_OUTER_RING_AUTO_JOIN set) is deactivated and kept listed instead, as the","Gateway's own Delete does. Owners are peers, and the organization always keeps one who can","act: the last owner who isn't deactivated can't be removed (LAST_OWNER). Asks first at a","terminal; elsewhere it needs --yes.","",`Example:
65
+ ${t} workspace remove ann@example.com --yes --json`].join(`
66
+ `)}}),Ua=c({loader:async()=>(await import("./workspace-CJC5I66L.js")).resetLink,parameters:{positional:{kind:"tuple",parameters:[V]},flags:m},docs:{brief:"Print a one-hour, single-use password-reset link to hand to a member",fullDescription:["Better Auth's own reset token, consumed by the Gateway's /reset-password page: whoever opens","it sets the account's password, so hand it to the person yourself. Only for an active","account (PASSWORD_RESET_REQUIRES_ACTIVE_USER) that belongs to this organization alone","(USER_IN_OTHER_ORGANIZATION: a password is account-wide, so the Gateway's rule holds here","too). Password sign-in must be on (EMAIL_PASSWORD_SIGN_IN) for the page to take it. An","owner's too: the operator is root (the Gateway refuses that to admins and other owners),","which is the way back in for a sole owner who lost their password.","",`Example:
67
+ ${t} workspace reset-link ann@example.com`].join(`
68
+ `)}}),Wa=c({loader:async()=>(await import("./groups-HDG5DVFY.js")).groups,parameters:{positional:{kind:"tuple",parameters:[]},flags:m},docs:{brief:"The groups, with how many members and apps each has",fullDescription:`Nothing is changed.
69
+
70
+ Example:
71
+ ${t} workspace groups`}}),it={kind:"parsed",parse:String,optional:!0,placeholder:"text",brief:"What the group is for (empty text clears it)"},qa=c({loader:async()=>(await import("./groups-HDG5DVFY.js")).groupCreate,parameters:{positional:{kind:"tuple",parameters:[{placeholder:"name",brief:"The group's name, 1 to 60 characters, unique in the organization",parse:String}]},flags:{description:it,...m}},docs:{brief:"Make a group: a named set of members that apps are granted to as one",fullDescription:["A member opens an app when they hold a grant to it, or belong to a group that does.","",`Example:
72
+ ${t} workspace group create Sales --description "The sales team"`].join(`
73
+ `)}}),za=c({loader:async()=>(await import("./groups-HDG5DVFY.js")).groupSet,parameters:{positional:{kind:"tuple",parameters:[K]},flags:{name:{kind:"parsed",parse:String,optional:!0,placeholder:"name",brief:"A new name"},description:it,...m}},docs:{brief:"Rename or describe a group",fullDescription:`Example:
74
+ ${t} workspace group set Sales --name "Sales and marketing"`}}),Va=c({loader:async()=>(await import("./groups-HDG5DVFY.js")).groupDelete,parameters:{positional:{kind:"tuple",parameters:[K]},flags:{yes:st("Delete"),...m},aliases:{y:"yes"}},docs:{brief:"Delete a group: what it granted ends with it",fullDescription:["Its members keep their direct grants and their other groups. Asks first at a terminal;","elsewhere it needs --yes.","",`Example:
75
+ ${t} workspace group delete Sales --yes`].join(`
76
+ `)}}),Ka=c({loader:async()=>(await import("./groups-HDG5DVFY.js")).groupMembers,parameters:{positional:{kind:"tuple",parameters:[K]},flags:{...de("a member, by email or user id","email"),...m}},docs:{brief:"Who is in a group; --add, --remove or --set change it",fullDescription:["Without a change flag, lists every member of the organization and whether they are in the","group. Only members of the organization can be in its groups.","","Examples:",` ${t} workspace group members Sales`,` ${t} workspace group members Sales --add ann@example.com --add bob@example.com`,` ${t} workspace group members Sales --set ann@example.com`].join(`
77
+ `)}}),Ya=c({loader:async()=>(await import("./groups-HDG5DVFY.js")).groupApps,parameters:{positional:{kind:"tuple",parameters:[K]},flags:{...de("an app, by id","app"),...m}},docs:{brief:"Which apps a group opens; --add, --remove or --set change it",fullDescription:["Without a change flag, lists the organization's own apps and whether the group opens each.","A shared app opens for everyone already and is never granted to a group.","","Examples:",` ${t} workspace group apps Sales`,` ${t} workspace group apps Sales --add crm`].join(`
78
+ `)}}),Ha=c({loader:async()=>(await import("./apps-4RCFXT74.js")).apps,parameters:{positional:{kind:"tuple",parameters:[]},flags:m},docs:{brief:"Every app with who can open it, whether everyone can, its state and what it still needs set",fullDescription:["The admin's view (Admin \u2192 Apps); everyapp status has the operator's. Nothing is changed.","",`Example:
79
+ ${t} workspace apps --json`].join(`
80
+ `)}}),Ba=c({loader:async()=>(await import("./apps-4RCFXT74.js")).appSet,parameters:{positional:{kind:"tuple",parameters:[le]},flags:{name:{kind:"parsed",parse:Re,optional:!0,placeholder:"name",brief:"The name the app library shows (1 to 255 characters)"},description:{kind:"parsed",parse:String,optional:!0,placeholder:"text",brief:"The description under it"},everyone:{kind:"enum",values:["on","off"],optional:!0,brief:"Available to everyone: on grants every member now and every future member on joining; off keeps existing access"},...m}},docs:{brief:"Change an app's name, description or whether everyone can open it",fullDescription:["Catalog metadata only: the next deploy sets the name and description again from","everyapp.config.ts.","","Examples:",` ${t} workspace app set crm --everyone on`,` ${t} workspace app set crm --name "Open CRM" --description "Contacts and deals"`].join(`
81
+ `)}}),Xa=c({loader:async()=>(await import("./apps-4RCFXT74.js")).appAccess,parameters:{positional:{kind:"tuple",parameters:[le]},flags:{...de("a member's direct grant, by email or user id","email"),...m}},docs:{brief:"Who can open an app; --add, --remove or --set change the direct grants",fullDescription:["Without a change flag, lists every member with whether they hold a direct grant and which","groups open the app for them. A change touches direct grants only; what a group grants","stays (workspace group apps). A shared app's access can't be changed.","","Examples:",` ${t} workspace app access crm`,` ${t} workspace app access crm --add ann@example.com`,` ${t} workspace app access crm --set ann@example.com --set bob@example.com --json`].join(`
82
+ `)}});function pt(e){let o=e.trim().toLowerCase();if(o==="off"||o==="none")return"off";if(!/^\d+$/.test(o))throw new Error(`a cap is a whole number of calls per month, or off (not ${e})`);let a=Number(o);if(a<1||a>Z)throw new Error(`a cap is from 1 to ${Z.toLocaleString("en-US")} calls per month`);return a}var Ja=c({loader:async()=>(await import("./apps-4RCFXT74.js")).appCap,parameters:{positional:{kind:"tuple",parameters:[{...le,brief:"The app, by id or row id: the organization's own, or a shared one"},{placeholder:"n|off",brief:"Provider calls per UTC month (1 to 1,000,000,000), or off for no cap of its own (the workspace default applies); left out with --unlimited",parse:pt,optional:!0}]},flags:{unlimited:{kind:"boolean",optional:!0,brief:"No cap at all, even with a workspace default (instead of a number or off)"},...m}},docs:{brief:"Cap an app's provider calls per month, lift its own cap, or exempt it from the workspace default",fullDescription:["An app has a cap of its own (a number), no cap whatever the workspace default","(--unlimited), or neither (off): the default set with workspace cap default binds it,","and without one it is uncapped. Past the cap that binds it, a provider tool answers a","tool error naming it and an app's brokered call gets 429 app_monthly_cap_exceeded until","the next UTC month. Binds within seconds. --unlimited and a number or off together are","refused (INVALID_VALUE); on a Gateway from before the workspace default, --unlimited is","refused (GATEWAY_PREDATES_DEFAULT_CAPS) and a number or off still work.","","Examples:",` ${t} workspace app cap crm 5000`,` ${t} workspace app cap crm off`,` ${t} workspace app cap crm --unlimited`].join(`
83
+ `)}}),Za=c({loader:async()=>(await import("./apps-4RCFXT74.js")).capDefault,parameters:{positional:{kind:"tuple",parameters:[{placeholder:"n|off",brief:"Provider calls per UTC month (1 to 1,000,000,000) for every app without its own cap, or off for no default",parse:pt}]},flags:m},docs:{brief:"Set or clear the workspace default cap: what binds every app without a cap or --unlimited of its own",fullDescription:["The same setting as Manage workspace \u2192 Usage \u2192 Default monthly cap. An app's own cap, or","its --unlimited, stays. The Gateway holds every app without one to it within 30 seconds;","past it, a provider tool answers a tool error naming the cap and an app's brokered call","gets 429 app_monthly_cap_exceeded until the next UTC month. As in the Gateway, the","workspace's first cap makes the built-in Cap alerts subscription, and a default set,","raised or removed queues cap.raised (a lowered one doesn't). Refused on a Gateway from","before the workspace default (GATEWAY_PREDATES_DEFAULT_CAPS): run update first.","","Examples:",` ${t} workspace cap default 1000`,` ${t} workspace cap default off --json`].join(`
84
+ `)}});function Qa(e){let o=e.trim();if(!Te.test(o))throw new Error(`a month is written YYYY-MM (not ${e})`);return o}var eo=c({loader:async()=>(await import("./activity-RSD4D66F.js")).usage,parameters:{positional:{kind:"tuple",parameters:[]},flags:{month:{kind:"parsed",parse:Qa,optional:!0,placeholder:"YYYY-MM",brief:"The UTC month (default: this one)"},...m}},docs:{brief:"What the apps spent in a month: per app (with the cap that binds it), per member and per provider",fullDescription:["Provider calls, failures, tokens and provider-reported cost, counted at the Gateway after a","provider answered, and allowed MCP tool calls from the audit trail. Every callable app is","listed, with zeros in a month it made no call, its own cap, the cap that binds it and where","it comes from (its own, or the workspace default), whether it is exempt (--unlimited) and","whether it is paused this month; the workspace default cap comes with it. Nothing is","changed. Refused on a Gateway from before the workspace default","(GATEWAY_PREDATES_DEFAULT_CAPS): run update first.","",`Example:
85
+ ${t} workspace usage --month 2026-10 --json`].join(`
86
+ `)}});function to(e){let o=Date.parse(e.trim());if(Number.isNaN(o))throw new Error(`a time is written like 2026-10-24 or 2026-10-24T09:00:00Z (not ${e})`);return o}function ao(e){let o=Number(e.trim());if(!Number.isInteger(o)||o<1||o>M)throw new Error(`a limit is a whole number from 1 to ${M}`);return o}function oo(e){let o=/^(\d+):(.+)$/.exec(e.trim());if(!o)throw new Error("a cursor is the previous page's nextBefore, written <createdAt>:<id>");return{createdAt:Number(o[1]),id:o[2]}}var no=c({loader:async()=>(await import("./activity-RSD4D66F.js")).activity,parameters:{positional:{kind:"tuple",parameters:[]},flags:{app:{kind:"parsed",parse:String,optional:!0,placeholder:"app",brief:"Calls on this app only, by id or row id"},user:{kind:"parsed",parse:String,optional:!0,placeholder:"email",brief:"Calls by this member only, by email or user id"},decision:{kind:"enum",values:["allowed","blocked"],optional:!0,brief:"Allowed or blocked calls only"},risk:{kind:"enum",values:["read","write","destructive"],optional:!0,brief:"Tools of this risk only"},since:{kind:"parsed",parse:to,optional:!0,placeholder:"time",brief:"Calls at or after this time (ISO 8601, UTC)"},limit:{kind:"parsed",parse:ao,optional:!0,placeholder:"n",brief:`Rows per page, 1 to ${M} (default 50)`},before:{kind:"parsed",parse:oo,optional:!0,placeholder:"cursor",brief:"The next page: the previous page's nextBefore, as <createdAt>:<id>"},...m}},docs:{brief:"The tool-call audit trail, newest first: who called which tool on which app, and what came of it",fullDescription:["Never the arguments or the result: the trail holds neither. One page at a time; --json","carries data.nextBefore for the next page. Nothing is changed.","","Examples:",` ${t} workspace activity --limit 20`,` ${t} workspace activity --app crm --decision blocked --since 2026-10-24 --json`].join(`
87
+ `)}}),lt={kind:"parsed",parse:String,optional:!0,placeholder:"email",brief:"One member's only, by email or user id"},so=c({loader:async()=>(await import("./activity-RSD4D66F.js")).tokens,parameters:{positional:{kind:"tuple",parameters:[]},flags:{user:lt,all:{kind:"boolean",optional:!0,brief:"Revoked and expired tokens too"},...m}},docs:{brief:"Every member's personal access tokens for the organization (never a token's value)",fullDescription:["Tokens are created in Admin \u2192 Tokens only: their hash is keyed by a Gateway secret the CLI","never holds. Nothing is changed.","",`Example:
88
+ ${t} workspace tokens --user ann@example.com`].join(`
89
+ `)}}),ro=c({loader:async()=>(await import("./activity-RSD4D66F.js")).tokenRevoke,parameters:{positional:{kind:"tuple",parameters:[{placeholder:"id",brief:"The token's id (workspace tokens lists them)",parse:String}]},flags:m},docs:{brief:"Revoke a personal access token: it stops working on its next request",fullDescription:`Example:
90
+ ${t} workspace token revoke 3f2a\u2026`}}),io=c({loader:async()=>(await import("./activity-RSD4D66F.js")).connections,parameters:{positional:{kind:"tuple",parameters:[]},flags:{user:lt,...m}},docs:{brief:"Every member's AI connections to the organization: which AI app, which apps it may use, read or write",fullDescription:["A connection is an OAuth client (Claude, Cursor, \u2026) a member connected to the Gateway's /mcp.","Nothing is changed.","",`Example:
91
+ ${t} workspace connections`].join(`
92
+ `)}}),po=c({loader:async()=>(await import("./activity-RSD4D66F.js")).connectionRevoke,parameters:{positional:{kind:"tuple",parameters:[{placeholder:"id",brief:"The connection's id (workspace connections lists them)",parse:String}]},flags:m},docs:{brief:"Revoke an AI connection: the client is out on its next request",fullDescription:`Example:
93
+ ${t} workspace connection revoke mcpc_\u2026`}}),lo=G({routes:{create:qa,set:za,delete:Va,members:Ka,apps:Ya},docs:{brief:"Make, change or delete a group, and set its members and apps"}}),co=G({routes:{set:Ba,access:Xa,cap:Ja},docs:{brief:"Change an app's listing, who can open it, and its monthly cap"}}),mo=G({routes:{default:Za},docs:{brief:"The workspace default cap on every app's provider calls"}}),ho=G({routes:{revoke:ro},docs:{brief:"Revoke a personal access token"}}),uo=G({routes:{revoke:po},docs:{brief:"Revoke an AI connection"}}),fo=c({loader:async()=>{let{rename:e}=await import("./workspace-CJC5I66L.js");return e},parameters:{positional:{kind:"tuple",parameters:[{placeholder:"name",brief:"The new name: 1 to 64 characters, no line breaks (quote one with spaces)",parse:String}]},flags:nt},docs:{brief:"Rename the workspace: the name members see in the organization switcher and in invitations",fullDescription:["The workspace is the Gateway's organization: the one the setup claim made, named after","its owner. This gives it the name you want; the same rename is under Manage workspace in","the Gateway, for owners and admins. Nothing is built or deployed: the Gateway reads the","name live, and each member sees it on their next page.","","Before the Gateway is claimed there is no workspace to rename (WORKSPACE_NOT_CLAIMED):","claim it in a browser first.","","Examples:",` ${t} workspace rename 'Acme Corp'`,` ${t} workspace rename 'Acme Corp' --json`].join(`
94
+ `)}}),go=c({loader:async()=>{let{role:e}=await import("./workspace-CJC5I66L.js");return e},parameters:{positional:{kind:"tuple",parameters:[{placeholder:"email",brief:"The member's email address, as Manage workspace \u2192 Users lists it",parse:String},{placeholder:"owner|admin|member",brief:"The role to give them",parse:_a}]},flags:nt},docs:{brief:"Set a member's role: owner, admin or member",fullDescription:["The workspace is the Gateway's own organization, the one its owner claimed. Owners are","peers: any owner can make a member or an admin an owner, and change another owner's","role, from Manage workspace \u2192 Users or with this command under the Cloudflare login.","The workspace always keeps at least one owner, so the last owner's role is never","changed (LAST_OWNER): make someone else an owner first. Deactivated owners don't","count here, so this command can't leave a workspace whose only owner is locked out","(the Gateway's own Users page needs no such rule: a deactivated owner can't act, and","only an owner acts on an owner). Only a member can be given a role; someone still","invited isn't one yet (MEMBER_NOT_FOUND). The Gateway picks up the change within 30","seconds.","","Examples:",` ${t} workspace role sam@example.com owner`,` ${t} workspace role sam@example.com member --json`].join(`
95
+ `)}}),dt=G({routes:{show:ja,rename:fo,users:Oa,role:go,invite:La,"invite-link":Pa,uninvite:Ia,deactivate:Na,reactivate:Fa,remove:Ma,"reset-link":Ua,groups:Wa,group:lo,apps:Ha,app:co,cap:mo,usage:eo,activity:no,tokens:so,token:ho,connections:io,connection:uo},docs:{brief:"Manage the workspace from the terminal: members, invitations, groups, app access, caps, usage, activity, tokens and AI connections"}});var H=yo({routes:{create:Ne,dev:We,deploy:Ue,release:Be,db:Fe,teardown:at,login:Ve,setup:Qe,update:ot,install:ze,configure:Ie,status:tt,delete:Me,access:Pe,signin:et,secret:Ze,provider:He,mcp:Ke,email:Se,events:qe,workspace:dt},docs:{brief:"Deploy and run Every App apps on your own Cloudflare account."}}),Y=H;var ct=[["BUILD AN APP",["create","dev","deploy","release","db"]],["RUN A GATEWAY",["login","setup","update","install","configure","status","delete","access","signin","secret","provider","mcp","email","events","teardown"]],["MANAGE THE WORKSPACE",["workspace"]]],vo={secret:["secret set GITHUB_TOKEN","secret set GITHUB_TOKEN --from-env GH_TOKEN","secret set MAIN_SECRET --app analytics","secret list crm"],email:["email show","email set --sender '*@mail.example.com'","email unset inbound"],events:["events add https://hooks.example.com/everyapp --events cap.*,member.*","events add --email admins --events cap.*","events test sub_\u2026","events deliveries --dead"],access:["access on","access on --email-domain example.com","access off"],signin:["signin list","signin show google","signin add google","signin add github --client-id Iv1.0123456789abcdef --client-secret-from-env GITHUB_SECRET --json","signin remove github"],provider:["provider list","provider add stripe.json","provider show stripe"],mcp:["mcp list","mcp on dataforseo","mcp add https://treg.to/mcp/ --auth bearer","mcp show treg","mcp off treg"],db:["db migrate","db query 'select count(*) from todos'"],workspace:["workspace rename 'Acme Corp'","workspace users","workspace role sam@example.com owner","workspace role sam@example.com member","workspace invite ann@example.com --role admin","workspace app access crm --add ann@example.com","workspace group members Sales --set ann@example.com --set bob@example.com","workspace usage --month 2026-10 --json"]},ko={email:["Invites, and apps that don't set their own senders, send as the Gateway's sender.",`Set it with: ${t} secret set EMAIL_FROM EMAIL_FROM_NAME`],events:["Each webhook is signed: X-EveryApp-Signature, HMAC-SHA256 over <t>.<body>; verify it with the snippet on /docs/events."],workspace:["Everything Admin \u2192 Users, Groups, Apps, Tokens, Usage and Activity do, from the terminal.","Acts under your Cloudflare login (the operator is root in every organization of the Gateway),","on the install organization unless --org names another by slug, id or name (a name two","organizations share is refused: give the slug). The Gateway mails nothing from here: invite","and reset-link print the link to hand over.",`Depth-two groups have their own help: ${t} workspace group --help, app, token, connection.`]},Ao=e=>H.getRoutingTargetForInput(e).brief;function mt(){let e=Math.max(...ct.flatMap(([,a])=>a.map(n=>n.length))),o=(a,n)=>["",v.bold(a),...n.map(r=>` ${r.padEnd(e)} ${Ao(r)}`)];return[H.brief,"",v.bold("USAGE"),` ${t} <command> [flags]`,...ct.flatMap(([a,n])=>o(a,n)),"",v.bold("FLAGS")," -h, --help Show help for everyapp or a command"," -v, --version Show everyapp's version"," --no-color Print without colors (also NO_COLOR=1)","",v.bold("EXAMPLES"),` $ ${t} setup --domain apps.example.com`,` $ ${t} create todo`,` $ ${t} deploy`,` $ ${t} install https://github.com/<owner>/<repo>`,` $ ${t} configure crm`,"",`Run ${v.bold(`${t} <command> --help`)} for a command's flags.`,""].join(`
96
+ `)}function ht(e){let o=e.filter(p=>p!=="--help"&&p!=="-h");if(o.length!==1||e.length-o.length>1)return null;let{path:a,target:n}=W(Y,o);if(a.length!==1||!("getAllEntries"in n))return null;let r=a[0],s=Y.getAllEntries().find(p=>p.target===n)?.name.original??r,u=n.getAllEntries().filter(p=>!p.hidden),g=Math.max(...u.map(p=>p.name.original.length)),A=vo[s]??[],y=ko[s]??[];return[`${n.brief}.`,...y.length>0?["",...y]:[],"",v.bold("USAGE"),` ${t} ${r} <command> [flags]`,"",v.bold("COMMANDS"),...u.map(p=>` ${p.name.original.padEnd(g)} ${p.target.brief}`),...A.length>0?["",v.bold("EXAMPLES"),...A.map(p=>` $ ${t} ${p}`)]:[],"",`Run ${v.bold(`${t} ${r} <command> --help`)} for its flags.`,""].join(`
97
+ `)}function ut(){return`${me} ${B}
98
+ `}function ft({color:e,args:o,report:a}){let n=s=>(a(s),""),r=s=>n({code:"COMMAND_FAILED",message:ye(s),data:{}});return wo(H,{name:t,versionInfo:{currentVersion:B},scanner:{allowArgumentEscapeSequence:!0,caseStyle:"allow-kebab-for-camel"},documentation:{caseStyle:"convert-camel-to-kebab",disableAnsiColor:!e},localization:{loadText:()=>({...bo,exceptionWhileParsingArguments:s=>n(Le(Y,o,s)),noCommandRegisteredForInput:({input:s})=>n(Oe(Y,o,s)),exceptionWhileLoadingCommandFunction:r,exceptionWhileRunningCommand:r,commandErrorResult:r})}})}function So(e){let o=e.indexOf("--"),a=o<0?e:e.slice(0,o),n=s=>o>=0&&s>o,r=e.filter((s,u)=>s!=="--no-color"||n(u)).map((s,u)=>(s==="--help-all"||s==="-H")&&!n(u)?"--help":s);return{args:r[0]==="help"?[...r.slice(1),"--help"]:r,json:a.includes("--json"),noColor:a.includes("--no-color")}}var{args:k,json:ce,noColor:wt}=So(process.argv.slice(2)),Ro=Date.now();ke({argv:process.argv.slice(2),json:ce});process.on("exit",e=>Ae(e,Date.now()-Ro));var yt=be(wt);yt||(Co.level=0);wt&&(process.env.NO_COLOR="1");var To=k.some(e=>e==="--help"||e==="-h"),gt=ve();if(gt){let e=J(ce);Ee(e,gt),process.exitCode=e.exitCode}else if(k.length===0||k.length===1&&To)process.stdout.write(mt());else if(k.length===1&&(k[0]==="--version"||k[0]==="-v"))process.stdout.write(ut());else{let e=ht(k);e?process.stdout.write(e):await $o()}async function $o(){let e,o=ft({color:yt,args:k,report:r=>{e??=J(ce),e.emit({type:"error",retryable:!1,...r})}}),a={stdout:process.stdout,stderr:{write:()=>!0},env:process.env,exitCode:void 0};await Eo(o,k,Ge(a));let n=Ce()??a.exitCode;n!==void 0&&(process.exitCode=n)}
@@ -0,0 +1 @@
1
+ import{a as l,c as i}from"./chunk-FJJSSVET.js";import{h as n}from"./chunk-GKBPYVP3.js";import"./chunk-PNLU5U3P.js";import"./chunk-CZTEDWZ2.js";import"./chunk-N4E5YE4X.js";import"./chunk-BHMRY53V.js";import"./chunk-AGTCKFRB.js";import"./chunk-E3EPK27P.js";import"./chunk-IFCPALVC.js";import"./chunk-WOVS3GV5.js";import"./chunk-OM2HDWVP.js";import"./chunk-J455FAEN.js";import"./chunk-EGEWRFVY.js";import"./chunk-2Y5Q6A5K.js";import"./chunk-H6QQMY7B.js";import"./chunk-6OGVO7QK.js";import"./chunk-PS7S74DG.js";import"./chunk-YHJZMJYZ.js";import"./chunk-N5GQLGEC.js";import"./chunk-W3JCQHHU.js";import"./chunk-TLRM3P7V.js";import"./chunk-ZFCUH5PK.js";import"./chunk-4JRIS6S6.js";import"./chunk-23HJ5I2A.js";import"./chunk-ZECBN24L.js";import"./chunk-ONLNJXVQ.js";import"./chunk-6PGUCTJ6.js";import"./chunk-HOUHG236.js";import{qa as a}from"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-H7PDL3X5.js";import"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{wc as r}from"./chunk-LYNBZ7RV.js";async function b(e,p){await r(e,async o=>{let m=a(e.gateway),t=await n(p,{out:o});try{let s=await l({cwd:process.cwd(),manifest:t.manifest,release:t,gateway:m,accountId:e["account-id"],out:o,json:e.json,verbose:e.verbose,allowDeleteDurableObjectData:e["allow-delete-durable-object-data"],allowDeleteWorkflows:e["allow-delete-workflows"],forceDns:e["force-dns"],enableEmailRouting:e["enable-email-routing"],waitForLive:!e["no-wait"],offerInstall:{yes:e.yes}});o.emit({type:"done",...i(s)})}finally{await t.cleanup()}})}export{b as install};
@@ -0,0 +1 @@
1
+ import{a as l,c as m,e as s}from"./chunk-T2GD7RHS.js";import{a as r}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{ac as i,wc as p}from"./chunk-LYNBZ7RV.js";var n="cloudflare.login";async function v(e){await p(e,async o=>{await f({out:o,interactive:r(e.json??!1)}),o.emit({type:"done"})})}async function f({out:e,interactive:o,cf:t=i()}){let a=await l(t);if(a.authenticated){e.emit({type:"step",step:n,status:"skip",message:"Already logged in to Cloudflare.",data:{email:a.email??null,token:!!process.env.CLOUDFLARE_API_TOKEN}});return}let c=await s({cf:t,interactive:o,onDeviceLogin:m(e,n)});e.emit({type:"step",step:n,status:"ok",message:"Logged in to Cloudflare.",data:{email:c.email??null}})}export{f as logInToCloudflare,v as login};
@@ -0,0 +1 @@
1
+ import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}from"./chunk-IUOBIB5M.js";import"./chunk-IFCPALVC.js";import"./chunk-WOVS3GV5.js";import"./chunk-OM2HDWVP.js";import"./chunk-ZFCUH5PK.js";import"./chunk-4JRIS6S6.js";import"./chunk-ZECBN24L.js";import"./chunk-HOUHG236.js";import"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-H7PDL3X5.js";import"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import"./chunk-LYNBZ7RV.js";export{a as add,i as addServer,p as changeTool,e as list,m as listMcp,d as off,c as on,g as refresh,o as refreshApp,b as remove,l as removeApp,f as show,n as showApp,h as tool,k as turnOff,j as turnOn};
@@ -0,0 +1,13 @@
1
+ import{j as z,k as V}from"./chunk-IUOBIB5M.js";import"./chunk-IFCPALVC.js";import{a as G,c as M,d as J}from"./chunk-WOVS3GV5.js";import"./chunk-OM2HDWVP.js";import"./chunk-ZFCUH5PK.js";import{a as T}from"./chunk-4JRIS6S6.js";import"./chunk-ZECBN24L.js";import"./chunk-HOUHG236.js";import{na as x,qa as B,sa as D}from"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-H7PDL3X5.js";import{a as L}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{$a as C,Bb as S,D as $,Fb as E,J as U,Yb as F,c as f,eb as _,fb as N,k as y,pc as K,qb as j,wc as v,xa as I}from"./chunk-LYNBZ7RV.js";import R from"node:fs/promises";import k from"node:path";import{stripVTControlCharacters as H}from"node:util";import m from"chalk";var P=64*1024;async function Ce(e,t){await v(e,n=>ne({flags:e,out:n},t))}async function Ne(e){await v(e,t=>ie({flags:e,out:t}))}async function je(e,t){await v(e,n=>de({flags:e,out:n},t))}async function Ee(e,t){await v(e,n=>ce({flags:e,out:n},t))}async function Te(e,t){await v(e,n=>q({flags:e,out:n},"on",t))}async function xe(e,t){await v(e,n=>q({flags:e,out:n},"off",t))}async function q(e,t,n){e.out.emit({type:"step",step:"provider.alias",status:"ok",message:`everyapp provider ${t} is now everyapp mcp ${t}; this alias goes after launch week.`,data:{command:`${f} mcp ${t} ${n}`}}),await(t==="on"?z:V)(e,n)}function b({flags:e,out:t,createCf:n}){return D({gateway:B(e.gateway),accountId:e["account-id"],interactive:L(e.json??!1),login:{json:e.json,out:t,step:"login"},createCf:n})}async function Y(e){try{return await R.access(k.join(e,"everyapp.config.ts")),!0}catch{return!1}}function u(e,t){return new S("PROVIDER_SPEC_INVALID",e,{fix:t})}async function ee(e,{cwd:t,fetcher:n=fetch}){let a;if(/^[a-z][a-z0-9+.-]*:\/\//i.test(e)){let c;try{c=new URL(e)}catch{throw u(`${e} isn't a URL`,"give the spec's https URL, or a path to the file")}if(c.protocol!=="https:")throw u(`${e} isn't https`,"fetch specs over https only, or save the file and give its path");let o;try{o=await n(c,{headers:{accept:"application/json"},redirect:"follow"})}catch(i){throw u(`Couldn't fetch ${e}: ${E(i).split(`
2
+ `)[0]}`,"check the URL, or save the file and give its path")}if(o.url&&!o.url.startsWith("https://"))throw u(`${e} redirected to a URL that isn't https`,"give the spec's final https URL");if(!o.ok)throw u(`${e} answered ${o.status}`,"check the URL, or save the file and give its path");a=await te(o,e)}else{let c=k.resolve(t,e),o;try{if((await R.stat(c)).size>P)throw u(`${e} is over ${P/1024} KiB`,"a spec is a short JSON file");o=await R.readFile(c)}catch(i){throw i instanceof S?i:F(i)?u(`No file at ${e}`,"give the path to the spec's JSON file, or its https URL"):i}a=o.toString("utf8")}try{return JSON.parse(a)}catch(c){throw u(`${e} isn't JSON: ${E(c).split(`
3
+ `)[0]}`,"fix the file, then add it again")}}async function te(e,t){let n=Number(e.headers.get("content-length")),a=()=>u(`${t} is over ${P/1024} KiB`,"a spec is a short JSON file");if(Number.isFinite(n)&&n>P)throw a();if(!e.body)return"";let c=e.body.getReader(),o=[],i=0;for(;;){let{done:l,value:r}=await c.read();if(l)break;if(i+=r.byteLength,i>P)throw await c.cancel(),a();o.push(r)}return Buffer.concat(o).toString("utf8")}function W(e){return y([...e.hosts,...e.hostSetting?[`the host ${e.hostSetting} names`]:[]])}function se(e){let{auth:t}=e;switch(t.kind){case"bearer":return`as ${t.scheme??"a bearer"} token`;case"header":return`in the ${t.header} header`;case"query":return`as the ${t.param} query parameter`;case"basic":return"as HTTP Basic"}}async function ne(e,t){let{out:n,flags:a}=e,c=e.cwd??process.cwd(),o=await ee(t,{cwd:c,fetcher:e.fetch}),i=await b(e),l=o&&typeof o=="object"&&typeof o.id=="string"?o.id:"the provider";n.emit({type:"step",step:"provider.add",status:"start",message:`Registering ${l}...`});let r=await M(i.db,{spec:o,deployer:i.deployer,replace:a.replace??!1,install:i.install,now:e.now?.()}),{id:d,capability:s}=r,p=[...$(s)],w=i.gatewayUrl.replace(/^https:\/\//,"");n.emit({type:"step",step:"provider.add",status:"ok",message:`${r.replaced?"Replaced":"Registered"} ${s.label} (${d}) on ${w}`,data:{id:d,replaced:r.replaced}});let g=null;await Y(c)&&(g=N(d),await X(c,d,s));let O=p.join(" "),h=[`${r.replaced?"Replaced":"Registered"} ${s.label} (${d}) on ${w}.`,`Its key goes to ${W(s)} only, ${se(s)}.`,...r.replaced?["The key set before was for the old spec: set it again before the Gateway sends it."]:[],...g?[`Wrote ${g} for everyapp dev (your key goes in .dev.vars).`]:[],`Apps list it as capabilities: { ${JSON.stringify(d)}: { access: "${s.access[0]}", why: "..." } }.`];n.emit({type:"done",message:H(h.join(`
4
+ `)),display:[h[0],...h.slice(1).map(A=>m.dim(A))].join(`
5
+ `),data:{id:d,name:s.label,hosts:[...s.hosts],...s.hostSetting?{hostSetting:s.hostSetting}:{},settings:p,source:"row",replaced:r.replaced,...g?{devFile:g}:{},next:[{command:`${f} secret set ${O}`,note:`${s.label}'s key, from ${s.docs}; the Gateway sends it only to ${W(s)}`}]}})}async function X(e,t,n){let a=k.join(e,_,`${t}.json`);return await R.mkdir(k.dirname(a),{recursive:!0}),await R.writeFile(a,`${JSON.stringify(C(t,n),null,2)}
6
+ `),a}function oe(e){switch(e.mode){case"api_key":return"api key";case"ai":return"ai";case"oauth_client":return"oauth client";case"service":return null}}function Q(e){switch(e.mode){case"api_key":return{hosts:[...e.hosts],...e.hostSetting?{hostSetting:e.hostSetting}:{}};case"ai":return{hosts:[new URL(e.origin).host]};case"oauth_client":return{hosts:[...new Set(e.token.flatMap(t=>t.host?[t.host]:[]))],...e.hostSetting?{hostSetting:e.hostSetting}:{}};case"service":return{hosts:[]}}}function Z(e,t,n){return e.filter(a=>a.manifest?n.mode==="ai"?I(a.manifest).includes(t):!!(a.manifest.capabilities&&Object.hasOwn(a.manifest.capabilities,t)):!1).map(a=>a.appSlug)}function re(e,t,n){let a=new Map(e.rows().map(o=>[o.id,o])),c=[];for(let[o,i]of e.entries()){let l=oe(i);if(!l)continue;let r=a.get(o);c.push({id:o,name:i.label,kind:l,...Q(i),settings:$(i).map(d=>({name:d,set:t.includes(d)})),bound:e.bound(o),source:r?"row":"catalog",...r?{addedBy:r.addedBy,addedAt:r.addedAt}:{},apps:Z(n,o,i)})}return c}async function ie(e){let{out:t}=e,n=await b(e),[a,c,o]=await Promise.all([G(n.db,n.install),T(n.cf,j),x(n.db)]),i=re(a,c,o),l=K(["ID","NAME","KIND","HOSTS","SETTINGS","SOURCE","APPS"],i.map(s=>[s.id,s.name,s.kind,[...s.hosts,...s.hostSetting?[`<${s.hostSetting}>`]:[]].join(", ")||m.dim("-"),[s.settings.map(p=>`${p.name} ${p.set?m.green("set"):m.yellow("not set")}`).join(", "),...s.source==="row"?[s.bound?m.green("bound"):m.yellow("not bound")]:[]].join(", "),s.source==="row"?`registered by ${s.addedBy??"someone"}`:m.dim("catalog"),s.apps.join(", ")||m.dim("-")])),r=i.filter(s=>s.source==="row").length,d=a.rejected.map(({id:s,code:p,message:w})=>({id:s,code:p,message:w}));t.emit({type:"done",message:`${i.length} providers: ${i.length-r} built in, ${r} registered`,display:[...l,...d.length>0?["",m.yellow(`The Gateway doesn't serve ${y(d.map(s=>s.id))}:`),...d.map(s=>m.dim(` ${s.id}: ${s.message} (${s.code})`))]:[],"",m.dim(`MCP apps: ${f} mcp list`)].join(`
7
+ `),data:{providers:i,...d.length>0?{rejected:d}:{},mcp:`${f} mcp list`}})}function ae(e,t){let n=[...$(t)];switch(t.mode){case"api_key":return C(e,t);case"ai":return{id:e,kind:"ai",name:t.label,...t.description?{description:t.description}:{},docs:t.docs,...t.api?{api:t.api}:{},...t.hint?{hint:t.hint}:{},settings:n,hosts:[new URL(t.origin).host],routes:[...t.inferenceRoutes],...t.setup?{setup:t.setup}:{}};case"oauth_client":return{id:e,kind:"oauth client",name:t.label,docs:t.console,settings:n,tokenEndpoints:U(t).split(", "),authorize:{url:t.authorize.url,scopes:[...t.authorize.scopes]},redirectPaths:[...t.redirectPaths],...t.hostSetting?{hostSetting:t.hostSetting}:{},...t.setup?{setup:t.setup}:{}};case"service":return{id:e,name:t.label}}}async function de(e,t){let{out:n,flags:a}=e,c=e.cwd??process.cwd();if(a.save&&!await Y(c))throw new S("MANIFEST_NOT_FOUND",`No everyapp.config.ts in this directory
8
+ --save writes the spec where everyapp dev reads it, in an app's directory. Nothing was written.`,{fix:"run this from the app's directory"});let o=await b(e),[i,l]=await Promise.all([G(o.db,o.install),x(o.db)]),r=i.get(t);if(!r||r.mode==="service"){let h=i.rejected.find(A=>A.id===t);throw new S("PROVIDER_NOT_FOUND",r?`${t} is a Gateway service, not a provider
9
+ Apps call it with its own helper (sendEmail(), listMembers()).`:h?`The Gateway doesn't serve ${t}: ${h.message}`:`${t} isn't a provider this Gateway offers`,{rerun:`${f} provider list`,rerunNote:"names every one"})}let d=i.rows().find(h=>h.id===t),s=ae(t,r),p=null;if(a.save){if(!d||r.mode!=="api_key")throw new S("PROVIDER_BUILTIN",`${t} is built in
10
+ everyapp dev reaches it without a file. Nothing was written.`,{fix:`put its key in .dev.vars: ${$(r).join(", ")}`});await X(c,t,r),p=N(t)}let w=Z(l,t,r),g=i.bound(t),O=[d?`Registered by ${d.addedBy??"someone"}${d.addedAt?` on ${new Date(d.addedAt).toISOString().slice(0,10)}`:""}; ${g?"its key is bound to these hosts":"its key isn't set for these hosts yet"}.`:"Built in.",w.length>0?`Used by ${y(w)}.`:"No app lists it yet.",...p?[`Wrote ${p} for everyapp dev.`]:[]];n.emit({type:"done",message:`${r.label} (${t})`,display:[JSON.stringify(s,null,2),"",...O.map(h=>m.dim(h))].join(`
11
+ `),data:{provider:s,source:d?"row":"catalog",bound:g,addedBy:d?.addedBy??null,addedAt:d?.addedAt??null,apps:w,...p?{saved:p}:{},...d&&!g?{next:[{command:`${f} secret set ${$(r).join(" ")}`,note:`${r.label}'s key; the Gateway sends it only to ${y(Q(r).hosts)}`}]}:{}}})}async function ce(e,t){let{out:n,flags:a}=e,c=await b(e);n.emit({type:"step",step:"provider.remove",status:"start",message:`Removing ${t}...`});let o=await J(c.db,t,c.deployer,{force:a.force??!1,now:e.now?.()}),i=await T(c.cf,j),l=o.settings.map(p=>({name:p,set:i.includes(p)})),r=l.filter(p=>p.set).map(p=>p.name),d=c.gatewayUrl.replace(/^https:\/\//,"");n.emit({type:"step",step:"provider.remove",status:"ok",message:`Removed ${o.name} (${t}) from ${d}`,data:{id:t}});let s=[`Removed ${o.name} (${t}) from ${d}.`,"The Gateway stops serving it within 30 seconds.",...o.apps.length>0?[`${y(o.apps)} ${o.apps.length===1?"lists":"list"} it: ${o.apps.length===1?"its":"their"} calls to it fail until it is registered again.`]:[],...r.length>0?[`${y(r)} ${r.length===1?"stays":"stay"} on the Gateway, read by nothing: ${f} secret unset ${r.join(" ")} removes ${r.length===1?"it":"them"}.`]:[]];n.emit({type:"done",message:H(s.join(`
12
+ `)),display:[s[0],...s.slice(1).map(p=>m.dim(p))].join(`
13
+ `),data:{id:t,name:o.name,removed:!0,settings:l,apps:o.apps,...r.length>0?{next:[{command:`${f} secret unset ${r.join(" ")}`,note:"the key nothing reads any more"}]}:{}}})}export{P as MAX_SPEC_BYTES,Ce as add,ne as addFromSpec,Ne as list,ie as listProviders,xe as off,Te as on,ee as readSpecSource,Ee as remove,ce as removeRegistered,q as runMcpAlias,je as show,de as showProvider};
@@ -0,0 +1 @@
1
+ import{b as v,c as g,d as k,e as w,g as A}from"./chunk-GKBPYVP3.js";import"./chunk-6OGVO7QK.js";import"./chunk-W3JCQHHU.js";import{e as h,g as b}from"./chunk-ONLNJXVQ.js";import{a as y}from"./chunk-H7PDL3X5.js";import{$b as d,Ub as c,ac as u,c as o,wc as f}from"./chunk-LYNBZ7RV.js";import C from"node:path";async function E({cwd:t,manifest:e,outFile:a,out:s,verbose:p=!1,createCf:R=()=>u(),installDeps:$=d}){e.install!==!1&&(s.emit({type:"step",step:"app.install",status:"start",message:"Installing dependencies..."}),await $({cwd:t,description:"Installing dependencies...",install:e.install,verbose:p}),s.emit({type:"step",step:"app.install",status:"ok"})),s.emit({type:"step",step:"app.build",status:"start",message:"Building..."}),await g({cwd:t,cf:R(),buildCommand:e.build,verbose:p});let l=h(e);await k({cwd:t,inputs:{...l,helperWorkers:(e.workers??[]).map(n=>b(l.workerName,n.name)),declared:e.resources}}),s.emit({type:"step",step:"app.build",status:"ok",message:"Built the app and checked its Build Output."}),await v({cwd:t,manifest:e,out:s});let i=C.resolve(t,a),m=C.isAbsolute(a)||a.startsWith(".")?a:`./${a}`,B=await c(t).then(n=>n.version,()=>"unknown"),r=await A({cwd:t,manifest:e,outFile:i,cfVersion:B});return s.emit({type:"step",step:"app.release",status:"ok",message:`Packed ${e.id} ${r.version} (${r.sha256.slice(0,12)}) into ${i}.`,data:{tarball:i,shown:m,appId:e.id,version:r.version,sha256:r.sha256}}),{tarball:i,shown:m,version:r.version,sha256:r.sha256}}async function H(t){await f(t,async e=>{let a=process.cwd(),s=await E({cwd:a,manifest:await y(a),outFile:t.out??w,out:e,verbose:t.verbose});e.emit({type:"done",data:{...s,next:[{command:`${o} install ${s.shown}`,note:"installs it on your Gateway"},{command:`${o} install <repository url>`,note:"installs it on any Gateway, once the tarball is attached to a GitHub release of the app's repository"}]}})})}export{H as release};
@@ -0,0 +1,3 @@
1
+ import{a as A,b as P,d as v,e as C}from"./chunk-6PGUCTJ6.js";import{c as u}from"./chunk-HOUHG236.js";import{e as R,ha as h,qa as k,sa as E}from"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import{a as T}from"./chunk-H7PDL3X5.js";import{a as w,i as l}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{Bb as c,f as b,jc as g,uc as I,vc as $}from"./chunk-LYNBZ7RV.js";async function K(e,o){let r=I(e.json);await $(r,async()=>{await x({cwd:process.cwd(),appId:o,gateway:e.gateway??!1,accountId:e["account-id"],yes:e.yes??!1,json:e.json??!1,out:r})})}async function x({cwd:e,appId:o,gateway:r,accountId:O,yes:j,json:m,out:n,createCf:D,interactive:y=w(m),confirm:S}){if(r&&o)throw new c("RESTORE_TARGET_TWICE",`Pass ${o} or --gateway, not both`,{data:{fix:"drop one of them"}});let a=r?null:o??(await T(e)).id,{cf:_,db:s}=await E({gateway:k(),accountId:O,interactive:y,login:{json:m,out:n,step:"db.login"},createCf:D}),d=a?P((await h(s,a)).workerName):A,i=a?`${a}'s database`:"the Gateway's database",t=await v(s,d);if(!t)throw new c("NO_RESTORE_POINT",`No restore point for ${i}
2
+ everyapp saves one when ${a?"a deploy":"setup or a Gateway upgrade"} migrates a database that has data.`);let p={appId:a,databaseId:t.databaseId,bookmark:t.bookmark,migrations:t.migrations,createdAt:t.createdAt,createdBy:t.createdBy};await l({yes:j,interactive:y,confirm:S,question:`Put ${i} back to before ${G(t)}?`,unattended:`Restoring ${i} needs a person at a terminal to confirm, or --yes
3
+ It undoes ${G(t)}; anything written to it since is lost too.`,context:["Anything written to the database since then is lost too."],data:p});let f=await u({db:s,id:d,purpose:"db.restore",...a?{app:a}:{},out:n,step:"db.lease"});try{await f.check(),n.emit({type:"step",step:"db.restore",status:"start",data:p}),await R(_,t.databaseId,t.bookmark),await C(s,d),n.emit({type:"step",step:"db.restore",status:"ok",message:`Restored ${i} to before ${t.migrations.join(", ")}.`,data:p})}finally{await f.release()}n.emit({type:"done",data:p})}function G(e,o=Date.now()){let r=e.createdBy.startsWith("api-token:")?"an API token":e.createdBy;return`${b(e.migrations.length,"migration")} (${e.migrations.join(", ")}) applied ${g(o-e.createdAt)} ago by ${r}`}export{K as restore,x as restoreDatabase};
@@ -0,0 +1 @@
1
+ import{A as e,B as f,C as g,D as h,E as i,F as j,G as k,H as l,w as a,x as b,y as c,z as d}from"./chunk-IFCPALVC.js";import"./chunk-WOVS3GV5.js";import"./chunk-OM2HDWVP.js";import"./chunk-ZFCUH5PK.js";import"./chunk-4JRIS6S6.js";import"./chunk-ZECBN24L.js";import"./chunk-HOUHG236.js";import"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-H7PDL3X5.js";import"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import"./chunk-LYNBZ7RV.js";export{j as ManifestSource,g as applyAppSettings,f as applyGatewaySettings,e as applySecretValues,l as doneData,c as list,i as listSecrets,a as set,d as setSecrets,k as storedManifestOf,b as unset,h as unsetSecrets};
@@ -0,0 +1 @@
1
+ import{a,b,c}from"./chunk-ZEXVHB22.js";import"./chunk-CZTEDWZ2.js";import"./chunk-N4E5YE4X.js";import"./chunk-AGTCKFRB.js";import"./chunk-E3EPK27P.js";import"./chunk-IFCPALVC.js";import"./chunk-WOVS3GV5.js";import"./chunk-OM2HDWVP.js";import"./chunk-2Y5Q6A5K.js";import"./chunk-H6QQMY7B.js";import"./chunk-6OGVO7QK.js";import"./chunk-N5GQLGEC.js";import"./chunk-W3JCQHHU.js";import"./chunk-TLRM3P7V.js";import"./chunk-ZFCUH5PK.js";import"./chunk-4JRIS6S6.js";import"./chunk-23HJ5I2A.js";import"./chunk-ZECBN24L.js";import"./chunk-ONLNJXVQ.js";import"./chunk-6PGUCTJ6.js";import"./chunk-HOUHG236.js";import"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-H7PDL3X5.js";import"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import"./chunk-LYNBZ7RV.js";export{c as reportGatewayResult,b as runGatewayCommand,a as setup};
@@ -0,0 +1,12 @@
1
+ import{B as D,q as F,r as U}from"./chunk-IFCPALVC.js";import"./chunk-WOVS3GV5.js";import{a as E,n as se}from"./chunk-OM2HDWVP.js";import"./chunk-ZFCUH5PK.js";import"./chunk-4JRIS6S6.js";import"./chunk-ZECBN24L.js";import"./chunk-HOUHG236.js";import{$ as te,B as ne,qa as ie,sa as ae,y as ee}from"./chunk-RMF4YGD6.js";import"./chunk-NFU4YFXB.js";import"./chunk-T2GD7RHS.js";import"./chunk-H7PDL3X5.js";import{a as G,f as B,g as J,h as X,i as Z}from"./chunk-CCWBPAKH.js";import"./chunk-JYKRUS5C.js";import{Bb as b,N as T,O as N,P as W,Q,R as Y,U as C,c as h,k as p,oc as A,pc as x,wc as P}from"./chunk-LYNBZ7RV.js";import{stripVTControlCharacters as le}from"node:util";import c from"chalk";async function Ue(e,s){await P(e,i=>he({flags:e,out:i},s))}async function De(e){await P(e,s=>Se({flags:e,out:s}))}async function je(e,s){await P(e,i=>ye({flags:e,out:i},s))}async function Le(e,s){await P(e,i=>$e({flags:e,out:i},s))}function O({flags:e,out:s,createCf:i}){return ae({gateway:ie(e.gateway),accountId:e["account-id"],interactive:G(e.json??!1),login:{json:e.json,out:s,step:"login"},createCf:i})}function K(e){let s=e.trim().toLowerCase();if(Y(s))return W[s];throw new b("SIGNIN_UNKNOWN_PROVIDER",`${e} isn't a sign-in provider
2
+ The Gateway offers ${p([...T])}; oidc is any OpenID Connect issuer (Okta, Entra ID, Keycloak, Auth0\u2026).`,{rerun:`${h} signin list`,data:{providers:[...T]}})}async function de(e,s,i,t){let n=await te(e);if(!n)return;let m=await ne(e,{organizationId:n.organization.id,type:i,actor:ee(s),data:{provider:t.id,label:t.label}});m.length>0&&await e.run(m)}var u=e=>`Sign in with ${e.label}`,L=e=>`${se}/${e.setup}`,V=e=>e.status==="incomplete"?"needs setup":e.status;function ce(e){return e==="on"?c.green("on"):e==="needs setup"?c.yellow("needs setup"):c.dim("off")}function q(e,s,i){e.emit({type:"done",message:le(s.join(`
3
+ `)),display:[s[0],...s.slice(1).map(t=>c.dim(t))].join(`
4
+ `),data:i})}var R={clientId:"--client-id",clientSecret:"--client-secret-from-env",issuer:"--issuer",label:"--label",tenant:"--tenant"},oe={clientId:"<client id>",clientSecret:"<VAR>",issuer:"<issuer url>",label:"<button text>",tenant:"<tenant id>"};function pe(e){return{clientId:e["client-id"],issuer:e.issuer,label:e.label,tenant:e.tenant}}var j=e=>/^[\w@%+=:,./-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`;function fe(e,s,i){let t=s.replace(/\s+/g," ").slice(0,80),n=U(e.role),m=e.role==="issuer"?"SIGNIN_ISSUER_INVALID":e.role==="tenant"?"SIGNIN_TENANT_INVALID":"SETTING_VALUE_INVALID";throw new b(m,`${e.name} can't be "${t}"
5
+ ${i}`,{...n?{fix:`use ${n}`}:{},data:{name:e.name}})}function re(e,s){let i=s.trim(),t=F(e.role,i);return t&&fe(e,i,t),i}async function we(e,{canKeep:s,set:i}){let t=U(e.role),n=i?"Set already: Enter keeps it.":s?"Optional: Enter leaves it unset.":null,m=[e.what,...t?[`Takes ${t}`]:[],...n?[n]:[]];return e.plain?(await B(e.name,{context:m,validate:l=>{let a=l.trim();return a?F(e.role,a):s?null:"Enter a value."}})).trim():(await J(`${e.name} (hidden)`,{context:m,optional:s})).trim()}async function he(e,s){let{out:i,flags:t}=e,n=K(s),m=new Set(n.settings.map(o=>o.role)),g=pe(t),l=Object.keys(g).filter(o=>g[o]!==void 0&&!m.has(o)).map(o=>R[o]);if(l.length>0){let o=l.map(r=>r==="--tenant"?"microsoft":"oidc");throw new b("SIGNIN_FLAG_NOT_APPLICABLE",`${p(l)} ${l.length===1?"isn't a setting":"aren't settings"} of ${u(n)}
6
+ ${p(l.map((r,S)=>`${r} is ${o[S]}'s`))}; ${n.id} reads ${p(n.settings.map(r=>r.name))}.`,{fix:`drop ${p(l)}`,data:{provider:n.id,flags:l}})}let a=new Map;for(let o of n.settings){if(o.role==="clientSecret")continue;let r=g[o.role]?.trim();r&&a.set(o.name,re(o,r))}let f=n.settings.find(o=>o.role==="clientSecret"),w=t["client-secret-from-env"]?.trim();if(w){let o=process.env[w]?.trim();if(!o)throw new b("SECRET_EMPTY",`$${w} is empty or not set`,{fix:`export ${w} first, or name another variable with --client-secret-from-env`,data:{name:f.name}});a.set(f.name,o)}let v=await O(e),y=new Set(await E(v.cf)),d=N(v.gatewayUrl,n.id),z=e.interactive??G(t.json??!1),$=n.settings.filter(o=>o.required&&!a.has(o.name)&&!y.has(o.name));if($.length>0&&!z){let o=[`${h} signin add ${n.id}`,...n.settings.flatMap(r=>{if(r.role==="clientSecret")return a.has(r.name)||$.includes(r)?[`${R.clientSecret} ${w||oe.clientSecret}`]:[];let S=a.get(r.name);return S?[`${R[r.role]} ${j(S)}`]:$.includes(r)?[`${R[r.role]} ${oe[r.role]}`]:[]}),...t.gateway?[`--gateway ${j(t.gateway)}`]:[],...t["account-id"]?[`--account-id ${j(t["account-id"])}`]:[],...t.json?["--json"]:[]].join(" ");throw new b("SIGNIN_VALUE_REQUIRED",`${u(n)} needs ${p($.map(r=>r.name))}, and there's no terminal to ask at
7
+ Give ${p($.map(r=>R[r.role]))} (the secret from an environment variable, never the command line), or run this at a terminal.`,{rerun:o,data:{provider:n.id,missing:$.map(r=>r.name),flags:$.map(r=>R[r.role]),callbackUrl:d}})}if(z){X([c.bold(u(n)),`Create the ${n.appNoun} at ${n.console}`,`Register this redirect URL with it: ${c.cyan(d)}`,c.dim(`Guide: ${L(n)}`)].join(`
8
+ `));let o=e.readValue??we;for(let r of n.settings){if(a.has(r.name))continue;let S=y.has(r.name),_=(await o(r,{canKeep:!r.required||S,set:S})).trim();if(_)a.set(r.name,r.plain?re(r,_):_);else if(r.required&&!S)throw new b("SIGNIN_VALUE_REQUIRED",`${u(n)} needs ${r.name}
9
+ Nothing was changed.`,{rerun:`${h} signin add ${n.id}`,data:{provider:n.id,missing:[r.name],flags:[R[r.role]],callbackUrl:d}})}}let H=Object.fromEntries(n.settings.filter(o=>a.has(o.name)).map(o=>[o.name,a.get(o.name)])),I=Object.keys(H),k=n.settings.filter(o=>!a.has(o.name)&&y.has(o.name)).map(o=>o.name),ge=C(n,o=>y.has(o)).status==="on",M=`${v.gatewayUrl}/sign-in`;I.length>0&&(i.emit({type:"step",step:"signin.add",status:"start",message:`Setting ${p(I)} on the Gateway...`}),await D(v,H,{flags:t,out:i}),ge||await de(v.db,v.deployer,"signin_provider.added",n),i.emit({type:"step",step:"signin.add",status:"ok",message:`${u(n)} is on`,data:{id:n.id}}));let ue=[I.length>0?`${u(n)} is on.`:`${u(n)} was on already; nothing changed.`,`Redirect URL (registered with the ${n.appNoun}): ${d}`,...I.length>0?[`Set ${p(I)}${k.length>0?`; kept ${p(k)} as it was`:""}.`]:[],...n.notes,`Sign in at ${M}: "Continue with ${n.label}" is there on the next request, for members and invited addresses.`,`Guide: ${L(n)}`];q(i,ue,{id:n.id,label:n.label,status:"on",changed:I.length>0,set:I,kept:k,callbackUrl:d,signInUrl:M,notes:n.notes,setup:n.setup})}function me(e,s){let i=C(e,t=>s.has(t));return i.status==="incomplete"?i:{...i,missing:[]}}function ve(e){let s=new Set(e);return Q.map(i=>({provider:i,state:me(i,s)}))}async function Se(e){let{out:s}=e,i=await O(e),t=ve(await E(i.cf)),n=x(["PROVIDER","STATUS","SETTINGS"],t.map(({provider:a,state:f})=>{let w=V(f);return[`${a.id} ${c.dim(a.label)}`,ce(w),w==="needs setup"?`${c.yellow("missing")} ${f.missing.join(", ")}`:w==="on"?c.dim(f.set.join(", ")):c.dim("none set")]})),m=t.filter(({state:a})=>a.status==="on").length,g=t.filter(({state:a})=>a.status==="incomplete"),l=`${m} of ${t.length} sign-in providers on`;s.emit({type:"done",message:l,display:[...n,"",c.dim(g.length>0?`A provider that needs setup is off until it has every required setting: ${h} signin add <id>`:`Turn one on: ${h} signin add <id> (${h} signin show <id> says where to make its OAuth app).`)].join(`
10
+ `),data:{providers:t.map(({provider:a,state:f})=>({id:a.id,label:a.label,status:V(f),missing:f.missing,set:f.set,callbackUrl:N(i.gatewayUrl,a.id),setup:a.setup})),signInUrl:`${i.gatewayUrl}/sign-in`,...g.length>0?{next:g.map(({provider:a})=>({command:`${h} signin add ${a.id}`,note:`finish ${u(a)}`}))}:{}}})}async function ye(e,s){let{out:i}=e,t=K(s),n=await O(e),m=new Set(await E(n.cf)),g=me(t,m),l=V(g),a=N(n.gatewayUrl,t.id),f=t.settings.map(d=>({name:d.name,role:d.role,required:d.required,plain:d.plain,what:d.what,set:m.has(d.name)})),w=[{label:"Status",value:ce(l)+(l==="needs setup"?c.dim(` (missing ${p(g.missing)})`):"")},{label:"Console",value:t.console},{label:"Create",value:t.appNoun},{label:"Redirect URL",value:a},{label:"Scopes",value:t.scopes.join(" ")},{label:"Email",value:t.emailClaim},{label:"Guide",value:L(t)}],v=x(["SETTING","","SET","WHAT IT HOLDS"],f.map(d=>[d.name,c.dim(d.required?"required":"optional"),d.set?c.green("set"):d.required?c.yellow("not set"):c.dim("not set"),c.dim(d.what)])),y=`${u(t)} (${t.id})`;i.emit({type:"done",message:le([y,...A(w)].join(`
11
+ `)),display:[c.bold(y),...A(w),"",...v,...t.notes.length>0?["",...t.notes.map(d=>c.dim(`\xB7 ${d}`))]:[]].join(`
12
+ `),data:{id:t.id,label:t.label,status:l,missing:g.missing,set:g.set,console:t.console,appNoun:t.appNoun,callbackUrl:a,scopes:t.scopes,emailClaim:t.emailClaim,settings:f,notes:t.notes,setup:t.setup,...l!=="on"?{next:[{command:`${h} signin add ${t.id}`,note:`turn ${u(t)} on`}]}:{}}})}async function $e(e,s){let{out:i,flags:t}=e,n=K(s),m=await O(e),g=new Set(await E(m.cf)),l=n.settings.filter(a=>g.has(a.name)).map(a=>a.name);if(l.length===0){q(i,[`${u(n)} isn't set up; nothing changed.`],{id:n.id,removed:[]});return}await Z({yes:t.yes,interactive:e.interactive??G(t.json??!1),confirm:e.confirm,question:`Turn ${u(n)} off?`,unattended:`Turning ${u(n)} off needs confirmation at a terminal, or --yes`,context:[`Removes ${p(l)} from the Gateway: the button leaves the sign-in page on the next request.`,"People who signed in with it keep their accounts and sign in another way."],cancelled:`Cancelled. ${u(n)} stays as it was.`,data:{provider:n.id,names:l}}),i.emit({type:"step",step:"signin.remove",status:"start",message:`Removing ${p(l)} from the Gateway...`}),await D(m,Object.fromEntries(l.map(a=>[a,null])),{flags:t,out:i}),C(n,a=>g.has(a)).status==="on"&&await de(m.db,m.deployer,"signin_provider.removed",n),i.emit({type:"step",step:"signin.remove",status:"ok",message:`${u(n)} is off`,data:{id:n.id}}),q(i,[`${u(n)} is off.`,`Removed ${p(l)}.`,"People who signed in with it keep their accounts: they sign in with a password (Forgot password sets one), another provider or Cloudflare Access.",`Delete the ${n.appNoun} at ${n.console} too: a client the Gateway no longer holds is still a client.`],{id:n.id,removed:l})}export{Ue as add,he as addProvider,De as list,Se as listProviders,Le as remove,$e as removeProvider,je as show,ye as showProvider};