@kizenapps/cli 1.10.0-0a9fae5 → 1.10.0-a7e2e79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -15
- package/dist/THIRD-PARTY-NOTICES.txt +4342 -0
- package/dist/index.js +329 -32
- package/dist/index.js.map +1 -1
- package/dist/viewer/assets/AppDetailPage-D9xr-bY8.js +1 -0
- package/dist/viewer/assets/CodeStepsPage-D_kTMpRO.js +1 -0
- package/dist/viewer/assets/{ConfigurationPage-XUysfO8v.js → ConfigurationPage-5qOX-sx0.js} +1 -1
- package/dist/viewer/assets/IconReferencePage-BxPfyqlV.js +1 -0
- package/dist/viewer/assets/SandboxPage-DuCHX1FY.js +1 -0
- package/dist/viewer/assets/{SecretsPage-BwDfBKbY.js → SecretsPage-Da55-e_S.js} +1 -1
- package/dist/viewer/assets/{SourceBrowserPage-D9z0jLNw.js → SourceBrowserPage-DluS8U4q.js} +1 -1
- package/dist/viewer/assets/blockDimensions-BhWxVVcK.js +1 -0
- package/dist/viewer/assets/{index-C570aZ49.js → index-BF1Fk_v0.js} +2 -2
- package/dist/viewer/assets/index-MRuQEa3q.css +2 -0
- package/dist/viewer/assets/{useCompleteSetup-3RGdCYrc.js → useCompleteSetup-DUHoBgca.js} +1 -1
- package/dist/viewer/assets/{usePluginConfig-XFnehL_S.js → usePluginConfig-C8d13THZ.js} +1 -1
- package/dist/viewer/assets/validIcons-D8mhuO5s.js +1 -0
- package/dist/viewer/index.html +2 -2
- package/package.json +27 -8
- package/dist/viewer/assets/AppDetailPage-CKDgNuvS.js +0 -1
- package/dist/viewer/assets/CodeStepsPage-BjnqiAQX.js +0 -1
- package/dist/viewer/assets/IconReferencePage-CN9Tha2W.js +0 -1
- package/dist/viewer/assets/SandboxPage-DbMklAzy.js +0 -1
- package/dist/viewer/assets/blockDimensions-XngD6WWh.js +0 -1
- package/dist/viewer/assets/fa-pro-icons-B6J9phvt.js +0 -1
- package/dist/viewer/assets/iconMap-B-cS2yrx.js +0 -1
- package/dist/viewer/assets/index-CortCmDi.css +0 -2
- /package/dist/viewer/assets/{CodeViewer-DpJLTTab.js → CodeViewer-CVECJY4e.js} +0 -0
- /package/dist/viewer/assets/{VersionsPage-CRnStnQ-.js → VersionsPage-yNilRkEf.js} +0 -0
- /package/dist/viewer/assets/{WhenBadge-Dm7YHpxd.js → WhenBadge-B7s7fns2.js} +0 -0
- /package/dist/viewer/assets/{formatBytes-BV6bvmhE.js → formatBytes-BXYIMbyB.js} +0 -0
- /package/dist/viewer/assets/{setupAssistant-C-3V_Vj3.js → setupAssistant-DtI9NWXr.js} +0 -0
- /package/dist/viewer/assets/{useLocalStorage-BZr9ZJI5.js → useLocalStorage-wp83IS34.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,11 +1,308 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as
|
|
3
|
-
`).map(
|
|
4
|
-
`)?
|
|
2
|
+
import{readFileSync as Ya}from"fs";import{dirname as Xa,join as Za}from"path";import{fileURLToPath as Qa}from"url";import{Command as el}from"commander";import{createElement as ui}from"react";import{render as fi}from"ink";import{useEffect as vr,useState as Me}from"react";import{Box as ze,Text as Re,useApp as ci}from"ink";import{PluginValidationError as di}from"@kizenapps/packager";import{mkdir as zo,writeFile as Ho}from"fs/promises";import{join as Uo}from"path";import{PluginValidationError as Vo,minifyFiles as qo,packagePlugin as Jo,parseManifestFromFiles as Wo,transformDeployablePlugin as Ko,validatePluginApp as Go}from"@kizenapps/packager";import{readdir as Do,readFile as fr}from"fs/promises";import{join as mr,relative as Fo}from"path";var Oo=new Set([".png",".svg"]),jo=new Set([".kzn"]),$o=new Set([".DS_Store"]),tt=new Set(["node_modules",".git",".kizenapp",".github",".claude","__pycache__"]),Lo=8e3;function Mo(e){return e.subarray(0,Lo).includes(0)}async function gr(e,t){let n=await Do(e,{withFileTypes:!0}),o=[];for(let r of n)if(r.isDirectory()){if(tt.has(r.name))continue;o.push(...await gr(mr(e,r.name),t))}else r.isFile()&&($o.has(r.name)||o.push(mr(e,r.name)));return o}async function rt(e,{detectBinaryByContent:t=!1}={}){let n=await gr(e,e);return Promise.all(n.map(async o=>{let r=Fo(e,o).split("\\").join("/"),i=r.lastIndexOf("."),d=i>=0?r.slice(i).toLowerCase():"";if(Oo.has(d)){let g=await fr(o);return{path:r,content:"",base64Image:g.toString("base64")}}let f=await fr(o);return jo.has(d)||t&&Mo(f)?{path:r,content:"",binaryData:f}:{path:r,content:f.toString("utf-8")}}))}var Yo=(e,t)=>({...e,thumbnail:e.thumbnail?Buffer.from(e.thumbnail).toString("base64"):null,kznFile:e.kznFile?Buffer.from(e.kznFile).toString("base64"):null,allReleaseNotes:t});async function nt(e,t,n){await zo(t,{recursive:!0}),n?.("reading-files");let o=await rt(e);n?.("validating");let r=Go(o);if(r.some(x=>x.severity==="error"))throw new Vo(r);n?.("minifying");let i=await qo(o);n?.("packaging");let d=Wo(i),f=Jo(i,d),g=Object.values(f).map(Ko);n?.("writing-bundle");let m=g.map(x=>{let p=x.release_notes_directory?.replace(/\/$/,""),y=p?o.filter(S=>S.path.startsWith(p+"/")&&S.path.endsWith(".md")&&S.content).map(S=>({version:S.path.slice(S.path.lastIndexOf("/")+1,-3),notes:S.content})).sort((S,H)=>H.version.localeCompare(S.version,void 0,{numeric:!0})):[];return Yo(x,y)}),b=JSON.stringify(m,null,2),T=(x,p)=>x==="allReleaseNotes"?void 0:p,P=Buffer.byteLength(JSON.stringify(m,T,2),"utf-8");return await Ho(Uo(t,"bundle.json"),b,"utf-8"),{bundleSize:P}}function $e(e){return e<1024?`${String(e)} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(2)} MB`}import{Box as ei,Text as ti}from"ink";import{Box as Xo,Text as Zo}from"ink";import{jsx as hr}from"react/jsx-runtime";var Qo=[" :::::::: "," :::::: ::::::::::: "," :::::: :::::::::: "," :::::: :::::: ::::::: "," ::::: :::::: ::::::::::::::::: "," ::::: ::::: ::::::::::::::::::: "," ::::: ::::: :::::: ::::: ",":::: ::::: ::: ::::: :: ","::::: :::::: :::::::::: ","::::: :::::: ::::::::::: "," ::::: ::: ::::::: "," ::::::: ::: ::::: "," ::::::::::: :::::: :::::"," :::::::::: :::::: :::::"," :: ::::: ::: ::::: ::::"," ::::: :::::: ::::: ::::: ::: "," ::::::::::::::::::: ::::: ::::: "," ::::::::::::::::: ::::: ::::: "," ::::::::: :::::: :::::: "," :::::::::: :::::: "," ::::::::::: :::::: "," :::::::: "],yr=()=>hr(Xo,{flexDirection:"column",children:Qo.map((e,t)=>hr(Zo,{color:"cyan",children:e},t))});import{Fragment as ri,jsx as jt,jsxs as ni}from"react/jsx-runtime";var q=({marginBottom:e=0})=>ni(ri,{children:[jt(yr,{}),jt(ei,{flexDirection:"column",marginTop:1,marginBottom:e,children:jt(ti,{bold:!0,color:"cyan",children:"Kizen App Development Toolkit"})})]});import{useEffect as oi,useState as ii}from"react";import{Text as si}from"ink";import{jsx as ai}from"react/jsx-runtime";var br=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],me=()=>{let[e,t]=ii(0);return oi(()=>{let n=setInterval(()=>{t(o=>(o+1)%br.length)},80);return()=>{clearInterval(n)}},[]),ai(si,{color:"cyan",children:br[e]??"\u280B"})};import{Box as $t,Text as ot}from"ink";import{jsx as xr,jsxs as Le}from"react/jsx-runtime";var li=e=>{let t=new Map;for(let n of e){let o=n.path??n.pluginApiName??"general",r=t.get(o)??[];r.push(n),t.set(o,r)}return t},it=({issues:e})=>{let t=e.filter(n=>n.severity==="error").length;return Le($t,{flexDirection:"column",marginTop:1,children:[Le(ot,{color:"red",children:["\u2717 ",t," validation ",t===1?"error":"errors"]}),[...li(e)].map(([n,o])=>Le($t,{flexDirection:"column",marginTop:1,children:[xr(ot,{bold:!0,children:n}),o.map((r,i)=>xr($t,{paddingLeft:2,children:Le(ot,{color:r.severity==="error"?"red":"yellow",children:[r.severity==="error"?"\u2717":"\u26A0"," ",r.message," ",Le(ot,{dimColor:!0,children:["(",r.rule,")"]})]})},`${r.rule}-${String(i)}`))]},n))]})};import{Fragment as pi,jsx as ge,jsxs as Ee}from"react/jsx-runtime";var wr=["creating-dir","reading-files","validating","minifying","packaging","writing-bundle"],st={"creating-dir":"Creating .kizenapp directory","reading-files":"Reading plugin files",validating:"Validating plugin app",minifying:"Minifying scripts",packaging:"Packaging plugin","writing-bundle":"Writing bundle.json"},Cr=({outputDir:e,pluginDir:t})=>{let n=ci(),[o,r]=Me("creating-dir"),[i,d]=Me(!1),[f,g]=Me(null),[m,b]=Me(null),[T,P]=Me(null);vr(()=>{nt(t,e,r).then(({bundleSize:y})=>{P(y),r("done")}).catch(y=>{y instanceof di?g(y.issues):b(y instanceof Error?y.message:String(y)),d(!0),process.exitCode=1})},[e,t]),vr(()=>{(o==="done"||i)&&n.exit()},[o,i,n]);let x=wr.indexOf(o),p=o==="done";return Ee(ze,{flexDirection:"column",paddingY:1,paddingX:2,children:[ge(q,{marginBottom:1}),Ee(ze,{flexDirection:"column",gap:0,children:[wr.map((y,S)=>{let H=o===y,O=p||x>S;return ge(ze,{gap:1,children:i&&S===x?Ee(Re,{color:"red",children:["\u2717 ",st[y]]}):O?Ee(Re,{color:"green",children:["\u2713 ",st[y]]}):H?Ee(pi,{children:[ge(me,{}),ge(Re,{children:st[y]})]}):Ee(Re,{dimColor:!0,children:[" ",st[y]]})},y)}),p&&T!==null&&ge(ze,{marginTop:1,gap:1,children:Ee(Re,{color:"green",children:["\u2713 bundle \u2014 ",$e(T)]})}),f!==null&&ge(it,{issues:f}),m!==null&&ge(ze,{marginTop:1,borderStyle:"single",borderColor:"red",paddingX:1,children:ge(Re,{color:"red",children:m})})]})]})};import*as Ae from"fs";import*as Sr from"path";function Ne(e){let t=Sr.join(e,".gitignore"),n=".kizenapp/",o="";if(Ae.existsSync(t)){o=Ae.readFileSync(t,"utf8");let i=o.split(`
|
|
3
|
+
`).map(d=>d.trim());if(i.includes(n)||i.includes(".kizenapp"))return}let r=o.endsWith(`
|
|
4
|
+
`)?n+`
|
|
5
5
|
`:`
|
|
6
|
-
`+
|
|
7
|
-
`;
|
|
8
|
-
`,"utf-8"),await Bt(Ee(e.targetDir,"src"),{recursive:!0}),await Bt(Ee(e.targetDir,"releaseNotes"),{recursive:!0}),Be(e.targetDir)}import{jsx as B,jsxs as z}from"react/jsx-runtime";var Pe=["name","apiName","externalLink","description","developerBusinessId"],fr={name:"Name",apiName:"API name",externalLink:"External link",description:"Description",developerBusinessId:"Business ID"},mr=["name","apiName"];function go(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}var Re=({text:e})=>B(R,{dimColor:!0,children:e});function yo(e){return{name:"",apiName:"",externalLink:"",description:"",developerBusinessId:e}}var gr=({parentDir:e,defaultBusinessId:t})=>{let o=fo(),[n,r]=Me({type:"target-select",cursor:0}),[i,u]=Me("in-place"),[p,m]=Me(()=>yo(t)),[b,y]=Me(""),[S,N]=Me(e),v=at((P,x)=>{u(P),y(x.name),r({type:"field-entry",field:0,values:x})},[]),c=at(async P=>{let x=await dr(P);if(x!=="ok"){r({type:"precheck-error",targetDir:P,reason:x});return}N(P),v("in-place",p)},[p,v]),h=at(async P=>{try{let x=await ur(e,P.apiName);N(x),r({type:"confirm",values:P})}catch(x){r({type:"error",message:x instanceof Error?x.message:String(x)})}},[e]),T=at(async(P,x)=>{try{await pr({targetDir:x,name:P.name,apiName:P.apiName,externalLink:P.externalLink,description:P.description,developerBusinessId:P.developerBusinessId}),r({type:"done",targetDir:x})}catch(w){r({type:"error",message:w instanceof Error?w.message:String(w)})}},[]);if(mo((P,x)=>{if(x.ctrl&&P==="c"){o.exit();return}if(n.type==="target-select"){x.upArrow?r({type:"target-select",cursor:0}):x.downArrow?r({type:"target-select",cursor:1}):x.return?n.cursor===0?c(e):v("sub-dir",p):x.escape&&o.exit();return}if(n.type==="precheck-error"){(x.return||x.escape)&&o.exit();return}if(n.type==="field-entry"){let{field:w,values:k}=n,f=Pe[w];if(!f)return;if(x.escape){o.exit();return}if(x.backspace||x.delete){y(a=>a.slice(0,-1));return}if(x.upArrow&&w>0){let a={...k,[f]:b},s=w-1,l=Pe[s];r({type:"field-entry",field:s,values:a}),m(a),y(l?a[l]:"");return}if(x.return||x.tab||x.downArrow){let a=b.trim();if(mr.includes(f)&&!a){r({type:"field-entry",field:w,values:k,fieldError:`${fr[f]} is required`});return}let l=f==="description"?b:a,d={...k,[f]:l};m(d);let g=w+1;if(g>=Pe.length)y(""),i==="sub-dir"?(r({type:"resolving-target"}),h(d)):r({type:"confirm",values:d});else{let I=Pe[g],E=I?d[I]:"",F=I==="apiName"&&!E?go(d.name):E;r({type:"field-entry",field:g,values:d}),y(F)}return}P&&!x.ctrl&&!x.meta&&y(a=>a+P);return}if(n.type==="confirm"){if(x.escape){let w=Pe.length-1,k=Pe[w];r({type:"field-entry",field:w,values:n.values}),y(k?n.values[k]:"");return}x.return&&(r({type:"writing"}),T(n.values,S));return}(n.type==="done"||n.type==="error")&&(x.return||x.escape)&&o.exit()}),n.type==="target-select"){let P=[{label:"Use current directory",desc:e},{label:"Create new sub-directory",desc:`${e}/<inferred from API name>`}];return z(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[B(q,{}),z(V,{flexDirection:"column",gap:0,children:[B(R,{bold:!0,children:"Where should the new plugin live?"}),P.map((x,w)=>{let k=n.cursor===w;return z(V,{gap:2,children:[B(R,{...k&&{color:"cyan"},children:k?"\u276F":" "}),B(R,{bold:k,...k&&{color:"cyan"},children:x.label}),B(R,{dimColor:!0,children:x.desc})]},x.label)})]}),B(Re,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(n.type==="precheck-error"){let{targetDir:P,reason:x}=n;return z(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[B(q,{}),B(R,{color:"red",bold:!0,children:"Cannot create plugin"}),z(V,{flexDirection:"column",gap:0,children:[z(R,{children:[P," already contains ",B(R,{bold:!0,children:x==="has-manifest"?"kizen.json":".kizenapp/"}),"."]}),B(R,{dimColor:!0,children:"Remove the conflicting file/directory or choose a different target to avoid overwriting an existing plugin."})]}),B(Re,{text:"Enter or Esc to exit"})]})}if(n.type==="field-entry"){let{field:P,fieldError:x}=n,w=i==="sub-dir"?`Target: sub-directory of ${e} (inferred from API name)`:`Target: ${S}`;return z(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[B(q,{}),z(V,{flexDirection:"column",gap:0,children:[B(R,{bold:!0,children:"Plugin details"}),B(R,{dimColor:!0,children:w})]}),x!==void 0&&z(R,{color:"red",children:["Error: ",x]}),B(V,{flexDirection:"column",gap:0,children:Pe.map((k,f)=>{let a=P===f,s=a?b:p[k],l=mr.includes(k),d=`${fr[k]}${l?"":" (optional)"}`;return z(V,{gap:2,children:[B(V,{width:24,children:B(R,{bold:a,...a&&{color:"cyan"},children:d})}),B(R,{...a&&{color:"cyan"},children:">"}),B(R,{children:s}),a&&B(R,{color:"cyan",children:"\u2588"})]},k)})}),B(Re,{text:"Enter/Tab/\u2193 next \xB7 \u2191 previous \xB7 Backspace delete \xB7 Esc cancel"})]})}if(n.type==="confirm"){let P=Rt({targetDir:S,name:n.values.name,apiName:n.values.apiName,externalLink:n.values.externalLink,description:n.values.description,developerBusinessId:n.values.developerBusinessId});return z(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[B(q,{}),z(V,{flexDirection:"column",gap:0,children:[B(R,{bold:!0,children:"Ready to create"}),z(R,{dimColor:!0,children:["Target: ",S]})]}),z(V,{flexDirection:"column",gap:0,children:[B(R,{bold:!0,children:"kizen.json preview"}),B(R,{children:JSON.stringify(P,null,2)})]}),z(V,{flexDirection:"column",gap:0,children:[B(R,{dimColor:!0,children:"Also creates:"}),z(R,{dimColor:!0,children:[" ",Dt(S,"src/")]}),z(R,{dimColor:!0,children:[" ",Dt(S,"releaseNotes/")]}),z(R,{dimColor:!0,children:[" ",Dt(S,".gitignore")," (adds .kizenapp/)"]})]}),B(Re,{text:"Enter to create \xB7 Esc to go back"})]})}return n.type==="resolving-target"?B(V,{paddingY:1,paddingX:2,children:B(R,{dimColor:!0,children:"Finding available sub-directory\u2026"})}):n.type==="writing"?B(V,{paddingY:1,paddingX:2,children:B(R,{dimColor:!0,children:"Creating plugin\u2026"})}):n.type==="done"?z(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[B(q,{}),z(R,{color:"green",bold:!0,children:["Plugin created at ",n.targetDir]}),z(V,{flexDirection:"column",gap:0,children:[B(R,{dimColor:!0,children:"Next steps:"}),z(R,{children:[" ","cd ",n.targetDir]}),z(R,{children:[" ","npx --yes @kizenapps/cli dev"]})]}),B(Re,{text:"Enter or Esc to exit"})]}):z(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[B(q,{}),B(R,{color:"red",bold:!0,children:"Failed to create plugin"}),B(R,{children:n.message}),B(Re,{text:"Enter or Esc to exit"})]})};import{mkdir as yr,readFile as ho,readdir as bo,writeFile as hr}from"fs/promises";import{homedir as xo}from"os";import{dirname as vo,join as lt}from"path";var re=["go","fmo","staging","integration","test1"];var ke=lt(xo(),".kizenappbuilder"),De=lt(ke,"credentials.json"),me="credentials";function wo(e){return re.includes(e)}function Co(e){if(typeof e!="object"||e===null)throw new Error("Credentials must be a JSON object");let t=e,o=t.environment;return{apiKey:typeof t.apiKey=="string"?t.apiKey:"",userId:typeof t.userId=="string"?t.userId:"",businessId:typeof t.businessId=="string"?t.businessId:"",environment:wo(o)?o:"go"}}async function ge(e){let t=await ho(e,"utf-8");return Co(JSON.parse(t))}async function Y(){try{return await ge(De)}catch{return null}}async function So(e){await yr(vo(De),{recursive:!0,mode:448}),await hr(De,JSON.stringify(e,null,2),{encoding:"utf-8",mode:384})}function br(e){return lt(ke,`${e}.json`)}async function _e(){let e=[{name:me,path:De,isDefault:!0}];try{let t=await bo(ke);for(let o of t){if(!o.endsWith(".json"))continue;let n=o.slice(0,-5);n!==me&&e.push({name:n,path:lt(ke,o),isDefault:!1})}}catch{}return e}async function xr(e,t){if(e===me){await So(t);return}await yr(ke,{recursive:!0,mode:448}),await hr(br(e),JSON.stringify(t,null,2),{encoding:"utf-8",mode:384})}async function le(e){try{return await ge(br(e))}catch{return null}}function vr(e){e.command("create").description("Scaffold a new Kizen plugin project").action(async()=>{let t=process.cwd(),n=(await Y())?.businessId??"",{waitUntilExit:r}=Eo(To(gr,{parentDir:t,defaultBusinessId:n}),{exitOnCtrlC:!1});await r()})}import{createElement as Xr}from"react";import{render as Zr}from"ink";import{useCallback as $e,useEffect as gt,useRef as ce,useState as X}from"react";import{Box as W,Text as D,useInput as Ci}from"ink";import{PluginValidationError as Si}from"@kizenapps/packager";import{watch as Ti}from"fs";import{createServer as Ei}from"http";import{join as Gr}from"path";import{WebSocketServer as Pi}from"ws";import{createReadStream as Dr,realpathSync as qo}from"fs";import{access as Jo,readdir as Wo,readFile as Go,realpath as Ko,stat as $r}from"fs/promises";import{dirname as Yo,extname as Lr,join as We,resolve as Xo,sep as Ut}from"path";import{fileURLToPath as Zo}from"url";var Po=new Set(["set-cookie","strict-transport-security","content-security-policy","content-security-policy-report-only","x-frame-options","content-encoding","content-length"]);function ct(e){let t={};for(let[o,n]of Object.entries(e)){let r=o.toLowerCase();Po.has(r)||r.startsWith("access-control-")||(t[o]=n)}return t}var $t=10*1024*1024,ko=6e4,_o=200,He=class extends Error{bytesRead;limit;constructor(t,o){super(`Upstream response exceeded ${String(o)} bytes (read ${String(t)}).`),this.name="ProxyResponseTooLargeError",this.bytesRead=t,this.limit=o}};async function Lt(e,t){let o=e.body;if(o===null)return Buffer.alloc(0);let n=[],r=0;for await(let i of o){if(r+=i.length,r>t)throw new He(r,t);n.push(i)}return Buffer.concat(n)}async function wr(e){let t=ct(Object.fromEntries(e.headers)),o=await Lt(e,$t);return{status:e.status,headers:t,body:o}}function Cr(e={}){let{onChange:t,enabled:o=!0}=e;if(!o)return{async get(u,p){return{response:await wr(await p()),fromCache:!1}},clear(){}};let n=new Map,r=()=>{t?.(n.size)},i=u=>{n.delete(u)&&r()};return{get(u,p){let m=n.get(u);if(m!==void 0){if(Date.now()-m.insertedAt<ko)return m.promise.then(y=>({response:y,fromCache:!0}));i(u)}if(n.size>=_o){let y=n.keys().next().value;y!==void 0&&i(y)}let b=p().then(wr).catch(y=>{throw i(u),y});return n.set(u,{insertedAt:Date.now(),promise:b}),r(),b.then(y=>((y.status<200||y.status>=300)&&i(u),{response:y,fromCache:!1}))},clear(){n.clear(),r()}}}var Ft={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".svg":"image/svg+xml",".ico":"image/x-icon",".json":"application/json; charset=utf-8",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json"};import{mkdir as Io,readFile as No,writeFile as Bo}from"fs/promises";import{join as Sr}from"path";async function ye(e){try{let t=await No(Sr(e,"config.json"),"utf-8");return JSON.parse(t)}catch{return{}}}async function he(e,t){await Io(e,{recursive:!0}),await Bo(Sr(e,"config.json"),JSON.stringify(t,null,2),"utf-8")}var At={prod:"https://plugin-wizard.kizen.com",dev:"https://plugin-wizard.kizen.dev",localDev:"http://localhost:9823"};function Ue(e){let t=process.env.PLUGIN_WIZARD_URL;return t!==void 0&&t!==""?t:e==="prod"?process.env.PLUGIN_WIZARD_URL_PROD||At.prod:process.env.PLUGIN_WIZARD_URL_DEV!==void 0&&process.env.PLUGIN_WIZARD_URL_DEV!==""?process.env.PLUGIN_WIZARD_URL_DEV:process.env.APPBUILDER_LOCAL_DEV!==void 0&&process.env.APPBUILDER_LOCAL_DEV!==""?At.localDev:At.dev}import{spawn as Mt}from"child_process";import{writeFile as Er,rm as zt,mkdtemp as Do,access as $o}from"fs/promises";import{join as qe}from"path";import{tmpdir as Lo}from"os";var Tr=`awslambdaric
|
|
6
|
+
`+n+`
|
|
7
|
+
`;Ae.writeFileSync(t,o+r)}function Tr(e){e.command("build").description("Bundle the plugin app into .kizenapp directory").action(async()=>{let t=process.cwd(),n=`${t}/.kizenapp`;Ne(t);let{waitUntilExit:o}=fi(ui(Cr,{outputDir:n,pluginDir:t}));await o()})}import{createElement as hs}from"react";import{render as ys}from"ink";import{useCallback as mt,useState as Be}from"react";import{Box as z,Text as I,useApp as rs,useInput as ns}from"ink";import{join as gt}from"path";import{access as Zi,mkdir as lt,writeFile as Ut}from"fs/promises";import{dirname as Qi,join as ce}from"path";var _r=`{
|
|
8
|
+
"name": "Hello Frame",
|
|
9
|
+
"api_name": "hello_frame",
|
|
10
|
+
"title": "Hello Frame",
|
|
11
|
+
"default_position": "bottom-right",
|
|
12
|
+
"minimized_style": "circle",
|
|
13
|
+
"height": 320,
|
|
14
|
+
"width": 280
|
|
15
|
+
}
|
|
16
|
+
`;var Er=`this.outputUI(\`
|
|
17
|
+
<div class="hello-frame">
|
|
18
|
+
<h2 class="hello-frame__title">Hello from a floating frame</h2>
|
|
19
|
+
<p class="hello-frame__body">Edit src/floatingFrames/helloFrame/script.js to change this.</p>
|
|
20
|
+
</div>
|
|
21
|
+
\`);
|
|
22
|
+
`;var kr=`.hello-frame {
|
|
23
|
+
padding: 16px;
|
|
24
|
+
font-family: system-ui, sans-serif;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.hello-frame__title {
|
|
28
|
+
margin: 0 0 8px;
|
|
29
|
+
font-size: 16px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.hello-frame__body {
|
|
33
|
+
margin: 0;
|
|
34
|
+
color: #555;
|
|
35
|
+
}
|
|
36
|
+
`;var Pr=`{
|
|
37
|
+
"name": "Hello Block",
|
|
38
|
+
"api_name": "hello_block",
|
|
39
|
+
"types": ["dashboards"]
|
|
40
|
+
}
|
|
41
|
+
`;var Ir=`this.outputUI(\`
|
|
42
|
+
<div class="hello-block">
|
|
43
|
+
<h2 class="hello-block__title">Hello from a block</h2>
|
|
44
|
+
<p class="hello-block__body">Edit src/blocks/helloBlock/script.js to change this.</p>
|
|
45
|
+
</div>
|
|
46
|
+
\`);
|
|
47
|
+
`;var Rr=`.hello-block {
|
|
48
|
+
padding: 16px;
|
|
49
|
+
font-family: system-ui, sans-serif;
|
|
50
|
+
background: #f8fafc;
|
|
51
|
+
border-radius: 6px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.hello-block__title {
|
|
55
|
+
margin: 0 0 8px;
|
|
56
|
+
font-size: 16px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.hello-block__body {
|
|
60
|
+
margin: 0;
|
|
61
|
+
color: #555;
|
|
62
|
+
}
|
|
63
|
+
`;var Ar=`{
|
|
64
|
+
"icon": "phone",
|
|
65
|
+
"color": "#0ea5e9",
|
|
66
|
+
"tooltip": "Hello adornment",
|
|
67
|
+
"field_type": "phonenumber"
|
|
68
|
+
}
|
|
69
|
+
`;var Nr=`this.showToast('Hello from a data adornment.', { variant: 'success' });
|
|
70
|
+
`;var Br=`{
|
|
71
|
+
"name": "Hello Page",
|
|
72
|
+
"api_name": "hello_page"
|
|
73
|
+
}
|
|
74
|
+
`;var Dr=`this.outputUI(\`
|
|
75
|
+
<div class="hello-page">
|
|
76
|
+
<p class="hello-page__loading">Loading\u2026</p>
|
|
77
|
+
</div>
|
|
78
|
+
\`);
|
|
79
|
+
|
|
80
|
+
this.runEventScript('greet');
|
|
81
|
+
`;var Fr=`.hello-page {
|
|
82
|
+
padding: 24px;
|
|
83
|
+
font-family: system-ui, sans-serif;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.hello-page__title {
|
|
87
|
+
margin: 0 0 8px;
|
|
88
|
+
font-size: 20px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hello-page__body {
|
|
92
|
+
margin: 0 0 16px;
|
|
93
|
+
color: #555;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.hello-page__loading {
|
|
97
|
+
margin: 0;
|
|
98
|
+
color: #94a3b8;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.hello-page__actions {
|
|
102
|
+
display: flex;
|
|
103
|
+
gap: 8px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.hello-page__button {
|
|
107
|
+
padding: 6px 12px;
|
|
108
|
+
font: inherit;
|
|
109
|
+
color: #0f172a;
|
|
110
|
+
background: #e2e8f0;
|
|
111
|
+
border: 0;
|
|
112
|
+
border-radius: 4px;
|
|
113
|
+
cursor: pointer;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.hello-page__button:hover {
|
|
117
|
+
background: #cbd5e1;
|
|
118
|
+
}
|
|
119
|
+
`;var Or=`const tone = this.args?.formData?.tone?.[0] ?? 'plain';
|
|
120
|
+
|
|
121
|
+
const greeting = tone === 'cheer' ? 'Hello, and good to see you!' : 'Hello from a routable page.';
|
|
122
|
+
|
|
123
|
+
this.outputUI(\`
|
|
124
|
+
<div class="hello-page">
|
|
125
|
+
<h1 class="hello-page__title">\${greeting}</h1>
|
|
126
|
+
<p class="hello-page__body">
|
|
127
|
+
This markup came from eventScripts/greet.js. Either button re-runs it and
|
|
128
|
+
repaints the page with a different greeting.
|
|
129
|
+
</p>
|
|
130
|
+
<div class="hello-page__actions">
|
|
131
|
+
<form data-script="greet">
|
|
132
|
+
<input type="hidden" name="tone" value="plain" />
|
|
133
|
+
<button class="hello-page__button" type="submit">Plain</button>
|
|
134
|
+
</form>
|
|
135
|
+
<form data-script="greet">
|
|
136
|
+
<input type="hidden" name="tone" value="cheer" />
|
|
137
|
+
<button class="hello-page__button" type="submit">Cheerful</button>
|
|
138
|
+
</form>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
\`);
|
|
142
|
+
`;var jr=`{
|
|
143
|
+
"api_name": "hello_toolbar_item",
|
|
144
|
+
"label": "Hello Toolbar Item",
|
|
145
|
+
"icon": "star",
|
|
146
|
+
"color": "#0ea5e9"
|
|
147
|
+
}
|
|
148
|
+
`;var $r=`this.showToast('Hello from a toolbar item.', { variant: 'success' });
|
|
149
|
+
`;var Lr=`{
|
|
150
|
+
"api_name": "hello_object_settings_item",
|
|
151
|
+
"label": "Hello Object Settings"
|
|
152
|
+
}
|
|
153
|
+
`;var Mr=`this.showToast('Hello from an object settings item.', { variant: 'success' });
|
|
154
|
+
`;var zr=`{
|
|
155
|
+
"name": "Hello Action",
|
|
156
|
+
"api_name": "hello_action",
|
|
157
|
+
"hint_object_name": "client_client"
|
|
158
|
+
}
|
|
159
|
+
`;var Hr=`this.showToast('Hello from a JS action.', { variant: 'success' });
|
|
160
|
+
`;var X=["floatingFrame","block","dataAdornment","page","toolbarItem","objectSettingsItem","jsAction"],Lt={floatingFrame:"Floating frame",block:"Block",dataAdornment:"Data adornment",page:"Routable page",toolbarItem:"Toolbar item",objectSettingsItem:"Object settings item",jsAction:"JS action"},Ni={floatingFrame:{directory:"floatingFrames",component:"helloFrame",files:{"config.json":_r,"script.js":Er,"styles.css":kr}},block:{directory:"blocks",component:"helloBlock",files:{"config.json":Pr,"script.js":Ir,"styles.css":Rr}},dataAdornment:{directory:"dataAdornments",component:"helloAdornment",files:{"config.json":Ar,"script.js":Nr}},page:{directory:"pages",component:"helloPage",files:{"config.json":Br,"script.js":Dr,"styles.css":Fr,"eventScripts/greet.js":Or}},toolbarItem:{directory:"toolbarItems",component:"helloToolbarItem",files:{"config.json":jr,"script.js":$r}},objectSettingsItem:{directory:"objectSettingsItems",component:"helloObjectSettingsItem",files:{"config.json":Lr,"script.js":Mr}},jsAction:{directory:"actions",component:"helloAction",files:{"config.json":zr,"script.js":Hr}}};function Bi(e,t="src"){let{directory:n,component:o,files:r}=Ni[e];return Object.entries(r).map(([i,d])=>({path:`${t}/${n}/${o}/${i}`,content:d}))}function Ur(e,t="src"){return[...new Set(e)].flatMap(n=>Bi(n,t))}var Vr='# Copilot review instructions for this Kizen plugin\n\nThis repo is a Kizen plugin app: a `kizen.json` manifest plus the artifacts\nthat `@kizenapps/packager` finds by walking the directory tree under the\nmanifest\'s `entry` (default `src/`). No manifest key lists artifacts. The\ndirectory layout decides what gets packaged.\n\n## Component directories\n\nUnder `entry`, the packager treats these directory names as component types:\n\n- `floatingFrames`\n- `blocks`\n- `dataAdornments`\n- `pages`\n- `views`\n- `toolbarItems`\n- `objectSettingsItems`\n- `actions`\n- `routeScripts`\n- `automationSteps`\n- `calendarSources`\n\nEvery directory under a component type needs a `config.json`. `views/` is the\none exception.\n\n## `api_name` rules\n\n- An `api_name` must match `/^[a-z_][a-z0-9_]+$/`: lowercase letters, digits\n and underscores, starting with a letter or underscore, at least 2 characters.\n- Set `api_name` explicitly in each artifact\'s `config.json`. The fallback\n lowercases and strips the directory name (`myFrame` becomes `myframe`), and\n that result can collide with another artifact\'s explicit `api_name`.\n- Data adornments have no `api_name` field. Flag one that adds it as dead\n configuration.\n- Sibling components in the same directory need unique `api_name`s. `pages/`\n and `views/` go further and share one namespace, so a page and a view with\n the same `api_name` collide even though they live in different directories.\n\n## A green build does not mean a correct artifact\n\nThe packager coerces malformed artifact config instead of rejecting it: an\ninvalid `field_type` on a data adornment becomes `phonenumber`, and an invalid\n`minimized_style` on a floating frame becomes `circle`. It also says nothing\nabout a missing required field. Publishing is the real gate. The publish step\ncreates each artifact with no defaulting, so a field the packager never emitted\nis absent and the publish request 400s. Review each\n`config.json` as if the build will not catch mistakes in it, because for these\ncases it does not.\n\nPublishing an app requires these fields per artifact type. An artifact missing\none builds clean and fails to publish:\n\n| Artifact | Required fields |\n| --- | --- |\n| Floating frame | `api_name`, `name`, `title` |\n| Block | `api_name`, `name` |\n| Data adornment | `field_type` (one of `phonenumber`, `date`, `datetime`) |\n| Routable page | `api_name`, `name` |\n| Toolbar item | `api_name`, `label`, and a non-blank `script.js` |\n| Object settings item | `api_name`, `label`, and a non-blank `script.js` |\n| JS action | `api_name`, `name`, `hint_object_name` (non-blank) |\n\nA floating frame whose `default_position` ends in `-fixed` must set\n`minimized_style: "circle"` or omit `minimized_style`. Any other value fails\nthe build with `structure/fixed-frame-minimized-style`.\n\n## Publishing\n\nPublishing an app requires exactly one `thumbnail.png`, and it must sit inside\nthe `entry` directory (`src/thumbnail.png` by default). The packager never sees\na thumbnail at the repo root, and publishing then fails with "Thumbnail is\nrequired for publishing".\n\n## Scope\n\nThis file covers repo structure and general review. Two path-scoped files\ncover the rest: `.github/instructions/security.instructions.md` for\nsecurity-sensitive patterns and\n`.github/instructions/version-discipline.instructions.md` for manifest version\nbumps.\n';var qr=`---
|
|
161
|
+
applyTo: "src/**/*.js,kizen.json"
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
# Security review rules for plugin scripts
|
|
165
|
+
|
|
166
|
+
These rules mirror the \`security/*\` validation rules in \`@kizenapps/packager\`.
|
|
167
|
+
Flag violations the way the packager would, and also flag the patterns listed
|
|
168
|
+
here that its static scan cannot detect.
|
|
169
|
+
|
|
170
|
+
## \`__dangerouslySkipProxy\`
|
|
171
|
+
|
|
172
|
+
The packager lets \`__dangerouslySkipProxy\` through with the build WARNING
|
|
173
|
+
\`security/dangerously-skip-proxy\`. Flag every occurrence for human review
|
|
174
|
+
anyway, because the request leaves the browser directly instead of passing
|
|
175
|
+
through the Kizen proxy.
|
|
176
|
+
|
|
177
|
+
## Plaintext credentials
|
|
178
|
+
|
|
179
|
+
In \`kizen.json\`, a service's \`auth_credentials.token\`,
|
|
180
|
+
\`auth_credentials.password\` and \`auth_credentials.client_secret\` must each be
|
|
181
|
+
one of:
|
|
182
|
+
|
|
183
|
+
- an encrypted envelope (\`{ "encrypted": true, "value": "..." }\`) that
|
|
184
|
+
\`appbuilder encrypt\` produced
|
|
185
|
+
- a \`{{secret.KEY}}\` reference, with \`KEY\` declared in \`base_config.secrets\`
|
|
186
|
+
- a reference through \`auth_credentials.integration_secret_api_name\`
|
|
187
|
+
|
|
188
|
+
A raw literal in any of those three fields is the build ERROR
|
|
189
|
+
\`security/plaintext-credential\`. Treat a credential that reaches a commit in
|
|
190
|
+
plaintext as compromised and rotate it; deleting the line does not undo the
|
|
191
|
+
exposure.
|
|
192
|
+
|
|
193
|
+
\`client_id\` is excluded from this rule on purpose. Public client ids are not
|
|
194
|
+
sensitive, so do not flag them.
|
|
195
|
+
|
|
196
|
+
## Undeclared secret references
|
|
197
|
+
|
|
198
|
+
A \`{{secret.KEY}}\` reference whose \`KEY\` is missing from \`base_config.secrets\`
|
|
199
|
+
is the build ERROR \`security/undeclared-secret-reference\`, because nothing
|
|
200
|
+
would supply the value at install time.
|
|
201
|
+
|
|
202
|
+
## Dynamic code execution
|
|
203
|
+
|
|
204
|
+
\`eval(...)\`, \`new Function(...)\` or \`Function(...)\`, and a string argument to
|
|
205
|
+
\`setTimeout\` or \`setInterval\` are the build ERROR \`security/dynamic-code\`.
|
|
206
|
+
|
|
207
|
+
This rule catches direct, literal usage only. The packager's scan is
|
|
208
|
+
parser-based, so a call built through a computed property or a reassigned
|
|
209
|
+
reference gets past it. Obfuscated dynamic code stays a human-review concern.
|
|
210
|
+
|
|
211
|
+
## Secret logging and exfiltration
|
|
212
|
+
|
|
213
|
+
The packager has no static check for a secret that gets logged, sent to an
|
|
214
|
+
unexpected endpoint, or otherwise exfiltrated. Review for this by hand: look
|
|
215
|
+
for credentials or decrypted secret values flowing into \`console.log\`, error
|
|
216
|
+
messages, analytics calls, or outbound requests to anything other than the
|
|
217
|
+
service they belong to.
|
|
218
|
+
|
|
219
|
+
## Handling secrets in this repo
|
|
220
|
+
|
|
221
|
+
Encrypt secrets locally with \`appbuilder encrypt\` before committing them. Do
|
|
222
|
+
not commit a plaintext secret value in any form; a comment, a script fixture,
|
|
223
|
+
and a commit you intend to rewrite later all count.
|
|
224
|
+
`;var Jr=`---
|
|
225
|
+
applyTo: "kizen.json"
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
# Version-bump discipline for \`kizen.json\`
|
|
229
|
+
|
|
230
|
+
## What a wrong bump breaks
|
|
231
|
+
|
|
232
|
+
A business that installs this plugin accumulates its own stored state
|
|
233
|
+
(automation runs, config values, references to entities) shaped by what was
|
|
234
|
+
published at the time. Publishing is additive: it never rewrites a business's
|
|
235
|
+
stored rows, and the plugin author has no way to migrate that state for them.
|
|
236
|
+
A change is breaking when it invalidates an assumption the business's existing
|
|
237
|
+
data already depends on.
|
|
238
|
+
|
|
239
|
+
A MINOR or PATCH republish applies at once to a business's running automations
|
|
240
|
+
and installed artifacts. Only a new MAJOR version waits for the business to
|
|
241
|
+
upgrade explicitly. A change that needed MAJOR but shipped as MINOR or PATCH
|
|
242
|
+
therefore breaks the business with no upgrade gate in between.
|
|
243
|
+
|
|
244
|
+
Two kinds of change get MAJOR because they fail without an error:
|
|
245
|
+
|
|
246
|
+
- Renaming a config field, changing its type, or adding a required key. A
|
|
247
|
+
template reference like \`{{config.key}}\` for a key that no longer exists
|
|
248
|
+
resolves to a literal \`null\`, and the artifact renders wrong or does
|
|
249
|
+
nothing.
|
|
250
|
+
- Removing or renaming a JS action. A business's automation and UI
|
|
251
|
+
associations key on the action's \`api_name\` as a plain string, with no
|
|
252
|
+
foreign key. After a rename or removal those associations stop firing.
|
|
253
|
+
|
|
254
|
+
Review every \`kizen.json\` diff against the table below before approving the
|
|
255
|
+
version bump in the same PR.
|
|
256
|
+
|
|
257
|
+
## Bump matrix
|
|
258
|
+
|
|
259
|
+
| Resource | Change | Required bump |
|
|
260
|
+
| --- | --- | --- |
|
|
261
|
+
| Plugin | change \`api_name\` | **HARD-BLOCK**: identity can never change |
|
|
262
|
+
| Service | add | MINOR |
|
|
263
|
+
| Service | remove | MAJOR |
|
|
264
|
+
| Service | change auth type or \`auth_level\` | MAJOR |
|
|
265
|
+
| Service | change \`auth_credentials\` (client id/secret, scopes, authorize/token URLs) | MAJOR |
|
|
266
|
+
| Service | change base URL or other non-auth field | PATCH |
|
|
267
|
+
| Service | rename \`api_name\` | MAJOR |
|
|
268
|
+
| Secret | add | MINOR |
|
|
269
|
+
| Secret | remove | MINOR |
|
|
270
|
+
| Secret | rename key | MAJOR |
|
|
271
|
+
| Secret | re-encrypt value only | PATCH |
|
|
272
|
+
| Automation step | add | MINOR |
|
|
273
|
+
| Automation step | remove entire step | MAJOR |
|
|
274
|
+
| Automation step | remove an input or output | MAJOR |
|
|
275
|
+
| Automation step | change input/output \`data_type\` | MAJOR |
|
|
276
|
+
| Automation step | add required input | MAJOR |
|
|
277
|
+
| Automation step | add optional input | MINOR |
|
|
278
|
+
| Automation step | change python runtime | PATCH |
|
|
279
|
+
| Automation step | edit script body only | PATCH |
|
|
280
|
+
| Artifact (frame, block, adornment, page, route script, toolbar/object-settings item, calendar source) | add | MINOR |
|
|
281
|
+
| Artifact | remove | MINOR |
|
|
282
|
+
| Artifact | rename \`api_name\` | MINOR |
|
|
283
|
+
| Artifact | edit script or behavior | PATCH |
|
|
284
|
+
| JS action | add | MINOR |
|
|
285
|
+
| JS action | remove | MAJOR |
|
|
286
|
+
| JS action | rename \`api_name\` | MAJOR |
|
|
287
|
+
| JS action | change \`hint_object_name\` or script | PATCH |
|
|
288
|
+
| Config field | add optional (with default) | MINOR |
|
|
289
|
+
| Config field | add required (no default) | MAJOR |
|
|
290
|
+
| Config field | remove | MINOR |
|
|
291
|
+
| Config field | rename | MAJOR |
|
|
292
|
+
| Config field | change type | MAJOR |
|
|
293
|
+
| Config field | change default or label | PATCH |
|
|
294
|
+
| \`required_entitlement\` | add gating | MINOR |
|
|
295
|
+
| \`required_entitlement\` | change or remove | PATCH |
|
|
296
|
+
| Manifest metadata (\`name\`, \`description\`, \`entry\`, \`release_branches\`, \`release_environments\`, \`published\`, \`developer_business_id\`) | any change | PATCH |
|
|
297
|
+
`;function Wr(){return[{path:".github/copilot-instructions.md",content:Vr},{path:".github/instructions/security.instructions.md",content:qr},{path:".github/instructions/version-discipline.instructions.md",content:Jr}]}import{deflateSync as ji}from"zlib";var zt=512,$i=150,Li=26,Ht=46,Kr=.6,Mi=Ht*.55,zi=.55,Hi=.47;function Ui(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=t+((t<<1)+(t<<4)+(t<<7)+(t<<8)+(t<<24))>>>0;return t}function Vi(e){let t=Ui(e);return{hue:t%360,quarterTurns:(t>>>16)%4}}function qi(e,t,n){let o=(1-Math.abs(2*n-1))*t,r=e/60,i=o*(1-Math.abs(r%2-1)),d=n-o/2,[f,g,m]=r<1?[o,i,0]:r<2?[i,o,0]:r<3?[0,o,i]:r<4?[0,i,o]:r<5?[i,0,o]:[o,0,i];return[Math.round((f+d)*255),Math.round((g+d)*255),Math.round((m+d)*255)]}function He(e,t,n,o,r){let i=Math.abs(e)-n+r,d=Math.abs(t)-o+r;return Math.hypot(Math.max(i,0),Math.max(d,0))+Math.min(Math.max(i,d),0)-r}function at(e,t,n,o,r){return Math.hypot(e-n,t-o)-r}function Ji(e,t){let n=$i,o=Ht,r=o*Kr,i=Mi,d=He(e,t,n,n,Li),f=Math.min(at(e,t,0,-n-r,o),He(e,t+n+r/2,i,r/2+1,0)),g=Math.min(at(e,t,n+r,0,o),He(e-n-r/2,t,r/2+1,i,0));d=Math.min(d,f,g);let m=Math.min(at(e,t,0,n-r,o),He(e,t-n+r/2,i,r/2+1,0)),b=Math.min(at(e,t,-n+r,0,o),He(e+n-r/2,t,r/2+1,i,0));return Math.max(d,-m,-b)}function Wi(e){let t=zt,n=new Uint8Array(t*t*4),[o,r,i]=qi(e.hue,zi,Hi),d=Ht*(1+Kr),f=(t-1)/2,g=d/2;for(let m=0;m<t;m+=1)for(let b=0;b<t;b+=1){let T=b-f,P=m-f;for(let S=0;S<e.quarterTurns;S+=1)[T,P]=[-P,T];let x=Ji(T+g,P-g),p=Math.min(1,Math.max(0,.5-x));if(p<=0)continue;let y=(m*t+b)*4;n[y]=o,n[y+1]=r,n[y+2]=i,n[y+3]=Math.round(p*255)}return n}var Ki=new Uint32Array(256).map((e,t)=>{let n=t;for(let o=0;o<8;o+=1)n=n&1?3988292384^n>>>1:n>>>1;return n>>>0});function Gi(e){let t=4294967295;for(let n of e)t=(Ki[(t^n)&255]??0)^t>>>8;return(t^4294967295)>>>0}function Mt(e,t){let n=Buffer.from(e,"latin1"),o=Buffer.alloc(4);o.writeUInt32BE(t.length);let r=Buffer.alloc(4);return r.writeUInt32BE(Gi(Buffer.concat([n,t]))),Buffer.concat([o,n,t,r])}var Yi=Buffer.from([137,80,78,71,13,10,26,10]);function Xi(e,t,n){if(n.length!==e*t*4)throw new Error(`encodePng: expected ${String(e*t*4)} bytes of RGBA for ${String(e)}x${String(t)}, got ${String(n.length)}`);let o=Buffer.alloc(13);o.writeUInt32BE(e,0),o.writeUInt32BE(t,4),o[8]=8,o[9]=6;let r=e*4,i=Buffer.alloc((r+1)*t);for(let d=0;d<t;d+=1)i.set(n.subarray(d*r,(d+1)*r),d*(r+1)+1);return Buffer.concat([Yi,Mt("IHDR",o),Mt("IDAT",ji(i,{level:9})),Mt("IEND",new Uint8Array(0))])}function Gr(e){return Xi(zt,zt,Wi(Vi(e)))}var es="src/thumbnail.png",ts=["go","fmo"];async function ct(e){try{return await Zi(e),!0}catch{return!1}}async function dt(e){return await ct(ce(e,"kizen.json"))?"has-manifest":await ct(ce(e,".kizenapp"))?"has-kizenapp":"ok"}async function Xr(e,t){let n=ce(e,t);if(!await ct(n))return n;for(let o=1;o<1e3;o++){let r=ce(e,`${t}-${String(o)}`);if(!await ct(r))return r}throw new Error(`Could not find an available directory name for "${t}"`)}function Vt(e){let t=e.developerBusinessId.trim(),n=t!==""&&!ts.includes(e.developerEnvironment)?[e.developerEnvironment]:["prod"];return{name:e.name,version:"1.0.0",published:!0,api_name:e.apiName,external_link:e.externalLink,description:e.description,entry:"src/",engine:"1.0.0",release_notes_directory:"releaseNotes/",release_environments:n,config_template:{},base_config:{},...t?{developer_business_id:{[e.developerEnvironment]:t}}:{}}}async function Yr(e,t){let n=t.map(r=>({fullPath:ce(e,...r.path.split("/")),content:r.content})),o=new Set(n.map(r=>Qi(r.fullPath)));await Promise.all([...o].map(r=>lt(r,{recursive:!0}))),await Promise.all(n.map(r=>Ut(r.fullPath,r.content,"utf-8")))}async function pt(e){await lt(e.targetDir,{recursive:!0});let t=Vt(e);await Ut(ce(e.targetDir,"kizen.json"),JSON.stringify(t,null,2)+`
|
|
298
|
+
`,"utf-8"),await lt(ce(e.targetDir,"src"),{recursive:!0}),await lt(ce(e.targetDir,"releaseNotes"),{recursive:!0}),await Promise.all([Yr(e.targetDir,Ur(e.artifacts??[])),Yr(e.targetDir,Wr()),Ut(ce(e.targetDir,...es.split("/")),Gr(e.apiName))]),Ne(e.targetDir)}var he=["name","apiName","externalLink","description","developerBusinessId"],ut={name:"Name",apiName:"API name",externalLink:"External link",description:"Description",developerBusinessId:"Business ID"},qt=["name","apiName","description"],Jt=/^[a-z_][a-z0-9_]+$/,Wt="must start with a letter or underscore and contain only lowercase letters, numbers, or underscores (minimum 2 characters)";function ft(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function Zr(e){return{name:"",apiName:"",externalLink:"",description:"",developerBusinessId:e}}function Qr(e,t){let n=t.trim();if(qt.includes(e)&&!n)return`${ut[e]} is required`;if(e==="apiName"&&!Jt.test(n))return`${ut[e]} ${Wt}`}function en(e,t){return e==="description"?t:t.trim()}function tn(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),X.filter(o=>n.has(o))}import{jsx as E,jsxs as N}from"react/jsx-runtime";var ke=({text:e})=>E(I,{dimColor:!0,children:e}),rn=({parentDir:e,defaultBusinessId:t,defaultEnvironment:n})=>{let o=rs(),[r,i]=Be({type:"target-select",cursor:0}),[d,f]=Be("in-place"),[g,m]=Be(()=>Zr(t)),[b,T]=Be(()=>[...X]),[P,x]=Be(""),[p,y]=Be(e),S=mt((v,c)=>{f(v),x(c.name),i({type:"field-entry",field:0,values:c})},[]),H=mt(async v=>{let c=await dt(v);if(c!=="ok"){i({type:"precheck-error",targetDir:v,reason:c});return}y(v),S("in-place",g)},[g,S]),O=mt(async(v,c)=>{try{let a=await Xr(e,v.apiName);y(a),i({type:"confirm",values:v,artifacts:c})}catch(a){i({type:"error",message:a instanceof Error?a.message:String(a)})}},[e]),w=mt(async(v,c,a)=>{try{await pt({targetDir:c,name:v.name,apiName:v.apiName,externalLink:v.externalLink,description:v.description,developerBusinessId:v.developerBusinessId,developerEnvironment:n,artifacts:a}),i({type:"done",targetDir:c})}catch(s){i({type:"error",message:s instanceof Error?s.message:String(s)})}},[n]);if(ns((v,c)=>{if(c.ctrl&&v==="c"){o.exit();return}if(r.type==="target-select"){c.upArrow?i({type:"target-select",cursor:0}):c.downArrow?i({type:"target-select",cursor:1}):c.return?r.cursor===0?H(e):S("sub-dir",g):c.escape&&o.exit();return}if(r.type==="precheck-error"){(c.return||c.escape)&&o.exit();return}if(r.type==="field-entry"){let{field:a,values:s}=r,l=he[a];if(!l)return;if(c.escape){o.exit();return}if(c.backspace||c.delete){x(u=>u.slice(0,-1));return}if(c.upArrow&&a>0){let u={...s,[l]:P},h=a-1,k=he[h];i({type:"field-entry",field:h,values:u}),m(u),x(k?u[k]:"");return}if(c.return||c.tab||c.downArrow){let u=Qr(l,P);if(u!==void 0){i({type:"field-entry",field:a,values:s,fieldError:u});return}let h=en(l,P),k={...s,[l]:h};m(k);let _=a+1;if(_>=he.length)x(""),i({type:"artifact-select",values:k,cursor:0,selected:b});else{let A=he[_],M=A?k[A]:"",W=A==="apiName"&&!M?ft(k.name):M;i({type:"field-entry",field:_,values:k}),x(W)}return}v&&!c.ctrl&&!c.meta&&x(u=>u+v);return}if(r.type==="artifact-select"){let{cursor:a,selected:s,values:l}=r;if(c.escape){let u=he.length-1,h=he[u];i({type:"field-entry",field:u,values:l}),x(h?l[h]:"");return}if(c.upArrow){i({...r,cursor:Math.max(0,a-1)});return}if(c.downArrow){i({...r,cursor:Math.min(X.length-1,a+1)});return}if(v===" "){let u=X[a];if(u){let h=tn(s,u);T(h),i({...r,selected:h})}return}if(v==="a"){T([...X]),i({...r,selected:[...X]});return}if(v==="n"){T([]),i({...r,selected:[]});return}c.return&&(d==="sub-dir"?(i({type:"resolving-target"}),O(l,s)):i({type:"confirm",values:l,artifacts:s}));return}if(r.type==="confirm"){if(c.escape){i({type:"artifact-select",values:r.values,cursor:0,selected:r.artifacts});return}c.return&&(i({type:"writing"}),w(r.values,p,r.artifacts));return}(r.type==="done"||r.type==="error")&&(c.return||c.escape)&&o.exit()}),r.type==="target-select"){let v=[{label:"Use current directory",desc:e},{label:"Create new sub-directory",desc:`${e}/<inferred from API name>`}];return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Where should the new plugin live?"}),v.map((c,a)=>{let s=r.cursor===a;return N(z,{gap:2,children:[E(I,{...s&&{color:"cyan"},children:s?"\u276F":" "}),E(I,{bold:s,...s&&{color:"cyan"},children:c.label}),E(I,{dimColor:!0,children:c.desc})]},c.label)})]}),E(ke,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="precheck-error"){let{targetDir:v,reason:c}=r;return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),E(I,{color:"red",bold:!0,children:"Cannot create plugin"}),N(z,{flexDirection:"column",gap:0,children:[N(I,{children:[v," already contains ",E(I,{bold:!0,children:c==="has-manifest"?"kizen.json":".kizenapp/"}),"."]}),E(I,{dimColor:!0,children:"Remove the conflicting file/directory or choose a different target to avoid overwriting an existing plugin."})]}),E(ke,{text:"Enter or Esc to exit"})]})}if(r.type==="field-entry"){let{field:v,fieldError:c}=r,a=d==="sub-dir"?`Target: sub-directory of ${e} (inferred from API name)`:`Target: ${p}`;return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Plugin details"}),E(I,{dimColor:!0,children:a})]}),c!==void 0&&N(I,{color:"red",children:["Error: ",c]}),E(z,{flexDirection:"column",gap:0,children:he.map((s,l)=>{let u=v===l,h=u?P:g[s],k=qt.includes(s),_=`${ut[s]}${k?"":" (optional)"}`;return N(z,{gap:2,children:[E(z,{width:24,children:E(I,{bold:u,...u&&{color:"cyan"},children:_})}),E(I,{...u&&{color:"cyan"},children:">"}),E(I,{children:h}),u&&E(I,{color:"cyan",children:"\u2588"})]},s)})}),E(ke,{text:"Enter/Tab/\u2193 next \xB7 \u2191 previous \xB7 Backspace delete \xB7 Esc cancel"})]})}if(r.type==="artifact-select"){let{cursor:v,selected:c}=r;return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Which artifacts should we scaffold?"}),E(I,{dimColor:!0,children:"Each one gets a directory with a config.json and a script that runs."})]}),E(z,{flexDirection:"column",gap:0,children:X.map((a,s)=>{let l=v===s,u=c.includes(a);return N(z,{gap:1,children:[E(I,{...l&&{color:"cyan"},children:l?"\u276F":" "}),E(I,{...u&&{color:"green"},children:u?"\u25C9":"\u25EF"}),E(I,{bold:l,...l&&{color:"cyan"},children:Lt[a]})]},a)})}),E(ke,{text:"\u2191\u2193 move \xB7 Space toggle \xB7 a all \xB7 n none \xB7 Enter continue \xB7 Esc back"})]})}if(r.type==="confirm"){let v=Vt({targetDir:p,name:r.values.name,apiName:r.values.apiName,externalLink:r.values.externalLink,description:r.values.description,developerBusinessId:r.values.developerBusinessId,developerEnvironment:n});return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Ready to create"}),N(I,{dimColor:!0,children:["Target: ",p]})]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"kizen.json preview"}),E(I,{children:JSON.stringify(v,null,2)})]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Artifacts"}),r.artifacts.length===0?N(I,{dimColor:!0,children:[" ","none (src/ will hold only thumbnail.png)"]}):r.artifacts.map(c=>N(I,{dimColor:!0,children:[" ",Lt[c]]},c))]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{dimColor:!0,children:"Also creates:"}),N(I,{dimColor:!0,children:[" ",gt(p,"src/")]}),N(I,{dimColor:!0,children:[" ",gt(p,"src/thumbnail.png")," (generated placeholder)"]}),N(I,{dimColor:!0,children:[" ",gt(p,"releaseNotes/")]}),N(I,{dimColor:!0,children:[" ",gt(p,".gitignore")," (adds .kizenapp/)"]})]}),E(ke,{text:"Enter to create \xB7 Esc to go back"})]})}return r.type==="resolving-target"?E(z,{paddingY:1,paddingX:2,children:E(I,{dimColor:!0,children:"Finding available sub-directory\u2026"})}):r.type==="writing"?E(z,{paddingY:1,paddingX:2,children:E(I,{dimColor:!0,children:"Creating plugin\u2026"})}):r.type==="done"?N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(I,{color:"green",bold:!0,children:["Plugin created at ",r.targetDir]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{dimColor:!0,children:"Next steps:"}),N(I,{children:[" ","cd ",r.targetDir]}),N(I,{children:[" ","npx --yes @kizenapps/cli dev"]}),N(I,{dimColor:!0,children:[" ","Replace src/thumbnail.png with real artwork before publishing."]})]}),E(ke,{text:"Enter or Esc to exit"})]}):N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),E(I,{color:"red",bold:!0,children:"Failed to create plugin"}),E(I,{children:r.message}),E(ke,{text:"Enter or Esc to exit"})]})};import{mkdir as nn,readFile as os,readdir as is,writeFile as on}from"fs/promises";import{homedir as ss}from"os";import{dirname as as,join as ht}from"path";var Y=["go","fmo","staging","integration","test1"];var Pe=ht(ss(),".kizenappbuilder"),De=ht(Pe,"credentials.json"),ye="credentials";function ls(e){return Y.includes(e)}function cs(e){if(typeof e!="object"||e===null)throw new Error("Credentials must be a JSON object");let t=e,n=t.environment;return{apiKey:typeof t.apiKey=="string"?t.apiKey:"",userId:typeof t.userId=="string"?t.userId:"",businessId:typeof t.businessId=="string"?t.businessId:"",environment:ls(n)?n:"go"}}async function be(e){let t=await os(e,"utf-8");return cs(JSON.parse(t))}async function Z(){try{return await be(De)}catch{return null}}async function ds(e){await nn(as(De),{recursive:!0,mode:448}),await on(De,JSON.stringify(e,null,2),{encoding:"utf-8",mode:384})}function sn(e){return ht(Pe,`${e}.json`)}async function Ie(){let e=[{name:ye,path:De,isDefault:!0}];try{let t=await is(Pe);for(let n of t){if(!n.endsWith(".json"))continue;let o=n.slice(0,-5);o!==ye&&e.push({name:o,path:ht(Pe,n),isDefault:!1})}}catch{}return e}async function an(e,t){if(e===ye){await ds(t);return}await nn(Pe,{recursive:!0,mode:448}),await on(sn(e),JSON.stringify(t,null,2),{encoding:"utf-8",mode:384})}async function de(e){try{return await be(sn(e))}catch{return null}}var ps="A hello-world Kizen plugin.";function us(e){if(e===void 0||e.trim()===""||e.trim()==="all")return[...X];if(e.trim()==="none")return[];let t=e.split(",").map(o=>o.trim()).filter(o=>o!==""),n=t.filter(o=>!X.includes(o));if(n.length>0)throw new Error(`Unknown artifact type(s): ${n.join(", ")}. Valid types: ${X.join(", ")}, or "all" / "none".`);return[...new Set(t)]}function fs(e,t,n){let o=e.name?.trim()??"";if(o==="")throw new Error("--name is required for a non-interactive run.");let r=(e.apiName?.trim()??"")||ft(o);if(!Jt.test(r))throw new Error(`api_name "${r}" is invalid: ${Wt}. Pass --api-name.`);let i=e.description?.trim(),d=e.businessId?.trim()??t.businessId,f=gs(e,t);return{targetDir:n,name:o,apiName:r,externalLink:e.externalLink?.trim()??"",description:i===void 0||i===""?ps:i,developerBusinessId:d,developerEnvironment:f,artifacts:us(e.artifacts)}}function ms(e){return Y.includes(e)}function gs(e,t){let n=e.environment?.trim();if(n!==void 0&&n!==""){if(!ms(n))throw new Error(`Unknown environment "${n}". Valid environments: ${Y.join(", ")}.`);return n}if(e.businessId!==void 0&&t.businessId==="")throw new Error("--environment is required alongside --business-id when no credentials are saved, so the id is keyed to the environment that issued it.");return t.environment}async function ln(e,t,n,o){let r;try{r=fs(e,t,n)}catch(f){o.writeStderr(`Error: ${f instanceof Error?f.message:String(f)}
|
|
299
|
+
`),o.setExitCode(1);return}let i=await o.precheckTargetDir(n);if(i!=="ok"){let f=i==="has-manifest"?"kizen.json":".kizenapp/";o.writeStderr(`Error: ${n} already contains ${f}. Refusing to overwrite an existing plugin.
|
|
300
|
+
`),o.setExitCode(1);return}try{await o.createPlugin(r)}catch(f){o.writeStderr(`Error: ${f instanceof Error?f.message:String(f)}
|
|
301
|
+
`),o.setExitCode(1);return}let d=r.artifacts&&r.artifacts.length>0?r.artifacts.join(", "):"none";o.writeStdout(`Created plugin ${r.apiName} at ${n}
|
|
302
|
+
`),o.writeStdout(`Artifacts: ${d}
|
|
303
|
+
`),o.writeStdout(`Thumbnail: src/thumbnail.png (generated placeholder; replace it before publishing)
|
|
304
|
+
`),r.developerBusinessId.trim()===""&&o.writeStderr(`Warning: no developer_business_id configured, so this plugin cannot be preview-published yet.
|
|
305
|
+
`)}function cn(e){e.command("create").description("Scaffold a new Kizen plugin project").option("-n, --name <name>","plugin display name (implies a non-interactive run)").option("-a, --api-name <name>","plugin api_name (inferred from --name when omitted)").option("-d, --description <text>","plugin description").option("-l, --external-link <url>","external link shown on the plugin listing").option("-b, --business-id <id>","developer business id (defaults to saved credentials)").option("-e, --environment <env>",`environment the business id belongs to: ${Y.join(", ")} (defaults to saved credentials)`).option("--artifacts <list>",`comma-separated artifact types, or "all" / "none" (default: all). Types: ${X.join(", ")}`).action(async t=>{let n=process.cwd(),o=await Z(),r=o?.businessId??"",i=o?.environment??"go",d=Object.values(t).some(m=>m!==void 0);if(!process.stdin.isTTY||!process.stdout.isTTY||d){await ln(t,{businessId:r,environment:i},n,{precheckTargetDir:dt,createPlugin:pt,writeStdout:m=>{process.stdout.write(m)},writeStderr:m=>{process.stderr.write(m)},setExitCode:m=>{process.exitCode=m}});return}let{waitUntilExit:g}=ys(hs(rn,{parentDir:n,defaultBusinessId:r,defaultEnvironment:i}),{exitOnCtrlC:!1});await g()})}import{createElement as Un}from"react";import{render as Vn}from"ink";import{useCallback as Fe,useEffect as St,useRef as pe,useState as Q}from"react";import{Box as K,Text as B,useInput as ma}from"ink";import{PluginValidationError as ga}from"@kizenapps/packager";import{watch as ha}from"fs";import{createServer as ya}from"http";import{join as Mn}from"path";import{WebSocketServer as ba}from"ws";import{createReadStream as _n,realpathSync as js}from"fs";import{access as $s,readdir as Ls,readFile as Ms,realpath as zs,stat as En}from"fs/promises";import{dirname as Hs,extname as kn,join as Ke,resolve as Us,sep as nr}from"path";import{fileURLToPath as Vs}from"url";var bs=new Set(["set-cookie","strict-transport-security","content-security-policy","content-security-policy-report-only","x-frame-options","content-encoding","content-length"]);function yt(e){let t={};for(let[n,o]of Object.entries(e)){let r=n.toLowerCase();bs.has(r)||r.startsWith("access-control-")||(t[n]=o)}return t}var Kt=10*1024*1024,xs=6e4,vs=200,Ue=class extends Error{bytesRead;limit;constructor(t,n){super(`Upstream response exceeded ${String(n)} bytes (read ${String(t)}).`),this.name="ProxyResponseTooLargeError",this.bytesRead=t,this.limit=n}};async function Gt(e,t){let n=e.body;if(n===null)return Buffer.alloc(0);let o=[],r=0;for await(let i of n){if(r+=i.length,r>t)throw new Ue(r,t);o.push(i)}return Buffer.concat(o)}async function dn(e){let t=yt(Object.fromEntries(e.headers)),n=await Gt(e,Kt);return{status:e.status,headers:t,body:n}}function pn(e={}){let{onChange:t,enabled:n=!0}=e;if(!n)return{async get(d,f){return{response:await dn(await f()),fromCache:!1}},clear(){}};let o=new Map,r=()=>{t?.(o.size)},i=d=>{o.delete(d)&&r()};return{get(d,f){let g=o.get(d);if(g!==void 0){if(Date.now()-g.insertedAt<xs)return g.promise.then(b=>({response:b,fromCache:!0}));i(d)}if(o.size>=vs){let b=o.keys().next().value;b!==void 0&&i(b)}let m=f().then(dn).catch(b=>{throw i(d),b});return o.set(d,{insertedAt:Date.now(),promise:m}),r(),m.then(b=>((b.status<200||b.status>=300)&&i(d),{response:b,fromCache:!1}))},clear(){o.clear(),r()}}}var Yt={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".svg":"image/svg+xml",".ico":"image/x-icon",".json":"application/json; charset=utf-8",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json"};import{mkdir as ws,readFile as Cs,writeFile as Ss}from"fs/promises";import{join as un}from"path";async function xe(e){try{let t=await Cs(un(e,"config.json"),"utf-8");return JSON.parse(t)}catch{return{}}}async function ve(e,t){await ws(e,{recursive:!0}),await Ss(un(e,"config.json"),JSON.stringify(t,null,2),"utf-8")}var Xt={prod:"https://plugin-wizard.kizen.com",dev:"https://plugin-wizard.kizen.dev",localDev:"http://localhost:9823"};function Ve(e){let t=process.env.PLUGIN_WIZARD_URL;return t!==void 0&&t!==""?t:e==="prod"?process.env.PLUGIN_WIZARD_URL_PROD||Xt.prod:process.env.PLUGIN_WIZARD_URL_DEV!==void 0&&process.env.PLUGIN_WIZARD_URL_DEV!==""?process.env.PLUGIN_WIZARD_URL_DEV:process.env.APPBUILDER_LOCAL_DEV!==void 0&&process.env.APPBUILDER_LOCAL_DEV!==""?Xt.localDev:Xt.dev}import{spawn as tr}from"child_process";import{writeFile as yn,rm as er,mkdtemp as ks,access as Ps}from"fs/promises";import{join as Je}from"path";import{tmpdir as Is}from"os";var fn=`awslambdaric
|
|
9
306
|
bcrypt
|
|
10
307
|
fpdf2
|
|
11
308
|
lxml
|
|
@@ -22,7 +319,8 @@ pytz
|
|
|
22
319
|
requests
|
|
23
320
|
sqlalchemy>=2.0,<2.1
|
|
24
321
|
tzdata
|
|
25
|
-
`;
|
|
322
|
+
`;function mn(e){return e.split(`
|
|
323
|
+
`).map(t=>t.trim().replace(/\s+#.*$/,"")).filter(t=>t.length>0&&!t.startsWith("#"))}function gn(e){let t=/^python-(\d+)[.-](\d+)$/.exec(e),n=t?.[1],o=t?.[2];return n!==void 0&&o!==void 0?`python${n}.${o}`:"python3"}function _s(e){return e==null||e.trim()===""?null:e}function Es(e){return e==null?null:typeof e=="string"?_s(e):typeof e=="number"||typeof e=="boolean"||typeof e=="bigint"?String(e):typeof e=="function"||typeof e=="symbol"?null:JSON.stringify(e)}function hn(e){return e?Object.fromEntries(Object.entries(e).map(([t,n])=>[t,Es(n)])):{}}var Rs=`
|
|
26
324
|
import sys, json, os, traceback
|
|
27
325
|
|
|
28
326
|
# --- Inputs proxy (attribute access) ---
|
|
@@ -182,30 +480,29 @@ sys.stdout.write('\\n__KIZEN_RESULT_START__\\n')
|
|
|
182
480
|
sys.stdout.write(json.dumps(result, ensure_ascii=False))
|
|
183
481
|
sys.stdout.write('\\n__KIZEN_RESULT_END__\\n')
|
|
184
482
|
sys.stdout.flush()
|
|
185
|
-
`.trim(),
|
|
186
|
-
`)
|
|
187
|
-
`)
|
|
188
|
-
`)}}),m.on("end",()=>{if(S.length>0){let N=S.replace(/\r$/,"");y.push(N),o?.(N,b)}}),y},p=u(i.stderr,"stderr");u(i.stdout,"stdout"),i.on("error",r),i.on("close",m=>{if(m===0)n();else{let b=p.slice(-10).join(`
|
|
189
|
-
`).trim(),y=b.length>0?`: ${b}`:"";r(new Error(`${e} exited with code ${String(m)}${y}`))}})})}var jt=null;function Ho(e,t){if(Ve)return t&&jt?.add(t),Ve;let o=new Set;t&&o.add(t),jt=o;let n=i=>{for(let u of o)u(i)},r=qe(dt,"bin","python");return Ve=(async()=>{try{let i=!1;try{await $o(r);let u=await Nr(r);i=u!==null&&Ir(u)}catch{i=!1}if(!i){await zt(dt,{recursive:!0,force:!0}).catch(()=>{});let u=await Mo(e);await Pr(u,["-m","venv",dt])}return n({kind:"start"}),await Pr(r,["-m","pip","install","--disable-pip-version-check",..._r],(u,p)=>{n({kind:"log",line:u,stream:p})}),n({kind:"complete"}),r}catch(i){let u=i instanceof Error?i.message:String(i);throw n({kind:"error",message:u}),Ve=null,await zt(dt,{recursive:!0,force:!0}).catch(()=>{}),i}finally{jt=null}})(),Ve}function Uo(e){let t="__KIZEN_RESULT_START__",o="__KIZEN_RESULT_END__",n=e.indexOf(t),r=e.indexOf(o);if(n===-1||r===-1)return{userStdout:e,result:null};let i=e.slice(0,n).trimEnd(),u=e.slice(n+t.length,r).trim();try{let p=JSON.parse(u);return{userStdout:i,result:p}}catch{return{userStdout:e,result:null}}}function Vo(e){return{success:!1,outputValues:{},logs:[],stdout:"",stderr:"",error:e,exitCode:1,durationMs:0}}async function Br(e){let t=e.timeout??Ao;if(!Oo(e.scriptRuntime))return Vo(`Unsupported runtime "${e.scriptRuntime}". Supported runtimes: ${kr.join(", ")}. Update the step's config.json "runtime" field (e.g. "python 3.13").`);let o=await Ho(e.scriptRuntime,e.onInstallProgress),n=Date.now(),r;try{r=await Do(qe(Lo(),"kizen-step-"));let i=qe(r,"wrapper.py"),u=qe(r,"script.py");await Promise.all([Er(i,Fo,"utf-8"),Er(u,e.script,"utf-8")]);let p={...process.env,__KIZEN_INPUTS__:JSON.stringify(e.inputs),__KIZEN_SECRETS__:JSON.stringify(e.secrets),__KIZEN_SCRIPT_PATH__:u},{exitCode:m,stdout:b,stderr:y}=await new Promise(h=>{let T=[],P=[],x=!1,w=Mt(o,[i],{env:p,cwd:r,stdio:["ignore","pipe","pipe"]}),k=setTimeout(()=>{w.kill("SIGKILL")},t);w.stdout.on("data",a=>{T.push(a)}),w.stderr.on("data",a=>{P.push(a)});let f=a=>{x||(x=!0,clearTimeout(k),h({exitCode:a??1,stdout:Buffer.concat(T).toString("utf-8"),stderr:Buffer.concat(P).toString("utf-8")}))};w.on("close",f),w.on("error",a=>{x||(x=!0,clearTimeout(k),h({exitCode:1,stdout:"",stderr:a.message}))})}),S=Date.now()-n,{userStdout:N,result:v}=Uo(b);if(v){let h={success:v.success,outputValues:v.outputValues,logs:v.logs,stdout:N,stderr:y,exitCode:m,durationMs:S};return v.error!==null&&(h.error=v.error),v.httpRequests&&(h.httpRequests=v.httpRequests),h}let c={success:!1,outputValues:{},logs:[],stdout:N,stderr:y,exitCode:m,durationMs:S};return m!==0&&(c.error=`Process exited with code ${String(m)}`),c}finally{r&&zt(r,{recursive:!0,force:!0})}}var Rr=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".json",".md",".mdx",".yml",".yaml",".toml",".css",".scss",".html",".htm",".xml",".svg",".txt",".sh",".py",".env",".gitignore",".prettierrc",".eslintrc"]);import{CRYPTO_ALG as Fr,CRYPTO_VERSION as Ar,deserializeEnvelope as Qo,encrypt as ei,serializeEnvelope as ti}from"@kizenapps/packager";function Ht(e){if(e.kind==="info")return e.message;let t=e.fromCache?" [cache]":"",o=e.upstreamStatus!==void 0?` (upstream ${String(e.upstreamStatus)})`:"";return`${e.method} ${e.url} \u2192 ${String(e.status)}${o}${t}`}var ri=2*1024*1024,ni=new Set([".DS_Store",".gitignore"]);function oi(e){if(e===void 0||e==="")return!1;let t=e.startsWith("[")?e.slice(0,e.indexOf("]")+1):e.split(":")[0]??"";return t==="localhost"||t==="127.0.0.1"||t==="[::1]"}var Mr=["kizen.com","kizen.dev"];function ii(e){let t;try{t=new URL(e)}catch{return!1}let o=t.hostname.toLowerCase();return o==="localhost"||o==="127.0.0.1"||o==="[::1]"?!0:t.protocol!=="https:"?!1:Mr.some(n=>o===n||o.endsWith("."+n))}function si(e){let t;try{t=new URL(e)}catch{return!1}if(t.protocol!=="https:")return!1;let o=t.hostname.toLowerCase();return Mr.some(n=>o===n||o.endsWith("."+n))}function ai(e){if(e===void 0||e==="")return!1;try{let{hostname:t}=new URL(e);return t==="localhost"||t==="127.0.0.1"||t==="::1"}catch{return!1}}async function Or(e,t){if(t.includes("\0"))return null;let o=t.replace(/^\/+/,""),n=Xo(e,o);if(n!==e&&!n.startsWith(e+Ut))return null;try{let r=await Ko(n);return r!==e&&!r.startsWith(e+Ut)?null:r}catch{return null}}function jr(e,t){let o=t===e?"":t.slice(e.length+1);return o===""?!1:o.split(Ut).some(r=>et.has(r))}function Hr(){let e=Zo(import.meta.url);return We(Yo(e),"viewer")}function zr(e,t,o){if(e.includes("/external-integrations/proxy")&&t["content-type"]?.includes("application/json"))try{let n=JSON.parse(o.toString("utf8"));return typeof n.status_code=="number"?n.status_code:void 0}catch{return}}async function Vt(e){try{return await Jo(e),!0}catch{return!1}}function Ur(e,t,o,n,r,i,u,p,m,b,y){let S=Cr({onChange:p,enabled:y}),N=qo(b);return(v,c)=>{(async()=>{let h=v.url??"/";try{if(!oi(v.headers.host)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Forbidden"}));return}if((v.method==="POST"||v.method==="PATCH"||v.method==="DELETE")&&!ai(v.headers.origin)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Forbidden"}));return}if(t(`Received request: ${h}`),h==="/api/credentials"){c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({credentials:n.current??null,activeProfile:r.current??null}));return}if(h==="/api/credential-profiles"&&v.method==="GET"){let a=await _e();c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({profiles:a,active:r.current}));return}if(h==="/api/credentials/switch"&&v.method==="POST"){let a=[];for await(let g of v)a.push(g);let l=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}").profile,d=l===void 0||l===""?await Y():await le(l);if(d!==null){n.current=d,r.current=l??void 0;let g=r.current,I=await ye(i);await he(i,{...I,credentialMode:"global",...g!==void 0&&{activeCredentialProfile:g}}),u({type:"credentials-updated",credentials:d,activeProfile:r.current??null})}c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({ok:d!==null}));return}if(h==="/api/bundle"){let a=We(process.cwd(),".kizenapp","bundle.json");try{let s=await Go(a,"utf-8");c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(s)}catch{c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end("{}")}return}if(h==="/api/last-path"&&v.method==="POST"){let a=[];for await(let l of v)a.push(l);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.path=="string"){m.current=s.path;let l=await ye(i);await he(i,{...l,lastPath:s.path})}c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end('{"ok":true}');return}if(h==="/api/encryption-target"&&v.method==="GET"){let s=(await ye(i)).encryptionTarget==="dev"?"dev":"prod";c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({target:s}));return}if(h==="/api/encryption-target"&&v.method==="POST"){let a=[];for await(let g of v)a.push(g);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}"),l=s!==null&&typeof s=="object"?s:{};if(l.target!=="dev"&&l.target!=="prod"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"target must be one of: 'dev', 'prod'"}));return}let d=await ye(i);await he(i,{...d,encryptionTarget:l.target}),c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end('{"ok":true}');return}if(h==="/api/execute-step"&&v.method==="POST"){let a=[];for await(let g of v)a.push(g);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.script!="string"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing required field: script"}));return}let l={script:s.script,scriptRuntime:s.scriptRuntime??"python-3-13",inputs:s.inputs??{},secrets:s.secrets??{},onInstallProgress:g=>{g.kind==="start"?u({type:"venv-install-start"}):g.kind==="log"?u({type:"venv-install-log",line:g.line,stream:g.stream}):g.kind==="complete"?u({type:"venv-install-complete"}):u({type:"venv-install-error",message:g.message})}};typeof s.timeout=="number"&&s.timeout>0&&(l.timeout=Math.min(s.timeout,300*1e3));let d=await Br(l);c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify(d));return}if(h==="/api/proxy-cache/clear"){S.clear(),o({kind:"info",message:"Proxy cache cleared"}),c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end('{"ok":true}');return}if(h==="/api/local/encrypt"&&v.method==="POST"){let a=[];for await(let l of v)a.push(l);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.publicKeyPem!="string"||typeof s.value!="string"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing required fields: publicKeyPem, value"}));return}try{let l=ei(s.value,s.publicKeyPem),d=ti(l);c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify(d))}catch(l){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:l.message}))}return}if(h==="/api/local/validate"&&v.method==="POST"){let a=[];for await(let E of v)a.push(E);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.value!="string"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing required field: value"}));return}let l,d;try{l=Qo(s.value)}catch(E){d=E.message}if(d!==void 0||l===void 0){c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({valid:!1,checks:[],error:d}));return}let g=E=>Buffer.from(E,"base64").length,I=[{label:"Version",expected:String(Ar),actual:String(l.v),pass:l.v===Ar},{label:"Algorithm",expected:Fr,actual:l.alg,pass:l.alg===Fr},{label:"Wrapped key",expected:"384 bytes (RSA-3072)",actual:`${String(g(l.k))} bytes`,pass:g(l.k)===384},{label:"IV",expected:"12 bytes",actual:`${String(g(l.iv))} bytes`,pass:g(l.iv)===12},{label:"Auth tag",expected:"16 bytes",actual:`${String(g(l.tag))} bytes`,pass:g(l.tag)===16},{label:"Ciphertext",expected:"\u2265 1 byte",actual:`${String(g(l.ct))} bytes`,pass:g(l.ct)>=1}];c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({valid:I.every(E=>E.pass),checks:I}));return}if(h.startsWith("/api/wizard")){let a=v.headers["x-encryption-target"],l=(Array.isArray(a)?a[0]:a)==="dev"?"dev":"prod",d=Ue(l);if(!ii(d)){c.writeHead(500,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:`Encryption API host is not allowed: ${d}`}));return}let g=h.slice(11)||"/",I=`${d}${g}`,E=v.method??"GET",F=[];for await(let we of v)F.push(we);let{host:M,"x-encryption-target":K,...Q}=v.headers,ne=F.length>0?Buffer.concat(F):void 0,oe=ne&&ne.length>0?ne:void 0,ee;try{ee=await fetch(I,{method:E,headers:Q,...oe!==void 0&&{body:oe}})}catch(we){let wt=we.code==="ECONNREFUSED"?`plugin-wizard is not running at ${d}`:`Failed to reach plugin-wizard: ${we.message}`;c.writeHead(503,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:wt}));return}let Z=ct(Object.fromEntries(ee.headers)),Le=await ee.arrayBuffer();c.writeHead(ee.status,Z),c.end(Buffer.from(Le));return}if(h.startsWith("/api/proxy")){let a=v.headers["x-proxy-target"];if(typeof a!="string"){c.writeHead(400),c.end("Missing x-proxy-target header");return}if(!si(a)){c.writeHead(400),c.end("Invalid proxy target");return}let s=h.slice(10)||"/",l=`${a}${s}`,d=v.method??"GET",g=[];for await(let ee of v)g.push(ee);let{host:I,"x-proxy-target":E,...F}=v.headers;if(d==="GET"){let ee=`GET::${l}`,{response:Z,fromCache:Le}=await S.get(ee,()=>fetch(l,{method:"GET",headers:F}));o({kind:"request",method:"GET",status:Z.status,upstreamStatus:zr(s,Z.headers,Z.body),fromCache:Le,url:s}),c.writeHead(Z.status,Z.headers),c.end(Z.body);return}let M=g.length>0?Buffer.concat(g):void 0,K=M&&M.length>0?M:void 0,Q=await fetch(l,{method:d,headers:F,...K!==void 0&&{body:K}}),ne=ct(Object.fromEntries(Q.headers)),oe=await Lt(Q,$t);o({kind:"request",method:d,status:Q.status,upstreamStatus:zr(s,ne,oe),fromCache:!1,url:s}),c.writeHead(Q.status,ne),c.end(oe);return}if(h.startsWith("/api/source/tree")&&v.method==="GET"){let s=new URL(h,"http://localhost").searchParams.get("path")??"",l=await Or(N,s);if(l===null){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Invalid path"}));return}if(jr(N,l)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Path is excluded"}));return}try{let d=await Wo(l,{withFileTypes:!0}),g=await Promise.all(d.filter(E=>E.isDirectory()?!et.has(E.name):E.isFile()?!ni.has(E.name):!1).map(async E=>{let F=E.isDirectory()?"dir":"file",M={name:E.name,kind:F};if(F==="file")try{let K=await $r(We(l,E.name));M.size=K.size}catch{}return M}));g.sort((E,F)=>E.kind!==F.kind?E.kind==="dir"?-1:1:E.name.localeCompare(F.name));let I=l===N?"":l.slice(N.length+1);c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({path:I,entries:g}))}catch(d){let g=d instanceof Error?d.message:String(d);t(`source/tree failed (${s}): ${g}`),c.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Not found"}))}return}if(h.startsWith("/api/source/file")&&v.method==="GET"){let s=new URL(h,"http://localhost").searchParams.get("path")??"";if(s===""){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing path"}));return}let l=await Or(N,s);if(l===null){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Invalid path"}));return}if(jr(N,l)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Path is excluded"}));return}try{let d=await $r(l);if(!d.isFile()){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Not a file"}));return}if(d.size>ri){c.writeHead(413,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"File too large",size:d.size}));return}let g=Lr(l).toLowerCase(),I=Ft[g],E=Rr.has(g),F=I??(E?"text/plain; charset=utf-8":"application/octet-stream");c.writeHead(200,{"Content-Type":F,"Content-Length":String(d.size)}),Dr(l).pipe(c)}catch(d){let g=d instanceof Error?d.message:String(d);t(`source/file failed (${s}): ${g}`),c.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Not found"}))}return}let x=We(e,h==="/"?"/index.html":h),w=await Vt(x)?x:We(e,"index.html"),k=Lr(w),f=Ft[k]??"application/octet-stream";c.writeHead(200,{"Content-Type":f}),Dr(w).pipe(c)}catch(T){if(h.startsWith("/api/proxy")){let P=h.slice(10)||"/",x=v.method??"GET";T instanceof He?o({kind:"info",message:`${x} ${P} \u2192 502 (response exceeded ${String(T.limit)} bytes)`}):o({kind:"request",method:x,status:502,fromCache:!1,url:P})}else o({kind:"info",message:`Error handling ${h}: ${T instanceof Error?T.message:String(T)}`});c.headersSent||(c.writeHead(502),c.end("Bad Gateway"))}})()}}import{launch as li}from"chrome-launcher";import{createRequire as ci}from"module";import{mkdirSync as di}from"fs";import{readFile as ui}from"fs/promises";import{dirname as pi,join as fi}from"path";import{fileURLToPath as mi}from"url";var Vr=ci(import.meta.url)("chrome-remote-interface"),gi=new Set(["content-security-policy","content-security-policy-report-only","x-frame-options"]),Jr=["kizen.dev","kizen.com"];function qr(e){try{let{hostname:t}=new URL(e);return Jr.some(o=>t===o||t.endsWith("."+o))}catch{return!1}}async function yi(e){try{let t=fi(pi(mi(import.meta.url)),"viewer","icon.png"),o=await ui(t);await e.Browser.setDockTile({image:o.toString("base64")})}catch{}}async function Wr(e){di(e.userDataDir,{recursive:!0});let t=`http://localhost:${String(e.port)}`,o=await li({startingUrl:t,chromeFlags:[`--app=${t}`,"--no-first-run","--no-default-browser-check","--disable-extensions","--disable-features=DeviceBoundSessions"],userDataDir:e.userDataDir,handleSIGINT:!1,logLevel:"silent"}),n=o.port,r=null,i=null,u=null,p=null,m=0,b=!1,y=w=>{e.debugLog?.(w)},S=w=>{e.verbose&&e.debugLog?.(w)},N=()=>{i!==null&&(clearInterval(i),i=null)},v=w=>w==="chrome://new-tab-page/"||w==="chrome://newtab/",c=async w=>{N(),u=null,await yi(w),await w.Fetch.enable({patterns:Jr.flatMap(f=>[{urlPattern:`*://${f}/*`,requestStage:"Response"},{urlPattern:`*://*.${f}/*`,requestStage:"Response"}])}),w.on("Fetch.requestPaused",f=>{(async()=>{let a=f,{requestId:s,request:l,responseHeaders:d,responseStatusCode:g}=a,I=l.url;S(`Fetch ${String(g??"?")} ${I}`);let E=[],F=!1;for(let M of d??[])if(!gi.has(M.name.toLowerCase()))if(M.name.toLowerCase()==="set-cookie"&&qr(I)){let K=M.value.split(`
|
|
190
|
-
`).map(Q=>/SameSite=/i.test(Q)?Q.replace(/SameSite=\w+/i,"SameSite=None"):Q+"; SameSite=None; Secure").join(`
|
|
191
|
-
`);E.push({name:M.name,value:K}),F=!0}else E.push(M);F&&S(` rewrote Set-Cookie SameSite on ${I}`);try{let{body:M,base64Encoded:K}=await w.Fetch.getResponseBody({requestId:s});await w.Fetch.fulfillRequest({requestId:s,responseCode:g??200,responseHeaders:E,body:M,...K&&{base64Encoded:!0}})}catch(M){S(` fulfillRequest failed (${M.message}), falling through`);try{await w.Fetch.continueRequest({requestId:s})}catch(K){S(` continueRequest also failed (${K.message})`)}}})()}),i=setInterval(()=>{(async()=>{try{let{cookies:f}=await w.Network.getAllCookies(),a=0;for(let s of f){if(!qr(`https://${s.domain??""}`)||s.sameSite==="None")continue;let l=s.domain??"",d=l.startsWith(".")?l.slice(1):l;await w.Network.setCookie({url:`https://${d}`,name:s.name,value:s.value,domain:l,path:s.path??"/",secure:!0,...s.httpOnly!==void 0&&{httpOnly:s.httpOnly},...s.expirationDate!==void 0&&{expires:s.expirationDate},sameSite:"None"}),a++}a>0&&S(`cookie-patch cycle: updated ${String(a)} cookie(s) to SameSite=None`)}catch(f){S(`cookie-patch cycle failed: ${f.message}`)}})()},2e3),await w.Target.setDiscoverTargets({discover:!0});let k=f=>{if(f.type==="page"){if(v(f.url)){y(`closed stray new-tab-page target ${f.targetId}`),u!==null&&w.Target.activateTarget({targetId:u}).catch(()=>{}),w.Target.closeTarget({targetId:f.targetId}).catch(()=>{});return}u===null&&(u=f.targetId,y(`captured main target ${f.targetId} (${f.url})`))}};w.on("Target.targetCreated",f=>{let{targetInfo:a}=f;S(`target +${a.type} ${a.targetId} ${a.url}`),k(a)}),w.on("Target.targetInfoChanged",f=>{let{targetInfo:a}=f;S(`target ~${a.type} ${a.targetId} ${a.url}`),k(a)}),w.on("disconnect",()=>{b||r!==w||(y("CDP disconnected"),r=null,N(),h())})},h=()=>{if(b||p!==null)return;let w=Math.min(1e3*2**m,1e4),k=m+1;m++,y(`CDP reconnect scheduled in ${String(w)}ms (attempt #${String(k)})`),p=setTimeout(()=>{p=null,(async()=>{let f;try{f=await Vr({port:n})}catch{y(`CDP reconnect attempt #${String(k)} failed`),h();return}if(b){try{await f.close()}catch{}return}r=f;try{await c(f),y(`CDP reconnected after ${String(k)} attempt(s)`),m=0}catch{r===f&&(r=null);try{await f.close()}catch{}y(`CDP reconnect attempt #${String(k)} failed during setup`),h()}})()},w)},T=30,P=300;for(let w=0;w<T;w++){await new Promise(k=>setTimeout(k,P)),y(`CDP connect attempt ${String(w+1)}/${String(T)}`);try{let k=await Vr({port:n});r=k,e.path&&k.send("Page.navigate",{url:`${t}${e.path}`});try{await c(k),y("CDP connected")}catch{r===k&&(r=null);try{await k.close()}catch{}y("CDP setup failed after connect")}break}catch{if(w===T-1){let k=`CDP unavailable after ${String(T)} attempts \u2014 viewer running without interception (CSP/cookie rewrites disabled)`;return y(k),e.onWarn?.(k),{kill:()=>{o.kill()}}}}}return r?{kill:()=>{if(y("CDP kill requested \u2014 tearing down"),b=!0,p!==null&&(clearTimeout(p),p=null),N(),r!==null){try{r.close()}catch{}r=null}o.kill()}}:{kill:()=>{o.kill()}}}import{useCallback as hi,useState as bi}from"react";function ut(e){let[t,o]=bi([]),n=hi(r=>{o(i=>[...i,`${new Date().toLocaleTimeString()}: ${r}`].slice(-e))},[e]);return[t,n]}import{useCallback as pt,useEffect as qt,useState as ft}from"react";import{Box as U,Text as A,useInput as xi}from"ink";import{jsx as _,jsxs as J}from"react/jsx-runtime";var be=["apiKey","userId","businessId"],vi={apiKey:"API Key",userId:"User ID",businessId:"Business ID"},Ge=({text:e})=>_(A,{dimColor:!0,children:e}),mt=({initialMode:e,showProfileManager:t,onComplete:o,onCancel:n})=>{let[r,i]=ft(e==="global"&&!t?{type:"loading"}:e==="global"&&t?{type:"profile-loading"}:{type:"mode-select",cursor:0}),[u,p]=ft(""),[m,b]=ft(null),[y,S]=ft(void 0),N=pt(f=>{if(f==="local"){o({mode:"local",credentials:null});return}i({type:"profile-loading"})},[o]),v=pt(async f=>{if(f===null){i({type:"profile-loading"});let l=await _e();i({type:"name-entry",nameBuffer:"",existingProfiles:l});return}S(f.isDefault?void 0:f.name),i({type:"loading"});let a=f.isDefault?await Y():await le(f.name),s=a?Math.max(0,re.indexOf(a.environment)):0;i({type:"creds-entry",field:0,values:a??{},envCursor:s})},[]),c=pt(async(f,a)=>{let s=re[a]??"go",l={apiKey:f.apiKey??"",userId:f.userId??"",businessId:f.businessId??"",environment:s};i({type:"saving"});try{await xr(y??me,l),o({mode:"global",credentials:l,...y!==void 0&&{profileName:y}})}catch(d){b(d instanceof Error?d.message:String(d)),i({type:"creds-entry",field:0,values:f,envCursor:a})}},[o,y]);xi((f,a)=>{if(a.ctrl&&f==="c"&&process.exit(0),a.escape){if((r.type==="creds-entry"||r.type==="name-entry")&&e==="global"&&t){i({type:"profile-loading"}),h();return}n?.();return}if(r.type==="mode-select"){if(a.upArrow)i({type:"mode-select",cursor:0});else if(a.downArrow)i({type:"mode-select",cursor:1});else if(a.return){let s=r.cursor===0?"global":"local";N(s)}return}if(r.type==="profile-select"){let{profiles:s,cursor:l}=r,d=s.length,g=s.length+1;if(a.upArrow)i({...r,cursor:(l-1+g)%g});else if(a.downArrow)i({...r,cursor:(l+1)%g});else if(a.return)if(l===d)i({type:"name-entry",nameBuffer:"",existingProfiles:s});else{let I=s[l]??s[0];I&&v(I)}return}if(r.type==="name-entry"){let{nameBuffer:s,existingProfiles:l}=r;if(a.backspace||a.delete)i({type:"name-entry",nameBuffer:s.slice(0,-1),existingProfiles:l});else if(a.return){let d=s.trim();if(!d){i({...r,nameError:"Name cannot be empty"});return}if(d===me){i({...r,nameError:`"${me}" is reserved`});return}if(l.some(g=>g.name===d)){i({...r,nameError:`Profile "${d}" already exists`});return}S(d),i({type:"creds-entry",field:0,values:{},envCursor:0}),p("")}else f&&!a.ctrl&&!a.meta&&i({type:"name-entry",nameBuffer:s+f,existingProfiles:l});return}if(r.type==="creds-entry"){let{field:s,values:l,envCursor:d}=r;if(s===be.length){a.leftArrow?i({...r,envCursor:(d-1+re.length)%re.length}):a.rightArrow?i({...r,envCursor:(d+1)%re.length}):a.upArrow?(i({...r,field:s-1}),p(l[be[s-1]]??"")):a.return&&c(l,d);return}let I=be[s];if(!I)return;if(a.backspace||a.delete)p(E=>E.slice(0,-1));else if(a.upArrow&&s>0){let E={...l,[I]:u},F=s-1;i({...r,field:F,values:E}),p(E[be[F]]??"")}else if(a.return||a.tab||a.downArrow){let E={...l,[I]:u},F=s+1;i({...r,field:F,values:E}),F<be.length?p(E[be[F]]??""):p("")}else f&&!a.ctrl&&!a.meta&&p(E=>E+f)}});let h=pt(async()=>{let f=await _e();i({type:"profile-select",profiles:f,cursor:0})},[]);if(qt(()=>{r.type==="profile-loading"&&h()},[r.type,h]),qt(()=>{e==="global"&&!t&&(async()=>{let f=await Y(),a=f?Math.max(0,re.indexOf(f.environment)):0;i({type:"creds-entry",field:0,values:f??{},envCursor:a})})()},[]),qt(()=>{r.type==="creds-entry"&&r.field===0&&p(r.values.apiKey??"")},[r.type]),r.type==="loading"||r.type==="saving"||r.type==="profile-loading"){let f=r.type==="saving"?"Saving credentials\u2026":r.type==="profile-loading"?"Loading profiles\u2026":"Loading credentials\u2026";return _(U,{paddingY:1,paddingX:2,children:_(A,{dimColor:!0,children:f})})}if(r.type==="done")return null;if(r.type==="mode-select")return J(U,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),J(U,{flexDirection:"column",gap:0,children:[_(A,{bold:!0,children:"Credential mode"}),[{label:"Global",desc:"~/.kizenappbuilder/credentials.json",mode:"global"},{label:"Local",desc:"Enter credentials in the browser dev tools",mode:"local"}].map((a,s)=>{let l=r.cursor===s;return J(U,{gap:2,children:[_(A,{...l&&{color:"cyan"},children:l?"\u276F":" "}),_(A,{bold:l,...l&&{color:"cyan"},children:a.label}),_(A,{dimColor:!0,children:a.desc})]},a.mode)})]}),_(Ge,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]});if(r.type==="profile-select"){let{profiles:f,cursor:a}=r,s=f.length;return J(U,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),J(U,{flexDirection:"column",gap:0,children:[_(A,{bold:!0,children:"Credential profiles"}),f.map((l,d)=>{let g=a===d;return J(U,{gap:2,children:[_(A,{...g&&{color:"cyan"},children:g?"\u276F":" "}),_(A,{bold:g,...g&&{color:"cyan"},children:l.isDefault?"Default":l.name}),_(A,{dimColor:!0,children:l.path})]},l.name)}),J(U,{gap:2,children:[_(A,{...a===s&&{color:"cyan"},children:a===s?"\u276F":" "}),_(A,{bold:a===s,...a===s&&{color:"cyan"},children:"+ Add new profile"})]})]}),_(Ge,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="name-entry"){let{nameBuffer:f,nameError:a}=r;return J(U,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),_(U,{flexDirection:"column",gap:0,children:_(A,{bold:!0,children:"New credential profile"})}),a&&J(A,{color:"red",children:["Error: ",a]}),J(U,{gap:2,children:[_(U,{width:12,children:_(A,{bold:!0,color:"cyan",children:"Profile name"})}),_(A,{color:"cyan",children:">"}),_(A,{children:f}),_(A,{color:"cyan",children:"\u2588"})]}),_(Ge,{text:"Type a name \xB7 Enter to confirm \xB7 Esc to go back"})]})}let{field:T,values:P,envCursor:x}=r,w=T===be.length,k=y??me;return J(U,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),J(U,{flexDirection:"column",gap:0,children:[_(A,{bold:!0,children:y!==void 0?`Profile: ${y}`:"Global credentials"}),J(A,{dimColor:!0,children:["Saved to:"," ",y!==void 0?`~/.kizenappbuilder/${y}.json`:De]})]}),m&&J(A,{color:"red",children:["Error: ",m]}),J(U,{flexDirection:"column",gap:0,children:[be.map((f,a)=>{let s=T===a,l=s?u:P[f]??"";return J(U,{gap:2,children:[_(U,{width:12,children:_(A,{bold:s,...s&&{color:"cyan"},children:vi[f]})}),_(A,{...s&&{color:"cyan"},children:">"}),_(A,{children:l}),s&&_(A,{color:"cyan",children:"\u2588"})]},f)}),J(U,{gap:2,children:[_(U,{width:12,children:_(A,{bold:w,...w&&{color:"cyan"},children:"Environment"})}),_(A,{...w&&{color:"cyan"},children:">"}),_(U,{gap:1,children:re.map((f,a)=>{let s=a===x;return w?_(A,{bold:s,...s&&{color:"cyan"},children:s?`[${f}]`:f},f):_(A,{dimColor:!s,bold:s,children:f},f)})})]})]}),w?_(Ge,{text:"\u2190\u2192 to select \xB7 \u2191\u2193 to move \xB7 Enter to save \xB7 Esc to cancel"}):_(Ge,{text:"\u2191\u2193 to move \xB7 Backspace to delete \xB7 Esc to cancel"}),J(A,{dimColor:!0,children:["Profile: ",k]})]})};import{jsx as $,jsxs as H}from"react/jsx-runtime";var ki=[".kizenapp",".git"],Kr=({port:e,pluginDir:t,outputDir:o,credentials:n,credentialMode:r,activeCredentialProfile:i,lastPath:u,debug:p=!1,verbose:m=!1,autoViewer:b=!0,cacheEnabled:y=!0})=>{let S=ce(n),N=ce(i),v=ce(u),[c,h]=X("main"),[T,P]=X(r),[x,w]=X("starting"),[k,f]=X(null),[a,s]=ut(50),[l,d]=ut(50),[g,I]=ut(50),[E,F]=X([]),[M,K]=X("pending"),[Q,ne]=X(null),[oe,ee]=X(null),[Z,Le]=X(null),[we,wt]=X(null),[Ct,St]=X(0),[Gt,Sn]=X(0),[Tn,En]=X(0),[Tt,Pn]=X(0),Et=ce(!1),Kt=ce(!1),Ye=ce(null),Fe=ce(null),de=ce(new Set),Xe=ce([]),te=$e(C=>{let j=JSON.stringify(C);if(de.current.size===0){Xe.current=[...Xe.current,j].slice(-50);return}let ue=!1;for(let ie of de.current)if(ie.readyState===1)try{ie.send(j)}catch{de.current.delete(ie),ue=!0}ue&&St(de.current.size)},[]),Ze=s,Pt=$e(()=>{Ye.current?.kill(),Ye.current=null,Wr({port:e,userDataDir:Gr(o,".chrome"),broadcast:te,onWarn:C=>{s(`\u26A0 ${C}`)},...v.current!==void 0&&{path:v.current},...p&&{debugLog:I},...m&&{verbose:!0}}).then(C=>{Ye.current=C})},[e,o,te,p,m,I,s]);gt(()=>{let C=()=>{Ye.current?.kill()};return process.on("exit",C),()=>{process.off("exit",C)}},[]),Ci((C,j)=>{(C==="q"||j.ctrl&&C==="c")&&process.exit(0),C==="c"&&h("editing"),C==="v"&&Pt()},{isActive:c==="main"}),gt(()=>{x!=="running"||Kt.current||!b||(Kt.current=!0,Pt())},[x,b,Pt]);let kn=$e(C=>{S.current=C.credentials,N.current=C.profileName,h("main"),P(C.mode);let j=C.profileName;he(o,{credentialMode:C.mode,...j!==void 0&&{activeCredentialProfile:j}}),te({type:"credentials-updated",credentials:C.credentials})},[o,te]),Yt=$e(C=>{F(j=>[...j,`${new Date().toLocaleTimeString()}: ${Ht(C)}`].slice(-50)),C.kind==="request"&&(C.fromCache?En(j=>j+1):Pn(j=>j+1)),te({type:"proxy-log",entry:C})},[te]),Ce=$e(C=>{d(C),te({type:"log",message:C})},[d,te]),kt=$e(()=>{Et.current||(Et.current=!0,K("building"),ne(null),ee(null),Ce("Build started"),rt(t,o).then(({bundleSize:C})=>{Ce(`Build finished \u2014 bundle: ${Ae(C)}`),K("done"),Le(new Date),wt(C),Ce("Notifying viewers to reload"),te({type:"rebuild"})}).catch(C=>{C instanceof Si?(ee(C.issues),ne(null)):(ne(C instanceof Error?C.message:String(C)),ee(null)),K("error")}).finally(()=>{Et.current=!1}))},[t,o,Ce,te]);if(gt(()=>{kt();let C=Ti(t,{recursive:!0},(j,ue)=>{if(!ue)return;let ie=ue.replace(/\\/g,"/");ki.some(Qe=>ie.startsWith(Qe))||(Ce(`File change detected: ${ue}`),Fe.current!==null&&clearTimeout(Fe.current),Fe.current=setTimeout(kt,150))});return C.on("error",j=>{Ce(`File watcher error \u2014 rebuilds have stopped: ${j.message}`)}),()=>{C.close(),Fe.current!==null&&clearTimeout(Fe.current)}},[t,kt,Ce]),gt(()=>{let C=Hr();Vt(Gr(C,"index.html")).then(j=>{if(!j){f("Viewer not built. Run 'pnpm build:viewer' first."),w("error");return}let ue=Ur(C,Ze,Yt,S,N,o,te,Sn,v,t,y),ie=Ei(ue),Qe=new Pi({server:ie});return Qe.on("connection",Se=>{for(let In of Xe.current)Se.readyState===1&&Se.send(In);Xe.current=[],Ze("Viewer connected for live reload"),de.current.add(Se),St(de.current.size),Se.on("close",()=>{de.current.delete(Se),St(de.current.size)})}),ie.listen(e,"127.0.0.1",()=>{w("running"),Ze(`Server started on 127.0.0.1:${String(e)}`)}),ie.on("error",Se=>{f(Se.message),w("error")}),()=>{Qe.close(),ie.close()}})},[e,Ze,Yt,te,o,t,y]),c==="editing")return $(mt,{...T!==void 0&&{initialMode:T},showProfileManager:T==="global",onComplete:kn,onCancel:()=>{h("main")}});let _t=Z!==null?Math.round((Date.now()-Z.getTime())/1e3):null,_n=_t===null?"":_t<5?" (just now)":` (${String(_t)}s ago)`,Xt=oe?.filter(C=>C.severity==="error").length??0;return H(W,{flexDirection:"column",paddingY:1,paddingX:2,children:[$(q,{marginBottom:1}),H(W,{flexDirection:"column",children:[H(W,{gap:2,marginBottom:0,children:[$(D,{bold:!0,dimColor:!0,children:"App Build"}),M==="pending"&&$(D,{dimColor:!0,children:"waiting\u2026"}),M==="building"&&H(W,{gap:1,children:[$(pe,{}),$(D,{children:"Building plugin package\u2026"})]}),M==="done"&&H(W,{gap:1,children:[$(D,{color:"green",children:"\u2713 Built"}),Z!==null&&H(D,{dimColor:!0,children:["at ",Z.toLocaleTimeString(),_n]}),we!==null&&H(D,{dimColor:!0,children:["\xB7 bundle: ",Ae(we)]})]}),M==="error"&&(oe!==null?H(D,{color:"red",children:["\u2717 ",Xt," validation ",Xt===1?"error":"errors"]}):H(D,{color:"red",children:["\u2717 ",Q??"unknown error"]}))]}),oe!==null&&$(ot,{issues:oe}),$(W,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:l.slice(-8).map((C,j)=>$(D,{dimColor:!0,wrap:"truncate",children:C},j))})]}),H(W,{marginTop:1,flexDirection:"column",children:[H(W,{gap:2,children:[$(D,{bold:!0,dimColor:!0,children:"Web Server"}),x==="starting"&&$(D,{dimColor:!0,children:"starting\u2026"}),x==="running"&&H(W,{gap:2,children:[$(D,{color:"green",children:"\u2713 Running"}),H(D,{dimColor:!0,children:["\u25CF ",Ct," viewer",Ct!==1?"s":""]})]}),x==="error"&&H(D,{color:"red",children:["\u2717 ",k??"Server error"]})]}),$(W,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:a.slice(-8).map((C,j)=>$(D,{dimColor:!0,wrap:"truncate",children:C},j))})]}),H(W,{marginTop:1,flexDirection:"column",children:[H(W,{gap:2,children:[$(D,{bold:!0,dimColor:!0,children:"Network Proxy"}),$(D,{color:"green",children:"\u2713 Active"}),$(D,{dimColor:!0,children:y?`\u25CF ${String(Gt)} key${Gt!==1?"s":""} in the network cache \xB7 ${String(Tn)} hit \xB7 ${String(Tt)} miss`:`\u25CF network cache disabled \xB7 ${String(Tt)} request${Tt!==1?"s":""}`})]}),$(W,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:E.length===0?$(D,{dimColor:!0,children:" No requests yet."}):E.slice(-8).map((C,j)=>$(D,{dimColor:!0,wrap:"truncate",children:C},j))})]}),p&&H(W,{marginTop:1,flexDirection:"column",children:[H(W,{gap:2,children:[$(D,{bold:!0,dimColor:!0,children:"CDP Debug"}),H(D,{dimColor:!0,children:["\u25CF ",g.length," event(s)"]})]}),$(W,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:g.length===0?$(D,{dimColor:!0,children:" No CDP events yet."}):g.slice(-8).map((C,j)=>$(D,{dimColor:!0,wrap:"truncate",children:C},j))})]}),H(W,{marginTop:1,gap:1,children:[$(D,{dimColor:!0,children:"["}),$(D,{children:"q"}),$(D,{dimColor:!0,children:"] quit ["}),$(D,{children:"c"}),$(D,{dimColor:!0,children:"] credentials ["}),$(D,{children:"v"}),H(D,{dimColor:!0,children:["] ",Ct===0?"open viewer":"relaunch viewer"]})]})]})};async function Yr(e){return new Promise(t=>{let o=null,n=i=>{o?.(),t(i)},{unmount:r}=Zr(Xr(mt,{...e!==void 0&&{initialMode:e},onComplete:n}),{exitOnCtrlC:!1});o=r})}function Qr(e){e.command("dev").description("Start the plugin viewer dev server").option("-p, --port <port>","port to listen on","3121").option("-c, --credentials <path>","path to a credentials JSON file").option("-d, --debug","Enable CDP lifecycle logs in the TUI").option("-v, --verbose","Log every CDP event and handled error (implies --debug)").option("--no-viewer","Don't auto-launch the viewer on startup (press [v] to launch manually)").option("--no-cache","Disable the network proxy cache (always fetch upstream)").action(async t=>{let o=parseInt(t.port,10),n=process.cwd(),r=`${n}/.kizenapp`;Be(n);let i=null,u,p,{lastPath:m}=await ye(r);if(t.credentials)i=await ge(t.credentials);else{let c=await ye(r);if(c.credentialMode==="local")u="local";else if(c.credentialMode==="global"){if(u="global",p=c.activeCredentialProfile,p?(i=await le(p),i||(i=await Y(),p=void 0)):i=await Y(),!i){let h=await Yr("global");i=h.credentials,p=h.profileName}}else{let h=await Yr();i=h.credentials,u=h.mode,p=h.profileName;let T=h.profileName;await he(r,{credentialMode:h.mode,...T!==void 0&&{activeCredentialProfile:T}})}}let b=t.verbose===!0,y=b||t.debug===!0,S=t.viewer!==!1,N=t.cache!==!1,{waitUntilExit:v}=Zr(Xr(Kr,{port:o,pluginDir:n,outputDir:r,credentials:i,...u!==void 0&&{credentialMode:u},...p!==void 0&&{activeCredentialProfile:p},...m!==void 0&&{lastPath:m},debug:y,verbose:b,autoViewer:S,cacheEnabled:N}),{exitOnCtrlC:!1});await v()})}import{createElement as zi}from"react";import{readFile as Mi,writeFile as Hi}from"fs/promises";import{join as Ui}from"path";import{render as Vi}from"ink";import{useCallback as ht,useEffect as sn,useState as bt}from"react";import{Box as se,Text as O,useApp as Oi,useInput as ji}from"ink";import{encrypt as _i,serializeEnvelope as Ii}from"@kizenapps/packager";function Ni(e){let t=e;return t.code==="ECONNREFUSED"||t.cause?.code==="ECONNREFUSED"}function en(e){return{"Content-Type":"application/json","x-api-key":e.apiKey,"x-user-id":e.userId,"x-business-id":e.businessId,"x-auth-environment":e.environment}}async function tn(e,t,o){try{return await fetch(`${e}${t}`,o)}catch(n){throw new Error(Ni(n)?`Plugin-wizard is not running at ${e}`:`Failed to reach plugin-wizard: ${n.message}`)}}async function rn(e){let t=await e.text();if(t==="")return{};try{let o=JSON.parse(t);return typeof o=="object"&&o!==null?o:{}}catch{return{}}}async function Bi(e,t,o){let n=Ue(e.stage),r=await tn(n,"/get-public-key",{method:"POST",headers:en(t),body:JSON.stringify({api_name:o})}),i=await rn(r);if(!r.ok||typeof i.public_key!="string"){let u=typeof i.error=="string"?i.error:`HTTP ${String(r.status)}`;throw new Error(`Failed to fetch public key: ${u}`)}return i.public_key}function Ri(e,t){let o=_i(t,e),n=Ii(o);if(typeof n.value!="string")throw new Error("Unexpected serialized envelope shape from @kizenapps/packager");return n.value}async function Di(e,t,o,n){let r=Ue(e.stage),i=await tn(r,"/encrypt",{method:"POST",headers:en(t),body:JSON.stringify({api_name:o,value:n})}),u=await rn(i);if(!i.ok||u.encrypted!==!0||typeof u.value!="string"){let p=typeof u.error=="string"?u.error:`HTTP ${String(i.status)}`;throw new Error(`Encryption via plugin-wizard failed: ${p}`)}return u.value}async function yt(e,t,o,n,r){if(e.isRemote)return r?.("encrypting"),Di(e,t,o,n);r?.("fetching-key");let i=await Bi(e,t,o);return r?.("encrypting"),Ri(i,n)}import{spawn as $i}from"child_process";import{platform as nn}from"process";function Li(){return nn==="darwin"?[{cmd:"pbcopy",args:[]}]:nn==="win32"?[{cmd:"clip",args:[]}]:[{cmd:"wl-copy",args:[]},{cmd:"xclip",args:["-selection","clipboard"]},{cmd:"xsel",args:["--clipboard","--input"]}]}var Fi=2e3;function Ai(e,{cmd:t,args:o}){return new Promise(n=>{let r;try{r=$i(t,o,{stdio:["pipe","ignore","ignore"]})}catch{n(!1);return}let i=r,u=!1;function p(b){u||(u=!0,clearTimeout(m),n(b))}let m=setTimeout(()=>{i.kill(),p(!1)},Fi);m.unref(),i.on("error",()=>{p(!1)}),i.on("close",b=>{p(b===0)}),i.stdin.on("error",()=>{p(!1)});try{i.stdin.end(e)}catch{p(!1)}})}async function on(e){for(let t of Li())if(await Ai(e,t))return!0;return!1}import{Fragment as xt,jsx as L,jsxs as G}from"react/jsx-runtime";var Jt=({text:e})=>L(O,{dimColor:!0,children:e}),an=({ctx:e,stageDefaulted:t,credentialsPath:o,initialApiName:n,defaultApiName:r,initialValue:i,onDone:u})=>{let p=Oi(),[m,b]=bt({type:"loading"}),[y,S]=bt(null),[N,v]=bt(n??""),[c,h]=bt(i??""),T=ht(s=>{process.exitCode=1,b({type:"error",message:s instanceof Error?s.message:String(s)})},[]),P=ht(async(s,l,d)=>{try{let g=await yt(e,s,l,d,F=>{b(F==="fetching-key"?{type:"fetching-key"}:{type:"encrypting"})}),I=JSON.stringify({encrypted:!0,value:g},null,2);u?.(g);let E=await on(I);b({type:"done",envelope:I,copied:E})}catch(g){T(g)}},[e,T,u]),x=ht((s,l,d)=>{if(l.trim()===""){b({type:"api-name-entry",buffer:r??""});return}if(d===""){b({type:"value-entry",buffer:""});return}P(s,l.trim(),d)},[r,P]),w=ht(async s=>{try{b({type:"loading"});let l=s.isDefault?await Y():await le(s.name);if(l===null)throw new Error(`Could not load credential profile: ${s.name}`);S(l),x(l,N,c)}catch(l){T(l)}},[N,c,x,T]);sn(()=>{(async()=>{try{if(o!==void 0){let d;try{d=await ge(o)}catch(g){throw new Error(`Could not load credentials from ${o}: ${g instanceof Error?g.message:String(g)}`)}S(d),x(d,N,c);return}let s=await _e();if(s.length===0)throw new Error("No credential profiles found. Create ~/.kizenappbuilder/credentials.json first.");let[l]=s;if(s.length===1&&l!==void 0){let d=l.isDefault?await Y():await le(l.name);if(d===null)throw new Error(`Could not load credential profile: ${l.name}`);S(d),x(d,N,c);return}b({type:"profile-select",profiles:s,cursor:0})}catch(s){T(s)}})()},[]),sn(()=>{(m.type==="done"||m.type==="error")&&p.exit()},[m,p]),ji((s,l)=>{if(l.ctrl&&s==="c"){process.exitCode=130,p.exit();return}if(m.type==="profile-select"){let{profiles:d,cursor:g}=m;if(l.upArrow)b({...m,cursor:(g-1+d.length)%d.length});else if(l.downArrow)b({...m,cursor:(g+1)%d.length});else if(l.return){let I=d[g];I!==void 0&&w(I)}return}if(m.type==="api-name-entry"){let{buffer:d}=m;if(l.backspace||l.delete)b({type:"api-name-entry",buffer:d.slice(0,-1)});else if(l.return){let g=d.trim();if(g===""){b({type:"api-name-entry",buffer:d,error:"api_name cannot be empty"});return}v(g),y?x(y,g,c):T(new Error("Internal error: credentials were not loaded"))}else s&&!l.ctrl&&!l.meta&&b({type:"api-name-entry",buffer:d+s});return}if(m.type==="value-entry"){let{buffer:d}=m;if(l.backspace||l.delete)b({type:"value-entry",buffer:d.slice(0,-1)});else if(l.return){if(d===""){b({type:"value-entry",buffer:d,error:"secret cannot be empty"});return}h(d),y?x(y,N,d):T(new Error("Internal error: credentials were not loaded"))}else s&&!l.ctrl&&!l.meta&&b({type:"value-entry",buffer:d+s});return}});let k=e.isRemote?"remote Kizen API":"on-machine",f=t===!0?`${e.stage} (default)`:e.stage,a=s=>G(se,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[L(q,{}),G(O,{dimColor:!0,children:["Mode: ",k," Stage: ",f]}),s]});if(m.type==="loading")return a(G(se,{gap:1,children:[L(pe,{}),L(O,{dimColor:!0,children:"Loading credentials\u2026"})]}));if(m.type==="profile-select"){let{profiles:s,cursor:l}=m;return a(G(xt,{children:[L(O,{bold:!0,children:"Credential profile"}),L(se,{flexDirection:"column",children:s.map((d,g)=>{let I=l===g;return G(se,{gap:2,children:[L(O,{...I&&{color:"cyan"},children:I?"\u276F":" "}),L(O,{bold:I,...I&&{color:"cyan"},children:d.isDefault?"Default":d.name}),L(O,{dimColor:!0,children:d.path})]},d.name)})}),L(Jt,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]}))}return m.type==="api-name-entry"?a(G(xt,{children:[L(O,{bold:!0,children:"Plugin api_name"}),m.error!==void 0&&G(O,{color:"red",children:["Error: ",m.error]}),G(se,{gap:1,children:[L(O,{color:"cyan",children:">"}),L(O,{children:m.buffer}),L(O,{color:"cyan",children:"\u2588"})]}),L(Jt,{text:"Type the api_name \xB7 Enter to confirm \xB7 Ctrl+C to quit"})]})):m.type==="value-entry"?a(G(xt,{children:[L(O,{bold:!0,children:"Secret value"}),m.error!==void 0&&G(O,{color:"red",children:["Error: ",m.error]}),G(se,{gap:1,children:[L(O,{color:"cyan",children:">"}),L(O,{children:"\u2022".repeat(m.buffer.length)}),L(O,{color:"cyan",children:"\u2588"})]}),L(Jt,{text:"Input hidden \xB7 Enter to encrypt \xB7 Ctrl+C to quit"})]})):m.type==="fetching-key"?a(G(se,{gap:1,children:[L(pe,{}),G(O,{children:["Fetching ",e.stage," public key for ",L(O,{bold:!0,children:N}),"\u2026"]})]})):m.type==="encrypting"?a(G(se,{gap:1,children:[L(pe,{}),L(O,{children:"Encrypting\u2026"})]})):m.type==="error"?a(G(se,{gap:1,children:[L(O,{color:"red",children:"\u2717"}),L(O,{color:"red",children:m.message})]})):a(G(xt,{children:[G(se,{gap:1,children:[L(O,{color:"green",children:"\u2713"}),L(O,{bold:!0,children:"Encrypted secret ready"})]}),m.copied?L(O,{color:"green",children:"\u2713 Copied to clipboard \u2014 paste it into the secret value in your kizen.json."}):L(O,{dimColor:!0,children:"Paste this into the secret value in your kizen.json (re-run with --out <path> to save it to a file; selecting it here may capture line wraps):"}),L(O,{children:m.envelope})]}))};function ln(e){return{encrypted:!0,value:e}}function qi(e){return JSON.stringify(ln(e))}async function cn(e,t){await Hi(e,`${JSON.stringify(ln(t),null,2)}
|
|
192
|
-
|
|
193
|
-
`)
|
|
194
|
-
`),
|
|
195
|
-
`)
|
|
196
|
-
`)}
|
|
197
|
-
`)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
`)}var as=/(^|\/)licen[cs]e(\.md|\.txt)?$/i;function vn(e){return e.filter(t=>t.path!=="kizen.json"&&t.path!=="plugin-report.html"&&!as.test(t.path))}function wn(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!ts.has(t)).map(([t,o])=>[t,t==="services"?rs(o):o]))}function ls(e,t){let o=wn(e),n=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",u=vn(t),p=[];p.push(`# ${n}${r?` v${r}`:""}`),i&&p.push("",i);let m=JSON.stringify(o,null,2),b=mn(m);p.push("","## Configuration (`kizen.json`)","",`${b}json`,m,b),p.push("","## File Tree","","```",xn(yn(u)),"```"),p.push("","## Files");for(let y of u)if(p.push("",`### \`${y.path}\``,""),y.base64Image!==void 0)p.push(`[Image file: ${y.path}]`);else if(y.binaryData!==void 0)p.push(`[Binary file: ${String(y.binaryData.length)} bytes]`);else{let S=mn(y.content);p.push(`${S}${ss(y.path)}`,y.content,S)}return p.join(`
|
|
483
|
+
`.trim(),As=3e4,bt=Je(process.cwd(),".kizenapp","venv"),xn=["python-3-12","python-3-13"];function Ns(e){return xn.includes(e)}var vn=mn(fn);if(vn.length===0)throw new Error("python-requirements.txt bundled no packages \u2014 check the build output");var qe=null,We=[3,10];function wn([e,t]){return e>We[0]||e===We[0]&&t>=We[1]}function Zt(e){return`${String(e[0])}.${String(e[1])}`}function Cn(e){return new Promise(t=>{let n=tr(e,["-c","import sys; print('%d.%d' % sys.version_info[:2])"],{stdio:["ignore","pipe","ignore"]}),o="";n.stdout.on("data",r=>{o+=r.toString("utf-8")}),n.on("error",()=>{t(null)}),n.on("close",r=>{let i=/(\d+)\.(\d+)/.exec(o);if(r!==0||!i){t(null);return}t([Number(i[1]),Number(i[2])])})})}async function Bs(e){let t=gn(e),n=t==="python3"?["python3"]:[t,"python3"],o=[];for(let r of n){let i=await Cn(r);if(!i){o.push(`${r}: not found`);continue}if(wn(i))return r;o.push(`${r}: ${Zt(i)} (too old)`)}throw new Error(`No Python >= ${Zt(We)} found for runtime "${e}". The local runner needs Python ${Zt(We)}+ to install the bundled packages (e.g. psycopg 3.3), matching the remote code-runner (3.12 / 3.13). Tried ${o.join(", ")}. Install Python 3.12 or 3.13 and retry.`)}function bn(e,t,n){return new Promise((o,r)=>{let i=tr(e,t,{stdio:["ignore","pipe","pipe"]}),d=(g,m)=>{let b=[],T="";return g.on("data",P=>{T+=P.toString("utf-8");let x=T.indexOf(`
|
|
484
|
+
`);for(;x>=0;){let p=T.slice(0,x).replace(/\r$/,"");T=T.slice(x+1),b.push(p),n?.(p,m),x=T.indexOf(`
|
|
485
|
+
`)}}),g.on("end",()=>{if(T.length>0){let P=T.replace(/\r$/,"");b.push(P),n?.(P,m)}}),b},f=d(i.stderr,"stderr");d(i.stdout,"stdout"),i.on("error",r),i.on("close",g=>{if(g===0)o();else{let m=f.slice(-10).join(`
|
|
486
|
+
`).trim(),b=m.length>0?`: ${m}`:"";r(new Error(`${e} exited with code ${String(g)}${b}`))}})})}var Qt=null;function Ds(e,t){if(qe)return t&&Qt?.add(t),qe;let n=new Set;t&&n.add(t),Qt=n;let o=i=>{for(let d of n)d(i)},r=Je(bt,"bin","python");return qe=(async()=>{try{let i=!1;try{await Ps(r);let d=await Cn(r);i=d!==null&&wn(d)}catch{i=!1}if(!i){await er(bt,{recursive:!0,force:!0}).catch(()=>{});let d=await Bs(e);await bn(d,["-m","venv",bt])}return o({kind:"start"}),await bn(r,["-m","pip","install","--disable-pip-version-check",...vn],(d,f)=>{o({kind:"log",line:d,stream:f})}),o({kind:"complete"}),r}catch(i){let d=i instanceof Error?i.message:String(i);throw o({kind:"error",message:d}),qe=null,await er(bt,{recursive:!0,force:!0}).catch(()=>{}),i}finally{Qt=null}})(),qe}function Fs(e){let t="__KIZEN_RESULT_START__",n="__KIZEN_RESULT_END__",o=e.indexOf(t),r=e.indexOf(n);if(o===-1||r===-1)return{userStdout:e,result:null};let i=e.slice(0,o).trimEnd(),d=e.slice(o+t.length,r).trim();try{let f=JSON.parse(d);return{userStdout:i,result:f}}catch{return{userStdout:e,result:null}}}function Os(e){return{success:!1,outputValues:{},logs:[],stdout:"",stderr:"",error:e,exitCode:1,durationMs:0}}async function Sn(e){let t=e.timeout??As;if(!Ns(e.scriptRuntime))return Os(`Unsupported runtime "${e.scriptRuntime}". Supported runtimes: ${xn.join(", ")}. Update the step's config.json "runtime" field (e.g. "python 3.13").`);let n=await Ds(e.scriptRuntime,e.onInstallProgress),o=Date.now(),r;try{r=await ks(Je(Is(),"kizen-step-"));let i=Je(r,"wrapper.py"),d=Je(r,"script.py");await Promise.all([yn(i,Rs,"utf-8"),yn(d,e.script,"utf-8")]);let f={...process.env,__KIZEN_INPUTS__:JSON.stringify(e.inputs),__KIZEN_SECRETS__:JSON.stringify(e.secrets),__KIZEN_SCRIPT_PATH__:d},{exitCode:g,stdout:m,stderr:b}=await new Promise(y=>{let S=[],H=[],O=!1,w=tr(n,[i],{env:f,cwd:r,stdio:["ignore","pipe","pipe"]}),v=setTimeout(()=>{w.kill("SIGKILL")},t);w.stdout.on("data",a=>{S.push(a)}),w.stderr.on("data",a=>{H.push(a)});let c=a=>{O||(O=!0,clearTimeout(v),y({exitCode:a??1,stdout:Buffer.concat(S).toString("utf-8"),stderr:Buffer.concat(H).toString("utf-8")}))};w.on("close",c),w.on("error",a=>{O||(O=!0,clearTimeout(v),y({exitCode:1,stdout:"",stderr:a.message}))})}),T=Date.now()-o,{userStdout:P,result:x}=Fs(m);if(x){let y={success:x.success,outputValues:x.outputValues,logs:x.logs,stdout:P,stderr:b,exitCode:g,durationMs:T};return x.error!==null&&(y.error=x.error),x.httpRequests&&(y.httpRequests=x.httpRequests),y}let p={success:!1,outputValues:{},logs:[],stdout:P,stderr:b,exitCode:g,durationMs:T};return g!==0&&(p.error=`Process exited with code ${String(g)}`),p}finally{r&&er(r,{recursive:!0,force:!0})}}var Tn=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".json",".md",".mdx",".yml",".yaml",".toml",".css",".scss",".html",".htm",".xml",".svg",".txt",".sh",".py",".env",".gitignore",".prettierrc",".eslintrc"]);import{CRYPTO_ALG as Pn,CRYPTO_VERSION as In,deserializeEnvelope as qs,encrypt as Js,serializeEnvelope as Ws}from"@kizenapps/packager";function rr(e){if(e.kind==="info")return e.message;let t=e.fromCache?" [cache]":"",n=e.upstreamStatus!==void 0?` (upstream ${String(e.upstreamStatus)})`:"";return`${e.method} ${e.url} \u2192 ${String(e.status)}${n}${t}`}var Ks=2*1024*1024,Gs=new Set([".DS_Store",".gitignore"]);function Ys(e){if(e===void 0||e==="")return!1;let t=e.startsWith("[")?e.slice(0,e.indexOf("]")+1):e.split(":")[0]??"";return t==="localhost"||t==="127.0.0.1"||t==="[::1]"}var Bn=["kizen.com","kizen.dev"];function Xs(e){let t;try{t=new URL(e)}catch{return!1}let n=t.hostname.toLowerCase();return n==="localhost"||n==="127.0.0.1"||n==="[::1]"?!0:t.protocol!=="https:"?!1:Bn.some(o=>n===o||n.endsWith("."+o))}function Zs(e){let t;try{t=new URL(e)}catch{return!1}if(t.protocol!=="https:")return!1;let n=t.hostname.toLowerCase();return Bn.some(o=>n===o||n.endsWith("."+o))}function Qs(e){if(e===void 0||e==="")return!1;try{let{hostname:t}=new URL(e);return t==="localhost"||t==="127.0.0.1"||t==="::1"}catch{return!1}}async function Rn(e,t){if(t.includes("\0"))return null;let n=t.replace(/^\/+/,""),o=Us(e,n);if(o!==e&&!o.startsWith(e+nr))return null;try{let r=await zs(o);return r!==e&&!r.startsWith(e+nr)?null:r}catch{return null}}function An(e,t){let n=t===e?"":t.slice(e.length+1);return n===""?!1:n.split(nr).some(r=>tt.has(r))}function Dn(){let e=Vs(import.meta.url);return Ke(Hs(e),"viewer")}function Nn(e,t,n){if(e.includes("/external-integrations/proxy")&&t["content-type"]?.includes("application/json"))try{let o=JSON.parse(n.toString("utf8"));return typeof o.status_code=="number"?o.status_code:void 0}catch{return}}async function or(e){try{return await $s(e),!0}catch{return!1}}function Fn(e,t,n,o,r,i,d,f,g,m,b){let T=pn({onChange:f,enabled:b}),P=js(m);return(x,p)=>{(async()=>{let y=x.url??"/";try{if(!Ys(x.headers.host)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Forbidden"}));return}if((x.method==="POST"||x.method==="PATCH"||x.method==="DELETE")&&!Qs(x.headers.origin)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Forbidden"}));return}if(t(`Received request: ${y}`),y==="/api/credentials"){p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({credentials:o.current??null,activeProfile:r.current??null}));return}if(y==="/api/credential-profiles"&&x.method==="GET"){let a=await Ie();p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({profiles:a,active:r.current}));return}if(y==="/api/credentials/switch"&&x.method==="POST"){let a=[];for await(let h of x)a.push(h);let l=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}").profile,u=l===void 0||l===""?await Z():await de(l);if(u!==null){o.current=u,r.current=l??void 0;let h=r.current,k=await xe(i);await ve(i,{...k,credentialMode:"global",...h!==void 0&&{activeCredentialProfile:h}}),d({type:"credentials-updated",credentials:u,activeProfile:r.current??null})}p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({ok:u!==null}));return}if(y==="/api/bundle"){let a=Ke(process.cwd(),".kizenapp","bundle.json");try{let s=await Ms(a,"utf-8");p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(s)}catch{p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end("{}")}return}if(y==="/api/last-path"&&x.method==="POST"){let a=[];for await(let l of x)a.push(l);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.path=="string"){g.current=s.path;let l=await xe(i);await ve(i,{...l,lastPath:s.path})}p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end('{"ok":true}');return}if(y==="/api/encryption-target"&&x.method==="GET"){let s=(await xe(i)).encryptionTarget==="dev"?"dev":"prod";p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({target:s}));return}if(y==="/api/encryption-target"&&x.method==="POST"){let a=[];for await(let h of x)a.push(h);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}"),l=s!==null&&typeof s=="object"?s:{};if(l.target!=="dev"&&l.target!=="prod"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"target must be one of: 'dev', 'prod'"}));return}let u=await xe(i);await ve(i,{...u,encryptionTarget:l.target}),p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end('{"ok":true}');return}if(y==="/api/execute-step"&&x.method==="POST"){let a=[];for await(let h of x)a.push(h);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.script!="string"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing required field: script"}));return}let l={script:s.script,scriptRuntime:s.scriptRuntime??"python-3-13",inputs:hn(s.inputs),secrets:s.secrets??{},onInstallProgress:h=>{h.kind==="start"?d({type:"venv-install-start"}):h.kind==="log"?d({type:"venv-install-log",line:h.line,stream:h.stream}):h.kind==="complete"?d({type:"venv-install-complete"}):d({type:"venv-install-error",message:h.message})}};typeof s.timeout=="number"&&s.timeout>0&&(l.timeout=Math.min(s.timeout,300*1e3));let u=await Sn(l);p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify(u));return}if(y==="/api/proxy-cache/clear"){T.clear(),n({kind:"info",message:"Proxy cache cleared"}),p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end('{"ok":true}');return}if(y==="/api/local/encrypt"&&x.method==="POST"){let a=[];for await(let l of x)a.push(l);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.publicKeyPem!="string"||typeof s.value!="string"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing required fields: publicKeyPem, value"}));return}try{let l=Js(s.value,s.publicKeyPem),u=Ws(l);p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify(u))}catch(l){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:l.message}))}return}if(y==="/api/local/validate"&&x.method==="POST"){let a=[];for await(let _ of x)a.push(_);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.value!="string"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing required field: value"}));return}let l,u;try{l=qs(s.value)}catch(_){u=_.message}if(u!==void 0||l===void 0){p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({valid:!1,checks:[],error:u}));return}let h=_=>Buffer.from(_,"base64").length,k=[{label:"Version",expected:String(In),actual:String(l.v),pass:l.v===In},{label:"Algorithm",expected:Pn,actual:l.alg,pass:l.alg===Pn},{label:"Wrapped key",expected:"384 bytes (RSA-3072)",actual:`${String(h(l.k))} bytes`,pass:h(l.k)===384},{label:"IV",expected:"12 bytes",actual:`${String(h(l.iv))} bytes`,pass:h(l.iv)===12},{label:"Auth tag",expected:"16 bytes",actual:`${String(h(l.tag))} bytes`,pass:h(l.tag)===16},{label:"Ciphertext",expected:"\u2265 1 byte",actual:`${String(h(l.ct))} bytes`,pass:h(l.ct)>=1}];p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({valid:k.every(_=>_.pass),checks:k}));return}if(y.startsWith("/api/wizard")){let a=x.headers["x-encryption-target"],l=(Array.isArray(a)?a[0]:a)==="dev"?"dev":"prod",u=Ve(l);if(!Xs(u)){p.writeHead(500,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:`Encryption API host is not allowed: ${u}`}));return}let h=y.slice(11)||"/",k=`${u}${h}`,_=x.method??"GET",A=[];for await(let Se of x)A.push(Se);let{host:M,"x-encryption-target":W,...te}=x.headers,oe=A.length>0?Buffer.concat(A):void 0,ie=oe&&oe.length>0?oe:void 0,re;try{re=await fetch(k,{method:_,headers:te,...ie!==void 0&&{body:ie}})}catch(Se){let It=Se.code==="ECONNREFUSED"?`plugin-wizard is not running at ${u}`:`Failed to reach plugin-wizard: ${Se.message}`;p.writeHead(503,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:It}));return}let ee=yt(Object.fromEntries(re.headers)),Oe=await re.arrayBuffer();p.writeHead(re.status,ee),p.end(Buffer.from(Oe));return}if(y.startsWith("/api/proxy")){let a=x.headers["x-proxy-target"];if(typeof a!="string"){p.writeHead(400),p.end("Missing x-proxy-target header");return}if(!Zs(a)){p.writeHead(400),p.end("Invalid proxy target");return}let s=y.slice(10)||"/",l=`${a}${s}`,u=x.method??"GET",h=[];for await(let re of x)h.push(re);let{host:k,"x-proxy-target":_,...A}=x.headers;if(u==="GET"){let re=`GET::${l}`,{response:ee,fromCache:Oe}=await T.get(re,()=>fetch(l,{method:"GET",headers:A}));n({kind:"request",method:"GET",status:ee.status,upstreamStatus:Nn(s,ee.headers,ee.body),fromCache:Oe,url:s}),p.writeHead(ee.status,ee.headers),p.end(ee.body);return}let M=h.length>0?Buffer.concat(h):void 0,W=M&&M.length>0?M:void 0,te=await fetch(l,{method:u,headers:A,...W!==void 0&&{body:W}}),oe=yt(Object.fromEntries(te.headers)),ie=await Gt(te,Kt);n({kind:"request",method:u,status:te.status,upstreamStatus:Nn(s,oe,ie),fromCache:!1,url:s}),p.writeHead(te.status,oe),p.end(ie);return}if(y.startsWith("/api/source/tree")&&x.method==="GET"){let s=new URL(y,"http://localhost").searchParams.get("path")??"",l=await Rn(P,s);if(l===null){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Invalid path"}));return}if(An(P,l)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Path is excluded"}));return}try{let u=await Ls(l,{withFileTypes:!0}),h=await Promise.all(u.filter(_=>_.isDirectory()?!tt.has(_.name):_.isFile()?!Gs.has(_.name):!1).map(async _=>{let A=_.isDirectory()?"dir":"file",M={name:_.name,kind:A};if(A==="file")try{let W=await En(Ke(l,_.name));M.size=W.size}catch{}return M}));h.sort((_,A)=>_.kind!==A.kind?_.kind==="dir"?-1:1:_.name.localeCompare(A.name));let k=l===P?"":l.slice(P.length+1);p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({path:k,entries:h}))}catch(u){let h=u instanceof Error?u.message:String(u);t(`source/tree failed (${s}): ${h}`),p.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Not found"}))}return}if(y.startsWith("/api/source/file")&&x.method==="GET"){let s=new URL(y,"http://localhost").searchParams.get("path")??"";if(s===""){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing path"}));return}let l=await Rn(P,s);if(l===null){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Invalid path"}));return}if(An(P,l)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Path is excluded"}));return}try{let u=await En(l);if(!u.isFile()){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Not a file"}));return}if(u.size>Ks){p.writeHead(413,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"File too large",size:u.size}));return}let h=kn(l).toLowerCase(),k=Yt[h],_=Tn.has(h),A=k??(_?"text/plain; charset=utf-8":"application/octet-stream");p.writeHead(200,{"Content-Type":A,"Content-Length":String(u.size)}),_n(l).pipe(p)}catch(u){let h=u instanceof Error?u.message:String(u);t(`source/file failed (${s}): ${h}`),p.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Not found"}))}return}let O=Ke(e,y==="/"?"/index.html":y),w=await or(O)?O:Ke(e,"index.html"),v=kn(w),c=Yt[v]??"application/octet-stream";p.writeHead(200,{"Content-Type":c}),_n(w).pipe(p)}catch(S){if(y.startsWith("/api/proxy")){let H=y.slice(10)||"/",O=x.method??"GET";S instanceof Ue?n({kind:"info",message:`${O} ${H} \u2192 502 (response exceeded ${String(S.limit)} bytes)`}):n({kind:"request",method:O,status:502,fromCache:!1,url:H})}else n({kind:"info",message:`Error handling ${y}: ${S instanceof Error?S.message:String(S)}`});p.headersSent||(p.writeHead(502),p.end("Bad Gateway"))}})()}}import{launch as ea}from"chrome-launcher";import{createRequire as ta}from"module";import{mkdirSync as ra}from"fs";import{readFile as na}from"fs/promises";import{dirname as oa,join as ia}from"path";import{fileURLToPath as sa}from"url";var On=ta(import.meta.url)("chrome-remote-interface"),aa=new Set(["content-security-policy","content-security-policy-report-only","x-frame-options"]),$n=["kizen.dev","kizen.com"];function jn(e){try{let{hostname:t}=new URL(e);return $n.some(n=>t===n||t.endsWith("."+n))}catch{return!1}}async function la(e){try{let t=ia(oa(sa(import.meta.url)),"viewer","icon.png"),n=await na(t);await e.Browser.setDockTile({image:n.toString("base64")})}catch{}}async function Ln(e){ra(e.userDataDir,{recursive:!0});let t=`http://localhost:${String(e.port)}`,n=await ea({startingUrl:t,chromeFlags:[`--app=${t}`,"--no-first-run","--no-default-browser-check","--disable-extensions","--disable-features=DeviceBoundSessions"],userDataDir:e.userDataDir,handleSIGINT:!1,logLevel:"silent"}),o=n.port,r=null,i=null,d=null,f=null,g=0,m=!1,b=w=>{e.debugLog?.(w)},T=w=>{e.verbose&&e.debugLog?.(w)},P=()=>{i!==null&&(clearInterval(i),i=null)},x=w=>w==="chrome://new-tab-page/"||w==="chrome://newtab/",p=async w=>{P(),d=null,await la(w),await w.Fetch.enable({patterns:$n.flatMap(c=>[{urlPattern:`*://${c}/*`,requestStage:"Response"},{urlPattern:`*://*.${c}/*`,requestStage:"Response"}])}),w.on("Fetch.requestPaused",c=>{(async()=>{let a=c,{requestId:s,request:l,responseHeaders:u,responseStatusCode:h}=a,k=l.url;T(`Fetch ${String(h??"?")} ${k}`);let _=[],A=!1;for(let M of u??[])if(!aa.has(M.name.toLowerCase()))if(M.name.toLowerCase()==="set-cookie"&&jn(k)){let W=M.value.split(`
|
|
487
|
+
`).map(te=>/SameSite=/i.test(te)?te.replace(/SameSite=\w+/i,"SameSite=None"):te+"; SameSite=None; Secure").join(`
|
|
488
|
+
`);_.push({name:M.name,value:W}),A=!0}else _.push(M);A&&T(` rewrote Set-Cookie SameSite on ${k}`);try{let{body:M,base64Encoded:W}=await w.Fetch.getResponseBody({requestId:s});await w.Fetch.fulfillRequest({requestId:s,responseCode:h??200,responseHeaders:_,body:M,...W&&{base64Encoded:!0}})}catch(M){T(` fulfillRequest failed (${M.message}), falling through`);try{await w.Fetch.continueRequest({requestId:s})}catch(W){T(` continueRequest also failed (${W.message})`)}}})()}),i=setInterval(()=>{(async()=>{try{let{cookies:c}=await w.Network.getAllCookies(),a=0;for(let s of c){if(!jn(`https://${s.domain??""}`)||s.sameSite==="None")continue;let l=s.domain??"",u=l.startsWith(".")?l.slice(1):l;await w.Network.setCookie({url:`https://${u}`,name:s.name,value:s.value,domain:l,path:s.path??"/",secure:!0,...s.httpOnly!==void 0&&{httpOnly:s.httpOnly},...s.expirationDate!==void 0&&{expires:s.expirationDate},sameSite:"None"}),a++}a>0&&T(`cookie-patch cycle: updated ${String(a)} cookie(s) to SameSite=None`)}catch(c){T(`cookie-patch cycle failed: ${c.message}`)}})()},2e3),await w.Target.setDiscoverTargets({discover:!0});let v=c=>{if(c.type==="page"){if(x(c.url)){b(`closed stray new-tab-page target ${c.targetId}`),d!==null&&w.Target.activateTarget({targetId:d}).catch(()=>{}),w.Target.closeTarget({targetId:c.targetId}).catch(()=>{});return}d===null&&(d=c.targetId,b(`captured main target ${c.targetId} (${c.url})`))}};w.on("Target.targetCreated",c=>{let{targetInfo:a}=c;T(`target +${a.type} ${a.targetId} ${a.url}`),v(a)}),w.on("Target.targetInfoChanged",c=>{let{targetInfo:a}=c;T(`target ~${a.type} ${a.targetId} ${a.url}`),v(a)}),w.on("disconnect",()=>{m||r!==w||(b("CDP disconnected"),r=null,P(),y())})},y=()=>{if(m||f!==null)return;let w=Math.min(1e3*2**g,1e4),v=g+1;g++,b(`CDP reconnect scheduled in ${String(w)}ms (attempt #${String(v)})`),f=setTimeout(()=>{f=null,(async()=>{let c;try{c=await On({port:o})}catch{b(`CDP reconnect attempt #${String(v)} failed`),y();return}if(m){try{await c.close()}catch{}return}r=c;try{await p(c),b(`CDP reconnected after ${String(v)} attempt(s)`),g=0}catch{r===c&&(r=null);try{await c.close()}catch{}b(`CDP reconnect attempt #${String(v)} failed during setup`),y()}})()},w)},S=30,H=300;for(let w=0;w<S;w++){await new Promise(v=>setTimeout(v,H)),b(`CDP connect attempt ${String(w+1)}/${String(S)}`);try{let v=await On({port:o});r=v,e.path&&v.send("Page.navigate",{url:`${t}${e.path}`});try{await p(v),b("CDP connected")}catch{r===v&&(r=null);try{await v.close()}catch{}b("CDP setup failed after connect")}break}catch{if(w===S-1){let v=`CDP unavailable after ${String(S)} attempts \u2014 viewer running without interception (CSP/cookie rewrites disabled)`;return b(v),e.onWarn?.(v),{kill:()=>{n.kill()}}}}}return r?{kill:()=>{if(b("CDP kill requested \u2014 tearing down"),m=!0,f!==null&&(clearTimeout(f),f=null),P(),r!==null){try{r.close()}catch{}r=null}n.kill()}}:{kill:()=>{n.kill()}}}import{useCallback as ca,useState as da}from"react";function xt(e){let[t,n]=da([]),o=ca(r=>{n(i=>[...i,`${new Date().toLocaleTimeString()}: ${r}`].slice(-e))},[e]);return[t,o]}import{useCallback as vt,useEffect as ir,useState as wt}from"react";import{Box as V,Text as j,useInput as pa}from"ink";import{jsx as R,jsxs as J}from"react/jsx-runtime";var we=["apiKey","userId","businessId"],ua={apiKey:"API Key",userId:"User ID",businessId:"Business ID"},Ge=({text:e})=>R(j,{dimColor:!0,children:e}),Ct=({initialMode:e,showProfileManager:t,onComplete:n,onCancel:o})=>{let[r,i]=wt(e==="global"&&!t?{type:"loading"}:e==="global"&&t?{type:"profile-loading"}:{type:"mode-select",cursor:0}),[d,f]=wt(""),[g,m]=wt(null),[b,T]=wt(void 0),P=vt(c=>{if(c==="local"){n({mode:"local",credentials:null});return}i({type:"profile-loading"})},[n]),x=vt(async c=>{if(c===null){i({type:"profile-loading"});let l=await Ie();i({type:"name-entry",nameBuffer:"",existingProfiles:l});return}T(c.isDefault?void 0:c.name),i({type:"loading"});let a=c.isDefault?await Z():await de(c.name),s=a?Math.max(0,Y.indexOf(a.environment)):0;i({type:"creds-entry",field:0,values:a??{},envCursor:s})},[]),p=vt(async(c,a)=>{let s=Y[a]??"go",l={apiKey:c.apiKey??"",userId:c.userId??"",businessId:c.businessId??"",environment:s};i({type:"saving"});try{await an(b??ye,l),n({mode:"global",credentials:l,...b!==void 0&&{profileName:b}})}catch(u){m(u instanceof Error?u.message:String(u)),i({type:"creds-entry",field:0,values:c,envCursor:a})}},[n,b]);pa((c,a)=>{if(a.ctrl&&c==="c"&&process.exit(0),a.escape){if((r.type==="creds-entry"||r.type==="name-entry")&&e==="global"&&t){i({type:"profile-loading"}),y();return}o?.();return}if(r.type==="mode-select"){if(a.upArrow)i({type:"mode-select",cursor:0});else if(a.downArrow)i({type:"mode-select",cursor:1});else if(a.return){let s=r.cursor===0?"global":"local";P(s)}return}if(r.type==="profile-select"){let{profiles:s,cursor:l}=r,u=s.length,h=s.length+1;if(a.upArrow)i({...r,cursor:(l-1+h)%h});else if(a.downArrow)i({...r,cursor:(l+1)%h});else if(a.return)if(l===u)i({type:"name-entry",nameBuffer:"",existingProfiles:s});else{let k=s[l]??s[0];k&&x(k)}return}if(r.type==="name-entry"){let{nameBuffer:s,existingProfiles:l}=r;if(a.backspace||a.delete)i({type:"name-entry",nameBuffer:s.slice(0,-1),existingProfiles:l});else if(a.return){let u=s.trim();if(!u){i({...r,nameError:"Name cannot be empty"});return}if(u===ye){i({...r,nameError:`"${ye}" is reserved`});return}if(l.some(h=>h.name===u)){i({...r,nameError:`Profile "${u}" already exists`});return}T(u),i({type:"creds-entry",field:0,values:{},envCursor:0}),f("")}else c&&!a.ctrl&&!a.meta&&i({type:"name-entry",nameBuffer:s+c,existingProfiles:l});return}if(r.type==="creds-entry"){let{field:s,values:l,envCursor:u}=r;if(s===we.length){a.leftArrow?i({...r,envCursor:(u-1+Y.length)%Y.length}):a.rightArrow?i({...r,envCursor:(u+1)%Y.length}):a.upArrow?(i({...r,field:s-1}),f(l[we[s-1]]??"")):a.return&&p(l,u);return}let k=we[s];if(!k)return;if(a.backspace||a.delete)f(_=>_.slice(0,-1));else if(a.upArrow&&s>0){let _={...l,[k]:d},A=s-1;i({...r,field:A,values:_}),f(_[we[A]]??"")}else if(a.return||a.tab||a.downArrow){let _={...l,[k]:d},A=s+1;i({...r,field:A,values:_}),A<we.length?f(_[we[A]]??""):f("")}else c&&!a.ctrl&&!a.meta&&f(_=>_+c)}});let y=vt(async()=>{let c=await Ie();i({type:"profile-select",profiles:c,cursor:0})},[]);if(ir(()=>{r.type==="profile-loading"&&y()},[r.type,y]),ir(()=>{e==="global"&&!t&&(async()=>{let c=await Z(),a=c?Math.max(0,Y.indexOf(c.environment)):0;i({type:"creds-entry",field:0,values:c??{},envCursor:a})})()},[]),ir(()=>{r.type==="creds-entry"&&r.field===0&&f(r.values.apiKey??"")},[r.type]),r.type==="loading"||r.type==="saving"||r.type==="profile-loading"){let c=r.type==="saving"?"Saving credentials\u2026":r.type==="profile-loading"?"Loading profiles\u2026":"Loading credentials\u2026";return R(V,{paddingY:1,paddingX:2,children:R(j,{dimColor:!0,children:c})})}if(r.type==="done")return null;if(r.type==="mode-select")return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),J(V,{flexDirection:"column",gap:0,children:[R(j,{bold:!0,children:"Credential mode"}),[{label:"Global",desc:"~/.kizenappbuilder/credentials.json",mode:"global"},{label:"Local",desc:"Enter credentials in the browser dev tools",mode:"local"}].map((a,s)=>{let l=r.cursor===s;return J(V,{gap:2,children:[R(j,{...l&&{color:"cyan"},children:l?"\u276F":" "}),R(j,{bold:l,...l&&{color:"cyan"},children:a.label}),R(j,{dimColor:!0,children:a.desc})]},a.mode)})]}),R(Ge,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]});if(r.type==="profile-select"){let{profiles:c,cursor:a}=r,s=c.length;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),J(V,{flexDirection:"column",gap:0,children:[R(j,{bold:!0,children:"Credential profiles"}),c.map((l,u)=>{let h=a===u;return J(V,{gap:2,children:[R(j,{...h&&{color:"cyan"},children:h?"\u276F":" "}),R(j,{bold:h,...h&&{color:"cyan"},children:l.isDefault?"Default":l.name}),R(j,{dimColor:!0,children:l.path})]},l.name)}),J(V,{gap:2,children:[R(j,{...a===s&&{color:"cyan"},children:a===s?"\u276F":" "}),R(j,{bold:a===s,...a===s&&{color:"cyan"},children:"+ Add new profile"})]})]}),R(Ge,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="name-entry"){let{nameBuffer:c,nameError:a}=r;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),R(V,{flexDirection:"column",gap:0,children:R(j,{bold:!0,children:"New credential profile"})}),a&&J(j,{color:"red",children:["Error: ",a]}),J(V,{gap:2,children:[R(V,{width:12,children:R(j,{bold:!0,color:"cyan",children:"Profile name"})}),R(j,{color:"cyan",children:">"}),R(j,{children:c}),R(j,{color:"cyan",children:"\u2588"})]}),R(Ge,{text:"Type a name \xB7 Enter to confirm \xB7 Esc to go back"})]})}let{field:S,values:H,envCursor:O}=r,w=S===we.length,v=b??ye;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),J(V,{flexDirection:"column",gap:0,children:[R(j,{bold:!0,children:b!==void 0?`Profile: ${b}`:"Global credentials"}),J(j,{dimColor:!0,children:["Saved to:"," ",b!==void 0?`~/.kizenappbuilder/${b}.json`:De]})]}),g&&J(j,{color:"red",children:["Error: ",g]}),J(V,{flexDirection:"column",gap:0,children:[we.map((c,a)=>{let s=S===a,l=s?d:H[c]??"";return J(V,{gap:2,children:[R(V,{width:12,children:R(j,{bold:s,...s&&{color:"cyan"},children:ua[c]})}),R(j,{...s&&{color:"cyan"},children:">"}),R(j,{children:l}),s&&R(j,{color:"cyan",children:"\u2588"})]},c)}),J(V,{gap:2,children:[R(V,{width:12,children:R(j,{bold:w,...w&&{color:"cyan"},children:"Environment"})}),R(j,{...w&&{color:"cyan"},children:">"}),R(V,{gap:1,children:Y.map((c,a)=>{let s=a===O;return w?R(j,{bold:s,...s&&{color:"cyan"},children:s?`[${c}]`:c},c):R(j,{dimColor:!s,bold:s,children:c},c)})})]})]}),w?R(Ge,{text:"\u2190\u2192 to select \xB7 \u2191\u2193 to move \xB7 Enter to save \xB7 Esc to cancel"}):R(Ge,{text:"\u2191\u2193 to move \xB7 Backspace to delete \xB7 Esc to cancel"}),J(j,{dimColor:!0,children:["Profile: ",v]})]})};import{jsx as D,jsxs as U}from"react/jsx-runtime";var xa=[".kizenapp",".git"],zn=({port:e,pluginDir:t,outputDir:n,credentials:o,credentialMode:r,activeCredentialProfile:i,lastPath:d,debug:f=!1,verbose:g=!1,autoViewer:m=!0,cacheEnabled:b=!0})=>{let T=pe(o),P=pe(i),x=pe(d),[p,y]=Q("main"),[S,H]=Q(r),[O,w]=Q("starting"),[v,c]=Q(null),[a,s]=xt(50),[l,u]=xt(50),[h,k]=xt(50),[_,A]=Q([]),[M,W]=Q("pending"),[te,oe]=Q(null),[ie,re]=Q(null),[ee,Oe]=Q(null),[Se,It]=Q(null),[Rt,At]=Q(0),[cr,ko]=Q(0),[Po,Io]=Q(0),[Nt,Ro]=Q(0),Bt=pe(!1),dr=pe(!1),Xe=pe(null),je=pe(null),ue=pe(new Set),Ze=pe([]),ne=Fe(C=>{let L=JSON.stringify(C);if(ue.current.size===0){Ze.current=[...Ze.current,L].slice(-50);return}let fe=!1;for(let se of ue.current)if(se.readyState===1)try{se.send(L)}catch{ue.current.delete(se),fe=!0}fe&&At(ue.current.size)},[]),Qe=s,Dt=Fe(()=>{Xe.current?.kill(),Xe.current=null,Ln({port:e,userDataDir:Mn(n,".chrome"),broadcast:ne,onWarn:C=>{s(`\u26A0 ${C}`)},...x.current!==void 0&&{path:x.current},...f&&{debugLog:k},...g&&{verbose:!0}}).then(C=>{Xe.current=C})},[e,n,ne,f,g,k,s]);St(()=>{let C=()=>{Xe.current?.kill()};return process.on("exit",C),()=>{process.off("exit",C)}},[]),ma((C,L)=>{(C==="q"||L.ctrl&&C==="c")&&process.exit(0),C==="c"&&y("editing"),C==="v"&&Dt()},{isActive:p==="main"}),St(()=>{O!=="running"||dr.current||!m||(dr.current=!0,Dt())},[O,m,Dt]);let Ao=Fe(C=>{T.current=C.credentials,P.current=C.profileName,y("main"),H(C.mode);let L=C.profileName;ve(n,{credentialMode:C.mode,...L!==void 0&&{activeCredentialProfile:L}}),ne({type:"credentials-updated",credentials:C.credentials})},[n,ne]),pr=Fe(C=>{A(L=>[...L,`${new Date().toLocaleTimeString()}: ${rr(C)}`].slice(-50)),C.kind==="request"&&(C.fromCache?Io(L=>L+1):Ro(L=>L+1)),ne({type:"proxy-log",entry:C})},[ne]),Te=Fe(C=>{u(C),ne({type:"log",message:C})},[u,ne]),Ft=Fe(()=>{Bt.current||(Bt.current=!0,W("building"),oe(null),re(null),Te("Build started"),nt(t,n).then(({bundleSize:C})=>{Te(`Build finished \u2014 bundle: ${$e(C)}`),W("done"),Oe(new Date),It(C),Te("Notifying viewers to reload"),ne({type:"rebuild"})}).catch(C=>{C instanceof ga?(re(C.issues),oe(null)):(oe(C instanceof Error?C.message:String(C)),re(null)),W("error")}).finally(()=>{Bt.current=!1}))},[t,n,Te,ne]);if(St(()=>{Ft();let C=ha(t,{recursive:!0},(L,fe)=>{if(!fe)return;let se=fe.replace(/\\/g,"/");xa.some(et=>se.startsWith(et))||(Te(`File change detected: ${fe}`),je.current!==null&&clearTimeout(je.current),je.current=setTimeout(Ft,150))});return C.on("error",L=>{Te(`File watcher error \u2014 rebuilds have stopped: ${L.message}`)}),()=>{C.close(),je.current!==null&&clearTimeout(je.current)}},[t,Ft,Te]),St(()=>{let C=Dn();or(Mn(C,"index.html")).then(L=>{if(!L){c("Viewer not built. Run 'pnpm build:viewer' first."),w("error");return}let fe=Fn(C,Qe,pr,T,P,n,ne,ko,x,t,b),se=ya(fe),et=new ba({server:se});return et.on("connection",_e=>{for(let Bo of Ze.current)_e.readyState===1&&_e.send(Bo);Ze.current=[],Qe("Viewer connected for live reload"),ue.current.add(_e),At(ue.current.size),_e.on("close",()=>{ue.current.delete(_e),At(ue.current.size)})}),se.listen(e,"127.0.0.1",()=>{w("running"),Qe(`Server started on 127.0.0.1:${String(e)}`)}),se.on("error",_e=>{c(_e.message),w("error")}),()=>{et.close(),se.close()}})},[e,Qe,pr,ne,n,t,b]),p==="editing")return D(Ct,{...S!==void 0&&{initialMode:S},showProfileManager:S==="global",onComplete:Ao,onCancel:()=>{y("main")}});let Ot=ee!==null?Math.round((Date.now()-ee.getTime())/1e3):null,No=Ot===null?"":Ot<5?" (just now)":` (${String(Ot)}s ago)`,ur=ie?.filter(C=>C.severity==="error").length??0;return U(K,{flexDirection:"column",paddingY:1,paddingX:2,children:[D(q,{marginBottom:1}),U(K,{flexDirection:"column",children:[U(K,{gap:2,marginBottom:0,children:[D(B,{bold:!0,dimColor:!0,children:"App Build"}),M==="pending"&&D(B,{dimColor:!0,children:"waiting\u2026"}),M==="building"&&U(K,{gap:1,children:[D(me,{}),D(B,{children:"Building plugin package\u2026"})]}),M==="done"&&U(K,{gap:1,children:[D(B,{color:"green",children:"\u2713 Built"}),ee!==null&&U(B,{dimColor:!0,children:["at ",ee.toLocaleTimeString(),No]}),Se!==null&&U(B,{dimColor:!0,children:["\xB7 bundle: ",$e(Se)]})]}),M==="error"&&(ie!==null?U(B,{color:"red",children:["\u2717 ",ur," validation ",ur===1?"error":"errors"]}):U(B,{color:"red",children:["\u2717 ",te??"unknown error"]}))]}),ie!==null&&D(it,{issues:ie}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:l.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),U(K,{marginTop:1,flexDirection:"column",children:[U(K,{gap:2,children:[D(B,{bold:!0,dimColor:!0,children:"Web Server"}),O==="starting"&&D(B,{dimColor:!0,children:"starting\u2026"}),O==="running"&&U(K,{gap:2,children:[D(B,{color:"green",children:"\u2713 Running"}),U(B,{dimColor:!0,children:["\u25CF ",Rt," viewer",Rt!==1?"s":""]})]}),O==="error"&&U(B,{color:"red",children:["\u2717 ",v??"Server error"]})]}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:a.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),U(K,{marginTop:1,flexDirection:"column",children:[U(K,{gap:2,children:[D(B,{bold:!0,dimColor:!0,children:"Network Proxy"}),D(B,{color:"green",children:"\u2713 Active"}),D(B,{dimColor:!0,children:b?`\u25CF ${String(cr)} key${cr!==1?"s":""} in the network cache \xB7 ${String(Po)} hit \xB7 ${String(Nt)} miss`:`\u25CF network cache disabled \xB7 ${String(Nt)} request${Nt!==1?"s":""}`})]}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:_.length===0?D(B,{dimColor:!0,children:" No requests yet."}):_.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),f&&U(K,{marginTop:1,flexDirection:"column",children:[U(K,{gap:2,children:[D(B,{bold:!0,dimColor:!0,children:"CDP Debug"}),U(B,{dimColor:!0,children:["\u25CF ",h.length," event(s)"]})]}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:h.length===0?D(B,{dimColor:!0,children:" No CDP events yet."}):h.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),U(K,{marginTop:1,gap:1,children:[D(B,{dimColor:!0,children:"["}),D(B,{children:"q"}),D(B,{dimColor:!0,children:"] quit ["}),D(B,{children:"c"}),D(B,{dimColor:!0,children:"] credentials ["}),D(B,{children:"v"}),U(B,{dimColor:!0,children:["] ",Rt===0?"open viewer":"relaunch viewer"]})]})]})};async function Hn(e){return new Promise(t=>{let n=null,o=i=>{n?.(),t(i)},{unmount:r}=Vn(Un(Ct,{...e!==void 0&&{initialMode:e},onComplete:o}),{exitOnCtrlC:!1});n=r})}function qn(e){e.command("dev").description("Start the plugin viewer dev server").option("-p, --port <port>","port to listen on","3121").option("-c, --credentials <path>","path to a credentials JSON file").option("-d, --debug","Enable CDP lifecycle logs in the TUI").option("-v, --verbose","Log every CDP event and handled error (implies --debug)").option("--no-viewer","Don't auto-launch the viewer on startup (press [v] to launch manually)").option("--no-cache","Disable the network proxy cache (always fetch upstream)").action(async t=>{let n=parseInt(t.port,10),o=process.cwd(),r=`${o}/.kizenapp`;Ne(o);let i=null,d,f,{lastPath:g}=await xe(r);if(t.credentials)i=await be(t.credentials);else{let p=await xe(r);if(p.credentialMode==="local")d="local";else if(p.credentialMode==="global"){if(d="global",f=p.activeCredentialProfile,f?(i=await de(f),i||(i=await Z(),f=void 0)):i=await Z(),!i){let y=await Hn("global");i=y.credentials,f=y.profileName}}else{let y=await Hn();i=y.credentials,d=y.mode,f=y.profileName;let S=y.profileName;await ve(r,{credentialMode:y.mode,...S!==void 0&&{activeCredentialProfile:S}})}}let m=t.verbose===!0,b=m||t.debug===!0,T=t.viewer!==!1,P=t.cache!==!1,{waitUntilExit:x}=Vn(Un(zn,{port:n,pluginDir:o,outputDir:r,credentials:i,...d!==void 0&&{credentialMode:d},...f!==void 0&&{activeCredentialProfile:f},...g!==void 0&&{lastPath:g},debug:b,verbose:m,autoViewer:T,cacheEnabled:P}),{exitOnCtrlC:!1});await x()})}import{createElement as Oa}from"react";import{render as ja}from"ink";import{useCallback as _t,useEffect as Xn,useState as Et}from"react";import{Box as ae,Text as $,useApp as Ra,useInput as Aa}from"ink";import{encrypt as va,serializeEnvelope as wa}from"@kizenapps/packager";function Ca(e){let t=e;return t.code==="ECONNREFUSED"||t.cause?.code==="ECONNREFUSED"}function Jn(e){return{"Content-Type":"application/json","x-api-key":e.apiKey,"x-user-id":e.userId,"x-business-id":e.businessId,"x-auth-environment":e.environment}}async function Wn(e,t,n){try{return await fetch(`${e}${t}`,n)}catch(o){throw new Error(Ca(o)?`Plugin-wizard is not running at ${e}`:`Failed to reach plugin-wizard: ${o.message}`)}}async function Kn(e){let t=await e.text();if(t==="")return{};try{let n=JSON.parse(t);return typeof n=="object"&&n!==null?n:{}}catch{return{}}}async function Sa(e,t,n){let o=Ve(e.stage),r=await Wn(o,"/get-public-key",{method:"POST",headers:Jn(t),body:JSON.stringify({api_name:n})}),i=await Kn(r);if(!r.ok||typeof i.public_key!="string"){let d=typeof i.error=="string"?i.error:`HTTP ${String(r.status)}`;throw new Error(`Failed to fetch public key: ${d}`)}return i.public_key}function Ta(e,t){let n=va(t,e),o=wa(n);if(typeof o.value!="string")throw new Error("Unexpected serialized envelope shape from @kizenapps/packager");return o.value}async function _a(e,t,n,o){let r=Ve(e.stage),i=await Wn(r,"/encrypt",{method:"POST",headers:Jn(t),body:JSON.stringify({api_name:n,value:o})}),d=await Kn(i);if(!i.ok||d.encrypted!==!0||typeof d.value!="string"){let f=typeof d.error=="string"?d.error:`HTTP ${String(i.status)}`;throw new Error(`Encryption via plugin-wizard failed: ${f}`)}return d.value}async function Tt(e,t,n,o,r){if(e.isRemote)return r?.("encrypting"),_a(e,t,n,o);r?.("fetching-key");let i=await Sa(e,t,n);return r?.("encrypting"),Ta(i,o)}import{spawn as Ea}from"child_process";import{platform as Gn}from"process";function ka(){return Gn==="darwin"?[{cmd:"pbcopy",args:[]}]:Gn==="win32"?[{cmd:"clip",args:[]}]:[{cmd:"wl-copy",args:[]},{cmd:"xclip",args:["-selection","clipboard"]},{cmd:"xsel",args:["--clipboard","--input"]}]}var Pa=2e3;function Ia(e,{cmd:t,args:n}){return new Promise(o=>{let r;try{r=Ea(t,n,{stdio:["pipe","ignore","ignore"]})}catch{o(!1);return}let i=r,d=!1;function f(m){d||(d=!0,clearTimeout(g),o(m))}let g=setTimeout(()=>{i.kill(),f(!1)},Pa);g.unref(),i.on("error",()=>{f(!1)}),i.on("close",m=>{f(m===0)}),i.stdin.on("error",()=>{f(!1)});try{i.stdin.end(e)}catch{f(!1)}})}async function Yn(e){for(let t of ka())if(await Ia(e,t))return!0;return!1}import{Fragment as kt,jsx as F,jsxs as G}from"react/jsx-runtime";var sr=({text:e})=>F($,{dimColor:!0,children:e}),Zn=({ctx:e,stageDefaulted:t,credentialsPath:n,initialApiName:o,defaultApiName:r,initialValue:i,onDone:d})=>{let f=Ra(),[g,m]=Et({type:"loading"}),[b,T]=Et(null),[P,x]=Et(o??""),[p,y]=Et(i??""),S=_t(s=>{process.exitCode=1,m({type:"error",message:s instanceof Error?s.message:String(s)})},[]),H=_t(async(s,l,u)=>{try{let h=await Tt(e,s,l,u,A=>{m(A==="fetching-key"?{type:"fetching-key"}:{type:"encrypting"})}),k=JSON.stringify({encrypted:!0,value:h},null,2);d?.(h);let _=await Yn(k);m({type:"done",envelope:k,copied:_})}catch(h){S(h)}},[e,S,d]),O=_t((s,l,u)=>{if(l.trim()===""){m({type:"api-name-entry",buffer:r??""});return}if(u===""){m({type:"value-entry",buffer:""});return}H(s,l.trim(),u)},[r,H]),w=_t(async s=>{try{m({type:"loading"});let l=s.isDefault?await Z():await de(s.name);if(l===null)throw new Error(`Could not load credential profile: ${s.name}`);T(l),O(l,P,p)}catch(l){S(l)}},[P,p,O,S]);Xn(()=>{(async()=>{try{if(n!==void 0){let u;try{u=await be(n)}catch(h){throw new Error(`Could not load credentials from ${n}: ${h instanceof Error?h.message:String(h)}`)}T(u),O(u,P,p);return}let s=await Ie();if(s.length===0)throw new Error("No credential profiles found. Create ~/.kizenappbuilder/credentials.json first.");let[l]=s;if(s.length===1&&l!==void 0){let u=l.isDefault?await Z():await de(l.name);if(u===null)throw new Error(`Could not load credential profile: ${l.name}`);T(u),O(u,P,p);return}m({type:"profile-select",profiles:s,cursor:0})}catch(s){S(s)}})()},[]),Xn(()=>{(g.type==="done"||g.type==="error")&&f.exit()},[g,f]),Aa((s,l)=>{if(l.ctrl&&s==="c"){process.exitCode=130,f.exit();return}if(g.type==="profile-select"){let{profiles:u,cursor:h}=g;if(l.upArrow)m({...g,cursor:(h-1+u.length)%u.length});else if(l.downArrow)m({...g,cursor:(h+1)%u.length});else if(l.return){let k=u[h];k!==void 0&&w(k)}return}if(g.type==="api-name-entry"){let{buffer:u}=g;if(l.backspace||l.delete)m({type:"api-name-entry",buffer:u.slice(0,-1)});else if(l.return){let h=u.trim();if(h===""){m({type:"api-name-entry",buffer:u,error:"api_name cannot be empty"});return}x(h),b?O(b,h,p):S(new Error("Internal error: credentials were not loaded"))}else s&&!l.ctrl&&!l.meta&&m({type:"api-name-entry",buffer:u+s});return}if(g.type==="value-entry"){let{buffer:u}=g;if(l.backspace||l.delete)m({type:"value-entry",buffer:u.slice(0,-1)});else if(l.return){if(u===""){m({type:"value-entry",buffer:u,error:"secret cannot be empty"});return}y(u),b?O(b,P,u):S(new Error("Internal error: credentials were not loaded"))}else s&&!l.ctrl&&!l.meta&&m({type:"value-entry",buffer:u+s});return}});let v=e.isRemote?"remote Kizen API":"on-machine",c=t===!0?`${e.stage} (default)`:e.stage,a=s=>G(ae,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[F(q,{}),G($,{dimColor:!0,children:["Mode: ",v," Stage: ",c]}),s]});if(g.type==="loading")return a(G(ae,{gap:1,children:[F(me,{}),F($,{dimColor:!0,children:"Loading credentials\u2026"})]}));if(g.type==="profile-select"){let{profiles:s,cursor:l}=g;return a(G(kt,{children:[F($,{bold:!0,children:"Credential profile"}),F(ae,{flexDirection:"column",children:s.map((u,h)=>{let k=l===h;return G(ae,{gap:2,children:[F($,{...k&&{color:"cyan"},children:k?"\u276F":" "}),F($,{bold:k,...k&&{color:"cyan"},children:u.isDefault?"Default":u.name}),F($,{dimColor:!0,children:u.path})]},u.name)})}),F(sr,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]}))}return g.type==="api-name-entry"?a(G(kt,{children:[F($,{bold:!0,children:"Plugin api_name"}),g.error!==void 0&&G($,{color:"red",children:["Error: ",g.error]}),G(ae,{gap:1,children:[F($,{color:"cyan",children:">"}),F($,{children:g.buffer}),F($,{color:"cyan",children:"\u2588"})]}),F(sr,{text:"Type the api_name \xB7 Enter to confirm \xB7 Ctrl+C to quit"})]})):g.type==="value-entry"?a(G(kt,{children:[F($,{bold:!0,children:"Secret value"}),g.error!==void 0&&G($,{color:"red",children:["Error: ",g.error]}),G(ae,{gap:1,children:[F($,{color:"cyan",children:">"}),F($,{children:"\u2022".repeat(g.buffer.length)}),F($,{color:"cyan",children:"\u2588"})]}),F(sr,{text:"Input hidden \xB7 Enter to encrypt \xB7 Ctrl+C to quit"})]})):g.type==="fetching-key"?a(G(ae,{gap:1,children:[F(me,{}),G($,{children:["Fetching ",e.stage," public key for ",F($,{bold:!0,children:P}),"\u2026"]})]})):g.type==="encrypting"?a(G(ae,{gap:1,children:[F(me,{}),F($,{children:"Encrypting\u2026"})]})):g.type==="error"?a(G(ae,{gap:1,children:[F($,{color:"red",children:"\u2717"}),F($,{color:"red",children:g.message})]})):a(G(kt,{children:[G(ae,{gap:1,children:[F($,{color:"green",children:"\u2713"}),F($,{bold:!0,children:"Encrypted secret ready"})]}),g.copied?F($,{color:"green",children:"\u2713 Copied to clipboard \u2014 paste it into the secret value in your kizen.json."}):F($,{dimColor:!0,children:"Paste this into the secret value in your kizen.json (re-run with --out <path> to save it to a file; selecting it here may capture line wraps):"}),F($,{children:g.envelope})]}))};import{readFile as Na,writeFile as Ba}from"fs/promises";import{join as Da}from"path";function Qn(e){return{encrypted:!0,value:e}}function eo(e){return JSON.stringify(Qn(e))}async function ar(e,t){await Ba(e,`${JSON.stringify(Qn(t),null,2)}
|
|
489
|
+
`,"utf-8")}var Fa="prod";function to(e){return e==="dev"||e==="prod"}function ro(e){return`Error: --stage must be "dev" or "prod" (got: "${e}")`}function no(e){return{stage:e==="dev"||e==="prod"?e:Fa,wasDefaulted:e===void 0}}function oo(e){return`No --stage given; defaulting to ${e} encryption keys (pass --stage dev to override)
|
|
490
|
+
`}async function io(e=process.cwd()){try{let t=await Na(Da(e,"kizen.json"),"utf-8"),n=JSON.parse(t),o=Array.isArray(n)?n[0]:n,r=typeof o.api_name=="string"&&o.api_name!==""?o.api_name:void 0;return{...r!==void 0&&{apiName:r}}}catch{}return{}}function so(e){return e.replace(/[\r\n]+$/,"")}async function ao(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}async function lo(e,t,n,o,r){let i=t.credentials!==void 0?await r.loadCredentialsFromFile(t.credentials):await r.loadGlobalCredentials();if(i===null)throw new Error("No credentials found. Pass --credentials or create ~/.kizenappbuilder/credentials.json.");let d=t.apiName??n.apiName;if(d===void 0||d.trim()==="")throw new Error("api_name is required in non-interactive mode. Pass --api-name or run inside a plugin directory.");o&&r.writeStderr(oo(e.stage));let f=t.value;if(f===void 0){if(r.stdinIsTTY())throw new Error('No secret provided and stdin is a terminal. Pass --value, or pipe the secret in (e.g. `printf %s "$SECRET" | npx --yes @kizenapps/cli encrypt \u2026`).');r.writeStderr(`Reading secret from stdin (pass --value to skip)\u2026
|
|
491
|
+
`),f=so(await r.readStdin())}if(f==="")throw new Error("A secret value is required. Pass --value or pipe it via stdin.");let g=await r.encryptSecret(e,i,d.trim(),f);if(r.writeStdout(`${eo(g)}
|
|
492
|
+
`),t.out!==void 0)try{await r.writeEnvelopeFile(t.out,g),r.writeStderr(`Wrote encrypted envelope to ${t.out}
|
|
493
|
+
`)}catch(m){r.writeStderr(`Error writing ${t.out}: ${m instanceof Error?m.message:String(m)}
|
|
494
|
+
`),r.setExitCode(1)}}function co(e){e.command("encrypt").description("Encrypt a secret for a plugin against its encryption keys").option("--remote","encrypt via the plugin-wizard's remote API instead of on-machine").option("-c, --credentials <path>","path to a credentials JSON file").option("-a, --api-name <name>","plugin api_name the secret belongs to").option("-v, --value <value>","plaintext secret value to encrypt").option("-s, --stage <stage>","which encryption API to use: dev or prod (default: prod)").option("-o, --out <path>","also write the encrypted envelope to a file").action(async t=>{t.stage!==void 0&&!to(t.stage)&&(console.error(ro(t.stage)),process.exit(1));let o=t.apiName===void 0?await io():{},{stage:r,wasDefaulted:i}=no(t.stage),d={isRemote:t.remote===!0,stage:r};if(!process.stdin.isTTY||!process.stdout.isTTY){try{await lo(d,t,o,i,{loadCredentialsFromFile:be,loadGlobalCredentials:Z,encryptSecret:Tt,readStdin:ao,stdinIsTTY:()=>process.stdin.isTTY,writeStdout:m=>{process.stdout.write(m)},writeStderr:m=>{process.stderr.write(m)},writeEnvelopeFile:ar,setExitCode:m=>{process.exitCode=m}})}catch(m){console.error(`Error: ${m instanceof Error?m.message:String(m)}`),process.exit(1)}return}let f,{waitUntilExit:g}=ja(Oa(Zn,{ctx:d,stageDefaulted:i,onDone:m=>{f=m},...t.credentials!==void 0&&{credentialsPath:t.credentials},...t.apiName!==void 0&&{initialApiName:t.apiName},...o.apiName!==void 0&&{defaultApiName:o.apiName},...t.value!==void 0&&{initialValue:t.value}}),{exitOnCtrlC:!1});if(await g(),f!==void 0&&t.out!==void 0)try{await ar(t.out,f),process.stderr.write(`Wrote encrypted envelope to ${t.out}
|
|
495
|
+
`)}catch(m){console.error(`Error writing ${t.out}: ${m instanceof Error?m.message:String(m)}`),process.exitCode=1}})}var $a=new Set(["phone","envelope","pen-nib","calendar-days","paperclip","file","clipboard","pen","tag","book","print","pen-to-square","folder","folder-open","thumbtack","globe","city","briefcase","compass","address-book","business-time","computer-classic","pen-fancy","badge-check","mug-saucer","landmark","chart-simple","envelopes","diagram-venn","calendar","pencil","phone-volume","copy","table","building","network-wired","address-card","tags","registered","signature","phone-office","projector","sitemap","marker","badge","wallet","copyright","bullseye","calculator","certificate","percent","eraser","file-spreadsheet","glasses","industry","vault","user-tie-hair-long","user-tie-hair","user-hair-mullet","trademark","timeline-arrow","timeline","table-tree","table-rows","table-pivot","table-layout","table-columns","stapler","square-poll-vertical","square-poll-horizontal","square-phone-flip","square-phone","square-pen","square-kanban","square-envelope","socks","slot-machine","signature-slash","signature-lock","shredder","scissors","scanner-image","scale-unbalanced-flip","scale-unbalanced","scale-balanced","router","rectangle-pro","print-slash","print-magnifying-glass","presentation-screen","podium","phone-slash","phone-intercom","phone-flip","person-chalkboard","pen-nib-slash","pen-clip","paste","paperclip-vertical","notebook","note-sticky","money-check-pen","money-check-dollar-pen","magnifying-glass-chart","magnifying-glass-arrow-right","list-tree","list-timeline","list-radio","list-dropdown","list-check","laptop-file","lamp-desk","keynote","industry-windows","inboxes","inbox-full","house-laptop","highlighter","folders","folder-xmark","folder-tree","folder-plus","folder-minus","folder-arrow-up","folder-arrow-down","floppy-disk-circle-xmark","floppy-disk-circle-arrow-right","floppy-disk","file-user","file-lines","file-circle-plus","file-circle-info","file-chart-pie","file-chart-column","fax","envelope-open","envelope-dot","envelope-circle-check","coffee-pot","cloud-word","clipboard-question","chart-user","chart-tree-map","chart-simple-horizontal","chart-pyramid","chart-pie-simple","chart-pie","chart-line-up","chart-line-down","chart-line","cake-candles","cabinet-filing","bullhorn","briefcase-blank","briefcase-arrow-right","brain-arrow-curved-right","boxes-packing","box-archive","book-section","bars-staggered","bars-progress","badge-percent","badge-dollar","arrows-to-eye","arrows-to-dot","arrows-spin","sparkles","megaphone","block-question","lightbulb-slash","comments-dollar","comments","bullseye-pointer","lightbulb","user-group-crown","user-crown","signal-stream-slash","signal-stream","rectangle-ad","ranking-star","person-rays","people-group","messages-dollar","message-dollar","magnifying-glass-location","magnifying-glass-dollar","lightbulb-on","lightbulb-exclamation","lightbulb-dollar","lightbulb-cfl-on","lightbulb-cfl","hundred-points","group-arrows-rotate","gift-card","filter-circle-dollar","envelopes-bulk","envelope-open-text","envelope-open-dollar","comment-dollar","chart-mixed","bullseye-arrow","star","heart","camera-retro","truck-fast","bell","cart-shopping","gift","barcode","bookmark","camera","thumbs-up","thumbs-down","key","truck","balloons","handshake","shop","shirt","bag-shopping","moped","cart-plus","credit-card","store","cash-register","booth-curtain","trophy","receipt","truck-container","truck-clock","truck-bolt","trophy-star","store-slash","store-lock","star-exclamation","shop-slash","shop-lock","rectangle-barcode","person-booth","nfc-trash","nfc-symbol","nfc-slash","nfc-signal","nfc-pen","nfc-magnifying-glass","nfc-lock","nfc","money-check-dollar","money-check","mobile-signal-out","mobile-signal","hexagon-vertical-nft-slanted","hexagon-vertical-nft","hexagon-image","hand-holding-box","gifts","gem","credit-card-front","credit-card-blank","cart-xmark","cart-shopping-fast","cart-minus","cart-circle-xmark","cart-circle-plus","cart-circle-exclamation","cart-circle-check","cart-circle-arrow-up","cart-circle-arrow-down","cart-arrow-up","cart-arrow-down","box-open-full","basket-shopping-simple","basket-shopping","barcode-scan","barcode-read","balloon","bags-shopping","bars","browser","chart-bar","cog","database","calendar-alt","play","kizen-k","add","book-alt","form-entity","arrows-to-circle","question-circle","chevron-down","chevron-up","window-restore","forward"]),La=[...$a].sort(),Ma=new Set(["kizen-k","form-entity"]),po=[...La,...[...Ma].sort()];function uo(e){e.command("icons").description("List all valid icon names accepted by toolbar items, pages, and adornments").action(()=>{for(let t of po)console.log(t)})}import{mkdir as Ka,writeFile as So,readFile as Ga}from"fs/promises";import{join as Pt}from"path";var za=new Set(["developer_business_id"]);function Ha(e){return Array.isArray(e)?e.map(t=>{if(typeof t!="object"||t===null)return t;let n=t;if(typeof n.auth_credentials!="object"||n.auth_credentials===null)return n;let o=Object.fromEntries(Object.keys(n.auth_credentials).map(r=>[r,"*****"]));return{...n,auth_credentials:o}}):e}function mo(e){let t={name:"",children:new Map,isFile:!1,filePath:""};for(let n of e){let o=n.path.split("/"),r=t;o.forEach((i,d)=>{r.children.has(i)||r.children.set(i,{name:i,children:new Map,isFile:d===o.length-1,filePath:o.slice(0,d+1).join("/")});let f=r.children.get(i);f&&(r=f)})}return t}function go(e){return[...e.children.values()].sort((t,n)=>t.isFile!==n.isFile?t.isFile?1:-1:t.name.localeCompare(n.name))}function lr(e){return"file-"+e.replace(/[^a-zA-Z0-9]/g,"-")}function le(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function ho(e){let t=e.lastIndexOf(".");return t>=0?e.slice(t).toLowerCase():""}var Ua={".ts":"typescript",".tsx":"typescript",".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".json":"json",".css":"css",".scss":"scss",".html":"html",".htm":"html",".md":"markdown",".mdx":"markdown",".py":"python",".sh":"bash",".yml":"yaml",".yaml":"yaml",".xml":"xml",".toml":"toml"};function Va(e){return Ua[ho(e)]??""}function fo(e){let t=[...e.matchAll(/`+/g)].reduce((n,o)=>Math.max(n,o[0].length),0);return"`".repeat(Math.max(3,t+1))}function yo(e,t=""){let n=go(e);return n.map((o,r)=>{let i=r===n.length-1,d=i?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",f=i?" ":"\u2502 ";return o.isFile?`${t}${d}${o.name}`:`${t}${d}${o.name}/
|
|
496
|
+
${yo(o,t+f)}`}).join(`
|
|
497
|
+
`)}var qa=/(^|\/)licen[cs]e(\.md|\.txt)?$/i;function bo(e){return e.filter(t=>t.path!=="kizen.json"&&t.path!=="plugin-report.html"&&!qa.test(t.path))}function xo(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!za.has(t)).map(([t,n])=>[t,t==="services"?Ha(n):n]))}var Ja={".png":"image/png",".svg":"image/svg+xml",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp"};function vo(e){return`<ul>${go(e).map(o=>o.isFile?`<li class="tf"><a href="#${lr(o.filePath)}" data-id="${lr(o.filePath)}">${le(o.name)}</a></li>`:`<li class="td"><span class="dn">${le(o.name)}/</span>${vo(o)}</li>`).join("")}</ul>`}function Wa(e){let t;return e.base64Image!==void 0?t=`<img src="data:${Ja[ho(e.path)]??"image/png"};base64,${e.base64Image}" alt="${le(e.path)}" style="max-width:100%">`:e.binaryData!==void 0?t=`<p class="bin">[Binary file: ${String(e.binaryData.length)} bytes]</p>`:t=`<pre><code>${le(e.content)}</code></pre>`,`<section id="${lr(e.path)}"><h2 class="fp">${le(e.path)}</h2><div class="fb">${t}</div></section>`}function wo(e,t){let n=xo(e),o=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",d=bo(t),f=[];f.push(`# ${o}${r?` v${r}`:""}`),i&&f.push("",i);let g=JSON.stringify(n,null,2),m=fo(g);f.push("","## Configuration (`kizen.json`)","",`${m}json`,g,m),f.push("","## File Tree","","```",yo(mo(d)),"```"),f.push("","## Files");for(let b of d)if(f.push("",`### \`${b.path}\``,""),b.base64Image!==void 0)f.push(`[Image file: ${b.path}]`);else if(b.binaryData!==void 0)f.push(`[Binary file: ${String(b.binaryData.length)} bytes]`);else{let T=fo(b.content);f.push(`${T}${Va(b.path)}`,b.content,T)}return f.join(`
|
|
201
498
|
`)+`
|
|
202
|
-
`}function
|
|
499
|
+
`}function Co(e,t){let n=xo(e),o=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",d=bo(t),f=vo(mo(d)),g=d.map(Wa).join(`
|
|
203
500
|
`);return`<!DOCTYPE html>
|
|
204
501
|
<html lang="en">
|
|
205
502
|
<head>
|
|
206
503
|
<meta charset="UTF-8">
|
|
207
504
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
208
|
-
<title>${
|
|
505
|
+
<title>${le(o)} \u2014 Plugin Report</title>
|
|
209
506
|
<style>
|
|
210
507
|
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
|
211
508
|
:root{
|
|
@@ -242,17 +539,17 @@ img{border:1px solid var(--bd);border-radius:4px}
|
|
|
242
539
|
</head>
|
|
243
540
|
<body>
|
|
244
541
|
<header>
|
|
245
|
-
<h1>${
|
|
246
|
-
${i?`<p>${
|
|
542
|
+
<h1>${le(o)}${r?` <span style="color:var(--mu);font-size:.8em">v${le(r)}</span>`:""}</h1>
|
|
543
|
+
${i?`<p>${le(i)}</p>`:""}
|
|
247
544
|
</header>
|
|
248
545
|
<div class="layout">
|
|
249
546
|
<nav>
|
|
250
547
|
<a href="#config" class="cfg" data-id="config">kizen.json (config)</a>
|
|
251
|
-
${
|
|
548
|
+
${f}
|
|
252
549
|
</nav>
|
|
253
550
|
<main>
|
|
254
|
-
<section id="config"><h2 class="fp">kizen.json \u2014 Plugin Configuration</h2><div class="fb"><pre><code>${
|
|
255
|
-
${
|
|
551
|
+
<section id="config"><h2 class="fp">kizen.json \u2014 Plugin Configuration</h2><div class="fb"><pre><code>${le(JSON.stringify(n,null,2))}</code></pre></div></section>
|
|
552
|
+
${g}
|
|
256
553
|
</main>
|
|
257
554
|
</div>
|
|
258
555
|
<script>
|
|
@@ -265,7 +562,7 @@ ${m}
|
|
|
265
562
|
})();
|
|
266
563
|
</script>
|
|
267
564
|
</body>
|
|
268
|
-
</html>`}var
|
|
565
|
+
</html>`}var To=Pt(Pe,"examples");function _o(e){e.command("report").description("Generate a self-contained HTML report of the plugin").option("-o, --output <path>",`output file path (default: ${To}/<api_name>.html)`).action(async t=>{let n=process.cwd(),o;try{let g=await Ga(Pt(n,"kizen.json"),"utf-8"),m=JSON.parse(g);o=Array.isArray(m)?m[0]:m}catch{console.error("Error: kizen.json not found. Run this command from a plugin directory."),process.exit(1)}let r=typeof o.api_name=="string"?o.api_name:"plugin",i=t.output??Pt(To,`${r}.html`),d=i.replace(/\.html$/,".md"),f=await rt(n,{detectBinaryByContent:!0});await Ka(Pt(i,".."),{recursive:!0}),await Promise.all([So(i,Co(o,f),"utf-8"),So(d,wo(o,f),"utf-8")]),console.log(`Plugin report written to:
|
|
269
566
|
${i}
|
|
270
|
-
${
|
|
567
|
+
${d}`)})}function tl(){let e=Za(Xa(Qa(import.meta.url)),"..","package.json");return JSON.parse(Ya(e,"utf-8")).version}function Eo(){let e=new el;return e.name("appbuilder").description("Kizen plugin app builder").version(tl()),cn(e),Tr(e),qn(e),co(e),_o(e),uo(e),e}Eo().parse();
|
|
271
568
|
//# sourceMappingURL=index.js.map
|