ripplo 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -315,7 +315,7 @@ ${t.join(`
315
315
  }
316
316
  }
317
317
  }
318
- `)});import{Box as ew,Text as Bo}from"ink";import{jsx as Hc,jsxs as Mc}from"react/jsx-runtime";function Jc({activeRunCount:e,browsersReady:t,maxConcurrency:n}){return Mc(ew,{paddingX:1,children:[Hc(Bo,{dimColor:!0,children:"Activity "}),Mc(Bo,{children:[String(e),"/",String(n)," running \xB7 browsers"," "]}),Hc(Bo,{color:t?"green":"yellow",children:t?"ready":"warming"})]})}var zc=f(()=>{"use strict"});import{Box as tw,Text as In}from"ink";import{jsx as _n,jsxs as rw}from"react/jsx-runtime";function Xc({check:e}){let{detail:t,label:n,tone:r}=On(e),o=nw[r];return rw(tw,{children:[_n(In,{color:o,children:r==="info"?"\u25CB":"\u25CF"}),_n(In,{children:" "}),_n(In,{children:n.padEnd(18," ")}),_n(In,{color:o,children:t})]})}var nw,Gc=f(()=>{"use strict";jo();nw={error:"red",info:"gray",ok:"green",warn:"yellow"}});import{Box as ow,Text as Kc}from"ink";import{jsx as Vo,jsxs as iw}from"react/jsx-runtime";function Qc({checks:e}){return iw(ow,{borderColor:"gray",borderStyle:"round",flexDirection:"column",marginTop:1,paddingX:1,children:[Vo(Kc,{bold:!0,children:"Health"}),e.length===0?Vo(Kc,{dimColor:!0,children:"Running first pass..."}):e.map(t=>Vo(Xc,{check:t},t.type))]})}var Yc=f(()=>{"use strict";Gc()});import{Box as Un,Text as yt}from"ink";import{jsx as gt,jsxs as jn}from"react/jsx-runtime";function Zc({appUrl:e,developerUrl:t,projectName:n}){return jn(Un,{borderColor:"gray",borderStyle:"round",flexDirection:"column",paddingX:1,children:[jn(Un,{children:[gt(yt,{dimColor:!0,children:"Project "}),gt(yt,{bold:!0,children:n})]}),jn(Un,{children:[gt(yt,{dimColor:!0,children:"App "}),gt(yt,{color:"cyan",children:e})]}),jn(Un,{children:[gt(yt,{dimColor:!0,children:"Dashboard "}),gt(yt,{color:"cyan",children:t})]})]})}var ed=f(()=>{"use strict"});import{Box as Wo,Text as qe}from"ink";import{jsx as Fe,jsxs as qo}from"react/jsx-runtime";function td({paused:e,scope:t}){return qo(Wo,{borderColor:"gray",borderStyle:"round",flexDirection:"column",marginTop:1,paddingX:1,children:[qo(Wo,{children:[Fe(qe,{bold:!0,children:"Scope"}),Fe(qe,{dimColor:!0,children:` (${String(t.length)})`}),Fe(qe,{children:" "}),Fe(qe,{dimColor:!0,children:"Hooks "}),Fe(qe,{color:e?"yellow":"green",children:e?"paused":"active"})]}),t.length===0?Fe(qe,{dimColor:!0,children:"no scope items \u2014 add from the dashboard or `ripplo scope add`"}):t.map(n=>qo(Wo,{children:[Fe(qe,{color:"cyan",children:"\u2022 "}),Fe(qe,{children:n.label})]},n.id))]})}var nd=f(()=>{"use strict"});import{Box as aw,Text as rd}from"ink";import{jsx as sw,jsxs as od}from"react/jsx-runtime";function id({preconditions:e,workflows:t}){let n=t?.type==="workflows"?t.total:0,r=t?.type==="workflows"?t.invalidNames.length:0,o=e?.type==="preconditions"?e.count:0;return od(aw,{marginTop:1,paddingX:1,children:[sw(rd,{dimColor:!0,children:"Workflows "}),od(rd,{children:[String(n)," tests \xB7 ",String(o)," preconditions",r>0?` \xB7 ${String(r)} invalid`:""]})]})}var ad=f(()=>{"use strict"});import tI from"chalk";import{z as sd}from"zod";async function ld(){let e=new AbortController,t=setTimeout(()=>{e.abort()},3e3);try{let n=await fetch(`https://registry.npmjs.org/${lw}/latest`,{headers:{accept:"application/json"},signal:e.signal});if(!n.ok)return;let r=await n.json();return cw.parse(r).version}catch{return}finally{clearTimeout(t)}}var Fo,lw,cw,cd=f(()=>{"use strict";G();Fo="0.3.2",lw="ripplo",cw=sd.object({version:sd.string()})});import{useEffect as dw,useState as pw}from"react";import{Text as Ye}from"ink";import{jsx as ht,jsxs as yw}from"react/jsx-runtime";function dd({activeRunCount:e,browsersReady:t,connected:n,projectId:r,ripploServerUrl:o,syncError:i,width:a}){let s=fw(),l=s!=null&&s!==Fo,c=uw({connected:n,syncError:i}),d=t?"":" warming up browsers...",u=e>0?` ${String(e)} running`:"",p=`v${Fo}`,m=l?` \u2192 v${s}`:"",h=`project ${r} \xB7 q to quit`,S=` ripplo ${p}${m} | ${o} ${c}${d}${u}`,w=Math.max(0,a-S.length-h.length-1);return yw(Ye,{inverse:!0,children:[ht(Ye,{bold:!0,children:" ripplo "}),ht(Ye,{dimColor:!0,children:p}),l?ht(Ye,{color:"yellow",children:` \u2192 v${s}`}):null,` | ${o} `,ht(Ye,{color:mw({connected:n,syncError:i}),children:c}),t?null:ht(Ye,{color:"yellow",children:d}),u," ".repeat(w),ht(Ye,{dimColor:!0,children:h})," "]})}function uw({connected:e,syncError:t}){return t!=null?"sync failed":e?"connected":"connecting..."}function mw({connected:e,syncError:t}){return t!=null?"red":e?"green":"yellow"}function fw(){let[e,t]=pw();return dw(()=>{ld().then(n=>{n!=null&&t(n)})},[]),e}var pd=f(()=>{"use strict";cd()});import{useEffect as gw}from"react";import{availableParallelism as hw}from"os";import{Box as Ho,Text as kw,useApp as Sw,useInput as ww}from"ink";import{jsx as He,jsxs as ud}from"react/jsx-runtime";function md({config:e,cwd:t}){let n=Sw(),{height:r,width:o}=ft(),{config:i,devSessionId:a,syncError:s}=xc({config:e,cwd:t}),{activeRunCount:l,browsersReady:c,connected:d}=sc({config:i,cwd:t,devSessionId:a}),{checks:u}=Ic({config:i,cwd:t}),{paused:p,projectName:m,scope:h}=qc({projectId:e.projectId});$c({cwd:t,projectId:e.projectId}),gw(()=>_l(t),[t]),ww(T=>{T==="q"&&n.exit()});let S=`${i.ripploServerUrl}/projects/${i.projectId}/developer`,w=u.filter(T=>bw.has(T.type)),k=u.find(T=>T.type==="workflows"),b=u.find(T=>T.type==="preconditions"),v=hw(),L=m??"\u2026";return ud(Ho,{flexDirection:"column",height:r,width:o,children:[He(dd,{activeRunCount:l,browsersReady:c,connected:d,projectId:i.projectId,ripploServerUrl:i.ripploServerUrl,syncError:s,width:o}),ud(Ho,{flexDirection:"column",flexGrow:1,paddingX:1,paddingY:1,children:[He(Zc,{appUrl:i.appUrl,developerUrl:S,projectName:L}),He(td,{paused:p,scope:h}),He(Qc,{checks:w}),He(id,{preconditions:b,workflows:k}),He(Jc,{activeRunCount:l,browsersReady:c,maxConcurrency:v}),He(Ho,{marginTop:1,paddingX:1,children:He(kw,{dimColor:!0,children:"q quit"})})]})]})}var bw,fd=f(()=>{"use strict";bo();En();Pc();_c();Dc();Fc();Lo();zc();Yc();ed();nd();ad();pd();bw=new Set(["dev-server","preconditions","adapter-enabled","webhook-verification","lockfile","pre-commit-hook","browser"])});import{Text as yd}from"ink";import Aw from"ink-spinner";import{jsx as gd,jsxs as Tw}from"react/jsx-runtime";function hd({loading:e}){return e?Tw(yd,{color:Rw,children:[gd(Aw,{type:"dots"})," Starting..."]}):gd(yd,{children:""})}var Rw,kd=f(()=>{"use strict";Rw="#24CFFF"});import{useEffect as vw,useState as $t}from"react";import{Box as Ze,Text as Mo,useInput as Nw}from"ink";import{jsx as Me,jsxs as Jo}from"react/jsx-runtime";function wd({onDismiss:e}){let{height:t,width:n}=ft(),[r,o]=$t(0),[i,a]=$t(!1),[s,l]=$t(!1),[c,d]=$t(!1),[u,p]=$t(!1);Nw(()=>{u&&e()}),vw(()=>{let S=80+$n.length*70+80,w=[...$n.map((k,b)=>setTimeout(()=>{o(b+1)},80+b*70)),setTimeout(()=>{a(!0)},S),setTimeout(()=>{l(!0)},S+200),setTimeout(()=>{d(!0)},S+400),setTimeout(()=>{d(!1),p(!0)},S+2e3),setTimeout(()=>{e()},S+2800)];return()=>{w.forEach(k=>{clearTimeout(k)})}},[e]);let m=$n.length+5,h=Math.max(0,Math.floor((t-m)/2));return Jo(Ze,{flexDirection:"column",height:t,width:n,children:[Me(Ze,{height:h}),Jo(Ze,{alignItems:"flex-start",flexDirection:"row",justifyContent:"center",children:[Me(Ze,{flexDirection:"column",children:$n.map((S,w)=>Me(Mo,{color:Sd,children:w<r?S:""},S))}),Jo(Ze,{flexDirection:"column",paddingLeft:4,paddingTop:5,children:[Me(Mo,{bold:!0,color:Sd,children:i?Cw:""}),Me(Ze,{marginTop:1,children:Me(Mo,{color:"gray",dimColor:!0,children:s?"developer CLI":""})}),Me(Ze,{marginTop:2,children:Me(hd,{loading:c})})]})]})]})}var $n,Sd,Cw,bd=f(()=>{"use strict";En();kd();$n=[" XXXX XXXXXXX "," XX XX X X "," XXX XX XX X X ","XXXXXX XX XX XXXXXXX ","XX XXX XX XX ","XX XXX XX XXXXXXXX "," XX XX XX XX "," XX XX XX XX "," XX XXXXX XX"," XX XX XX XX"," XX XX XXXX "," XXX XX "," XXXXXXXXX XX "," XXX XX "," XXXXXXX "],Sd="#24CFFF",Cw="ripplo"});import{createAuthClient as Lw}from"better-auth/client";import{deviceAuthorizationClient as xw}from"better-auth/client/plugins";function Dn({baseURL:e}){return Lw({baseURL:e,fetchOptions:{headers:{"User-Agent":"Ripplo CLI"}},plugins:[xw()]})}var zo=f(()=>{"use strict"});import{exec as Pw}from"child_process";async function Rd({cwd:e,onDeviceCode:t,url:n}){let r=n??Ot().RIPPLO_SERVER_URL,o=Dn({baseURL:r}),i=await o.device.code({client_id:Ad});if(i.error!=null)throw new Error(`Failed to request device code: ${i.error.error_description}`);let{device_code:a,user_code:s,verification_uri_complete:l}=i.data;t({userCode:s,verificationUrl:l}),$w(l);let c=await Ow({authClient:o,deviceCode:a});return Br(e,c),c}async function Ow({authClient:e,deviceCode:t}){for(;;){await Uw(Ew);let n=await e.device.token({client_id:Ad,device_code:t,grant_type:"urn:ietf:params:oauth:grant-type:device_code"});if(n.data?.access_token!=null)return n.data.access_token;if(n.error==null)continue;if(!_w(n.error.error))throw new Error(`Authorization failed: ${n.error.error_description}`)}}function _w(e){return Iw.has(e)}function Uw(e){return new Promise(t=>{setTimeout(t,e)})}function jw(){return process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open"}function $w(e){let t=jw();Pw(`${t} "${e}"`,()=>{})}var Ew,Ad,Iw,Td=f(()=>{"use strict";G();zo();dt();Ew=5e3,Ad="ripplo-cli";Iw=new Set(["authorization_pending","slow_down"])});import{useCallback as Bn,useEffect as Dw,useState as Je}from"react";import{exec as Bw}from"child_process";import{promisify as Vw}from"util";import J from"fs";import M from"path";function Nd({cwd:e,initialToken:t,serverUrl:n}){let[r,o]=Je(t==null?"login":"validating"),[i,a]=Je(),[s,l]=Je(),[c,d]=Je(t),[u,p]=Je(!1),[m,h]=Je(),[S,w]=Je(),[k,b]=Je([]);Dw(()=>{if(t==null)return;Dn({baseURL:n}).getSession({fetchOptions:{headers:{Authorization:`Bearer ${t}`}}}).then(C=>{if(C.data==null){o("login");return}return Xo({cwd:e,serverUrl:n,token:t})}).then(C=>{if(C==null){o("select-project");return}a(C),o("complete")}).catch(C=>{l(C instanceof Error?C.message:String(C)),o("login")})},[e,t,n]);let v=Bn(()=>{u||(p(!0),l(void 0),Rd({cwd:e,onDeviceCode:h,url:n}).then(O=>(d(O),Xo({cwd:e,serverUrl:n,token:O}))).then(O=>{O==null?o("select-project"):(a(O),o("complete"))}).catch(O=>{p(!1),h(void 0),l(O instanceof Error?O.message:String(O))}))},[e,u,n]),L=Bn(O=>{let C=i?.token??c??t;if(C==null){l("No authentication token available");return}o("scaffolding"),l(void 0),Hw({cwd:e,onStep:w,projectId:O.id}).then(async V=>{b(V);let ze=await Xo({cwd:e,serverUrl:n,token:C});a(ze??Ww({projectId:O.id,serverUrl:n,token:C})),o(V.length>0?"scaffolding-warnings":"complete")}).catch(V=>{l(V instanceof Error?V.message:String(V)),o("select-project")})},[i,e,t,n,c]),T=Bn(()=>{o("complete")},[]),I=Bn(()=>{a(void 0),o("login"),p(!1),h(void 0),l(void 0)},[]);return{config:i,deviceCodeInfo:m,dismissScaffoldWarnings:T,error:s,loginStarted:u,resetToLogin:I,scaffoldingStep:S,scaffoldWarnings:k,selectProject:L,setStage:o,stage:r,startLogin:v,token:c}}function Ww({projectId:e,serverUrl:t,token:n}){return{appUrl:"",engineUrl:"",projectId:e,ripploServerUrl:t,token:n,webhookSecret:""}}async function Xo({cwd:e,serverUrl:t,token:n}){let r=await _(e);if(r.ok)return{...r.result.config,ripploServerUrl:t,token:n}}async function Hw({cwd:e,onStep:t,projectId:n}){t("Scaffolding project files..."),Zw({cwd:e,projectId:n}),t("Updating .gitignore..."),lb(e),t("Marking ripplo.lock as generated..."),Xw(e),t("Installing dependencies...");let r=await Mw(e),o=[];if(r.ok||o.push({manualCommand:r.cmd,message:`Couldn't auto-install dev dependencies (${r.reason}). Run this manually, then re-run \`npx ripplo\`.`}),r.ok){t("Compiling initial lockfile...");let i=await Jw(e);i!=null&&o.push({manualCommand:void 0,message:i})}return t("Setting up browser..."),await br(),o}async function Mw(e){let t=Gw({cwd:e,pm:Yw(e)});A.info("Installing dependencies: %s",t);try{return await Fw(t,{cwd:e}),{ok:!0}}catch(n){let r=n instanceof Error?n.message.split(`
318
+ `)});import{Box as ew,Text as Bo}from"ink";import{jsx as Hc,jsxs as Mc}from"react/jsx-runtime";function Jc({activeRunCount:e,browsersReady:t,maxConcurrency:n}){return Mc(ew,{paddingX:1,children:[Hc(Bo,{dimColor:!0,children:"Activity "}),Mc(Bo,{children:[String(e),"/",String(n)," running \xB7 browsers"," "]}),Hc(Bo,{color:t?"green":"yellow",children:t?"ready":"warming"})]})}var zc=f(()=>{"use strict"});import{Box as tw,Text as In}from"ink";import{jsx as _n,jsxs as rw}from"react/jsx-runtime";function Xc({check:e}){let{detail:t,label:n,tone:r}=On(e),o=nw[r];return rw(tw,{children:[_n(In,{color:o,children:r==="info"?"\u25CB":"\u25CF"}),_n(In,{children:" "}),_n(In,{children:n.padEnd(18," ")}),_n(In,{color:o,children:t})]})}var nw,Gc=f(()=>{"use strict";jo();nw={error:"red",info:"gray",ok:"green",warn:"yellow"}});import{Box as ow,Text as Kc}from"ink";import{jsx as Vo,jsxs as iw}from"react/jsx-runtime";function Qc({checks:e}){return iw(ow,{borderColor:"gray",borderStyle:"round",flexDirection:"column",marginTop:1,paddingX:1,children:[Vo(Kc,{bold:!0,children:"Health"}),e.length===0?Vo(Kc,{dimColor:!0,children:"Running first pass..."}):e.map(t=>Vo(Xc,{check:t},t.type))]})}var Yc=f(()=>{"use strict";Gc()});import{Box as Un,Text as yt}from"ink";import{jsx as gt,jsxs as jn}from"react/jsx-runtime";function Zc({appUrl:e,developerUrl:t,projectName:n}){return jn(Un,{borderColor:"gray",borderStyle:"round",flexDirection:"column",paddingX:1,children:[jn(Un,{children:[gt(yt,{dimColor:!0,children:"Project "}),gt(yt,{bold:!0,children:n})]}),jn(Un,{children:[gt(yt,{dimColor:!0,children:"App "}),gt(yt,{color:"cyan",children:e})]}),jn(Un,{children:[gt(yt,{dimColor:!0,children:"Dashboard "}),gt(yt,{color:"cyan",children:t})]})]})}var ed=f(()=>{"use strict"});import{Box as Wo,Text as qe}from"ink";import{jsx as Fe,jsxs as qo}from"react/jsx-runtime";function td({paused:e,scope:t}){return qo(Wo,{borderColor:"gray",borderStyle:"round",flexDirection:"column",marginTop:1,paddingX:1,children:[qo(Wo,{children:[Fe(qe,{bold:!0,children:"Scope"}),Fe(qe,{dimColor:!0,children:` (${String(t.length)})`}),Fe(qe,{children:" "}),Fe(qe,{dimColor:!0,children:"Hooks "}),Fe(qe,{color:e?"yellow":"green",children:e?"paused":"active"})]}),t.length===0?Fe(qe,{dimColor:!0,children:"no scope items \u2014 add from the dashboard or `ripplo scope add`"}):t.map(n=>qo(Wo,{children:[Fe(qe,{color:"cyan",children:"\u2022 "}),Fe(qe,{children:n.label})]},n.id))]})}var nd=f(()=>{"use strict"});import{Box as aw,Text as rd}from"ink";import{jsx as sw,jsxs as od}from"react/jsx-runtime";function id({preconditions:e,workflows:t}){let n=t?.type==="workflows"?t.total:0,r=t?.type==="workflows"?t.invalidNames.length:0,o=e?.type==="preconditions"?e.count:0;return od(aw,{marginTop:1,paddingX:1,children:[sw(rd,{dimColor:!0,children:"Workflows "}),od(rd,{children:[String(n)," tests \xB7 ",String(o)," preconditions",r>0?` \xB7 ${String(r)} invalid`:""]})]})}var ad=f(()=>{"use strict"});import tI from"chalk";import{z as sd}from"zod";async function ld(){let e=new AbortController,t=setTimeout(()=>{e.abort()},3e3);try{let n=await fetch(`https://registry.npmjs.org/${lw}/latest`,{headers:{accept:"application/json"},signal:e.signal});if(!n.ok)return;let r=await n.json();return cw.parse(r).version}catch{return}finally{clearTimeout(t)}}var Fo,lw,cw,cd=f(()=>{"use strict";G();Fo="0.3.4",lw="ripplo",cw=sd.object({version:sd.string()})});import{useEffect as dw,useState as pw}from"react";import{Text as Ye}from"ink";import{jsx as ht,jsxs as yw}from"react/jsx-runtime";function dd({activeRunCount:e,browsersReady:t,connected:n,projectId:r,ripploServerUrl:o,syncError:i,width:a}){let s=fw(),l=s!=null&&s!==Fo,c=uw({connected:n,syncError:i}),d=t?"":" warming up browsers...",u=e>0?` ${String(e)} running`:"",p=`v${Fo}`,m=l?` \u2192 v${s}`:"",h=`project ${r} \xB7 q to quit`,S=` ripplo ${p}${m} | ${o} ${c}${d}${u}`,w=Math.max(0,a-S.length-h.length-1);return yw(Ye,{inverse:!0,children:[ht(Ye,{bold:!0,children:" ripplo "}),ht(Ye,{dimColor:!0,children:p}),l?ht(Ye,{color:"yellow",children:` \u2192 v${s}`}):null,` | ${o} `,ht(Ye,{color:mw({connected:n,syncError:i}),children:c}),t?null:ht(Ye,{color:"yellow",children:d}),u," ".repeat(w),ht(Ye,{dimColor:!0,children:h})," "]})}function uw({connected:e,syncError:t}){return t!=null?"sync failed":e?"connected":"connecting..."}function mw({connected:e,syncError:t}){return t!=null?"red":e?"green":"yellow"}function fw(){let[e,t]=pw();return dw(()=>{ld().then(n=>{n!=null&&t(n)})},[]),e}var pd=f(()=>{"use strict";cd()});import{useEffect as gw}from"react";import{availableParallelism as hw}from"os";import{Box as Ho,Text as kw,useApp as Sw,useInput as ww}from"ink";import{jsx as He,jsxs as ud}from"react/jsx-runtime";function md({config:e,cwd:t}){let n=Sw(),{height:r,width:o}=ft(),{config:i,devSessionId:a,syncError:s}=xc({config:e,cwd:t}),{activeRunCount:l,browsersReady:c,connected:d}=sc({config:i,cwd:t,devSessionId:a}),{checks:u}=Ic({config:i,cwd:t}),{paused:p,projectName:m,scope:h}=qc({projectId:e.projectId});$c({cwd:t,projectId:e.projectId}),gw(()=>_l(t),[t]),ww(T=>{T==="q"&&n.exit()});let S=`${i.ripploServerUrl}/projects/${i.projectId}/developer`,w=u.filter(T=>bw.has(T.type)),k=u.find(T=>T.type==="workflows"),b=u.find(T=>T.type==="preconditions"),v=hw(),L=m??"\u2026";return ud(Ho,{flexDirection:"column",height:r,width:o,children:[He(dd,{activeRunCount:l,browsersReady:c,connected:d,projectId:i.projectId,ripploServerUrl:i.ripploServerUrl,syncError:s,width:o}),ud(Ho,{flexDirection:"column",flexGrow:1,paddingX:1,paddingY:1,children:[He(Zc,{appUrl:i.appUrl,developerUrl:S,projectName:L}),He(td,{paused:p,scope:h}),He(Qc,{checks:w}),He(id,{preconditions:b,workflows:k}),He(Jc,{activeRunCount:l,browsersReady:c,maxConcurrency:v}),He(Ho,{marginTop:1,paddingX:1,children:He(kw,{dimColor:!0,children:"q quit"})})]})]})}var bw,fd=f(()=>{"use strict";bo();En();Pc();_c();Dc();Fc();Lo();zc();Yc();ed();nd();ad();pd();bw=new Set(["dev-server","preconditions","adapter-enabled","webhook-verification","lockfile","pre-commit-hook","browser"])});import{Text as yd}from"ink";import Aw from"ink-spinner";import{jsx as gd,jsxs as Tw}from"react/jsx-runtime";function hd({loading:e}){return e?Tw(yd,{color:Rw,children:[gd(Aw,{type:"dots"})," Starting..."]}):gd(yd,{children:""})}var Rw,kd=f(()=>{"use strict";Rw="#24CFFF"});import{useEffect as vw,useState as $t}from"react";import{Box as Ze,Text as Mo,useInput as Nw}from"ink";import{jsx as Me,jsxs as Jo}from"react/jsx-runtime";function wd({onDismiss:e}){let{height:t,width:n}=ft(),[r,o]=$t(0),[i,a]=$t(!1),[s,l]=$t(!1),[c,d]=$t(!1),[u,p]=$t(!1);Nw(()=>{u&&e()}),vw(()=>{let S=80+$n.length*70+80,w=[...$n.map((k,b)=>setTimeout(()=>{o(b+1)},80+b*70)),setTimeout(()=>{a(!0)},S),setTimeout(()=>{l(!0)},S+200),setTimeout(()=>{d(!0)},S+400),setTimeout(()=>{d(!1),p(!0)},S+2e3),setTimeout(()=>{e()},S+2800)];return()=>{w.forEach(k=>{clearTimeout(k)})}},[e]);let m=$n.length+5,h=Math.max(0,Math.floor((t-m)/2));return Jo(Ze,{flexDirection:"column",height:t,width:n,children:[Me(Ze,{height:h}),Jo(Ze,{alignItems:"flex-start",flexDirection:"row",justifyContent:"center",children:[Me(Ze,{flexDirection:"column",children:$n.map((S,w)=>Me(Mo,{color:Sd,children:w<r?S:""},S))}),Jo(Ze,{flexDirection:"column",paddingLeft:4,paddingTop:5,children:[Me(Mo,{bold:!0,color:Sd,children:i?Cw:""}),Me(Ze,{marginTop:1,children:Me(Mo,{color:"gray",dimColor:!0,children:s?"developer CLI":""})}),Me(Ze,{marginTop:2,children:Me(hd,{loading:c})})]})]})]})}var $n,Sd,Cw,bd=f(()=>{"use strict";En();kd();$n=[" XXXX XXXXXXX "," XX XX X X "," XXX XX XX X X ","XXXXXX XX XX XXXXXXX ","XX XXX XX XX ","XX XXX XX XXXXXXXX "," XX XX XX XX "," XX XX XX XX "," XX XXXXX XX"," XX XX XX XX"," XX XX XXXX "," XXX XX "," XXXXXXXXX XX "," XXX XX "," XXXXXXX "],Sd="#24CFFF",Cw="ripplo"});import{createAuthClient as Lw}from"better-auth/client";import{deviceAuthorizationClient as xw}from"better-auth/client/plugins";function Dn({baseURL:e}){return Lw({baseURL:e,fetchOptions:{headers:{"User-Agent":"Ripplo CLI"}},plugins:[xw()]})}var zo=f(()=>{"use strict"});import{exec as Pw}from"child_process";async function Rd({cwd:e,onDeviceCode:t,url:n}){let r=n??Ot().RIPPLO_SERVER_URL,o=Dn({baseURL:r}),i=await o.device.code({client_id:Ad});if(i.error!=null)throw new Error(`Failed to request device code: ${i.error.error_description}`);let{device_code:a,user_code:s,verification_uri_complete:l}=i.data;t({userCode:s,verificationUrl:l}),$w(l);let c=await Ow({authClient:o,deviceCode:a});return Br(e,c),c}async function Ow({authClient:e,deviceCode:t}){for(;;){await Uw(Ew);let n=await e.device.token({client_id:Ad,device_code:t,grant_type:"urn:ietf:params:oauth:grant-type:device_code"});if(n.data?.access_token!=null)return n.data.access_token;if(n.error==null)continue;if(!_w(n.error.error))throw new Error(`Authorization failed: ${n.error.error_description}`)}}function _w(e){return Iw.has(e)}function Uw(e){return new Promise(t=>{setTimeout(t,e)})}function jw(){return process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open"}function $w(e){let t=jw();Pw(`${t} "${e}"`,()=>{})}var Ew,Ad,Iw,Td=f(()=>{"use strict";G();zo();dt();Ew=5e3,Ad="ripplo-cli";Iw=new Set(["authorization_pending","slow_down"])});import{useCallback as Bn,useEffect as Dw,useState as Je}from"react";import{exec as Bw}from"child_process";import{promisify as Vw}from"util";import J from"fs";import M from"path";function Nd({cwd:e,initialToken:t,serverUrl:n}){let[r,o]=Je(t==null?"login":"validating"),[i,a]=Je(),[s,l]=Je(),[c,d]=Je(t),[u,p]=Je(!1),[m,h]=Je(),[S,w]=Je(),[k,b]=Je([]);Dw(()=>{if(t==null)return;Dn({baseURL:n}).getSession({fetchOptions:{headers:{Authorization:`Bearer ${t}`}}}).then(C=>{if(C.data==null){o("login");return}return Xo({cwd:e,serverUrl:n,token:t})}).then(C=>{if(C==null){o("select-project");return}a(C),o("complete")}).catch(C=>{l(C instanceof Error?C.message:String(C)),o("login")})},[e,t,n]);let v=Bn(()=>{u||(p(!0),l(void 0),Rd({cwd:e,onDeviceCode:h,url:n}).then(O=>(d(O),Xo({cwd:e,serverUrl:n,token:O}))).then(O=>{O==null?o("select-project"):(a(O),o("complete"))}).catch(O=>{p(!1),h(void 0),l(O instanceof Error?O.message:String(O))}))},[e,u,n]),L=Bn(O=>{let C=i?.token??c??t;if(C==null){l("No authentication token available");return}o("scaffolding"),l(void 0),Hw({cwd:e,onStep:w,projectId:O.id}).then(async V=>{b(V);let ze=await Xo({cwd:e,serverUrl:n,token:C});a(ze??Ww({projectId:O.id,serverUrl:n,token:C})),o(V.length>0?"scaffolding-warnings":"complete")}).catch(V=>{l(V instanceof Error?V.message:String(V)),o("select-project")})},[i,e,t,n,c]),T=Bn(()=>{o("complete")},[]),I=Bn(()=>{a(void 0),o("login"),p(!1),h(void 0),l(void 0)},[]);return{config:i,deviceCodeInfo:m,dismissScaffoldWarnings:T,error:s,loginStarted:u,resetToLogin:I,scaffoldingStep:S,scaffoldWarnings:k,selectProject:L,setStage:o,stage:r,startLogin:v,token:c}}function Ww({projectId:e,serverUrl:t,token:n}){return{appUrl:"",engineUrl:"",projectId:e,ripploServerUrl:t,token:n,webhookSecret:""}}async function Xo({cwd:e,serverUrl:t,token:n}){let r=await _(e);if(r.ok)return{...r.result.config,ripploServerUrl:t,token:n}}async function Hw({cwd:e,onStep:t,projectId:n}){t("Scaffolding project files..."),Zw({cwd:e,projectId:n}),t("Updating .gitignore..."),lb(e),t("Marking ripplo.lock as generated..."),Xw(e),t("Installing dependencies...");let r=await Mw(e),o=[];if(r.ok||o.push({manualCommand:r.cmd,message:`Couldn't auto-install dev dependencies (${r.reason}). Run this manually, then re-run \`npx ripplo\`.`}),r.ok){t("Compiling initial lockfile...");let i=await Jw(e);i!=null&&o.push({manualCommand:void 0,message:i})}return t("Setting up browser..."),await br(),o}async function Mw(e){let t=Gw({cwd:e,pm:Yw(e)});A.info("Installing dependencies: %s",t);try{return await Fw(t,{cwd:e}),{ok:!0}}catch(n){let r=n instanceof Error?n.message.split(`
319
319
  `)[0]??n.message:String(n);return A.warn("Install failed (%s): %s",t,r),{cmd:t,ok:!1,reason:r}}}async function Jw(e){try{await zw(e);return}catch(t){let n=t instanceof Error?t.message:String(t);return A.warn("Initial lockfile compile failed: %s",n),`Couldn't compile initial lockfile: ${n}. You can run \`npx ripplo\` again after fixing the DSL.`}}async function zw(e){let t=await _(e);if(!t.ok){A.warn("Initial compile failed, skipping lockfile write: %s",t.error);return}await me({cwd:e,result:t.result})}function Xw(e){let t=M.join(e,".gitattributes"),n=J.existsSync(t)?J.readFileSync(t,"utf8"):"";if(n.includes(vd))return;let r=n.length===0||n.endsWith(`
320
320
  `)?"":`
321
321
  `;J.writeFileSync(t,`${n}${r}${vd}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ripplo",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "CLI for Ripplo — AI-powered end-to-end testing",
5
5
  "type": "module",
6
6
  "homepage": "https://ripplo.ai",
@@ -57,9 +57,9 @@
57
57
  "typescript": "catalog:",
58
58
  "@ripplo/eslint-config": "0.0.0",
59
59
  "@ripplo/graphql": "^0.0.0",
60
+ "@ripplo/spec": "^0.0.0",
60
61
  "@ripplo/runtime": "^0.0.0",
61
- "@ripplo/testing": "^0.2.0",
62
- "@ripplo/spec": "^0.0.0"
62
+ "@ripplo/testing": "^0.3.1"
63
63
  },
64
64
  "scripts": {
65
65
  "dev": "tsx watch src/index.ts",