velloo 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/canvas/assets/index-B1OD0Yz5.css +2 -0
  2. package/canvas/assets/index-BWYFx2Rr.js +29 -0
  3. package/canvas/assets/lucide-all-Bcm80WFX.js +1 -0
  4. package/canvas/index.html +2 -2
  5. package/{chunk-t8xk4thc.js → chunk-00t0bz7x.js} +1 -1
  6. package/{chunk-c5zjen06.js → chunk-0446t32z.js} +1 -1
  7. package/{chunk-2fgfex9b.js → chunk-2dm4x17z.js} +1 -1
  8. package/{chunk-33r6266k.js → chunk-2h24va0j.js} +1 -1
  9. package/{chunk-jtsn41cs.js → chunk-2jbhv7vh.js} +1 -1
  10. package/{chunk-t4zss1tk.js → chunk-2y9nnzpr.js} +1 -1
  11. package/{chunk-nc5k1ez4.js → chunk-5ywkk7d6.js} +1 -1
  12. package/{chunk-25j8vgpa.js → chunk-6zr596r2.js} +1 -1
  13. package/{chunk-nte0t7v3.js → chunk-7a45tn73.js} +1 -1
  14. package/{chunk-sn9vg42q.js → chunk-7gtvstne.js} +1 -1
  15. package/{chunk-0r80246c.js → chunk-7xffbj5h.js} +1 -1
  16. package/{chunk-c6hywdvq.js → chunk-8t5phg0s.js} +1 -1
  17. package/{chunk-y0rwf1ze.js → chunk-91pajfnm.js} +1 -1
  18. package/{chunk-c4fym47a.js → chunk-a9mgvspm.js} +1 -1
  19. package/{chunk-ys3s5gaa.js → chunk-aa3str7g.js} +1 -1
  20. package/{chunk-8krqgzny.js → chunk-b4jy4hcd.js} +1 -1
  21. package/{chunk-e56eb38j.js → chunk-b58pnj20.js} +1 -1
  22. package/{chunk-38ev3cp3.js → chunk-b7famda5.js} +1 -1
  23. package/{chunk-vbe2r4kv.js → chunk-cejmmx3r.js} +1 -1
  24. package/{chunk-v0syg2hx.js → chunk-db7mf114.js} +1 -1
  25. package/{chunk-46xykc71.js → chunk-dj1pp4e3.js} +1 -1
  26. package/{chunk-hzjzmkp6.js → chunk-e6nhc3ay.js} +1 -1
  27. package/{chunk-tqwe5tc3.js → chunk-f5g45xed.js} +1 -1
  28. package/{chunk-n5acf0s3.js → chunk-hsrg23gd.js} +1 -1
  29. package/{chunk-rsy246re.js → chunk-hv52a6hf.js} +1 -1
  30. package/{chunk-bhx8k09w.js → chunk-j5axqyan.js} +1 -1
  31. package/{chunk-3gbmq4jz.js → chunk-jep31ffe.js} +1 -1
  32. package/{chunk-7cktk5qr.js → chunk-jwzhhhzn.js} +1 -1
  33. package/{chunk-zkn1m8tw.js → chunk-k3dpwjx4.js} +1 -1
  34. package/{chunk-cdxy4xzs.js → chunk-km3z2czq.js} +1 -1
  35. package/chunk-m1wp8cpt.js +2 -0
  36. package/{chunk-8g5ghy46.js → chunk-mcymwefw.js} +1 -1
  37. package/{chunk-6z0kpe65.js → chunk-n0kx20s2.js} +1 -1
  38. package/{chunk-tkvb3wb8.js → chunk-npsg7btt.js} +1 -1
  39. package/{chunk-5qd2ykvw.js → chunk-nwf2kn41.js} +1 -1
  40. package/{chunk-vh4144az.js → chunk-ph94nrc8.js} +1 -1
  41. package/chunk-phz993p3.js +2 -0
  42. package/{chunk-09385g5r.js → chunk-py6sjyzk.js} +1 -1
  43. package/{chunk-egccxmed.js → chunk-qan5dnjt.js} +11 -11
  44. package/{chunk-z1r0sc3k.js → chunk-r03aywsb.js} +1 -1
  45. package/{chunk-yjmawrv5.js → chunk-r5d0jsnd.js} +1 -1
  46. package/{chunk-js6mz7h1.js → chunk-r9ekd92e.js} +1 -1
  47. package/{chunk-8sfx5x8k.js → chunk-rfrbnw8r.js} +1 -1
  48. package/{chunk-1tdh4h14.js → chunk-shac6bat.js} +1 -1
  49. package/{chunk-syg6k8m0.js → chunk-t4zvcece.js} +1 -1
  50. package/{chunk-8yz604tw.js → chunk-t9ygewjx.js} +1 -1
  51. package/{chunk-6qfyem23.js → chunk-tarws372.js} +1 -1
  52. package/{chunk-4rvmpsda.js → chunk-tr49kraa.js} +1 -1
  53. package/{chunk-3kqtny5t.js → chunk-vjrn10xr.js} +1 -1
  54. package/{chunk-k10n8na7.js → chunk-xbhxzdat.js} +1 -1
  55. package/{chunk-8yadb6xz.js → chunk-yfttm20w.js} +1 -1
  56. package/chunk-yghypth2.js +2 -0
  57. package/chunk-ykdx12na.js +4 -0
  58. package/{chunk-q4d60wr3.js → chunk-zqtz23xk.js} +1 -1
  59. package/cli.js +1 -1
  60. package/package.json +1 -1
  61. package/pkgs/schema/src/comment.ts +12 -0
  62. package/pkgs/schema/src/index.ts +1 -0
  63. package/canvas/assets/index-CSSyvzzo.css +0 -2
  64. package/canvas/assets/index-MXiDRs_Q.js +0 -29
  65. package/canvas/assets/lucide-all-BSrW0hTo.js +0 -1
  66. package/chunk-cgzhcvsj.js +0 -2
  67. package/chunk-gsne0ap4.js +0 -2
  68. package/chunk-njhdn9j0.js +0 -4
  69. package/chunk-va9v9y5m.js +0 -2
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{BoardSchema,isArchived,designNameIssue,toDesignName,ConfigSchema,ScreenSchema}from"./chunk-nte0t7v3.js";import{writeJsonAtomic,listLocalDesigns,writeLocalDesign,readRepoManifestAt,findOwningManifest,recordedDesignName,findDesigns2,pickDesign}from"./chunk-egccxmed.js";import{isCancel,multiselect,select}from"./chunk-80fjfyha.js";import{fail}from"./chunk-s23gtejf.js";import{existsSync,realpathSync}from"fs";import{readdir,readFile,rm,stat}from"fs/promises";import{homedir}from"os";import{basename,dirname,isAbsolute,join,relative,resolve,sep}from"path";var MANIFEST_FILE="velloo.json",DEFAULT_FOLDER_NAME="velloo";function findManifest(dir){return readRepoManifestAt(dir,{strict:!0})}function manifestListing(folder){return findOwningManifest(folder,{strict:!0})}function findDesigns(cwd){return findDesigns2(cwd,{strict:!0})}function sameFolder(a,b){return a===b||existsSync(a)&&existsSync(b)&&realpathSync(a)===realpathSync(b)}function assertCurrent(found){if(found.legacy)throw Error(`${found.path} is in the pre-designs format (\`projects\`) \u2014 run \`velloo upgrade\` to migrate it first.`)}async function unregisterDesign(folder,projectDir){let abs=resolve(folder),here=projectDir?await findManifest(projectDir):null,found=here?.folders.some((path)=>sameFolder(path,abs))?here:await manifestListing(abs);if(!found)return{name:null,path:null,removedManifest:!1};let index=found.folders.findIndex((path)=>sameFolder(path,abs));if(index===-1)return{name:null,path:found.path,removedManifest:!1};assertCurrent(found);let name=recordedDesignName(abs)??basename(abs),manifest=withoutDesign(found.manifest,index,name);if(manifest===null)return await rm(found.path,{force:!0}),{name,path:found.path,removedManifest:!0};return await writeJsonAtomic(found.path,manifest),{name,path:found.path,removedManifest:!1}}function withoutDesign(manifest,index,name){let designs=manifest.designs.filter((_,i)=>i!==index),{defaultDesign,...rest}=manifest;if(designs.length===0&&!rest.feedback)return null;return{...rest,designs,...defaultDesign&&defaultDesign!==name?{defaultDesign}:{}}}function isWithin(parent,child){let rel=relative(parent,child);return rel===""||!rel.startsWith("..")&&!isAbsolute(rel)}async function findGitRoot(start){let home=homedir(),dir=resolve(start);while(dir!==home){try{return await stat(join(dir,".git")),dir}catch{}let parent=dirname(dir);if(parent===dir)return null;dir=parent}return null}var SCAN_SKIP=new Set(["node_modules",".git","dist","build",".next",".turbo","coverage",".velloo"]);async function discoverDesignFolders(root,maxDepth=3){let out=[],walk=async(dir,depth)=>{let entries;try{entries=await readdir(dir,{withFileTypes:!0})}catch{return}for(let entry of entries){if(!entry.isDirectory()||entry.name.startsWith(".")||SCAN_SKIP.has(entry.name))continue;let child=join(dir,entry.name);try{await stat(join(child,".design","config.json")),out.push(child);continue}catch{}if(depth<maxDepth)await walk(child,depth+1)}};return await walk(resolve(root),1),out.sort()}function deriveName(folder,projectDir){let base=basename(folder),nested=base===DEFAULT_FOLDER_NAME&&dirname(folder)!==projectDir;return toDesignName(nested?basename(dirname(folder)):base)??"app"}async function chooseDesignName(request){let folder=resolve(request.folder),issue=request.requested===void 0?null:designNameIssue(request.requested);if(issue)throw Error(`invalid --name ${JSON.stringify(request.requested)} \u2014 ${issue}`);let taken=await takenNames(request,folder);if(request.requested){let holder=taken.get(request.requested);if(holder)throw Error(`a design named "${request.requested}" already exists at ${holder} \u2014 pick another --name.`);return request.requested}let base;if(request.storage==="repository")base=deriveName(folder,resolve(request.checkout));else{let chosen=request.storage==="chosen"&&basename(folder)!==DEFAULT_FOLDER_NAME;base=deriveName(chosen?folder:request.appRoot)}let name=base;for(let n=2;taken.has(name);n++)name=`${base}-${n}`;return name}async function takenNames(request,folder){let from=request.checkout,taken=new Map,set=await findDesigns(from).catch(()=>null);for(let design of set?.designs??[])if(!sameFolder(design.root,folder))taken.set(design.name,design.root);if(!set?.repo)for(let sibling of await discoverDesignFolders(request.checkout,1)){let name=recordedDesignName(sibling);if(name&&!sameFolder(sibling,folder))taken.set(name,sibling)}return taken}async function writeDesignName(folder,name){let path=join(folder,".design","config.json"),config=ConfigSchema.parse(JSON.parse(await readFile(path,"utf8")));await writeJsonAtomic(path,{...config,name})}async function registerDesign(folder,projectDir){let abs=resolve(folder),name=recordedDesignName(abs);if(!name)throw Error(`${abs} has no design name \u2014 run \`velloo design upgrade ${abs}\` first.`);let dir=resolve(projectDir),found=await findManifest(dir),path=found?found.path:join(dir,MANIFEST_FILE);if(found?.folders.some((target)=>sameFolder(target,abs)))return{name,path,created:!1};if(found)assertCurrent(found);let clash=(await findDesigns(dir))?.designs.find((d)=>d.name===name&&!sameFolder(d.root,abs));if(clash)throw Error(`a design named "${name}" already exists at ${clash.root} \u2014 rename one with \`velloo design rename\`.`);let designs=[...found?.manifest.designs??[]],rel=(target)=>relative(dir,target).split("\\").join("/")||".",defaultDesign=found?.manifest.defaultDesign;if(!found)for(let sibling of await discoverDesignFolders(dir,1)){if(sibling===abs)continue;if(designs.push(rel(sibling)),sibling===join(dir,DEFAULT_FOLDER_NAME))defaultDesign=recordedDesignName(sibling)??void 0}designs.push(rel(abs));let manifest={...found?.manifest??{},designs,...defaultDesign?{defaultDesign}:{}};return await writeJsonAtomic(path,manifest),{name,path,created:!0}}async function registerLocalDesign(opts){await writeLocalDesign(opts.id,{root:opts.root,appRoot:opts.appRoot,...opts.designPath?{designPath:opts.designPath}:{}})}import{existsSync as existsSync2,readdirSync}from"fs";import{readdir as readdir2,readFile as readFile2}from"fs/promises";import{homedir as homedir2}from"os";import{basename as basename2,dirname as dirname2,join as join2,relative as relative2,resolve as resolve2,sep as sep2}from"path";var DEFAULT_FOLDER="velloo",DESIGN_ARG_DESCRIPTION="A design name from ./velloo.json, a design folder, or a velloo.json file or its directory (default: the design folder you're in, else this directory's velloo.json: its only design or defaultDesign)";async function existingDesignFolder(appRoot){try{let found=await findDesigns(appRoot);for(let design of found?.designs??[])if(design.exists)return design.root}catch{}let conventional=join2(resolve2(appRoot),DEFAULT_FOLDER);if(await hasDesignConfig(conventional))return conventional;let[first]=await discoverDesignFolders(resolve2(appRoot));return first??null}function isDesignFolderSync(dir){return existsSync2(join2(dir,".design","config.json"))}function isEmptyOrMissingSync(dir){try{return readdirSync(dir).length===0}catch(err){if(err.code==="ENOENT")return!0;throw err}}async function hasDesignConfig(dir){try{return await readFile2(join2(dir,".design","config.json"),"utf8"),!0}catch{return!1}}var DESIGN_ID_ARG={type:"string",description:"The design's number in `velloo design list`, instead of its name or path"};async function designFolder(set,design,abort){let repo=set.repo;if(repo&&design.outsideRepo){let entry=relative2(repo.dir,design.root);abort(`design ${JSON.stringify(design.name)} in ${repo.path} points outside the repository (${entry}), which velloo.json cannot authorize. Pass the design path explicitly, or run \`velloo design bind ${design.root}\` here to keep it as a local design on this machine.`)}if(!design.exists)abort(`design ${JSON.stringify(design.name)} ${design.local?"(a local design)":`in ${repo?.path}`} points at ${design.root}, which is not a velloo design folder (no .design/config.json).`);return design.root}function quoteArg(value){return/^[\w@%+=:,./-]+$/.test(value)?value:`'${value.replace(/'/g,"'\\''")}'`}function designsLabel(set){return set.repo?.path??"this checkout's local designs"}function byName(set,name,abort){let shared=set.conflicts.get(name);if(shared)abort(`${shared.length} designs are named ${JSON.stringify(name)}: ${shared.map((d)=>d.root).join(", ")}. Pass a path, and rename one with \`velloo design rename <path> <new-name>\`.`);return set.byName.get(name)}async function resolveDesign(arg,cmd,opts={}){let abort=opts.onFail??((m)=>fail(cmd,m)),cwd=resolve2(opts.cwd??"."),set=null;try{set=await findDesigns(cwd)}catch(err){abort(err.message)}if(opts.id!==void 0){if(arg)abort("pass a design or --id, not both.");let n=Number(opts.id);if(!Number.isInteger(n)||n<1)abort("--id takes a design's number from `velloo design list`.");if(!set||set.designs.length===0){if(n===1)return resolveDesign(void 0,cmd,{...opts,id:void 0});abort(`there is no design #${n} here \u2014 \`velloo design list\` numbers them.`)}let entry=set.designs[n-1];if(!entry)abort(`there is no design #${n} \u2014 ${designsLabel(set)} has ${set.designs.length}. \`velloo design list\` numbers them.`);return designFolder(set,entry,abort)}if(arg){let named=set&&!arg.includes(sep2)?byName(set,arg,abort):void 0;if(set&&named)return designFolder(set,named,abort);let explicit=resolve2(cwd,arg);if(await hasDesignConfig(explicit))return explicit;let project=basename2(explicit)==="velloo.json"&&existsSync2(explicit)?dirname2(explicit):explicit;if((await findDesigns(project).catch((err)=>abort(err.message)))?.designs.length)return resolveDesign(void 0,cmd,{...opts,cwd:project});let nested=join2(explicit,DEFAULT_FOLDER);if(await hasDesignConfig(nested))return nested;if(!set&&!arg.includes(sep2)){let above=await enclosingProject(cwd),match=above?.designs.find((d)=>d.name===arg);if(above&&match)abort(`design ${JSON.stringify(arg)} is listed in \`${shortPath(cwd,above.label)}\`, and commands only read the directory they run in. Run from \`${shortPath(cwd,above.dir)}\`, or pass its folder (\`${quoteArg(shortPath(cwd,match.root))}\`) instead of its name.`)}if(set&&!arg.includes(sep2))abort(`unknown design ${JSON.stringify(arg)} \u2014 ${designsLabel(set)} lists: ${set.designs.map((d)=>d.name).join(", ")}. Pass a design name or a folder path.`);if(opts.requireConfig)abort(`${explicit} is not a velloo design folder (no .design/config.json).`);return explicit}if(set&&set.designs.length>0){if(await hasDesignConfig(cwd))return cwd;let picked=pickDesign(set,cwd);if(picked&&picked.reason!=="arbitrary")return designFolder(set,picked.design,abort);let names=set.designs.map((d)=>d.name);if(opts.interactive&&process.stdin.isTTY){let chosen=await select({message:"Which design?",options:set.designs.map((d)=>({value:d.root,label:d.name,hint:relative2(cwd,d.root)}))});if(isCancel(chosen))abort("cancelled.");let design=set.designs.find((d)=>d.root===chosen);return designFolder(set,design,abort)}let example=cmd.startsWith("design ")?`velloo ${cmd} --id 1\` for ${quoteArg(names[0]??"")}, as numbered by \`velloo design list`:`velloo ${cmd} ${designExample(opts,names[0]??"")}`;abort(`${designsLabel(set)} lists several designs: ${names.join(", ")}. Pass one (e.g. \`${example}\`)${set.repo?' or set "defaultDesign"':""}.`)}if(await hasDesignConfig(cwd))return cwd;let here=join2(cwd,DEFAULT_FOLDER);if(await hasDesignConfig(here))return here;let takesDesign=opts.takesDesign!==!1,above=await enclosingProject(cwd);if(above){let nearest=[...above.designs].sort((a,b)=>relative2(cwd,a.root).length-relative2(cwd,b.root).length)[0],example=takesDesign&&nearest?`, or pass a design folder (e.g. \`velloo ${cmd} ${designExample(opts,relative2(cwd,nearest.root).split(sep2).join("/"))}\`)`:"";abort(`no velloo.json or design folder here. \`${shortPath(cwd,above.label)}\` lists ${above.designs.map((d)=>JSON.stringify(d.name)).join(", ")}, and commands only read the directory they run in: run from \`${shortPath(cwd,above.dir)}\`${example}.`)}let example=takesDesign?`, pass a design folder or a velloo.json path (e.g. \`velloo ${cmd} ${designExample(opts,"apps/web")}\`)`:"";abort(`no velloo.json or design folder in ${cwd}. Run from the directory that has your velloo.json${example}, or \`velloo init\` here.${movedCheckoutHint(cwd)}`)}function shortPath(cwd,path){let rel=relative2(cwd,path);return rel!==""&&rel.length<path.length?rel.split(sep2).join("/"):path}function designExample(opts,design){return opts.designFlag?`${opts.designFlag}=${quoteArg(design)}`:quoteArg(design)}async function enclosingProject(cwd){let here=resolve2(cwd);for(let dir=dirname2(here);dir!==here;){let set=await findDesigns(dir).catch(()=>null),designs=set?.designs.filter((d)=>d.exists&&!d.outsideRepo)??[];if(set&&designs.length>0)return{dir,label:set.repo?.path??`${dir} (local designs)`,designs};let parent=dirname2(dir);if(parent===dir)return null;dir=parent}return null}async function checkoutDesigns(cwd){let set=await findDesigns(cwd).catch(()=>null);if(set&&set.designs.length>0)return set.designs.filter((d)=>d.exists&&!d.outsideRepo).map((d)=>d.root);try{return[await resolveDesign(void 0,"upgrade",{requireConfig:!0,cwd,onFail:()=>{throw Error("no design here")}})]}catch{return[]}}async function resolveDesignForSession(arg,cmd,cwd=resolve2(".")){if(!arg&&!await hasDesignConfig(cwd)){let set=await findDesigns(cwd).catch(()=>null),picked=set?pickDesign(set,cwd):null;if(set&&picked?.reason==="arbitrary")return{folder:await designFolder(set,picked.design,(m)=>fail(cmd,m)),pick:"arbitrary"}}return{folder:await resolveDesign(arg,cmd,{cwd}),pick:void 0}}function movedCheckoutHint(cwd){if(!insideProject(cwd))return"";let orphans=listLocalDesigns().filter((design)=>!existsSync2(design.root)&&existsSync2(design.designRoot));if(orphans.length===0)return"";return`
2
+ import{BoardSchema,isArchived,designNameIssue,toDesignName,ConfigSchema,ScreenSchema}from"./chunk-7a45tn73.js";import{writeJsonAtomic,listLocalDesigns,writeLocalDesign,readRepoManifestAt,findOwningManifest,recordedDesignName,findDesigns2,pickDesign}from"./chunk-qan5dnjt.js";import{isCancel,multiselect,select}from"./chunk-80fjfyha.js";import{fail}from"./chunk-s23gtejf.js";import{existsSync,realpathSync}from"fs";import{readdir,readFile,rm,stat}from"fs/promises";import{homedir}from"os";import{basename,dirname,isAbsolute,join,relative,resolve,sep}from"path";var MANIFEST_FILE="velloo.json",DEFAULT_FOLDER_NAME="velloo";function findManifest(dir){return readRepoManifestAt(dir,{strict:!0})}function manifestListing(folder){return findOwningManifest(folder,{strict:!0})}function findDesigns(cwd){return findDesigns2(cwd,{strict:!0})}function sameFolder(a,b){return a===b||existsSync(a)&&existsSync(b)&&realpathSync(a)===realpathSync(b)}function assertCurrent(found){if(found.legacy)throw Error(`${found.path} is in the pre-designs format (\`projects\`) \u2014 run \`velloo upgrade\` to migrate it first.`)}async function unregisterDesign(folder,projectDir){let abs=resolve(folder),here=projectDir?await findManifest(projectDir):null,found=here?.folders.some((path)=>sameFolder(path,abs))?here:await manifestListing(abs);if(!found)return{name:null,path:null,removedManifest:!1};let index=found.folders.findIndex((path)=>sameFolder(path,abs));if(index===-1)return{name:null,path:found.path,removedManifest:!1};assertCurrent(found);let name=recordedDesignName(abs)??basename(abs),manifest=withoutDesign(found.manifest,index,name);if(manifest===null)return await rm(found.path,{force:!0}),{name,path:found.path,removedManifest:!0};return await writeJsonAtomic(found.path,manifest),{name,path:found.path,removedManifest:!1}}function withoutDesign(manifest,index,name){let designs=manifest.designs.filter((_,i)=>i!==index),{defaultDesign,...rest}=manifest;if(designs.length===0&&!rest.feedback)return null;return{...rest,designs,...defaultDesign&&defaultDesign!==name?{defaultDesign}:{}}}function isWithin(parent,child){let rel=relative(parent,child);return rel===""||!rel.startsWith("..")&&!isAbsolute(rel)}async function findGitRoot(start){let home=homedir(),dir=resolve(start);while(dir!==home){try{return await stat(join(dir,".git")),dir}catch{}let parent=dirname(dir);if(parent===dir)return null;dir=parent}return null}var SCAN_SKIP=new Set(["node_modules",".git","dist","build",".next",".turbo","coverage",".velloo"]);async function discoverDesignFolders(root,maxDepth=3){let out=[],walk=async(dir,depth)=>{let entries;try{entries=await readdir(dir,{withFileTypes:!0})}catch{return}for(let entry of entries){if(!entry.isDirectory()||entry.name.startsWith(".")||SCAN_SKIP.has(entry.name))continue;let child=join(dir,entry.name);try{await stat(join(child,".design","config.json")),out.push(child);continue}catch{}if(depth<maxDepth)await walk(child,depth+1)}};return await walk(resolve(root),1),out.sort()}function deriveName(folder,projectDir){let base=basename(folder),nested=base===DEFAULT_FOLDER_NAME&&dirname(folder)!==projectDir;return toDesignName(nested?basename(dirname(folder)):base)??"app"}async function chooseDesignName(request){let folder=resolve(request.folder),issue=request.requested===void 0?null:designNameIssue(request.requested);if(issue)throw Error(`invalid --name ${JSON.stringify(request.requested)} \u2014 ${issue}`);let taken=await takenNames(request,folder);if(request.requested){let holder=taken.get(request.requested);if(holder)throw Error(`a design named "${request.requested}" already exists at ${holder} \u2014 pick another --name.`);return request.requested}let base;if(request.storage==="repository")base=deriveName(folder,resolve(request.checkout));else{let chosen=request.storage==="chosen"&&basename(folder)!==DEFAULT_FOLDER_NAME;base=deriveName(chosen?folder:request.appRoot)}let name=base;for(let n=2;taken.has(name);n++)name=`${base}-${n}`;return name}async function takenNames(request,folder){let from=request.checkout,taken=new Map,set=await findDesigns(from).catch(()=>null);for(let design of set?.designs??[])if(!sameFolder(design.root,folder))taken.set(design.name,design.root);if(!set?.repo)for(let sibling of await discoverDesignFolders(request.checkout,1)){let name=recordedDesignName(sibling);if(name&&!sameFolder(sibling,folder))taken.set(name,sibling)}return taken}async function writeDesignName(folder,name){let path=join(folder,".design","config.json"),config=ConfigSchema.parse(JSON.parse(await readFile(path,"utf8")));await writeJsonAtomic(path,{...config,name})}async function registerDesign(folder,projectDir){let abs=resolve(folder),name=recordedDesignName(abs);if(!name)throw Error(`${abs} has no design name \u2014 run \`velloo design upgrade ${abs}\` first.`);let dir=resolve(projectDir),found=await findManifest(dir),path=found?found.path:join(dir,MANIFEST_FILE);if(found?.folders.some((target)=>sameFolder(target,abs)))return{name,path,created:!1};if(found)assertCurrent(found);let clash=(await findDesigns(dir))?.designs.find((d)=>d.name===name&&!sameFolder(d.root,abs));if(clash)throw Error(`a design named "${name}" already exists at ${clash.root} \u2014 rename one with \`velloo design rename\`.`);let designs=[...found?.manifest.designs??[]],rel=(target)=>relative(dir,target).split("\\").join("/")||".",defaultDesign=found?.manifest.defaultDesign;if(!found)for(let sibling of await discoverDesignFolders(dir,1)){if(sibling===abs)continue;if(designs.push(rel(sibling)),sibling===join(dir,DEFAULT_FOLDER_NAME))defaultDesign=recordedDesignName(sibling)??void 0}designs.push(rel(abs));let manifest={...found?.manifest??{},designs,...defaultDesign?{defaultDesign}:{}};return await writeJsonAtomic(path,manifest),{name,path,created:!0}}async function registerLocalDesign(opts){await writeLocalDesign(opts.id,{root:opts.root,appRoot:opts.appRoot,...opts.designPath?{designPath:opts.designPath}:{}})}import{existsSync as existsSync2,readdirSync}from"fs";import{readdir as readdir2,readFile as readFile2}from"fs/promises";import{homedir as homedir2}from"os";import{basename as basename2,dirname as dirname2,join as join2,relative as relative2,resolve as resolve2,sep as sep2}from"path";var DEFAULT_FOLDER="velloo",DESIGN_ARG_DESCRIPTION="A design name from ./velloo.json, a design folder, or a velloo.json file or its directory (default: the design folder you're in, else this directory's velloo.json: its only design or defaultDesign)";async function existingDesignFolder(appRoot){try{let found=await findDesigns(appRoot);for(let design of found?.designs??[])if(design.exists)return design.root}catch{}let conventional=join2(resolve2(appRoot),DEFAULT_FOLDER);if(await hasDesignConfig(conventional))return conventional;let[first]=await discoverDesignFolders(resolve2(appRoot));return first??null}function isDesignFolderSync(dir){return existsSync2(join2(dir,".design","config.json"))}function isEmptyOrMissingSync(dir){try{return readdirSync(dir).length===0}catch(err){if(err.code==="ENOENT")return!0;throw err}}async function hasDesignConfig(dir){try{return await readFile2(join2(dir,".design","config.json"),"utf8"),!0}catch{return!1}}var DESIGN_ID_ARG={type:"string",description:"The design's number in `velloo design list`, instead of its name or path"};async function designFolder(set,design,abort){let repo=set.repo;if(repo&&design.outsideRepo){let entry=relative2(repo.dir,design.root);abort(`design ${JSON.stringify(design.name)} in ${repo.path} points outside the repository (${entry}), which velloo.json cannot authorize. Pass the design path explicitly, or run \`velloo design bind ${design.root}\` here to keep it as a local design on this machine.`)}if(!design.exists)abort(`design ${JSON.stringify(design.name)} ${design.local?"(a local design)":`in ${repo?.path}`} points at ${design.root}, which is not a velloo design folder (no .design/config.json).`);return design.root}function quoteArg(value){return/^[\w@%+=:,./-]+$/.test(value)?value:`'${value.replace(/'/g,"'\\''")}'`}function designsLabel(set){return set.repo?.path??"this checkout's local designs"}function byName(set,name,abort){let shared=set.conflicts.get(name);if(shared)abort(`${shared.length} designs are named ${JSON.stringify(name)}: ${shared.map((d)=>d.root).join(", ")}. Pass a path, and rename one with \`velloo design rename <path> <new-name>\`.`);return set.byName.get(name)}async function resolveDesign(arg,cmd,opts={}){let abort=opts.onFail??((m)=>fail(cmd,m)),cwd=resolve2(opts.cwd??"."),set=null;try{set=await findDesigns(cwd)}catch(err){abort(err.message)}if(opts.id!==void 0){if(arg)abort("pass a design or --id, not both.");let n=Number(opts.id);if(!Number.isInteger(n)||n<1)abort("--id takes a design's number from `velloo design list`.");if(!set||set.designs.length===0){if(n===1)return resolveDesign(void 0,cmd,{...opts,id:void 0});abort(`there is no design #${n} here \u2014 \`velloo design list\` numbers them.`)}let entry=set.designs[n-1];if(!entry)abort(`there is no design #${n} \u2014 ${designsLabel(set)} has ${set.designs.length}. \`velloo design list\` numbers them.`);return designFolder(set,entry,abort)}if(arg){let named=set&&!arg.includes(sep2)?byName(set,arg,abort):void 0;if(set&&named)return designFolder(set,named,abort);let explicit=resolve2(cwd,arg);if(await hasDesignConfig(explicit))return explicit;let project=basename2(explicit)==="velloo.json"&&existsSync2(explicit)?dirname2(explicit):explicit;if((await findDesigns(project).catch((err)=>abort(err.message)))?.designs.length)return resolveDesign(void 0,cmd,{...opts,cwd:project});let nested=join2(explicit,DEFAULT_FOLDER);if(await hasDesignConfig(nested))return nested;if(!set&&!arg.includes(sep2)){let above=await enclosingProject(cwd),match=above?.designs.find((d)=>d.name===arg);if(above&&match)abort(`design ${JSON.stringify(arg)} is listed in \`${shortPath(cwd,above.label)}\`, and commands only read the directory they run in. Run from \`${shortPath(cwd,above.dir)}\`, or pass its folder (\`${quoteArg(shortPath(cwd,match.root))}\`) instead of its name.`)}if(set&&!arg.includes(sep2))abort(`unknown design ${JSON.stringify(arg)} \u2014 ${designsLabel(set)} lists: ${set.designs.map((d)=>d.name).join(", ")}. Pass a design name or a folder path.`);if(opts.requireConfig)abort(`${explicit} is not a velloo design folder (no .design/config.json).`);return explicit}if(set&&set.designs.length>0){if(await hasDesignConfig(cwd))return cwd;let picked=pickDesign(set,cwd);if(picked&&picked.reason!=="arbitrary")return designFolder(set,picked.design,abort);let names=set.designs.map((d)=>d.name);if(opts.interactive&&process.stdin.isTTY){let chosen=await select({message:"Which design?",options:set.designs.map((d)=>({value:d.root,label:d.name,hint:relative2(cwd,d.root)}))});if(isCancel(chosen))abort("cancelled.");let design=set.designs.find((d)=>d.root===chosen);return designFolder(set,design,abort)}let example=cmd.startsWith("design ")?`velloo ${cmd} --id 1\` for ${quoteArg(names[0]??"")}, as numbered by \`velloo design list`:`velloo ${cmd} ${designExample(opts,names[0]??"")}`;abort(`${designsLabel(set)} lists several designs: ${names.join(", ")}. Pass one (e.g. \`${example}\`)${set.repo?' or set "defaultDesign"':""}.`)}if(await hasDesignConfig(cwd))return cwd;let here=join2(cwd,DEFAULT_FOLDER);if(await hasDesignConfig(here))return here;let takesDesign=opts.takesDesign!==!1,above=await enclosingProject(cwd);if(above){let nearest=[...above.designs].sort((a,b)=>relative2(cwd,a.root).length-relative2(cwd,b.root).length)[0],example=takesDesign&&nearest?`, or pass a design folder (e.g. \`velloo ${cmd} ${designExample(opts,relative2(cwd,nearest.root).split(sep2).join("/"))}\`)`:"";abort(`no velloo.json or design folder here. \`${shortPath(cwd,above.label)}\` lists ${above.designs.map((d)=>JSON.stringify(d.name)).join(", ")}, and commands only read the directory they run in: run from \`${shortPath(cwd,above.dir)}\`${example}.`)}let example=takesDesign?`, pass a design folder or a velloo.json path (e.g. \`velloo ${cmd} ${designExample(opts,"apps/web")}\`)`:"";abort(`no velloo.json or design folder in ${cwd}. Run from the directory that has your velloo.json${example}, or \`velloo init\` here.${movedCheckoutHint(cwd)}`)}function shortPath(cwd,path){let rel=relative2(cwd,path);return rel!==""&&rel.length<path.length?rel.split(sep2).join("/"):path}function designExample(opts,design){return opts.designFlag?`${opts.designFlag}=${quoteArg(design)}`:quoteArg(design)}async function enclosingProject(cwd){let here=resolve2(cwd);for(let dir=dirname2(here);dir!==here;){let set=await findDesigns(dir).catch(()=>null),designs=set?.designs.filter((d)=>d.exists&&!d.outsideRepo)??[];if(set&&designs.length>0)return{dir,label:set.repo?.path??`${dir} (local designs)`,designs};let parent=dirname2(dir);if(parent===dir)return null;dir=parent}return null}async function checkoutDesigns(cwd){let set=await findDesigns(cwd).catch(()=>null);if(set&&set.designs.length>0)return set.designs.filter((d)=>d.exists&&!d.outsideRepo).map((d)=>d.root);try{return[await resolveDesign(void 0,"upgrade",{requireConfig:!0,cwd,onFail:()=>{throw Error("no design here")}})]}catch{return[]}}async function resolveDesignForSession(arg,cmd,cwd=resolve2(".")){if(!arg&&!await hasDesignConfig(cwd)){let set=await findDesigns(cwd).catch(()=>null),picked=set?pickDesign(set,cwd):null;if(set&&picked?.reason==="arbitrary")return{folder:await designFolder(set,picked.design,(m)=>fail(cmd,m)),pick:"arbitrary"}}return{folder:await resolveDesign(arg,cmd,{cwd}),pick:void 0}}function movedCheckoutHint(cwd){if(!insideProject(cwd))return"";let orphans=listLocalDesigns().filter((design)=>!existsSync2(design.root)&&existsSync2(design.designRoot));if(orphans.length===0)return"";return`
3
3
  This machine has designs for checkouts that no longer exist at their old paths:${orphans.map((design)=>`
4
4
  "${recordedDesignName(design.designRoot)??design.legacyName??design.id}" at ${design.designRoot}, made for ${design.root}`).join("")}
5
5
  If this is one of those checkouts, moved, attach its design with \`velloo design bind <design folder>\`. Otherwise forget it with \`velloo design remove <design folder>\`.`}function insideProject(cwd){let home=homedir2();for(let dir=cwd;dir!==home&&dirname2(dir)!==dir;dir=dirname2(dir))if(existsSync2(join2(dir,".git"))||existsSync2(join2(dir,"package.json")))return!0;return!1}async function listScreens(folder){let files;try{files=(await readdir2(join2(folder,"screens"))).filter((f)=>f.endsWith(".json"))}catch{return[]}let out=[];for(let f of files.sort()){let path=join2(folder,"screens",f);try{let s=ScreenSchema.parse(JSON.parse(await readFile2(path,"utf8")));out.push({id:s.id,name:s.name||s.id,path})}catch{}}return out}async function listBoards(folder){let files;try{files=(await readdir2(join2(folder,"boards"))).filter((f)=>f.endsWith(".json"))}catch{return[]}let out=[];for(let f of files.sort())try{let b=BoardSchema.parse(JSON.parse(await readFile2(join2(folder,"boards",f),"utf8")));out.push({id:b.id,name:b.name||b.id,screens:b.frames.map((fr)=>fr.screen),archived:isArchived(b)})}catch{}return out}function boardsByScreen(boards){let map=new Map;for(let b of boards)for(let sid of b.screens){let names=map.get(sid)??[];names.push(b.name),map.set(sid,names)}return map}async function pickBoards(folder,arg,interactive,cmd){let all=await listBoards(folder);if(all.length===0)return[];if(arg){let ids=new Set(arg.split(",").map((s)=>s.trim()).filter(Boolean)),chosen=all.filter((b)=>ids.has(b.id));if(chosen.length===0)fail(cmd,`no boards matched "${arg}". Available: ${all.map((b)=>b.id).join(", ")}`);return chosen}let boards=all.filter((b)=>!b.archived);if(boards.length===0)return[];if(!interactive)return boards;let chosen=await multiselect(boardSelectionPrompt(boards));if(isCancel(chosen))fail(cmd,"cancelled.");return resolveBoardSelection(boards,chosen)}function boardSelectionPrompt(boards){return{message:"Which boards to publish? (a: select all / clear all)",options:boards.map((board)=>({value:board.id,label:board.name,hint:`${board.screens.length} screen${board.screens.length===1?"":"s"}`})),initialValues:[],required:!1}}function resolveBoardSelection(boards,selectedIds){let selected=new Set(selectedIds),chosen=boards.filter((board)=>selected.has(board.id));return chosen.length>0?chosen:null}async function pickScreen(folder,arg,interactive,cmd){let screens=await listScreens(folder);if(arg){let byId=screens.find((s)=>s.id===arg);if(byId)return byId;return{id:arg,name:arg,path:resolve2(arg)}}if(screens.length===0)fail(cmd,`no screens found in ${folder}/screens.`);if(screens.length===1)return screens[0];if(!interactive)fail(cmd,`pick a screen: ${screens.map((s)=>s.id).join(", ")}`);let onBoard=boardsByScreen(await listBoards(folder)),chosen=await select({message:"Which screen?",options:screens.map((s)=>({value:s.id,label:s.name,hint:onBoard.get(s.id)?.join(", ")??`${s.id}.json`}))});if(isCancel(chosen))fail(cmd,"cancelled.");return screens.find((s)=>s.id===chosen)}
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{isCancel,confirm,select}from"./chunk-80fjfyha.js";import{designNameIssue}from"./chunk-nte0t7v3.js";import{managedDesignId,localDesignOf,removeLocalDesign,recordedDesignName,designRenameConflict,followDesignRename,loadDesignFolder}from"./chunk-egccxmed.js";import"./chunk-gsne0ap4.js";import"./chunk-c4fym47a.js";import{agentRootCandidates}from"./chunk-3kqtny5t.js";import"./chunk-q4d60wr3.js";import{daemonRoot,readLock,isLive,stopDaemon}from"./chunk-1tdh4h14.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-2fgfex9b.js";import"./chunk-z1r0sc3k.js";import"./chunk-cvn689d5.js";import{displayPath}from"./chunk-v0syg2hx.js";import"./chunk-tkvb3wb8.js";import{recordedAppRoot,planAppRootChange,applyAppRootChange,promptAppRootChoice,planRelocation,relocateDesign,runInit2}from"./chunk-5qd2ykvw.js";import"./chunk-njhdn9j0.js";import{repinAgentConfigs,migrateFolder2}from"./chunk-e56eb38j.js";import"./chunk-pjtg3wnm.js";import"./chunk-38ev3cp3.js";import"./chunk-8sfx5x8k.js";import{findManifest,manifestListing,findDesigns,unregisterDesign,isWithin,writeDesignName,registerLocalDesign,DESIGN_ARG_DESCRIPTION,hasDesignConfig,DESIGN_ID_ARG,resolveDesign,checkoutDesigns}from"./chunk-46xykc71.js";import"./chunk-vh4144az.js";import"./chunk-25j8vgpa.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{randomUUID}from"crypto";import{existsSync,realpathSync}from"fs";import{readdir,rm}from"fs/promises";import{join,relative,resolve}from"path";var import_picocolors=__toESM(require_picocolors(),1);async function countJson(dir,skipSuffix){try{return(await readdir(dir)).filter((f)=>f.endsWith(".json")&&!(skipSuffix&&f.endsWith(skipSuffix))).length}catch{return 0}}async function daemonState(folder){let rec=await readLock(daemonRoot(folder));if(!rec)return"stopped";return await isLive(rec)?`running :${rec.canvasPort}`:"stopped"}var list=defineCommand({meta:{name:"list",description:"List the repo's designs"},async run(){let cwd=resolve("."),found=await findDesigns(cwd).catch((err)=>{fail("design list",err.message)});if(!found||found.designs.length===0){let only=await resolveDesign(void 0,"design list",{requireConfig:!0,cwd,takesDesign:!1,onFail:(message)=>fail("design list",message)}),name=recordedDesignName(only)??"(unnamed)",owner=await manifestListing(only).catch(()=>null);if(owner&&owner.dir!==cwd){console.log(`velloo design: "${name}" (${relative(cwd,only)||only}) is listed in \`${relative(cwd,owner.path)}\`. Run \`velloo design list\` from \`${relative(cwd,owner.dir)||"."}\` to see that project's designs.`);return}console.log("velloo design: 1 design (no velloo.json yet)"),console.log(` ${import_picocolors.default.dim("1")} ${import_picocolors.default.bold(name)} ${relative(cwd,only)||only} ${await daemonState(only)}`),console.log(import_picocolors.default.dim(" `velloo design add` creates a second design and lists both."));return}let base=found.repo?.dir??found.local[0]?.root??cwd,rows=[];for(let design of found.designs){let live=design.exists&&!design.outsideRepo;rows.push({name:found.conflicts.has(design.name)?`${design.name} (duplicate)`:design.name,path:design.local?`${displayPath(design.root)} (local)`:relative(base,design.root)||".",boards:live?await countJson(join(design.root,"boards"),".notes.json"):0,state:design.outsideRepo?import_picocolors.default.yellow("outside the repo"):live?await daemonState(design.root):import_picocolors.default.yellow("missing"),live})}let pad=(text,width)=>text+" ".repeat(Math.max(0,width-Bun.stringWidth(text))),width=Math.max(...rows.map((r)=>Bun.stringWidth(r.name))),pathWidth=Math.max(...rows.map((r)=>Bun.stringWidth(r.path))),idWidth=String(rows.length).length;console.log(`velloo design: ${rows.length} in ${base}`);for(let[index,row]of rows.entries()){let marker=row.name===found.defaultDesign?import_picocolors.default.cyan("\u25CF"):" ",id=import_picocolors.default.dim(String(index+1).padStart(idWidth)),boards=row.live?`${row.boards} board${row.boards===1?"":"s"}`:"\u2014";console.log(` ${id} ${marker} ${import_picocolors.default.bold(pad(row.name,width))} ${import_picocolors.default.dim(pad(row.path,pathWidth))} ${boards.padEnd(9)} ${row.state}`)}console.log(import_picocolors.default.dim(" Pass a number as --id to the other `velloo design` commands."));for(let[name,designs]of found.conflicts)console.log(import_picocolors.default.yellow(` ! ${designs.length} designs are named "${name}" \u2014 rename one with \`velloo design rename <path> <new-name>\`.`))}}),add=defineCommand({meta:{name:"add",description:"Create another design in this repo (the init wizard, folder pre-chosen)"},args:{path:{type:"positional",required:!1,description:"Where the new design folder goes, relative to the repo (asked when omitted)"},external:{type:"boolean",description:"Create in Velloo-managed external storage"},nonInteractive:{type:"boolean",description:"Use defaults without prompting"},connect:{type:"boolean",default:!0,description:"Wire project agents"},library:{type:"string",description:"Component library (default: the sibling folder's)"},name:{type:"string",description:"The design's name (default: derived from its folder)"}},async run({args}){await runInit2({addFolder:!0,external:args.external,nonInteractive:args.nonInteractive,connect:args.connect,...args.path?{designFolder:args.path}:{},...args.library?{library:args.library}:{},...args.name?{name:args.name}:{}})}}),remove=defineCommand({meta:{name:"remove",description:"Remove a design \u2014 one outside the repo can keep its files (asked, or --delete-content)"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},id:DESIGN_ID_ARG,deleteContent:{type:"boolean",description:"Also delete the files of a design outside the repo (with --yes, or to skip the question)"},yes:{type:"boolean",description:"Skip the confirmation (required without an interactive terminal)"}},async run({args}){let cwd=resolve("."),folder=await resolveDesign(args.design,"design remove",{id:args.id,interactive:!0,requireConfig:!0,cwd}),local=localDesignOf(folder);if(!Boolean(process.stdin.isTTY)&&args.yes!==!0)fail("design remove","refusing to delete a design folder without --yes");let boards=await countJson(join(folder,"boards"),".notes.json"),screens=await countJson(join(folder,"screens"),".annotations.json"),name=recordedDesignName(folder)??folder;console.log(`velloo design: ${name} (${folder})`),console.log(import_picocolors.default.dim(` ${boards} board${boards===1?"":"s"}, ${screens} screen${screens===1?"":"s"}`));let keepContent=local!==null&&args.deleteContent!==!0;if(args.yes!==!0)if(local&&args.deleteContent!==!0){let managed=managedDesignId(folder)!==null,choice=await select({message:"Remove this design?",initialValue:managed?"delete":"keep",options:[{value:"delete",label:"Delete it and its files",hint:managed?"in Velloo's storage":folder},{value:"keep",label:"Forget it, keep the files",hint:folder},{value:"cancel",label:"Cancel"}]});if(isCancel(choice)||choice==="cancel"){console.log(import_picocolors.default.dim(" Nothing changed."));return}keepContent=choice==="keep"}else{let approved=await confirm({message:"Delete this design folder and everything in it?",initialValue:!1});if(isCancel(approved)||!approved){console.log(import_picocolors.default.dim(" Nothing changed."));return}}if(await stopDaemon(daemonRoot(folder)))console.log(import_picocolors.default.dim(" Stopped its canvas."));let dropped=local?null:await unregisterDesign(folder,cwd).catch((err)=>fail("design remove",err.message));if(local)await removeLocalDesign(local.id);if(!keepContent)await rm(folder,{recursive:!0,force:!0});if(console.log(`velloo design: ${keepContent?"retained content at":"removed"} ${folder}`),local)console.log(import_picocolors.default.dim(` Forgot the local design "${name}".`));if(dropped?.name)console.log(import_picocolors.default.dim(dropped.removedManifest?` Dropped "${dropped.name}" \u2014 velloo.json listed no other designs, so it's gone too.`:` Dropped "${dropped.name}" from velloo.json.`))}}),move=defineCommand({meta:{name:"move",description:"Preview moving a design between the repository, managed storage and another directory; --yes applies"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},id:DESIGN_ID_ARG,external:{type:"boolean",description:"Move to managed storage (a local design)"},to:{type:"string",description:"New directory \u2014 inside the repository it goes in velloo.json, outside it is local"},yes:{type:"boolean",description:"Apply the displayed move"}},async run({args}){let source=await resolveDesign(args.design,"design move",{id:args.id,interactive:!0,requireConfig:!0}),plan=await planRelocation(source,resolve("."),args.to,args.external===!0).catch((err)=>fail("design move",err.message)),local="a local design on this machine",recorded=plan.sourceManifestPath?plan.destinationLocal?`velloo.json path "${plan.sourceManifestPath}" \u2192 ${"a local design on this machine"}`:`velloo.json path "${plan.sourceManifestPath}" \u2192 "${plan.destinationManifestPath}"`:plan.destinationLocal?"stays a local design on this machine":`${"a local design on this machine"} \u2192 velloo.json path "${plan.destinationManifestPath}"`;if(console.log(`Source: ${plan.source}
2
+ import{isCancel,confirm,select}from"./chunk-80fjfyha.js";import{designNameIssue}from"./chunk-7a45tn73.js";import{managedDesignId,localDesignOf,removeLocalDesign,recordedDesignName,designRenameConflict,followDesignRename,loadDesignFolder}from"./chunk-qan5dnjt.js";import"./chunk-m1wp8cpt.js";import"./chunk-a9mgvspm.js";import{agentRootCandidates}from"./chunk-vjrn10xr.js";import"./chunk-zqtz23xk.js";import{daemonRoot,readLock,isLive,stopDaemon}from"./chunk-shac6bat.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-2dm4x17z.js";import"./chunk-r03aywsb.js";import"./chunk-cvn689d5.js";import{displayPath}from"./chunk-db7mf114.js";import"./chunk-npsg7btt.js";import{recordedAppRoot,planAppRootChange,applyAppRootChange,promptAppRootChoice,planRelocation,relocateDesign,runInit2}from"./chunk-nwf2kn41.js";import"./chunk-ykdx12na.js";import{repinAgentConfigs,migrateFolder2}from"./chunk-b58pnj20.js";import"./chunk-pjtg3wnm.js";import"./chunk-b7famda5.js";import"./chunk-rfrbnw8r.js";import{findManifest,manifestListing,findDesigns,unregisterDesign,isWithin,writeDesignName,registerLocalDesign,DESIGN_ARG_DESCRIPTION,hasDesignConfig,DESIGN_ID_ARG,resolveDesign,checkoutDesigns}from"./chunk-dj1pp4e3.js";import"./chunk-ph94nrc8.js";import"./chunk-6zr596r2.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{randomUUID}from"crypto";import{existsSync,realpathSync}from"fs";import{readdir,rm}from"fs/promises";import{join,relative,resolve}from"path";var import_picocolors=__toESM(require_picocolors(),1);async function countJson(dir,skipSuffix){try{return(await readdir(dir)).filter((f)=>f.endsWith(".json")&&!(skipSuffix&&f.endsWith(skipSuffix))).length}catch{return 0}}async function daemonState(folder){let rec=await readLock(daemonRoot(folder));if(!rec)return"stopped";return await isLive(rec)?`running :${rec.canvasPort}`:"stopped"}var list=defineCommand({meta:{name:"list",description:"List the repo's designs"},async run(){let cwd=resolve("."),found=await findDesigns(cwd).catch((err)=>{fail("design list",err.message)});if(!found||found.designs.length===0){let only=await resolveDesign(void 0,"design list",{requireConfig:!0,cwd,takesDesign:!1,onFail:(message)=>fail("design list",message)}),name=recordedDesignName(only)??"(unnamed)",owner=await manifestListing(only).catch(()=>null);if(owner&&owner.dir!==cwd){console.log(`velloo design: "${name}" (${relative(cwd,only)||only}) is listed in \`${relative(cwd,owner.path)}\`. Run \`velloo design list\` from \`${relative(cwd,owner.dir)||"."}\` to see that project's designs.`);return}console.log("velloo design: 1 design (no velloo.json yet)"),console.log(` ${import_picocolors.default.dim("1")} ${import_picocolors.default.bold(name)} ${relative(cwd,only)||only} ${await daemonState(only)}`),console.log(import_picocolors.default.dim(" `velloo design add` creates a second design and lists both."));return}let base=found.repo?.dir??found.local[0]?.root??cwd,rows=[];for(let design of found.designs){let live=design.exists&&!design.outsideRepo;rows.push({name:found.conflicts.has(design.name)?`${design.name} (duplicate)`:design.name,path:design.local?`${displayPath(design.root)} (local)`:relative(base,design.root)||".",boards:live?await countJson(join(design.root,"boards"),".notes.json"):0,state:design.outsideRepo?import_picocolors.default.yellow("outside the repo"):live?await daemonState(design.root):import_picocolors.default.yellow("missing"),live})}let pad=(text,width)=>text+" ".repeat(Math.max(0,width-Bun.stringWidth(text))),width=Math.max(...rows.map((r)=>Bun.stringWidth(r.name))),pathWidth=Math.max(...rows.map((r)=>Bun.stringWidth(r.path))),idWidth=String(rows.length).length;console.log(`velloo design: ${rows.length} in ${base}`);for(let[index,row]of rows.entries()){let marker=row.name===found.defaultDesign?import_picocolors.default.cyan("\u25CF"):" ",id=import_picocolors.default.dim(String(index+1).padStart(idWidth)),boards=row.live?`${row.boards} board${row.boards===1?"":"s"}`:"\u2014";console.log(` ${id} ${marker} ${import_picocolors.default.bold(pad(row.name,width))} ${import_picocolors.default.dim(pad(row.path,pathWidth))} ${boards.padEnd(9)} ${row.state}`)}console.log(import_picocolors.default.dim(" Pass a number as --id to the other `velloo design` commands."));for(let[name,designs]of found.conflicts)console.log(import_picocolors.default.yellow(` ! ${designs.length} designs are named "${name}" \u2014 rename one with \`velloo design rename <path> <new-name>\`.`))}}),add=defineCommand({meta:{name:"add",description:"Create another design in this repo (the init wizard, folder pre-chosen)"},args:{path:{type:"positional",required:!1,description:"Where the new design folder goes, relative to the repo (asked when omitted)"},external:{type:"boolean",description:"Create in Velloo-managed external storage"},nonInteractive:{type:"boolean",description:"Use defaults without prompting"},connect:{type:"boolean",default:!0,description:"Wire project agents"},library:{type:"string",description:"Component library (default: the sibling folder's)"},name:{type:"string",description:"The design's name (default: derived from its folder)"}},async run({args}){await runInit2({addFolder:!0,external:args.external,nonInteractive:args.nonInteractive,connect:args.connect,...args.path?{designFolder:args.path}:{},...args.library?{library:args.library}:{},...args.name?{name:args.name}:{}})}}),remove=defineCommand({meta:{name:"remove",description:"Remove a design \u2014 one outside the repo can keep its files (asked, or --delete-content)"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},id:DESIGN_ID_ARG,deleteContent:{type:"boolean",description:"Also delete the files of a design outside the repo (with --yes, or to skip the question)"},yes:{type:"boolean",description:"Skip the confirmation (required without an interactive terminal)"}},async run({args}){let cwd=resolve("."),folder=await resolveDesign(args.design,"design remove",{id:args.id,interactive:!0,requireConfig:!0,cwd}),local=localDesignOf(folder);if(!Boolean(process.stdin.isTTY)&&args.yes!==!0)fail("design remove","refusing to delete a design folder without --yes");let boards=await countJson(join(folder,"boards"),".notes.json"),screens=await countJson(join(folder,"screens"),".annotations.json"),name=recordedDesignName(folder)??folder;console.log(`velloo design: ${name} (${folder})`),console.log(import_picocolors.default.dim(` ${boards} board${boards===1?"":"s"}, ${screens} screen${screens===1?"":"s"}`));let keepContent=local!==null&&args.deleteContent!==!0;if(args.yes!==!0)if(local&&args.deleteContent!==!0){let managed=managedDesignId(folder)!==null,choice=await select({message:"Remove this design?",initialValue:managed?"delete":"keep",options:[{value:"delete",label:"Delete it and its files",hint:managed?"in Velloo's storage":folder},{value:"keep",label:"Forget it, keep the files",hint:folder},{value:"cancel",label:"Cancel"}]});if(isCancel(choice)||choice==="cancel"){console.log(import_picocolors.default.dim(" Nothing changed."));return}keepContent=choice==="keep"}else{let approved=await confirm({message:"Delete this design folder and everything in it?",initialValue:!1});if(isCancel(approved)||!approved){console.log(import_picocolors.default.dim(" Nothing changed."));return}}if(await stopDaemon(daemonRoot(folder)))console.log(import_picocolors.default.dim(" Stopped its canvas."));let dropped=local?null:await unregisterDesign(folder,cwd).catch((err)=>fail("design remove",err.message));if(local)await removeLocalDesign(local.id);if(!keepContent)await rm(folder,{recursive:!0,force:!0});if(console.log(`velloo design: ${keepContent?"retained content at":"removed"} ${folder}`),local)console.log(import_picocolors.default.dim(` Forgot the local design "${name}".`));if(dropped?.name)console.log(import_picocolors.default.dim(dropped.removedManifest?` Dropped "${dropped.name}" \u2014 velloo.json listed no other designs, so it's gone too.`:` Dropped "${dropped.name}" from velloo.json.`))}}),move=defineCommand({meta:{name:"move",description:"Preview moving a design between the repository, managed storage and another directory; --yes applies"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},id:DESIGN_ID_ARG,external:{type:"boolean",description:"Move to managed storage (a local design)"},to:{type:"string",description:"New directory \u2014 inside the repository it goes in velloo.json, outside it is local"},yes:{type:"boolean",description:"Apply the displayed move"}},async run({args}){let source=await resolveDesign(args.design,"design move",{id:args.id,interactive:!0,requireConfig:!0}),plan=await planRelocation(source,resolve("."),args.to,args.external===!0).catch((err)=>fail("design move",err.message)),local="a local design on this machine",recorded=plan.sourceManifestPath?plan.destinationLocal?`velloo.json path "${plan.sourceManifestPath}" \u2192 ${"a local design on this machine"}`:`velloo.json path "${plan.sourceManifestPath}" \u2192 "${plan.destinationManifestPath}"`:plan.destinationLocal?"stays a local design on this machine":`${"a local design on this machine"} \u2192 velloo.json path "${plan.destinationManifestPath}"`;if(console.log(`Source: ${plan.source}
3
3
  Destination: ${plan.destination}
4
4
  Design "${plan.designName}": ${recorded}`),!args.yes){console.log("Preview only. Add --yes to apply the move.");return}await relocateDesign(plan),console.log(`Moved ${plan.designName} to ${plan.destination}. Run velloo connect to refresh existing agent guidance.`)}});async function renameThroughCanvas(folder,name){let rec=await readLock(daemonRoot(folder));if(!rec||!await isLive(rec))return!1;let res;try{res=await fetch(`http://127.0.0.1:${rec.canvasPort}/api/mutate/update_design_name`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({name}),signal:AbortSignal.timeout(1e4)})}catch(err){fail("design rename",`the running canvas didn't answer (${err.message}).`)}if(res.ok)return!0;let body=await res.json().catch(()=>null);fail("design rename",body?.error?.message??`the running canvas refused (HTTP ${res.status}).`)}var rename=defineCommand({meta:{name:"rename",description:"Rename a design"},args:{design:{type:"positional",required:!1,description:"The design to rename \u2014 its current name or its folder path (or use --id)"},name:{type:"positional",required:!1,description:"The new name"},id:DESIGN_ID_ARG},async run({args}){let cwd=resolve("."),newName=args.id!==void 0&&args.name===void 0?args.design:args.name,target=args.id!==void 0&&args.name===void 0?void 0:args.design;if(newName===void 0)fail("design rename","pass the design and its new name: `velloo design rename <design> <new name>`.");let folder=await resolveDesign(target,"design rename",{id:args.id,requireConfig:!0,cwd}),previous=recordedDesignName(folder);if(previous===newName){console.log(import_picocolors.default.dim(` Already named "${newName}" \u2014 nothing changed.`));return}let conflict=await designRenameConflict(folder,newName).catch((err)=>fail("design rename",err.message));if(conflict)fail("design rename",conflict);if(!await renameThroughCanvas(folder,newName)){if(await writeDesignName(folder,newName),previous&&await followDesignRename(folder,previous,newName))console.log(import_picocolors.default.dim(` velloo.json defaultDesign \u2192 "${newName}"`))}console.log(`velloo design: renamed ${previous?`"${previous}" `:""}to "${newName}".`);let repinned=previous?await repinAgentConfigs({projectRoots:await agentRootCandidates(folder),designFolder:folder,names:[previous]}).catch(()=>[]):[];for(let path of repinned)console.log(import_picocolors.default.dim(` ${relative(cwd,path)||path}: no longer names the design`))}}),upgrade=defineCommand({meta:{name:"upgrade",description:"Migrate a design to this Velloo's format, without upgrading Velloo itself"},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},id:DESIGN_ID_ARG,all:{type:"boolean",description:"Migrate every design in this checkout"},"dry-run":{type:"boolean",default:!1,description:"Show what would change without writing"},skills:{type:"boolean",default:!0,description:"Also refresh the installed agent skills / plugin / rules to this velloo's versions"}},async run({args}){if(args.all&&(args.design||args.id!==void 0))fail("design upgrade","pass a design or --all, not both.");let folders=args.all?await checkoutDesigns(resolve(".")):[await resolveDesign(args.design,"design upgrade",{id:args.id,interactive:!0,requireConfig:!0})];if(folders.length===0)fail("design upgrade","no designs here \u2014 `velloo init` creates one.");for(let folder of folders)await migrateFolder2(folder,{dryRun:args["dry-run"],skills:args.skills})}}),bind=defineCommand({meta:{name:"bind",description:"Attach a design folder outside this checkout to it, on this machine only"},args:{design:{type:"positional",required:!0,description:"The design folder (in managed storage or anywhere outside the checkout)"},name:{type:"string",description:"Rename the design as it is bound"},yes:{type:"boolean",description:"Confirm the local binding"}},async run({args}){let cwd=resolve("."),folder=resolve(args.design);if(!await hasDesignConfig(folder))fail("design bind",`${folder} is not a velloo design folder (no .design/config.json).`);let root=cwd;if(isWithin(root,folder))fail("design bind",`${folder} is inside this checkout (${root}); a design here belongs in velloo.json \u2014 see \`velloo design add\`.`);let name=args.name??recordedDesignName(folder);if(!name)fail("design bind",`${folder} has no design name \u2014 run \`velloo upgrade ${folder}\` first.`);let issue=designNameIssue(name);if(issue)fail("design bind",`invalid --name ${JSON.stringify(name)} \u2014 ${issue}`);let clash=(await findDesigns(root).catch((err)=>fail("design bind",err.message)))?.designs.find((d)=>d.name===name&&!(existsSync(d.root)&&realpathSync(d.root)===realpathSync(folder)));if(clash)fail("design bind",`a design named "${name}" already exists at ${clash.root} \u2014 pass --name to bind this one under another.`);let existing=localDesignOf(folder),appRoot=existing?join(root,relative(existing.root,existing.appRoot)):root,listed=(await findManifest(cwd).catch(()=>null))?.folders.some((path)=>existsSync(path)&&realpathSync(path)===realpathSync(folder));if(console.log(`Design: ${name} (${folder})
5
5
  Checkout: ${root}
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{registry2,loadManifest2}from"./chunk-vbe2r4kv.js";import"./chunk-c6hywdvq.js";import{snapshotVersion2,entryCssPath2,componentsDir2}from"./chunk-cvn689d5.js";export{componentsDir2 as componentsDir,entryCssPath2 as entryCssPath,loadManifest2 as loadManifest,registry2 as registry,snapshotVersion2 as snapshotVersion};
2
+ import{registry2,loadManifest2}from"./chunk-cejmmx3r.js";import"./chunk-8t5phg0s.js";import{snapshotVersion2,entryCssPath2,componentsDir2}from"./chunk-cvn689d5.js";export{componentsDir2 as componentsDir,entryCssPath2 as entryCssPath,loadManifest2 as loadManifest,registry2 as registry,snapshotVersion2 as snapshotVersion};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{fail}from"./chunk-s23gtejf.js";import"./chunk-z1r0sc3k.js";import{SHELLS,completionScript,commandSpecs,detectShell,installCompletions}from"./chunk-vh4144az.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);var completions_default=defineCommand({meta:{name:"completions",description:"Shell TAB completions \u2014 print the script, or install it with --install"},args:{shell:{type:"positional",required:!1,description:`Shell: ${SHELLS.join(" | ")} (default: detected from $SHELL)`},install:{type:"boolean",default:!1,description:"Write the script + wire it into your shell (idempotent)"}},async run({args}){let shell=args.shell??detectShell();if(!shell||!SHELLS.includes(shell))fail("completions",`unsupported or undetected shell${args.shell?` "${args.shell}"`:""} \u2014 pass one of: ${SHELLS.join(", ")}.`);if(!args.install){console.log(completionScript(shell,await commandSpecs()));return}let r=await installCompletions(shell);if(console.log(""),console.log(import_picocolors.default.green(`\u2713 ${shell} completions installed.`)),console.log(` script ${import_picocolors.default.cyan(r.scriptPath)}`),r.rcPath)console.log(r.rcUpdated?` rc ${import_picocolors.default.cyan(r.rcPath)} ${import_picocolors.default.dim("(source line appended)")}`:` rc ${import_picocolors.default.cyan(r.rcPath)} ${import_picocolors.default.dim("(already wired)")}`);console.log(""),console.log(import_picocolors.default.dim(shell==="fish"?" New fish sessions pick it up automatically.":` Restart your shell (or \`source ${r.rcPath}\`) to activate TAB completion.`))}});export{completions_default as default};
2
+ import{fail}from"./chunk-s23gtejf.js";import"./chunk-r03aywsb.js";import{SHELLS,completionScript,commandSpecs,detectShell,installCompletions}from"./chunk-ph94nrc8.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);var completions_default=defineCommand({meta:{name:"completions",description:"Shell TAB completions \u2014 print the script, or install it with --install"},args:{shell:{type:"positional",required:!1,description:`Shell: ${SHELLS.join(" | ")} (default: detected from $SHELL)`},install:{type:"boolean",default:!1,description:"Write the script + wire it into your shell (idempotent)"}},async run({args}){let shell=args.shell??detectShell();if(!shell||!SHELLS.includes(shell))fail("completions",`unsupported or undetected shell${args.shell?` "${args.shell}"`:""} \u2014 pass one of: ${SHELLS.join(", ")}.`);if(!args.install){console.log(completionScript(shell,await commandSpecs()));return}let r=await installCompletions(shell);if(console.log(""),console.log(import_picocolors.default.green(`\u2713 ${shell} completions installed.`)),console.log(` script ${import_picocolors.default.cyan(r.scriptPath)}`),r.rcPath)console.log(r.rcUpdated?` rc ${import_picocolors.default.cyan(r.rcPath)} ${import_picocolors.default.dim("(source line appended)")}`:` rc ${import_picocolors.default.cyan(r.rcPath)} ${import_picocolors.default.dim("(already wired)")}`);console.log(""),console.log(import_picocolors.default.dim(shell==="fish"?" New fish sessions pick it up automatically.":` Restart your shell (or \`source ${r.rcPath}\`) to activate TAB completion.`))}});export{completions_default as default};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{isCancel,select}from"./chunk-80fjfyha.js";import{closePooledBrowser}from"./chunk-c4fym47a.js";import"./chunk-nte0t7v3.js";import{writeText,findFrame,exportFilename,exportFramePng,exportBoardPng,exportFramePdf,exportBoardPdf,exportScreenHtml,exportScreenPng,exportScreenPdf,exportFrameHtml,exportBoardHtml,screensForExportTarget}from"./chunk-egccxmed.js";import"./chunk-gsne0ap4.js";import{fail}from"./chunk-s23gtejf.js";import{captureWithBrowserSetup}from"./chunk-2fgfex9b.js";import{confirmRenderFailures}from"./chunk-y0rwf1ze.js";import{loadPipeline}from"./chunk-7cktk5qr.js";import{withAssetServer}from"./chunk-0zen7bzb.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-46xykc71.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{extname,isAbsolute,resolve}from"path";var export_default=defineCommand({meta:{name:"export",description:"Export a screen, frame, or board as PNG, PDF, or standalone HTML (format = --to extension)"},args:{target:{type:"positional",required:!1,description:"Screen, frame, or board id. Omit to pick interactively."},design:{type:"string",description:DESIGN_ARG_DESCRIPTION},to:{type:"string",description:"Output path; extension picks the format (.png | .pdf | .html). Default: ./<target>.png"},mode:{type:"string",description:"light (default) | dark | compare (side-by-side light|dark; PNG, non-board only)"},scale:{type:"string",description:"PNG raster density (0.25\u20133; default 1; 2 = retina)"},theme:{type:"string",description:"Named theme to render with (default: the board's pin, else the folder default)"},w:{type:"string",description:"Viewport width for screen targets (default: first preset)"},h:{type:"string",description:"Viewport height for screen targets (default: first preset)"},yes:{type:"boolean",description:"Export even when a component fails to render (required without an interactive terminal)"}},async run({args}){let folder=await resolveDesign(args.design,"export",{designFlag:"--design"}),pipeline=await loadPipeline(folder),design=pipeline.design,mode=args.mode??"light";if(!["light","dark","compare"].includes(mode))fail("export",`--mode must be light, dark, or compare \u2014 got '${args.mode}'`);let scale=args.scale?Number(args.scale):1;if(!Number.isFinite(scale)||scale<0.25||scale>3)fail("export",`--scale must be between 0.25 and 3 \u2014 got '${args.scale}'`);let targetId=args.target;if(!targetId){let options=[...[...design.boards.values()].map((b)=>({value:b.id,label:b.name,hint:`board \xB7 ${b.frames.length} frame${b.frames.length===1?"":"s"}`})),...[...design.screens.values()].map((s)=>({value:s.id,label:s.name||s.id,hint:"screen"}))];if(options.length===0)fail("export",`nothing to export in ${folder}.`);if(!process.stdin.isTTY)fail("export",`pass a target: ${options.map((o)=>o.value).join(", ")} (boards and screens; frame ids work too)`);let chosen=await select({message:"Export what?",options});if(isCancel(chosen))fail("export","cancelled.");targetId=chosen}let screen=design.screens.get(targetId),framed=screen?null:findFrame(design,targetId),board=screen||framed?null:design.boards.get(targetId),kind=screen?"screen":framed?"frame":board?"board":null;if(!kind)fail("export",`no screen, frame, or board with id "${targetId}" in ${folder}. Boards: ${[...design.boards.keys()].join(", ")||"(none)"}; screens: ${[...design.screens.keys()].join(", ")||"(none)"}.`);let name=screen?.name||framed?.frame.label||(framed?design.screens.get(framed.frame.screen)?.name:void 0)||board?.name||targetId,outPath=args.to?isAbsolute(args.to)?args.to:resolve(args.to):resolve(exportFilename(name,"png")),ext=extname(outPath).toLowerCase().slice(1);if(ext!=="png"&&ext!=="pdf"&&ext!=="html")fail("export",`unsupported output extension ".${ext}" \u2014 use .png, .pdf, or .html.`);let format=ext;if(mode==="compare"&&(format!=="png"||kind==="board"))fail("export",'mode "compare" is PNG-only and not available for boards.');let preset=design.config.viewportPresets[0]??{name:"default",w:1440,h:900},viewport={w:args.w?Number(args.w):preset.w,h:args.h?Number(args.h):preset.h};await confirmRenderFailures("export",{folder:design,providers:pipeline.providers,defaultProvider:pipeline.defaultProvider},screensForExportTarget(design,kind,targetId),args.yes===!0);let opts={mode,scale,...args.theme?{theme:args.theme}:{}},assetOrigin,p={folder:design,providers:pipeline.providers,defaultProvider:pipeline.defaultProvider,snapshotCss:async()=>pipeline.snapshotCss,assetOrigin:()=>assetOrigin},produce=async()=>{if(kind==="screen"&&screen){if(format==="html"){let out=await exportScreenHtml(p,screen,{dark:mode==="dark",...args.theme?{theme:args.theme}:{},viewport});return{bytes:out.html,warnings:out.warnings}}if(format==="pdf")return{bytes:await exportScreenPdf(p,screen,{...opts,viewport}),warnings:[]};return{bytes:await exportScreenPng(p,screen,{...opts,viewport}),warnings:[]}}if(kind==="frame"&&framed){if(format==="html"){let out=await exportFrameHtml(p,framed.board,framed.frame,opts);return{bytes:out.html,warnings:out.warnings}}return{bytes:format==="pdf"?await exportFramePdf(p,framed.board,framed.frame,opts):await exportFramePng(p,framed.board,framed.frame,opts),warnings:[]}}if(!board)fail("export","internal: target resolution failed");if(format==="html"){let out=await exportBoardHtml(p,board,opts);return{bytes:out.html,warnings:out.warnings}}return{bytes:format==="pdf"?await exportBoardPdf(p,board,opts):await exportBoardPng(p,board,opts),warnings:[]}},result;try{if(format==="html")result=await produce();else await withAssetServer(folder,null,async(baseHref)=>{assetOrigin=baseHref,await captureWithBrowserSetup("export",async()=>{result=await produce()})})}finally{await closePooledBrowser()}if(!result)fail("export","capture produced no output");if(typeof result.bytes==="string")await writeText(outPath,result.bytes);else await Bun.write(outPath,result.bytes);console.log(`velloo export: wrote ${outPath} (${kind}=${targetId}, mode=${mode})`);for(let warning of result.warnings)console.log(` note: ${warning}`)}});export{export_default as default};
2
+ import{isCancel,select}from"./chunk-80fjfyha.js";import{closePooledBrowser}from"./chunk-a9mgvspm.js";import"./chunk-7a45tn73.js";import{writeText,findFrame,exportFilename,exportFramePng,exportBoardPng,exportFramePdf,exportBoardPdf,exportScreenHtml,exportScreenPng,exportScreenPdf,exportFrameHtml,exportBoardHtml,screensForExportTarget}from"./chunk-qan5dnjt.js";import"./chunk-m1wp8cpt.js";import{fail}from"./chunk-s23gtejf.js";import{captureWithBrowserSetup}from"./chunk-2dm4x17z.js";import{confirmRenderFailures}from"./chunk-91pajfnm.js";import{loadPipeline}from"./chunk-jwzhhhzn.js";import{withAssetServer}from"./chunk-0zen7bzb.js";import{DESIGN_ARG_DESCRIPTION,resolveDesign}from"./chunk-dj1pp4e3.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{extname,isAbsolute,resolve}from"path";var export_default=defineCommand({meta:{name:"export",description:"Export a screen, frame, or board as PNG, PDF, or standalone HTML (format = --to extension)"},args:{target:{type:"positional",required:!1,description:"Screen, frame, or board id. Omit to pick interactively."},design:{type:"string",description:DESIGN_ARG_DESCRIPTION},to:{type:"string",description:"Output path; extension picks the format (.png | .pdf | .html). Default: ./<target>.png"},mode:{type:"string",description:"light (default) | dark | compare (side-by-side light|dark; PNG, non-board only)"},scale:{type:"string",description:"PNG raster density (0.25\u20133; default 1; 2 = retina)"},theme:{type:"string",description:"Named theme to render with (default: the board's pin, else the folder default)"},w:{type:"string",description:"Viewport width for screen targets (default: first preset)"},h:{type:"string",description:"Viewport height for screen targets (default: first preset)"},yes:{type:"boolean",description:"Export even when a component fails to render (required without an interactive terminal)"}},async run({args}){let folder=await resolveDesign(args.design,"export",{designFlag:"--design"}),pipeline=await loadPipeline(folder),design=pipeline.design,mode=args.mode??"light";if(!["light","dark","compare"].includes(mode))fail("export",`--mode must be light, dark, or compare \u2014 got '${args.mode}'`);let scale=args.scale?Number(args.scale):1;if(!Number.isFinite(scale)||scale<0.25||scale>3)fail("export",`--scale must be between 0.25 and 3 \u2014 got '${args.scale}'`);let targetId=args.target;if(!targetId){let options=[...[...design.boards.values()].map((b)=>({value:b.id,label:b.name,hint:`board \xB7 ${b.frames.length} frame${b.frames.length===1?"":"s"}`})),...[...design.screens.values()].map((s)=>({value:s.id,label:s.name||s.id,hint:"screen"}))];if(options.length===0)fail("export",`nothing to export in ${folder}.`);if(!process.stdin.isTTY)fail("export",`pass a target: ${options.map((o)=>o.value).join(", ")} (boards and screens; frame ids work too)`);let chosen=await select({message:"Export what?",options});if(isCancel(chosen))fail("export","cancelled.");targetId=chosen}let screen=design.screens.get(targetId),framed=screen?null:findFrame(design,targetId),board=screen||framed?null:design.boards.get(targetId),kind=screen?"screen":framed?"frame":board?"board":null;if(!kind)fail("export",`no screen, frame, or board with id "${targetId}" in ${folder}. Boards: ${[...design.boards.keys()].join(", ")||"(none)"}; screens: ${[...design.screens.keys()].join(", ")||"(none)"}.`);let name=screen?.name||framed?.frame.label||(framed?design.screens.get(framed.frame.screen)?.name:void 0)||board?.name||targetId,outPath=args.to?isAbsolute(args.to)?args.to:resolve(args.to):resolve(exportFilename(name,"png")),ext=extname(outPath).toLowerCase().slice(1);if(ext!=="png"&&ext!=="pdf"&&ext!=="html")fail("export",`unsupported output extension ".${ext}" \u2014 use .png, .pdf, or .html.`);let format=ext;if(mode==="compare"&&(format!=="png"||kind==="board"))fail("export",'mode "compare" is PNG-only and not available for boards.');let preset=design.config.viewportPresets[0]??{name:"default",w:1440,h:900},viewport={w:args.w?Number(args.w):preset.w,h:args.h?Number(args.h):preset.h};await confirmRenderFailures("export",{folder:design,providers:pipeline.providers,defaultProvider:pipeline.defaultProvider},screensForExportTarget(design,kind,targetId),args.yes===!0);let opts={mode,scale,...args.theme?{theme:args.theme}:{}},assetOrigin,p={folder:design,providers:pipeline.providers,defaultProvider:pipeline.defaultProvider,snapshotCss:async()=>pipeline.snapshotCss,assetOrigin:()=>assetOrigin},produce=async()=>{if(kind==="screen"&&screen){if(format==="html"){let out=await exportScreenHtml(p,screen,{dark:mode==="dark",...args.theme?{theme:args.theme}:{},viewport});return{bytes:out.html,warnings:out.warnings}}if(format==="pdf")return{bytes:await exportScreenPdf(p,screen,{...opts,viewport}),warnings:[]};return{bytes:await exportScreenPng(p,screen,{...opts,viewport}),warnings:[]}}if(kind==="frame"&&framed){if(format==="html"){let out=await exportFrameHtml(p,framed.board,framed.frame,opts);return{bytes:out.html,warnings:out.warnings}}return{bytes:format==="pdf"?await exportFramePdf(p,framed.board,framed.frame,opts):await exportFramePng(p,framed.board,framed.frame,opts),warnings:[]}}if(!board)fail("export","internal: target resolution failed");if(format==="html"){let out=await exportBoardHtml(p,board,opts);return{bytes:out.html,warnings:out.warnings}}return{bytes:format==="pdf"?await exportBoardPdf(p,board,opts):await exportBoardPng(p,board,opts),warnings:[]}},result;try{if(format==="html")result=await produce();else await withAssetServer(folder,null,async(baseHref)=>{assetOrigin=baseHref,await captureWithBrowserSetup("export",async()=>{result=await produce()})})}finally{await closePooledBrowser()}if(!result)fail("export","capture produced no output");if(typeof result.bytes==="string")await writeText(outPath,result.bytes);else await Bun.write(outPath,result.bytes);console.log(`velloo export: wrote ${outPath} (${kind}=${targetId}, mode=${mode})`);for(let warning of result.warnings)console.log(` note: ${warning}`)}});export{export_default as default};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{ConfigSchema}from"./chunk-nte0t7v3.js";import{readFile}from"fs/promises";import{dirname,join,resolve}from"path";async function findDesignConfig(startPath){let dir=resolve(startPath);if(!dir.endsWith("/"))dir=dirname(dir);while(!0){let candidate=join(dir,".design","config.json");try{let raw=await readFile(candidate,"utf8"),config=ConfigSchema.parse(JSON.parse(raw));return{folder:dir,config}}catch(err){if(err.code!=="ENOENT")throw err}let parent=dirname(dir);if(parent===dir)return null;dir=parent}}
2
+ import{ConfigSchema}from"./chunk-7a45tn73.js";import{readFile}from"fs/promises";import{dirname,join,resolve}from"path";async function findDesignConfig(startPath){let dir=resolve(startPath);if(!dir.endsWith("/"))dir=dirname(dir);while(!0){let candidate=join(dir,".design","config.json");try{let raw=await readFile(candidate,"utf8"),config=ConfigSchema.parse(JSON.parse(raw));return{folder:dir,config}}catch(err){if(err.code!=="ENOENT")throw err}let parent=dirname(dir);if(parent===dir)return null;dir=parent}}
3
3
  export{findDesignConfig};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import"./chunk-gsne0ap4.js";import"./chunk-nte0t7v3.js";import{loadCredential,verifyCredential}from"./chunk-njhdn9j0.js";import"./chunk-egccxmed.js";import"./chunk-c4fym47a.js";import"./chunk-q4d60wr3.js";import{listDaemons}from"./chunk-1tdh4h14.js";import"./chunk-80fjfyha.js";import"./chunk-s23gtejf.js";import"./chunk-2fgfex9b.js";import"./chunk-z1r0sc3k.js";import"./chunk-cvn689d5.js";import"./chunk-v0syg2hx.js";import{designWithFolder}from"./chunk-09385g5r.js";import"./chunk-vh4144az.js";import{defaultCloudUrl}from"./chunk-25j8vgpa.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);var status_default=defineCommand({meta:{name:"status",description:"List the velloo canvas daemons running on this machine + cloud sign-in"},args:{},async run(){let daemons=await listDaemons();if(daemons.length===0)console.log("velloo: no canvas daemons running.");else for(let d of daemons)console.log(`${d.canvasUrl} ${designWithFolder(d.root,void 0,{absolute:!0})} (pid ${d.pid}, since ${d.startedAt})`);let cloudUrl=defaultCloudUrl(),cred=await loadCredential(cloudUrl);if(!cred){console.log(import_picocolors.default.dim(`cloud: not signed in (${cloudUrl}) \u2014 run \`velloo login\` to share.`));return}let email=await verifyCredential(cloudUrl,cred.token,3000);console.log(email?`cloud: signed in as ${email} (${cloudUrl})`:import_picocolors.default.dim(`cloud: stored credential for ${cred.email} (${cloudUrl}) \u2014 expired or cloud unreachable; \`velloo login\` to refresh.`))}});export{status_default as default};
2
+ import"./chunk-m1wp8cpt.js";import"./chunk-7a45tn73.js";import{loadCredential,verifyCredential}from"./chunk-ykdx12na.js";import"./chunk-qan5dnjt.js";import"./chunk-a9mgvspm.js";import"./chunk-zqtz23xk.js";import{listDaemons}from"./chunk-shac6bat.js";import"./chunk-80fjfyha.js";import"./chunk-s23gtejf.js";import"./chunk-2dm4x17z.js";import"./chunk-r03aywsb.js";import"./chunk-cvn689d5.js";import"./chunk-db7mf114.js";import{designWithFolder}from"./chunk-py6sjyzk.js";import"./chunk-ph94nrc8.js";import{defaultCloudUrl}from"./chunk-6zr596r2.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);var status_default=defineCommand({meta:{name:"status",description:"List the velloo canvas daemons running on this machine + cloud sign-in"},args:{},async run(){let daemons=await listDaemons();if(daemons.length===0)console.log("velloo: no canvas daemons running.");else for(let d of daemons)console.log(`${d.canvasUrl} ${designWithFolder(d.root,void 0,{absolute:!0})} (pid ${d.pid}, since ${d.startedAt})`);let cloudUrl=defaultCloudUrl(),cred=await loadCredential(cloudUrl);if(!cred){console.log(import_picocolors.default.dim(`cloud: not signed in (${cloudUrl}) \u2014 run \`velloo login\` to share.`));return}let email=await verifyCredential(cloudUrl,cred.token,3000);console.log(email?`cloud: signed in as ${email} (${cloudUrl})`:import_picocolors.default.dim(`cloud: stored credential for ${cred.email} (${cloudUrl}) \u2014 expired or cloud unreachable; \`velloo login\` to refresh.`))}});export{status_default as default};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{loadDesignFolder,resolveProviders,findHostTailwindConfig,TailwindJit,extraThemeBlock}from"./chunk-egccxmed.js";import{join}from"path";async function loadPipeline(folderPath){let design=await loadDesignFolder(folderPath),config=design.config,{providers,defaultProvider}=await resolveProviders(config,folderPath),jit=new TailwindJit(Object.values(providers),join(folderPath,"screens"),void 0,()=>extraThemeBlock(design),void 0,()=>findHostTailwindConfig(folderPath,config.hostApp),config.styling?.framework),snapshotCss=await jit.build();return{folderPath,design,config,providers,defaultProvider,jit,snapshotCss}}
2
+ import{loadDesignFolder,resolveProviders,findHostTailwindConfig,TailwindJit,extraThemeBlock}from"./chunk-qan5dnjt.js";import{join}from"path";async function loadPipeline(folderPath){let design=await loadDesignFolder(folderPath),config=design.config,{providers,defaultProvider}=await resolveProviders(config,folderPath),jit=new TailwindJit(Object.values(providers),join(folderPath,"screens"),void 0,()=>extraThemeBlock(design),void 0,()=>findHostTailwindConfig(folderPath,config.hostApp),config.styling?.framework),snapshotCss=await jit.build();return{folderPath,design,config,providers,defaultProvider,jit,snapshotCss}}
3
3
  export{loadPipeline};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import"./chunk-nte0t7v3.js";import{withMcpSessionUrl,MCP_SURFACE_MODES,parseMcpSurfaceSelection,withMcpSurfaceUrl,runStdioFormatGate,runStdioMcpProxy}from"./chunk-egccxmed.js";import"./chunk-gsne0ap4.js";import"./chunk-c4fym47a.js";import"./chunk-q4d60wr3.js";import{assertLoopbackHost,daemonRoot,DesignFolderFormatError,ensureDaemon,stopDaemon}from"./chunk-1tdh4h14.js";import"./chunk-80fjfyha.js";import"./chunk-s23gtejf.js";import{upgradeFolder}from"./chunk-8sfx5x8k.js";import{DESIGN_ARG_DESCRIPTION,resolveDesignForSession}from"./chunk-46xykc71.js";import"./chunk-25j8vgpa.js";import{traceEnabled}from"./chunk-6tx68d90.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{join}from"path";async function serveFormatGate(err){console.error(`velloo mcp: ${err.message.slice(8)}`),console.error("velloo mcp: serving the upgrade gate over MCP instead of the design tools.");let closing=!1,shutdown=async(close)=>{if(closing)return;closing=!0,await close?.(),process.exit(0)},gate=await runStdioFormatGate({root:err.root,found:err.found,current:err.current,upgrade:err.found<err.current?async()=>(await stopDaemon(daemonRoot(err.root)),upgradeFolder(err.root)):void 0,onExit:()=>void shutdown()});return process.on("SIGINT",()=>void shutdown(gate.close)),process.on("SIGTERM",()=>void shutdown(gate.close)),process.stdin.on("end",()=>void shutdown(gate.close)),process.stdin.on("close",()=>void shutdown(gate.close)),await new Promise(()=>{})}var mcp_default=defineCommand({meta:{name:"mcp",description:"Connect this agent to the folder's canvas over MCP (stdio by default). Usually spawned by your agent."},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},http:{type:"boolean",default:!1,description:"Print the daemon's HTTP MCP URL instead of bridging over stdio"},port:{type:"string",description:"Preferred canvas port when starting the daemon fresh (default 7300)"},host:{type:"string",description:"Loopback bind hostname: 127.0.0.1 (default), localhost or ::1"},surface:{type:"string",description:`Tool surface: ${MCP_SURFACE_MODES.join(", ")} (default guided; env VELLOO_MCP_SURFACE)`}},async run({args}){assertLoopbackHost(args.host??"127.0.0.1");let{folder,pick}=await resolveDesignForSession(args.design,"mcp"),preferredPort=args.port?Number(args.port):void 0,parsedSurface=parseMcpSurfaceSelection(args.surface??process.env.VELLOO_MCP_SURFACE);if(!parsedSurface.ok)throw Error(`velloo mcp: ${parsedSurface.error}`);let surface=parsedSurface.selection,spawned=!1,rec;try{rec=await ensureDaemon(folder,{preferredPort,host:args.host,onSpawn:()=>{spawned=!0}})}catch(err){if(err instanceof DesignFolderFormatError&&!args.http)await serveFormatGate(err);throw err}if(traceEnabled())console.error(spawned?`velloo: \u29BF trace recording ON \u2014 tapes \u2192 ${join(folder,".velloo","trace")} (view with \`velloo trace\`)`:"velloo: VELLOO_TRACE is set, but attached to an already-running canvas \u2014 recording is only active if that daemon was started trace-enabled (`velloo stop` then reconnect to force a fresh one).");if(args.http){let selectedUrl=withMcpSessionUrl(withMcpSurfaceUrl(rec.mcpUrl,surface),{pick});console.log(`velloo: canvas at ${rec.canvasUrl}`),console.log(`velloo: MCP server at ${selectedUrl} (point your AI agent here)`),console.log("velloo: it keeps running in the background \u2014 `velloo stop` to stop it.");return}console.error(`velloo: bridging MCP to the canvas at ${rec.canvasUrl}`);let closing=!1,shutdown=async(close)=>{if(closing)return;closing=!0,await close?.(),process.exit(0)},current=folder,portFor=(root)=>root===folder?preferredPort:void 0,sessionUrl=(mcpUrl,opened)=>withMcpSessionUrl(withMcpSurfaceUrl(mcpUrl,surface),{switchable:!0,pick:opened}),proxy=await runStdioMcpProxy(sessionUrl(rec.mcpUrl,pick),{onExit:()=>void shutdown(),rediscover:async()=>{try{let fresh=await ensureDaemon(current,{preferredPort:portFor(current),host:args.host});return sessionUrl(fresh.mcpUrl,void 0)}catch{return null}},switchTo:async(root)=>{try{let next=await ensureDaemon(root,{preferredPort:portFor(root),host:args.host});return current=root,{url:sessionUrl(next.mcpUrl,void 0)}}catch(err){let message=err instanceof Error?err.message:String(err);return{error:message.startsWith("velloo: ")?message.slice(8):message}}}});process.on("SIGINT",()=>void shutdown(proxy.close)),process.on("SIGTERM",()=>void shutdown(proxy.close)),process.stdin.on("end",()=>void shutdown(proxy.close)),process.stdin.on("close",()=>void shutdown(proxy.close)),await new Promise(()=>{})}});export{mcp_default as default};
2
+ import"./chunk-7a45tn73.js";import{withMcpSessionUrl,MCP_SURFACE_MODES,parseMcpSurfaceSelection,withMcpSurfaceUrl,runStdioFormatGate,runStdioMcpProxy}from"./chunk-qan5dnjt.js";import"./chunk-m1wp8cpt.js";import"./chunk-a9mgvspm.js";import"./chunk-zqtz23xk.js";import{assertLoopbackHost,daemonRoot,DesignFolderFormatError,ensureDaemon,stopDaemon}from"./chunk-shac6bat.js";import"./chunk-80fjfyha.js";import"./chunk-s23gtejf.js";import{upgradeFolder}from"./chunk-rfrbnw8r.js";import{DESIGN_ARG_DESCRIPTION,resolveDesignForSession}from"./chunk-dj1pp4e3.js";import"./chunk-6zr596r2.js";import{traceEnabled}from"./chunk-6tx68d90.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{join}from"path";async function serveFormatGate(err){console.error(`velloo mcp: ${err.message.slice(8)}`),console.error("velloo mcp: serving the upgrade gate over MCP instead of the design tools.");let closing=!1,shutdown=async(close)=>{if(closing)return;closing=!0,await close?.(),process.exit(0)},gate=await runStdioFormatGate({root:err.root,found:err.found,current:err.current,upgrade:err.found<err.current?async()=>(await stopDaemon(daemonRoot(err.root)),upgradeFolder(err.root)):void 0,onExit:()=>void shutdown()});return process.on("SIGINT",()=>void shutdown(gate.close)),process.on("SIGTERM",()=>void shutdown(gate.close)),process.stdin.on("end",()=>void shutdown(gate.close)),process.stdin.on("close",()=>void shutdown(gate.close)),await new Promise(()=>{})}var mcp_default=defineCommand({meta:{name:"mcp",description:"Connect this agent to the folder's canvas over MCP (stdio by default). Usually spawned by your agent."},args:{design:{type:"positional",required:!1,description:DESIGN_ARG_DESCRIPTION},http:{type:"boolean",default:!1,description:"Print the daemon's HTTP MCP URL instead of bridging over stdio"},port:{type:"string",description:"Preferred canvas port when starting the daemon fresh (default 7300)"},host:{type:"string",description:"Loopback bind hostname: 127.0.0.1 (default), localhost or ::1"},surface:{type:"string",description:`Tool surface: ${MCP_SURFACE_MODES.join(", ")} (default guided; env VELLOO_MCP_SURFACE)`}},async run({args}){assertLoopbackHost(args.host??"127.0.0.1");let{folder,pick}=await resolveDesignForSession(args.design,"mcp"),preferredPort=args.port?Number(args.port):void 0,parsedSurface=parseMcpSurfaceSelection(args.surface??process.env.VELLOO_MCP_SURFACE);if(!parsedSurface.ok)throw Error(`velloo mcp: ${parsedSurface.error}`);let surface=parsedSurface.selection,spawned=!1,rec;try{rec=await ensureDaemon(folder,{preferredPort,host:args.host,onSpawn:()=>{spawned=!0}})}catch(err){if(err instanceof DesignFolderFormatError&&!args.http)await serveFormatGate(err);throw err}if(traceEnabled())console.error(spawned?`velloo: \u29BF trace recording ON \u2014 tapes \u2192 ${join(folder,".velloo","trace")} (view with \`velloo trace\`)`:"velloo: VELLOO_TRACE is set, but attached to an already-running canvas \u2014 recording is only active if that daemon was started trace-enabled (`velloo stop` then reconnect to force a fresh one).");if(args.http){let selectedUrl=withMcpSessionUrl(withMcpSurfaceUrl(rec.mcpUrl,surface),{pick});console.log(`velloo: canvas at ${rec.canvasUrl}`),console.log(`velloo: MCP server at ${selectedUrl} (point your AI agent here)`),console.log("velloo: it keeps running in the background \u2014 `velloo stop` to stop it.");return}console.error(`velloo: bridging MCP to the canvas at ${rec.canvasUrl}`);let closing=!1,shutdown=async(close)=>{if(closing)return;closing=!0,await close?.(),process.exit(0)},current=folder,portFor=(root)=>root===folder?preferredPort:void 0,sessionUrl=(mcpUrl,opened)=>withMcpSessionUrl(withMcpSurfaceUrl(mcpUrl,surface),{switchable:!0,pick:opened}),proxy=await runStdioMcpProxy(sessionUrl(rec.mcpUrl,pick),{onExit:()=>void shutdown(),rediscover:async()=>{try{let fresh=await ensureDaemon(current,{preferredPort:portFor(current),host:args.host});return sessionUrl(fresh.mcpUrl,void 0)}catch{return null}},switchTo:async(root)=>{try{let next=await ensureDaemon(root,{preferredPort:portFor(root),host:args.host});return current=root,{url:sessionUrl(next.mcpUrl,void 0)}}catch(err){let message=err instanceof Error?err.message:String(err);return{error:message.startsWith("velloo: ")?message.slice(8):message}}}});process.on("SIGINT",()=>void shutdown(proxy.close)),process.on("SIGTERM",()=>void shutdown(proxy.close)),process.stdin.on("end",()=>void shutdown(proxy.close)),process.stdin.on("close",()=>void shutdown(proxy.close)),await new Promise(()=>{})}});export{mcp_default as default};