velloo 0.1.0 → 0.2.0
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 +66 -40
- package/canvas/assets/index-ClaBqcaS.js +28 -0
- package/canvas/assets/lucide-all-iIF-pmzN.js +1 -0
- package/canvas/index.html +1 -1
- package/{chunk-k6ferbam.js → chunk-08sv3k41.js} +1 -1
- package/{chunk-74skmg76.js → chunk-0fe83yzt.js} +1 -1
- package/{chunk-n5007jcz.js → chunk-1h55s5he.js} +1 -1
- package/{chunk-5js0qw32.js → chunk-2c7jbx46.js} +1 -1
- package/chunk-308ynsxd.js +2 -0
- package/{chunk-w5rzk6ms.js → chunk-3e8vez4d.js} +2 -2
- package/{chunk-bk8b7f9a.js → chunk-40xgcth8.js} +4 -3
- package/chunk-4dn75m6t.js +3 -0
- package/chunk-4fj5tahv.js +3 -0
- package/chunk-6nqghjda.js +3 -0
- package/chunk-6w6ch4ce.js +2 -0
- package/chunk-735ezz23.js +86 -0
- package/chunk-7eq7nx37.js +7 -0
- package/chunk-7eyb8yrf.js +6 -0
- package/{chunk-8ssr8a8w.js → chunk-80fjfyha.js} +3 -6
- package/{chunk-b7j86xq7.js → chunk-80r93t2e.js} +1 -1
- package/chunk-94vx1yb0.js +3 -0
- package/{chunk-g02nd9hn.js → chunk-a84n72m2.js} +1 -1
- package/chunk-ampmdzz4.js +10 -0
- package/chunk-avns4dbf.js +2 -0
- package/{chunk-kxk5x7g6.js → chunk-ayrb3qnm.js} +1 -1
- package/{chunk-fgw3hp2v.js → chunk-bwnvcncx.js} +1 -1
- package/chunk-ccszg02q.js +5 -0
- package/{chunk-jnsfgtn9.js → chunk-cvn689d5.js} +1 -1
- package/{chunk-65wb0g7d.js → chunk-dg6z4vdd.js} +1 -1
- package/chunk-dgwjpbp9.js +3 -0
- package/{chunk-hs2j6s1v.js → chunk-dy41n60j.js} +8 -31
- package/{chunk-e2ag33vd.js → chunk-ek71z2fv.js} +2 -2
- package/{chunk-h0c36khx.js → chunk-er1fxb7d.js} +1 -1
- package/{chunk-xr6f94rj.js → chunk-eyr8hrzf.js} +1 -1
- package/{chunk-56vqqr8s.js → chunk-fsbsksga.js} +1 -1
- package/{chunk-t2ttkxe9.js → chunk-hcb68zt7.js} +1 -1
- package/chunk-j11fyeqh.js +2 -0
- package/{chunk-d385435m.js → chunk-jb21jkp1.js} +1 -1
- package/{chunk-7e39xe21.js → chunk-jfx9xjmr.js} +1 -1
- package/{chunk-b2ebm1t3.js → chunk-jr0ss0mm.js} +1 -1
- package/chunk-jv0xggh0.js +2 -0
- package/chunk-k17gfwq3.js +2 -0
- package/chunk-mh2pr7cq.js +5 -0
- package/chunk-mnapdp1y.js +2 -0
- package/chunk-n9gs6yx9.js +2 -0
- package/chunk-ngnymg2q.js +3 -0
- package/{chunk-79ykzywe.js → chunk-pjtg3wnm.js} +1 -1
- package/{chunk-2z0k59hz.js → chunk-pp86v6m6.js} +1 -1
- package/chunk-r22epxz2.js +3 -0
- package/chunk-rgasy862.js +5 -0
- package/{chunk-7p7ha0qk.js → chunk-rpwpeph5.js} +1 -1
- package/{chunk-k784090q.js → chunk-sjgqnykd.js} +1 -1
- package/chunk-sn3x2m0m.js +6 -0
- package/{chunk-mq4znqv2.js → chunk-t448rrfr.js} +1 -1
- package/{chunk-329e3phg.js → chunk-tdsk5wxa.js} +25 -25
- package/{chunk-2vx420g2.js → chunk-v40fn08f.js} +1 -1
- package/chunk-vdkrbzh1.js +2 -0
- package/{chunk-1gx45384.js → chunk-vgmr98cv.js} +7 -8
- package/chunk-vsv8z729.js +6 -0
- package/chunk-x4f4k9pp.js +26 -0
- package/{chunk-cep3ktr3.js → chunk-xt5ayg7g.js} +1 -1
- package/{chunk-rksq3w72.js → chunk-ydhwv29b.js} +1 -1
- package/chunk-zb6hc1y0.js +2 -0
- package/cli.js +1 -1
- package/launcher.cjs +1 -1
- package/package.json +3 -3
- package/pkgs/schema/src/config.ts +8 -1
- package/pkgs/schema/src/index.ts +8 -0
- package/pkgs/schema/src/migrate.ts +57 -4
- package/pkgs/schema/src/repo.ts +98 -16
- package/pkgs/schema/src/svg-sanitize.ts +472 -59
- package/skills/velloo-setup/SKILL.md +1 -1
- package/canvas/assets/index-BcBJ11d2.js +0 -28
- package/canvas/assets/lucide-all-BdEyryfF.js +0 -1
- package/chunk-1bywxgc5.js +0 -4
- package/chunk-1y50g9vp.js +0 -2
- package/chunk-1yhc252b.js +0 -3
- package/chunk-2mv65qxs.js +0 -5
- package/chunk-40657ggd.js +0 -10
- package/chunk-582y60bv.js +0 -2
- package/chunk-5x173xay.js +0 -2
- package/chunk-75wbh438.js +0 -2
- package/chunk-7dggmqwq.js +0 -53
- package/chunk-946pcnt5.js +0 -5
- package/chunk-aapybh30.js +0 -6
- package/chunk-bjnhhsak.js +0 -2
- package/chunk-dt03awr1.js +0 -2
- package/chunk-erwfk47h.js +0 -3
- package/chunk-nfr3q7mg.js +0 -5
- package/chunk-nsqs1bqf.js +0 -2
- package/chunk-pphgrsxa.js +0 -2
- package/chunk-qpvj6kzq.js +0 -6
- package/chunk-qwv7xkms.js +0 -2
- package/chunk-tmtzxcs5.js +0 -2
- package/chunk-y0zxzefg.js +0 -5
- package/chunk-zf3xc1wz.js +0 -2
package/chunk-1bywxgc5.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{RepoManifestSchema}from"./chunk-bk8b7f9a.js";import{writeJsonAtomic,localDesignsAt,localDesignOf,writeLocalDesign}from"./chunk-329e3phg.js";import{existsSync,realpathSync}from"fs";import{readdir,readFile,rm,stat,writeFile}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",PROJECT_NAME=/^[a-z0-9][a-z0-9._-]*$/i,ManifestSchema=RepoManifestSchema;async function findManifest(startDir){let dir=resolve(startDir);while(!0){let path=join(dir,MANIFEST_FILE),raw=null;try{raw=await readFile(path,"utf8")}catch(err){if(err.code!=="ENOENT")throw err}if(raw!==null){let parsed;try{parsed=JSON.parse(raw)}catch(err){throw Error(`${path} is not valid JSON: ${err.message}`)}let projects=parsed?.projects;for(let[name,entry]of Object.entries(projects&&typeof projects==="object"?projects:{}))if(entry&&typeof entry==="object"&&"managed"in entry)throw Error(`${path}: project "${name}" is a managed design locator, which velloo.json no longer holds \u2014 a design outside the repository is recorded only on the machine that has it. Remove the entry, then run \`velloo folder bind <design folder>\` from this checkout.`);let result=ManifestSchema.safeParse(parsed);if(!result.success){let issues=result.error.issues.map((i)=>`${i.path.join(".")||"(root)"}: ${i.message}`).join("; ");throw Error(`${path} is not a valid velloo manifest: ${issues}`)}let folders=new Map(Object.entries(result.data.projects).map(([name,rel])=>[name,resolve(dir,rel.replace(/\\/g,"/"))]));return{path,dir,manifest:result.data,folders}}let parent=dirname(dir);if(parent===dir)return null;dir=parent}}async function findProjects(cwd){let repo=await findManifest(cwd),local=localDesignsAt(cwd);if(!repo&&local.length===0)return null;let folders=new Map(repo?.folders??[]);for(let design of local){let clash=folders.get(design.projectName);if(clash!==void 0)throw Error(`Project "${design.projectName}" names both ${clash} (in ${repo?.path??"another local design"}) and the local design ${design.designRoot}. Remove one with \`velloo folder remove\`, or rename the velloo.json entry.`);folders.set(design.projectName,design.designRoot)}return{repo,local,folders,defaultProject:repo?.manifest.defaultProject}}function pickProject(projects,cwd){let entries=[...projects.folders],appMatches=projects.local.filter((design)=>resolve(design.appRoot)!==resolve(design.root)&&isWithin(resolve(design.appRoot),cwd));if(appMatches.length===1&&appMatches[0])return appMatches[0].projectName;let containing=entries.find(([,folder])=>cwd===folder||cwd.startsWith(folder+sep));if(containing)return containing[0];let under=entries.filter(([,folder])=>folder.startsWith(cwd+sep));if(under.length===1&&under[0])return under[0][0];if(entries.length===1&&entries[0])return entries[0][0];return projects.defaultProject??null}async function projectLabel(folder){let abs=resolve(folder),local=localDesignOf(abs);if(local)return`${local.projectName} \u2014 ${abs} (local, for ${local.root})`;let found;try{found=await findManifest(abs)}catch{return null}if(!found)return null;let entry=[...found.folders].find(([,path])=>path===abs||existsSync(path)&&existsSync(abs)&&realpathSync(path)===realpathSync(abs));if(!entry)return null;let rel=relative(found.dir,abs)||".";return`${entry[0]} \u2014 ${rel} (in ${found.dir})`}async function unregisterProject(folder,appRoot){let abs=resolve(folder),found=await findManifest(appRoot);if(!found)return{name:null,path:null,removedManifest:!1};let name=null;for(let[candidate,target]of found.folders)if(target===abs||existsSync(target)&&existsSync(abs)&&realpathSync(target)===realpathSync(abs))name=candidate;if(!name)return{name:null,path:found.path,removedManifest:!1};let{[name]:_dropped,...projects}=found.manifest.projects;if(Object.keys(projects).length===0)return await rm(found.path,{force:!0}),{name,path:found.path,removedManifest:!0};let manifest={...found.manifest,projects,...found.manifest.defaultProject===name?{defaultProject:void 0}:{}};if(manifest.defaultProject===void 0)delete manifest.defaultProject;return await writeFile(found.path,`${JSON.stringify(manifest,null,2)}
|
|
3
|
-
`,"utf8"),{name,path:found.path,removedManifest:!1}}async function manifestDirFor(folder,appRoot){let git=await findGitRoot(appRoot);if(git)return git;let dir=resolve(appRoot);while(!isWithin(dir,folder)&&dirname(dir)!==dir)dir=dirname(dir);return dir}async function checkoutRoot(appRoot,launchRoot){let found=await findManifest(launchRoot).catch(()=>null);if(found)return found.dir;let git=await findGitRoot(appRoot);if(git)return git;return isWithin(resolve(launchRoot),resolve(appRoot))?resolve(launchRoot):resolve(appRoot)}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){let base=basename(folder);return(base==="velloo"||base==="."?basename(dirname(folder)):base).toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[^a-z0-9]+/,"")||"app"}async function registerProject(folder,appRoot,requestedName){checkProjectName(requestedName);let abs=resolve(folder),found=await findManifest(abs),dir=found?found.dir:await manifestDirFor(abs,appRoot),path=found?found.path:join(dir,MANIFEST_FILE),localNames=new Set(localDesignsAt(dir).map((design)=>design.projectName)),projects={...found?.manifest.projects??{}};for(let[existing,target]of found?.folders??[])if(target===abs||existsSync(target)&&existsSync(abs)&&realpathSync(target)===realpathSync(abs))return{name:existing,path,created:!1};let add=(folder,wanted)=>{let name=wanted??deriveName(folder);for(let n=2;name in projects||localNames.has(name);n++)name=`${wanted??deriveName(folder)}-${n}`;return projects[name]=relative(dir,folder)||".",name},defaultProject=found?.manifest.defaultProject;if(!found)for(let sibling of await discoverDesignFolders(dir)){if(sibling===abs)continue;let name=add(sibling);if(sibling===join(dir,DEFAULT_FOLDER_NAME))defaultProject=name}let outsideApp=!isWithin(resolve(appRoot),abs),name=add(abs,requestedName??(outsideApp?deriveName(appRoot):void 0)),manifest={...found?.manifest??{},projects,...defaultProject?{defaultProject}:{}};return await writeJsonAtomic(path,manifest),{name,path,created:!0}}function checkProjectName(name){if(name&&!PROJECT_NAME.test(name))throw Error(`invalid --project ${JSON.stringify(name)} \u2014 names are letters/digits plus . _ -`)}async function registerLocalDesign(opts){checkProjectName(opts.requestedName);let existing=localDesignsAt(opts.root).find((design)=>design.id===opts.id),taken=new Set((await findProjects(opts.root))?.folders.keys()??[]);if(existing)taken.delete(existing.projectName);let base=opts.requestedName??existing?.projectName??deriveName(opts.appRoot);if(opts.requestedName&&taken.has(base))throw Error(`project "${base}" already exists for ${opts.root} \u2014 pick another --project.`);let name=base;for(let n=2;taken.has(name);n++)name=`${base}-${n}`;return await writeLocalDesign(opts.id,{root:opts.root,appRoot:opts.appRoot,projectName:name,...opts.designPath?{designPath:opts.designPath}:{}}),name}
|
|
4
|
-
export{findManifest,findProjects,pickProject,projectLabel,unregisterProject,checkoutRoot,isWithin,findGitRoot,discoverDesignFolders,registerProject,registerLocalDesign};
|
package/chunk-1y50g9vp.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import"./chunk-65wb0g7d.js";import{refreshUpdateCache}from"./chunk-cep3ktr3.js";import{defineCommand}from"./chunk-2smsg2ct.js";var update_check_default=defineCommand({meta:{name:"__update_check",description:"Internal release check"},async run(){await refreshUpdateCache()}});export{update_check_default as default};
|
package/chunk-1yhc252b.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{failWithError}from"./chunk-s23gtejf.js";import{traceEnabled}from"./chunk-6tx68d90.js";var LOADERS={init:()=>import("./chunk-qwv7xkms.js").then((m)=>m.default),login:()=>import("./chunk-7p7ha0qk.js").then((m)=>m.default),logout:()=>import("./chunk-74skmg76.js").then((m)=>m.default),connect:()=>import("./chunk-erwfk47h.js").then((m)=>m.default),run:()=>import("./chunk-nsqs1bqf.js").then((m)=>m.default),folder:()=>import("./chunk-qpvj6kzq.js").then((m)=>m.default),mcp:()=>import("./chunk-5x173xay.js").then((m)=>m.default),stop:()=>import("./chunk-75wbh438.js").then((m)=>m.default),status:()=>import("./chunk-zf3xc1wz.js").then((m)=>m.default),__daemon:()=>import("./chunk-n5007jcz.js").then((m)=>m.default),__update_check:()=>import("./chunk-1y50g9vp.js").then((m)=>m.default),render:()=>import("./chunk-582y60bv.js").then((m)=>m.default),capture:()=>import("./chunk-aapybh30.js").then((m)=>m.default),browser:()=>import("./chunk-dt03awr1.js").then((m)=>m.default),export:()=>import("./chunk-bjnhhsak.js").then((m)=>m.default),upgrade:()=>import("./chunk-tmtzxcs5.js").then((m)=>m.default),publish:()=>import("./chunk-2mv65qxs.js").then((m)=>m.default),emit:()=>import("./chunk-40657ggd.js").then((m)=>m.default),"theme:export":()=>import("./chunk-nfr3q7mg.js").then((m)=>m.default),completions:()=>import("./chunk-h0c36khx.js").then((m)=>m.default),...traceEnabled()?{trace:()=>import("./chunk-e2ag33vd.js").then((m)=>m.default)}:{}};function guarded(name,load){return async()=>{let cmd=await load(),run=cmd.run;if(!run)return cmd;return{...cmd,async run(ctx){try{await run(ctx)}catch(err){failWithError(name,err)}}}}}var COMMANDS=Object.fromEntries(Object.entries(LOADERS).map(([name,load])=>[name,guarded(name,load)]));
|
|
3
|
-
export{COMMANDS};
|
package/chunk-2mv65qxs.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isCancel,confirm,password,select,FOLDER_ARG_DESCRIPTION,resolveDesignFolder,pickBoards}from"./chunk-8ssr8a8w.js";import{PRICING_URL,protectedSharesAllowed,PROTECTED_SHARES_UNAVAILABLE,describeCloudError}from"./chunk-mq4znqv2.js";import"./chunk-bk8b7f9a.js";import{closePooledBrowser}from"./chunk-w5rzk6ms.js";import{loadDesignFolder,screensForBoards,resolveProviders,findHostTailwindConfig,TailwindJit,extraThemeBlock}from"./chunk-329e3phg.js";import{loadCredential}from"./chunk-b7j86xq7.js";import{fail}from"./chunk-s23gtejf.js";import{confirmRenderFailures}from"./chunk-g02nd9hn.js";import{publishedDesignSubtitle,listPublishedDesigns,unpublishDesign,listPublishDestinations,designGitEnv,describePublishError,recommendedPublishSlot,exactPublishSlots,gitContext,resolveTeam,publishDesign,createPublishBundler}from"./chunk-946pcnt5.js";import{createProgress}from"./chunk-79ykzywe.js";import{fetchAccount}from"./chunk-fgw3hp2v.js";import"./chunk-1bywxgc5.js";import{defaultCloudUrl,publishedBoardsUrl,billingPageUrl,checkCloudHealth}from"./chunk-2z0k59hz.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{join as join2}from"path";import{execFileSync}from"child_process";import{realpathSync}from"fs";import{join,relative,resolve}from"path";function plainJsonStem(path,dir){let prefix=`${dir}/`;if(!path.startsWith(prefix)||!path.endsWith(".json"))return null;let stem=path.slice(prefix.length,-5);if(stem.includes("/")||stem.includes("."))return null;return stem}function classifyChanges(changes){let set={screens:new Map,global:!1,snippets:new Set,assets:new Set};for(let{status,path}of changes){let screen=plainJsonStem(path,"screens");if(screen){set.screens.set(screen,status);continue}if(path.startsWith("theme/")||path===".design/config.json"){set.global=!0;continue}let snippet=plainJsonStem(path,"snippets");if(snippet){set.snippets.add(snippet);continue}if(path.startsWith("assets/"))set.assets.add(`/${path}`)}return set}function snippetIdsIn(value,acc){if(Array.isArray(value)){for(let v of value)snippetIdsIn(v,acc);return}if(value!==null&&typeof value==="object"){let id=value.$snippet;if(typeof id==="string")acc.add(id);for(let v of Object.values(value))snippetIdsIn(v,acc)}}function snippetsUsedByScreen(screen,snippets){let used=new Set;snippetIdsIn(screen.tree,used);let grew=!0;while(grew){grew=!1;for(let id of[...used]){let body=snippets.get(id);if(!body)continue;let inner=new Set;snippetIdsIn(body,inner);for(let innerId of inner)if(!used.has(innerId))used.add(innerId),grew=!0}}return used}function detectChangedScreens(changes,afterScreens,afterSnippets){let out=new Map;for(let[id,status]of changes.screens)out.set(id,{id,status:status==="A"?"added":status==="D"?"deleted":"modified",reasons:["screen"]});let markModified=(id,reason)=>{let existing=out.get(id);if(existing){if(!existing.reasons.includes(reason))existing.reasons.push(reason);return}out.set(id,{id,status:"modified",reasons:[reason]})};if(changes.global||changes.snippets.size>0||changes.assets.size>0)for(let[id,screen]of afterScreens){if(changes.global)markModified(id,"theme");if(changes.snippets.size===0&&changes.assets.size===0)continue;let used=snippetsUsedByScreen(screen,afterSnippets);for(let snippetId of changes.snippets)if(used.has(snippetId))markModified(id,`snippet:${snippetId}`);if(changes.assets.size>0){let haystack=JSON.stringify(screen);for(let snippetId of used){let body=afterSnippets.get(snippetId);if(body)haystack+=JSON.stringify(body)}for(let asset of changes.assets)if(haystack.includes(asset))markModified(id,`asset:${asset}`)}}return[...out.values()].sort((a,b)=>a.id.localeCompare(b.id))}function git(repo,args){return execFileSync("git",["-C",repo,...args],{encoding:"utf8",maxBuffer:67108864,stdio:["ignore","pipe","pipe"]})}function resolveGitContext(designFolder,base,head){let repoRoot;try{repoRoot=execFileSync("git",["-C",designFolder,"rev-parse","--show-toplevel"],{encoding:"utf8",stdio:["ignore","pipe","pipe"],env:designGitEnv(designFolder)}).trim()}catch{throw Error(`design folder ${designFolder} is not in a git repository, so there are no refs to compare`)}let designRel=relative(realpathSync(repoRoot),realpathSync(resolve(designFolder)));if(designRel.startsWith(".."))throw Error(`design folder ${designFolder} is outside the git repo at ${repoRoot}`);let rev=(ref)=>{try{return git(repoRoot,["rev-parse","--verify",`${ref}^{commit}`]).trim()}catch{throw Error(`cannot resolve git ref '${ref}'`)}},baseSha=rev(base),headSha=rev(head),currentSha=rev("HEAD");return{repoRoot,designRel,baseSha,headSha,headIsWorktree:headSha===currentSha}}function diffDesignFolder(ctx){let args=["diff","--name-status","--no-renames",ctx.baseSha];if(!ctx.headIsWorktree)args.push(ctx.headSha);if(ctx.designRel!=="")args.push("--",ctx.designRel);let output=git(ctx.repoRoot,args),prefix=ctx.designRel===""?"":`${ctx.designRel}/`,out=[];for(let line of output.split(`
|
|
3
|
-
`)){if(line.trim()==="")continue;let tab=line.indexOf("\t");if(tab===-1)continue;let code=line.slice(0,tab).trim(),repoPath=line.slice(tab+1);if(!repoPath.startsWith(prefix))continue;let status=code==="A"?"A":code==="D"?"D":code==="M"||code==="T"?"M":null;if(!status)continue;out.push({status,path:repoPath.slice(prefix.length)})}return out}function changedBoardId(path){if(!path.startsWith("boards/")||!path.endsWith(".json"))return null;let id=path.slice(7,-5);return id.includes("/")||id.includes(".")?null:id}function selectChangedPreviews(changes,screens,snippets,boards){let availableScreens=new Map(screens.map((screen)=>[screen.id,screen])),screenIds=new Set(detectChangedScreens(classifyChanges(changes),availableScreens,snippets).filter((change)=>change.status!=="deleted"&&availableScreens.has(change.id)).map((change)=>change.id)),directlyChangedBoards=new Set(changes.map((change)=>changedBoardId(change.path)).filter((id)=>id!==null)),boardIds=new Set(boards.filter((board)=>directlyChangedBoards.has(board.id)||board.frames.some((frame)=>screenIds.has(frame.screen))).map((board)=>board.id));return{screenIds,boardIds}}function changedPreviewsSince(designFolder,baseRef,screens,snippets,boards){let git=resolveGitContext(designFolder,baseRef,"HEAD");return selectChangedPreviews(diffDesignFolder(git),screens,snippets,boards)}async function resolveCloud(command,args){let baseUrl=args.url?args.url.replace(/\/+$/,""):defaultCloudUrl(),token=args.token??process.env.VELLOO_CLOUD_TOKEN??(await loadCredential(baseUrl))?.token;if(!token)fail(command,"not logged in. Run `velloo login` first.");return{baseUrl,token}}function cloudFailure(command,error){fail(command,describeCloudError(error))}async function listPublished(args){let{baseUrl,token}=await resolveCloud("publish",args),listed=await listPublishedDesigns({baseUrl,token});if(!listed.ok)cloudFailure("publish",listed.error);let designs=listed.value;if(designs.length===0){console.log("velloo publish: no published designs."),console.log(` ${await publishedBoardsUrl(baseUrl)}`);return}console.log(`velloo publish: ${designs.length} design${designs.length===1?"":"s"}`);for(let design of designs){let access=design.passwordProtected?"password protected":design.visibility==="private"?"private":"public";console.log(`
|
|
4
|
-
${design.title?.trim()||"Untitled design"}`),console.log(` ${access}`),console.log(` ${publishedDesignSubtitle(design)}`),console.log(` ${design.url}`)}console.log(`
|
|
5
|
-
Manage in velloo-cloud: ${await publishedBoardsUrl(baseUrl)}`)}async function removePublished(args){let{baseUrl,token}=await resolveCloud("publish",args),interactive=Boolean(process.stdin.isTTY);if(!interactive&&!args.design)fail("publish","pass the full share URL and --yes when there is no interactive terminal");if(!interactive&&args.yes!==!0)fail("publish","refusing to remove a published design without --yes");let listed=await listPublishedDesigns({baseUrl,token});if(!listed.ok)cloudFailure("publish",listed.error);let designs=listed.value,manageable=designs.filter((design)=>design.canManage);if(manageable.length===0)fail("publish",`there are no published designs you can remove. Manage boards at ${await publishedBoardsUrl(baseUrl)}`);let target;if(args.design){if(target=designFromReference(args.design,designs),!target)fail("publish",`that share URL is not in your published designs. Manage boards at ${await publishedBoardsUrl(baseUrl)}`);if(!target.canManage)fail("publish","you do not have permission to remove that design")}else{let value=await select({message:"Design to unpublish",options:manageable.map((design)=>({value:design.slug,label:design.title?.trim()||"Untitled design",hint:publishedDesignSubtitle(design)}))});if(target=resolveUnpublishSelection(isCancel(value)?null:String(value),manageable),!target)fail("publish","cancelled")}if(args.yes!==!0){let approved=await confirm({message:`Unpublish \u201C${target.title?.trim()||"Untitled design"}\u201D? Its share URL will stop working.`,initialValue:!1});if(isCancel(approved)||!approved)fail("publish","cancelled")}let removed=await unpublishDesign({baseUrl,token,slug:target.slug});if(!removed.ok)cloudFailure("publish",removed.error);console.log(`velloo publish: removed ${target.title?.trim()||"Untitled design"}`),console.log(` ${target.url}`)}function resolveUnpublishSelection(value,designs){return value===null?null:designs.find((design)=>design.slug===value)??null}function designFromReference(reference,designs){if(!/^https?:\/\//i.test(reference.trim()))return null;let normalize=(raw)=>{try{let url=new URL(raw.trim());return url.search="",url.hash="",url.toString().replace(/\/+$/,"")}catch{return null}},normalized=normalize(reference);if(normalized===null)return null;return designs.find((design)=>normalize(design.url)===normalized)??null}function privacyFlagsError(args,protectedShares=!0,upgradeUrl=PRICING_URL){if(args.visibility!==void 0&&args.visibility!=="public"&&args.visibility!=="private")return`--visibility must be 'public' or 'private', got '${args.visibility}'`;if(args.private&&args.public)return"--private and --public cannot be used together";if(args.private&&args.visibility==="public")return"--private conflicts with --visibility public";if(args.public&&args.visibility==="private")return"--public conflicts with --visibility private";if((args.private===!0||args.visibility==="private"||args.password===!0)&&!protectedShares)return`${PROTECTED_SHARES_UNAVAILABLE}. Publish with --public, or upgrade at ${upgradeUrl}`;return null}async function resolvePublishPrivacy(args,interactive,{protectedShares=!0,upgradeUrl=PRICING_URL,choose=promptForPrivacyMode}={}){let invalid=privacyFlagsError(args,protectedShares,upgradeUrl);if(invalid)throw Error(invalid);if(args.visibility!==void 0||args.private===!0||args.public===!0||args.password===!0)return{visibility:args.private||args.visibility==="private"?"private":"public",password:args.password===!0};if(!interactive)throw Error("privacy mode is required without a terminal; pass --public, --private, --password, or --visibility");let mode=await choose(protectedShares,upgradeUrl);if(typeof mode==="symbol")throw Error("cancelled");if(mode!=="public"&&!protectedShares)throw Error(PROTECTED_SHARES_UNAVAILABLE);return mode==="private"?{visibility:"private",password:!1}:{visibility:"public",password:mode==="password"}}async function promptForPrivacyMode(protectedShares,upgradeUrl){let locked=protectedShares?{}:{disabled:!0,hint:"Team & Business plans"};return select({message:protectedShares?"Who should be able to view this publish?":`Who should be able to view this publish? (free plan: public links \u2014 upgrade at ${upgradeUrl})`,initialValue:"public",options:[{value:"public",label:"Public",hint:"anyone with the link"},{value:"private",label:"Private",hint:"only your organization",...locked},{value:"password",label:"Password protected",hint:"anyone with the password",...locked}]})}var publish_default=defineCommand({meta:{name:"publish",description:"Publish the design folder as a velloo-cloud share link (the cloud renders it). --list shows what you've published; --remove takes one down"},args:{folder:{type:"positional",required:!1,description:`${FOLDER_ARG_DESCRIPTION}. With --remove, the share URL to take down instead`},list:{type:"boolean",description:"List your published designs instead of publishing"},remove:{type:"boolean",description:"Take a published design down instead of publishing \u2014 pass its share URL, or pick one interactively"},yes:{type:"boolean",description:"Skip confirmations \u2014 the --remove prompt, and publishing a screen whose component fails to render (required without an interactive terminal)"},url:{type:"string",description:"velloo-cloud base URL (default: $VELLOO_CLOUD_URL or the built-in default)"},token:{type:"string",description:"velloo-cloud access token (default: $VELLOO_CLOUD_TOKEN)"},slug:{type:"string",description:"Custom slug for --new (default: server-generated)"},new:{type:"boolean",description:"Create a separate publish link instead of updating an existing slot"},update:{type:"boolean",description:"Update the exact matching published design"},title:{type:"string",description:"Link title (default: folder name)"},boards:{type:"string",description:"Comma-separated board ids to publish (default: pick interactively; all when non-interactive)"},visibility:{type:"string",description:"public | private \u2014 explicit alternative to the interactive privacy prompt"},public:{type:"boolean",description:"Publish for anyone with the link; skips the privacy prompt"},private:{type:"boolean",description:"Publish for your organization only; skips the privacy prompt"},password:{type:"boolean",description:"Password-protect the link; anyone with the password can view. Prompts for it, or reads $VELLOO_SHARE_PASSWORD"},"password-expires":{type:"string",description:"Stop accepting the password after this date (YYYY-MM-DD or ISO timestamp)"},team:{type:"string",description:"Publish into a team by name or UUID (default: personal workspace)"},w:{type:"string",description:"Viewport width in px (default: 1440)"},h:{type:"string",description:"Viewport height in px (default: 900)"},"changed-since":{type:"string",description:"Capture only screen/board previews affected since this git ref (the full design still publishes)"}},async run({args}){if(args.list&&args.remove)fail("publish","--list and --remove do different things");if(args.list)return listPublished(args);if(args.remove)return removePublished({...args,design:args.folder,yes:args.yes});let folder=await resolveDesignFolder(args.folder,"publish"),baseUrl=args.url?args.url.replace(/\/+$/,""):defaultCloudUrl(),token=args.token??process.env.VELLOO_CLOUD_TOKEN??(await loadCredential(baseUrl))?.token;if(!token)fail("publish","not logged in. Run `velloo login` (or pass --token / VELLOO_CLOUD_TOKEN).");let interactive=Boolean(process.stdin.isTTY),team=await resolveTeam(baseUrl,token,args.team);if(!team.ok)fail("publish",describePublishError(team.error));let teamId=team.value,viewport={w:args.w?Number(args.w):1440,h:args.h?Number(args.h):900},design=await loadDesignFolder(folder),config=design.config,health=await checkCloudHealth(baseUrl);if(health.status==="unreachable")fail("publish",`cannot reach ${baseUrl} (${health.reason}). Is velloo-cloud up? (bun cloud:up)`);if(health.status==="unhealthy")fail("publish",health.detail);let account=await fetchAccount(baseUrl,token,5000),protectedShares=protectedSharesAllowed(account.status==="ok"?account.account.tier:void 0),upgradeUrl=protectedShares?void 0:await billingPageUrl(baseUrl),flagsError=privacyFlagsError(args,protectedShares,upgradeUrl);if(flagsError)fail("publish",flagsError);let selected=await pickBoards(folder,args.boards,interactive,"publish");if(selected===null){console.log("velloo publish: no boards selected \u2014 nothing was published.");return}let provenance=gitContext(folder),selectedBoardIds=new Set(selected.map((board)=>board.id)),selectedBoards=[...design.boards.values()].filter((board)=>selectedBoardIds.has(board.id)),screenshotSelection=args["changed-since"]?(()=>{try{return changedPreviewsSince(folder,args["changed-since"],[...design.screens.values()],design.snippets,selectedBoards)}catch(error){fail("publish",`cannot determine previews changed since '${args["changed-since"]}': ${error instanceof Error?error.message:String(error)}`)}})():void 0,listed=await(async()=>{if(!config.folderId||args.new===!0)return{effectiveTeamId:teamId??null,slots:[]};let destinations=await listPublishDestinations({baseUrl,token,folderId:config.folderId,...teamId?{teamId}:{}});if(!destinations.ok)fail("publish",describePublishError(destinations.error));return destinations.value})(),source={boardIds:selected.map((board)=>board.id),teamId:listed.effectiveTeamId,...provenance},destination=await choosePublishDestination({slots:listed.slots,source,interactive,createNew:args.new===!0,updateExisting:args.update===!0,customSlug:args.slug,manageUrl:await publishedBoardsUrl(baseUrl)}),privacy=await resolvePublishPrivacy(args,interactive,{protectedShares,...upgradeUrl?{upgradeUrl}:{}}).catch((error)=>fail("publish",error instanceof Error?error.message:String(error))),visibility=privacy.visibility,password=privacy.password?await readSharePassword():void 0,passwordExpiresAt=resolvePasswordExpiry(args["password-expires"],password!=null),{providers,defaultProvider}=await resolveProviders(config,folder);await confirmRenderFailures("publish",{folder:design,providers,defaultProvider},source.boardIds.length>0?screensForBoards(design,source.boardIds):[...design.screens.values()],args.yes===!0);let bundler=createPublishBundler(folder,config),jit=new TailwindJit(Object.values(providers),join2(folder,"screens"),void 0,()=>extraThemeBlock(design),()=>bundler.hostSourceDirs(),()=>findHostTailwindConfig(folder,config.hostApp),config.styling?.framework),progress=createProgress(),report=createPublishReporter(progress),outcome;try{let published=await publishDesign({baseUrl,token},{folder:design,providers,defaultProvider,snapshotCss:()=>jit.build(),liveBundler:bundler},{boardIds:selected.map((b)=>b.id),...args.title?{title:args.title}:{},visibility,...password?{password}:{},...passwordExpiresAt?{passwordExpiresAt}:{},destination,...teamId?{teamId}:{},provenance,viewport,...screenshotSelection?{screenshotSelection}:{}},report);if(!published.ok)progress.fail("publish failed"),fail("publish",describePublishError(published.error));outcome=published.value,progress.succeed("published design")}catch(error){progress.fail("publish failed"),fail("publish",error instanceof Error?error.message:String(error))}finally{await closePooledBrowser()}console.log(`velloo publish: ${outcome.files} files, ${Math.round(outcome.bytes/1024)} KB${outcome.screenshots>0?`, ${outcome.screenshots} screenshots`:""}${outcome.commitSha?`, commit ${outcome.commitSha.slice(0,7)}`:""}`),console.log(` ${outcome.shareUrl}`),console.log(` ${describeAccess(outcome)}`);let history=outcome.history;if(history&&!history.retained&&history.pruned>0)console.log(" replaced the previous version \u2014 the free plan keeps only the latest."),console.log(` Upgrade to Team to keep version history and revisit past publishes: ${PRICING_URL}`);else if(history?.retained&&history.versions>1)console.log(` history: ${history.versions} versions kept \u2014 pin any of them from ${outcome.shareUrl}v/<version>/`)}});function resolvePublishDestinationChoice(value,slots){if(value===null)return null;if(value==="new")return{mode:"new"};let slug=value.replace(/^update:/,""),slot=slots.find((candidate)=>candidate.slug===slug);if(!slot)return null;return{mode:"update",slug:slot.slug,expectedVersionId:slot.latestVersionId}}async function choosePublishDestination(opts){if(opts.createNew&&opts.updateExisting)fail("publish","choose either --new or --update, not both");if(opts.customSlug&&!opts.createNew)fail("publish","--slug names a new link; use it together with --new");let matching=exactPublishSlots(opts.slots,opts.source);if(opts.updateExisting){let slot=matching[0];if(!slot)fail("publish",`there is no exact published-design match to update. Manage existing boards at ${opts.manageUrl}`);return{mode:"update",slug:slot.slug,expectedVersionId:slot.latestVersionId}}if(opts.createNew)return{mode:"new",...opts.customSlug?{slug:opts.customSlug}:{}};if(matching.length===0)return(opts.log??console.log)("velloo publish: no matching published design \u2014 a new link will be created."),{mode:"new"};if(!opts.interactive)fail("publish","this folder already has published designs; pass --update or --new explicitly");let recommended=recommendedPublishSlot(opts.slots,opts.source),latestMatch=matching[0],value=await select({message:"Publish destination",initialValue:recommended?`update:${recommended.slug}`:"new",options:[...latestMatch?[{value:`update:${latestMatch.slug}`,label:`Update ${latestMatch.title||"Untitled design"}`,hint:"latest exact match for this team, board selection, and source"}]:[],{value:"new",label:"Create a new link",hint:recommended?"keep the matching design separate":"recommended for this source"}]}),destination=resolvePublishDestinationChoice(isCancel(value)?null:String(value),matching);if(!destination)fail("publish",isCancel(value)?"cancelled":"selected publish slot is no longer available");return destination}function createPublishReporter(progress){let latestCapture;return(event)=>{if(event.kind==="capture"){latestCapture=`capturing previews ${event.done}/${event.total}`,progress.step(latestCapture,{transient:!0});return}if(event.kind==="step"){if(latestCapture)progress.step(latestCapture);latestCapture=void 0,progress.step(event.message);return}progress.log(event.message)}}async function readSharePassword(){let fromEnv=process.env.VELLOO_SHARE_PASSWORD?.trim();if(fromEnv){if(fromEnv.length<3)fail("publish","VELLOO_SHARE_PASSWORD must be at least 3 characters");return fromEnv}if(!process.stdin.isTTY)fail("publish","--password needs a terminal to prompt \u2014 set $VELLOO_SHARE_PASSWORD instead");let entered=await password({message:"Password for this share link",validate:(value)=>(value??"").length<3?"At least 3 characters.":void 0});if(isCancel(entered))fail("publish","cancelled");return entered}function resolvePasswordExpiry(raw,hasPassword){if(!raw)return;if(!hasPassword)fail("publish","--password-expires needs --password");let value=/^\d{4}-\d{2}-\d{2}$/.test(raw)?`${raw}T23:59:59`:raw,when=new Date(value);if(Number.isNaN(when.getTime()))fail("publish",`--password-expires must be a date (YYYY-MM-DD) or ISO timestamp, got '${raw}'`);return when.toISOString()}function describeAccess(outcome){if(outcome.visibility==="private")return outcome.passwordProtected?"private \u2014 your organization, or anyone with the password":"private \u2014 anyone signed in at your organization";return outcome.passwordProtected?"public \u2014 anyone with the link and the password":"public \u2014 anyone with the link"}export{publish_default as default};
|
package/chunk-40657ggd.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ScreenSchema}from"./chunk-bk8b7f9a.js";import{detectTailwindMajor,emitCode,moduleTarget,v3ClassIssues,classNamesInJsx,styleChannelOf,loadDesignFolder,hostAppRootFrom,resolveProviders}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import{fail}from"./chunk-s23gtejf.js";import{findDesignConfig,FOLDER_ARG_DESCRIPTION,resolveDesignFolder,pickScreen}from"./chunk-8ssr8a8w.js";import{createProgress}from"./chunk-79ykzywe.js";import"./chunk-1bywxgc5.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{readFile,writeFile}from"fs/promises";import{isAbsolute,resolve}from"path";import{stdout}from"process";async function folderEmitContext(screenPath,screen){let found=await findDesignConfig(screenPath);if(!found)return{};let design=await loadDesignFolder(found.folder),{providers,defaultProvider}=await resolveProviders(design.config,found.folder),provider=screen.library&&providers[screen.library]||defaultProvider,adapter=provider,target;if(adapter.codegenModule){let manifest=await provider.loadManifest();target=moduleTarget(manifest.filter((c)=>c.source!=="velloo").map((c)=>c.id),adapter.codegenModule)}let inlineStyle=styleChannelOf(provider,design.config.styling?.framework).kind==="style";return{snippets:design.snippets,...design.config.extensions?{extensions:design.config.extensions}:{},...target?{target}:{},...inlineStyle?{inlineStyle:!0}:{}}}var emit_default=defineCommand({meta:{name:"emit",description:"Print or write agent-consumed IR for a screen."},args:{screen:{type:"positional",required:!1,description:"Screen id, or a path to a screen JSON. Omit to pick interactively."},folder:{type:"string",description:FOLDER_ARG_DESCRIPTION},to:{type:"string",description:"Write IR as JSON to this path. Omit to print the JSX body to stdout (agent-friendly when piped)."},"components-alias":{type:"string",description:'Override the import prefix the IR mentions in snippet identifiers. Defaults to .design/config.json#codegen.componentsAlias, else "@/components/ui".'}},async run({args}){let interactive=Boolean(process.stdin.isTTY),screenArg=args.screen,screenPath=!!screenArg&&(screenArg.includes("/")||screenArg.endsWith(".json"))?resolve(screenArg):(await pickScreen(await resolveDesignFolder(args.folder,"emit"),screenArg,interactive,"emit")).path,screenJson=JSON.parse(await readFile(screenPath,"utf8")),screen=ScreenSchema.parse(screenJson),progress=createProgress();progress.start("preparing code");try{let componentsAlias=args["components-alias"]??await readConfigAlias(screenPath),context=await folderEmitContext(screenPath,screen);progress.step("generating code");let result=await emitCode(screen,{...componentsAlias?{componentsAlias}:{},...context});if(!result.ok){progress.fail("code generation failed");let e=result.error;if(e.kind==="UnknownComponent")fail("emit",`unknown component: ${JSON.stringify(e.ref)}`);else if(e.kind==="SnippetNotFound")fail("emit",`snippet not found: ${JSON.stringify(e.snippetId)}`);else fail("emit",`screen not found: ${JSON.stringify(e.screenId)}`)}let found=await findDesignConfig(screenPath),tailwindV3Compat=found&&!context?.target&&!context?.inlineStyle?detectTailwindMajor(hostAppRootFrom(found.folder,found.config.hostApp))===3?v3ClassIssues([...result.value.classesUsed,...result.value.snippetsUsed.flatMap((s)=>classNamesInJsx(s.jsx))]):[]:[];if(args.to){progress.step("writing code");let outPath=isAbsolute(args.to)?args.to:resolve(args.to),ir=tailwindV3Compat.length>0?{...result.value,tailwindV3Compat}:result.value;await writeFile(outPath,JSON.stringify(ir,null,2),"utf8"),progress.succeed("generated code"),console.log(`velloo emit: wrote ${outPath}`);return}if(progress.succeed("generated code"),stdout.write(`// screen: ${result.value.screen.id} (${result.value.screen.name})
|
|
3
|
-
`),stdout.write(`// components: ${result.value.componentsUsed.join(", ")||"(none)"}
|
|
4
|
-
`),result.value.iconsUsed.length>0)stdout.write(`// icons (lucide): ${result.value.iconsUsed.join(", ")}
|
|
5
|
-
`);if(result.value.snippetsUsed.length>0)stdout.write(`// snippets: ${result.value.snippetsUsed.map((s)=>`${s.componentName}(${s.id})`).join(", ")}
|
|
6
|
-
`);for(let issue of tailwindV3Compat)stdout.write(issue.v3?`// tailwind v3 host: \`${issue.class}\` \u2192 \`${issue.v3}\` (${issue.note})
|
|
7
|
-
`:`// tailwind v3 host: \`${issue.class}\` \u2014 ${issue.note}
|
|
8
|
-
`);stdout.write(`
|
|
9
|
-
`),stdout.write(`${result.value.jsx}
|
|
10
|
-
`)}catch(error){throw progress.fail("code generation failed"),error}}});async function readConfigAlias(screenPath){return(await findDesignConfig(screenPath))?.config.codegen?.componentsAlias}export{emit_default as default};
|
package/chunk-582y60bv.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isCancel,select,findDesignConfig,FOLDER_ARG_DESCRIPTION,resolveDesignFolder,pickScreen}from"./chunk-8ssr8a8w.js";import{closePooledBrowser,renderScreen,screenshot}from"./chunk-w5rzk6ms.js";import{ScreenSchema}from"./chunk-bk8b7f9a.js";import{writeText,registryForScreen,renderPassForScreen}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import{fail}from"./chunk-s23gtejf.js";import{captureWithBrowserSetup}from"./chunk-k6ferbam.js";import{loadPipeline}from"./chunk-kxk5x7g6.js";import{withAssetServer}from"./chunk-9vg3yafz.js";import{createProgress}from"./chunk-79ykzywe.js";import"./chunk-1bywxgc5.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{readFile}from"fs/promises";import{extname,isAbsolute,resolve}from"path";var render_default=defineCommand({meta:{name:"render",description:"dev: render a screen headless to .html or .png"},args:{screen:{type:"positional",required:!1,description:"Screen id, or a path to a screen JSON. Omit to pick interactively."},folder:{type:"string",description:FOLDER_ARG_DESCRIPTION},to:{type:"string",description:"Output path; extension picks the format (.html | .png). Default: ./<screen>.html"},w:{type:"string",description:"Viewport width in px (default: 1440)"},h:{type:"string",description:"Viewport height in px (default: 900)"}},async run({args}){let interactive=Boolean(process.stdin.isTTY),screenArg=args.screen,looksLikePath=!!screenArg&&(screenArg.includes("/")||screenArg.endsWith(".json")),folder,screenPath;if(looksLikePath&&screenArg)if(screenPath=resolve(screenArg),args.folder)folder=await resolveDesignFolder(args.folder,"render");else{let found=await findDesignConfig(screenPath);if(!found)fail("render",`${screenPath} is not inside a velloo design folder (no .design/config.json above it). Pass --folder with a project name or a path.`);folder=found.folder}else folder=await resolveDesignFolder(args.folder,"render"),screenPath=(await pickScreen(folder,screenArg,interactive,"render")).path;let screen=ScreenSchema.parse(JSON.parse(await readFile(screenPath,"utf8"))),viewport={w:args.w?Number(args.w):1440,h:args.h?Number(args.h):900},outPath;if(args.to)outPath=isAbsolute(args.to)?args.to:resolve(args.to);else{let ext="html";if(interactive){let fmt=await select({message:"Output format?",options:[{value:"html",label:"HTML",hint:"no browser needed"},{value:"png",label:"PNG",hint:"screenshot (needs a headless browser)"}]});if(isCancel(fmt))fail("render","cancelled.");ext=fmt}outPath=resolve(`${screen.id}.${ext}`)}let out=extname(outPath).toLowerCase();if(out!==".html"&&out!==".png")fail("render",`unsupported output extension ${JSON.stringify(out)}. Use .html or .png.`);let progress=createProgress();progress.start("preparing render");try{let pipeline=await loadPipeline(folder),{design,config,providers,defaultProvider,snapshotCss}=pipeline,theme=design.theme,registry=registryForScreen(screen,providers,defaultProvider,config.extensions??{}),renderPass=renderPassForScreen(screen,providers,defaultProvider,theme),renderHtml=async(baseHref)=>{let{html}=await renderScreen(screen,theme,{viewport,snapshotCss,registry,snippets:design.snippets,renderPass,customCss:design.customCss,...baseHref?{baseHref}:{}});return html};if(out===".html"){progress.step("rendering HTML"),await writeText(outPath,await renderHtml()),progress.succeed("rendered HTML"),console.log(`velloo render: wrote ${outPath} (screen=${screen.id})`);return}progress.step("rendering screen"),await withAssetServer(folder,null,async(baseHref)=>{let html=await renderHtml(baseHref);try{await captureWithBrowserSetup("render",async()=>{progress.step("capturing PNG");try{await screenshot({html,viewport,outPath})}catch(error){throw progress.fail("PNG capture failed"),error}})}finally{await closePooledBrowser()}}),progress.succeed("rendered PNG"),console.log(`velloo render: wrote ${outPath} (screen=${screen.id})`)}catch(error){throw progress.fail("render failed"),error}}});export{render_default as default};
|
package/chunk-5x173xay.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import"./chunk-bk8b7f9a.js";import{MCP_SURFACE_MODES,parseMcpSurfaceSelection,withMcpSurfaceUrl,runStdioFormatGate,runStdioMcpProxy}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import"./chunk-65wb0g7d.js";import{assertLoopbackHost,daemonRoot,DesignFolderFormatError,ensureDaemon,stopDaemon}from"./chunk-k784090q.js";import{FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import"./chunk-s23gtejf.js";import{upgradeFolder}from"./chunk-y0zxzefg.js";import"./chunk-1bywxgc5.js";import"./chunk-2z0k59hz.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:{folder:{type:"positional",required:!1,description:FOLDER_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=await resolveDesignFolder(args.folder,"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=withMcpSurfaceUrl(rec.mcpUrl,surface);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)},proxy=await runStdioMcpProxy(withMcpSurfaceUrl(rec.mcpUrl,surface),{onExit:()=>void shutdown(),rediscover:async()=>{try{let fresh=await ensureDaemon(folder,{preferredPort,host:args.host});return withMcpSurfaceUrl(fresh.mcpUrl,surface)}catch{return null}}});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};
|
package/chunk-75wbh438.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import"./chunk-bk8b7f9a.js";import"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import"./chunk-65wb0g7d.js";import{daemonRoot,listDaemons,stopDaemon}from"./chunk-k784090q.js";import{FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import"./chunk-s23gtejf.js";import{projectLabel}from"./chunk-1bywxgc5.js";import"./chunk-2z0k59hz.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);var stop_default=defineCommand({meta:{name:"stop",description:"Stop the persistent canvas daemon for a folder (or --all)"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},all:{type:"boolean",default:!1,description:"Stop every running velloo canvas daemon on this machine"}},async run({args}){if(args.all){let daemons=await listDaemons();if(daemons.length===0){console.log("velloo: no canvas daemons running.");return}for(let d of daemons)await stopDaemon(d.root),console.log(`velloo: stopped ${d.canvasUrl} (${d.root})`);return}let folder=await resolveDesignFolder(args.folder,"stop"),root=daemonRoot(folder);if(await stopDaemon(root)){console.log(`velloo: stopped canvas for ${root}`);return}console.log(`velloo: no canvas running for ${root}`);let others=await listDaemons();if(others.length===0)return;console.log(import_picocolors.default.dim(` ${others.length} canvas${others.length===1?"":"es"} running elsewhere \u2014 stop one by path, or \`velloo stop --all\`:`));for(let d of others)console.log(import_picocolors.default.dim(` ${d.canvasUrl} ${await projectLabel(d.root)??d.root}`))}});export{stop_default as default};
|
package/chunk-7dggmqwq.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{COMMANDS}from"./chunk-1yhc252b.js";var SHELLS=["zsh","bash","fish"],zshName=(name)=>name.replace(/\\/g,"\\\\").replace(/:/g,"\\:");function zshScript(specs){let commandLines=specs.map((c)=>` '${zshName(c.name)}:${c.description}'`).join(`
|
|
3
|
-
`),cases=specs.map((c)=>{let flagSpecs=c.flags.map((f)=>` '${f.flag}${f.takesValue?"=":""}[${f.description}]'`).join(" \\\n"),body=flagSpecs?` _arguments \\
|
|
4
|
-
${flagSpecs} \\
|
|
5
|
-
'*:file:_files'`:" _files";return` ${c.name})
|
|
6
|
-
${body}
|
|
7
|
-
;;`}).join(`
|
|
8
|
-
`);return`#compdef velloo
|
|
9
|
-
# velloo shell completions (zsh) \u2014 generated by \`velloo completions\`.
|
|
10
|
-
_velloo() {
|
|
11
|
-
local -a _velloo_commands
|
|
12
|
-
_velloo_commands=(
|
|
13
|
-
${commandLines}
|
|
14
|
-
)
|
|
15
|
-
if (( CURRENT == 2 )); then
|
|
16
|
-
_describe 'velloo command' _velloo_commands
|
|
17
|
-
return
|
|
18
|
-
fi
|
|
19
|
-
case $words[2] in
|
|
20
|
-
${cases}
|
|
21
|
-
esac
|
|
22
|
-
}
|
|
23
|
-
if ! (( $+functions[compdef] )); then
|
|
24
|
-
autoload -Uz compinit && compinit -i
|
|
25
|
-
fi
|
|
26
|
-
compdef _velloo velloo
|
|
27
|
-
`}function bashScript(specs){let names=specs.map((c)=>c.name).join(" "),cases=specs.map((c)=>` ${c.name}) flags="${c.flags.map((f)=>f.flag).join(" ")}" ;;`).join(`
|
|
28
|
-
`);return`# velloo shell completions (bash) \u2014 generated by \`velloo completions\`.
|
|
29
|
-
_velloo() {
|
|
30
|
-
local cur cmd flags
|
|
31
|
-
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
32
|
-
cmd="\${COMP_WORDS[1]}"
|
|
33
|
-
if [[ $COMP_CWORD -eq 1 ]]; then
|
|
34
|
-
COMPREPLY=( $(compgen -W "${names}" -- "$cur") )
|
|
35
|
-
return
|
|
36
|
-
fi
|
|
37
|
-
flags=""
|
|
38
|
-
case "$cmd" in
|
|
39
|
-
${cases}
|
|
40
|
-
esac
|
|
41
|
-
if [[ "$cur" == -* && -n "$flags" ]]; then
|
|
42
|
-
COMPREPLY=( $(compgen -W "$flags" -- "$cur") )
|
|
43
|
-
fi
|
|
44
|
-
}
|
|
45
|
-
complete -o default -F _velloo velloo
|
|
46
|
-
`}function fishScript(specs){let lines=["# velloo shell completions (fish) \u2014 generated by `velloo completions`."];for(let c of specs){lines.push(`complete -c velloo -f -n "__fish_use_subcommand" -a "${c.name}" -d "${c.description}"`);for(let f of c.flags){let long=f.flag.replace(/^--/,"");lines.push(`complete -c velloo -n "__fish_seen_subcommand_from ${c.name}" -l ${long}${f.takesValue?" -r":""} -d "${f.description}"`)}}return`${lines.join(`
|
|
47
|
-
`)}
|
|
48
|
-
`}function completionScript(shell,specs){switch(shell){case"zsh":return zshScript(specs);case"bash":return bashScript(specs);case"fish":return fishScript(specs)}}async function resolvable(value){return typeof value==="function"?await value():value}var kebab=(name)=>name.replace(/[A-Z]/g,(c)=>`-${c.toLowerCase()}`);function sanitize(desc){return(desc??"").split(`
|
|
49
|
-
`)[0]?.replace(/['"[\]:`$\\]/g,"").trim()??""}async function commandSpecs(){let out=[];for(let[name,load]of Object.entries(COMMANDS)){if(name.startsWith("__"))continue;let meta,args;try{let cmd=await resolvable(load);meta=cmd.meta?await resolvable(cmd.meta):void 0,args=cmd.args?await resolvable(cmd.args):{}}catch{continue}let flags=[];for(let[argName,def]of Object.entries(args)){if(def.type==="positional")continue;let isBool=def.type==="boolean",negated=isBool&&def.default===!0;flags.push({flag:negated?`--no-${kebab(argName)}`:`--${kebab(argName)}`,description:sanitize(def.description),takesValue:!isBool})}out.push({name,description:sanitize(meta?.description),flags})}return out}import{existsSync}from"fs";import{appendFile,mkdir,readFile,writeFile}from"fs/promises";import{homedir}from"os";import{basename,dirname,join}from"path";function detectShell(env=process.env){let name=basename(env.SHELL??"");return SHELLS.includes(name)?name:null}var RC_MARKER="# velloo completions";function targets(shell,homeDir){switch(shell){case"zsh":return{scriptPath:join(homeDir,".velloo","completions","velloo.zsh"),rcPath:join(homeDir,".zshrc")};case"bash":return{scriptPath:join(homeDir,".velloo","completions","velloo.bash"),rcPath:join(homeDir,".bashrc")};case"fish":return{scriptPath:join(homeDir,".config","fish","completions","velloo.fish")}}}function completionsInstalled(homeDir=homedir(),shell){return(shell?[shell]:SHELLS).some((s)=>existsSync(targets(s,homeDir).scriptPath))}async function installCompletions(shell,homeDir=homedir()){let{scriptPath,rcPath}=targets(shell,homeDir),script=completionScript(shell,await commandSpecs());await mkdir(dirname(scriptPath),{recursive:!0}),await writeFile(scriptPath,script);let rcUpdated=!1;if(rcPath){let rc=await readFile(rcPath,"utf8").catch(()=>"");if(!rc.includes(RC_MARKER)){let rel=scriptPath.slice(homeDir.length+1),line=`[ -f "$HOME/${rel}" ] && source "$HOME/${rel}" ${RC_MARKER}`;await appendFile(rcPath,`${rc.endsWith(`
|
|
50
|
-
`)||rc===""?"":`
|
|
51
|
-
`}${line}
|
|
52
|
-
`),rcUpdated=!0}}return{shell,scriptPath,rcPath,rcUpdated}}
|
|
53
|
-
export{SHELLS,completionScript,commandSpecs,detectShell,completionsInstalled,installCompletions};
|
package/chunk-946pcnt5.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ok,err,PRICING_URL,PROTECTED_SHARES_UNAVAILABLE,PublishDestinationsResponseSchema,LinkResponseSchema,LinkAccessResponseSchema,VersionUploadResponseSchema,PublishedDesignsResponseSchema,TeamsResponseSchema,unreachable,protocolViolation,uploadRaceLost,readFailure,cloudFailure,httpFailureFrom,boardLimitFrom,describeBoardLimit,describeCloudError,cloudJson,cloudFetch}from"./chunk-mq4znqv2.js";import{prettifyError,string,number,boolean,array,object,strictObject,record,literal,AnnotationSchema,CanvasNoteSchema,BoardSchema,ExtensionSchema,ViewportPresetSchema,LibrarySchema,ScreenSchema,SnippetSchema,ThemeSchema,ViewportSchema}from"./chunk-bk8b7f9a.js";import{buildBoardComposite,MAX_CONCURRENT_RENDERS,renderScreen,captureScreenshot}from"./chunk-w5rzk6ms.js";import{writeJsonAtomic,managedDesignId,localDesignOf,orderedBoards,activeBoards,registryForScreen,renderPassForScreen,liveExtensions,LiveBundler}from"./chunk-329e3phg.js";import{withAssetServer}from"./chunk-9vg3yafz.js";import{checkCloudHealth}from"./chunk-2z0k59hz.js";var VERSION_UPLOAD_TIMEOUT_MS=60000,VERSION_UPLOAD_RETRIES=1;async function listPublishDestinations(opts){let query=new URLSearchParams({folderId:opts.folderId});if(opts.teamId)query.set("teamId",opts.teamId);return cloudFetch(`${opts.baseUrl}/v1/publish-destinations?${query}`,PublishDestinationsResponseSchema,{operation:"listing publish destinations",token:opts.token})}async function uploadLinkBundle(opts){let{baseUrl,token,form}=opts,authorized={authorization:`Bearer ${token}`},createRes=await fetch(`${baseUrl}/v1/links`,{method:"POST",headers:authorized,body:JSON.stringify(opts.link)}).catch((error)=>error);if(!(createRes instanceof Response))return err(unreachable(createRes,{url:baseUrl}));if(createRes.status!==200&&createRes.status!==201)return err(await httpFailureFrom("link creation",createRes));let created=createRes.status===201,createdLink=await cloudJson(createRes,LinkResponseSchema,"link creation");if(!createdLink.ok)return createdLink;let link=createdLink.value;if(opts.link.publishMode==="new"&&!created)return err(protocolViolation("the cloud reused a link even though a new publish destination was requested"));if(opts.link.publishMode==="update"&&created)return await fetch(`${baseUrl}/v1/links/${link.slug}`,{method:"DELETE",headers:authorized}).catch(()=>{}),err(protocolViolation("the cloud created a link even though an existing destination was selected"));if(!created){let accessRes=await fetch(`${baseUrl}/v1/links/${link.slug}/access`,{method:"PUT",headers:{...authorized,"content-type":"application/json"},body:JSON.stringify({visibility:opts.link.visibility,password:opts.link.password??null,passwordExpiresAt:opts.link.password?opts.link.passwordExpiresAt??null:null,expectedVersionId:opts.link.expectedVersionId??null})});if(!accessRes.ok)return err(await httpFailureFrom("privacy update",accessRes));let access=await cloudJson(accessRes,LinkAccessResponseSchema,"privacy update");if(!access.ok)return access;link={...link,...access.value}}if(form.append("publishMode",opts.link.publishMode),opts.link.expectedVersionId)form.append("expectedVersionId",opts.link.expectedVersionId);let attempt=await uploadVersionWithRetry({url:`${baseUrl}/v1/links/${link.slug}/versions`,headers:authorized,form,timeoutMs:opts.uploadTimeoutMs??VERSION_UPLOAD_TIMEOUT_MS,retries:opts.uploadRetries??VERSION_UPLOAD_RETRIES});if(!attempt.ok)return attempt;let upload=attempt.value,uploadRes=upload.response;if(uploadRes.status!==201){let{detail,code}=await readFailure(uploadRes);if(upload.transientFailures>0&&uploadRes.status===409&&/slot changed|already has a version/i.test(detail))return err(uploadRaceLost());if(created)await fetch(`${baseUrl}/v1/links/${link.slug}`,{method:"DELETE",headers:authorized}).catch(()=>{});return err(cloudFailure("upload",uploadRes.status,detail,code))}let parsed=await cloudJson(uploadRes,VersionUploadResponseSchema,"upload");if(!parsed.ok)return parsed;let uploaded=parsed.value;return ok({link:{slug:link.slug,visibility:link.visibility??opts.link.visibility,passwordProtected:link.passwordProtected??opts.link.password!=null},created,files:uploaded.files,bytes:uploaded.bytes,shareUrl:uploaded.url.startsWith("http")?uploaded.url:`${baseUrl}${uploaded.url}`,...uploaded.tier!==void 0?{tier:uploaded.tier}:{},...uploaded.history!==void 0?{history:uploaded.history}:{}})}async function uploadVersionWithRetry(opts){let attempts=Math.max(1,Math.floor(opts.retries)+1),transientFailures=0,lastNetworkError="unknown network error",lastTimedOut=!1;for(let attempt=1;attempt<=attempts;attempt+=1){let controller=new AbortController,timedOut=!1,timer=setTimeout(()=>{timedOut=!0,controller.abort()},Math.max(1,opts.timeoutMs));try{let response=await fetch(opts.url,{method:"POST",headers:opts.headers,body:opts.form,signal:controller.signal});if(response.status<500||attempt===attempts)return ok({response,transientFailures});transientFailures+=1,await response.body?.cancel().catch(()=>{})}catch(error){if(transientFailures+=1,lastTimedOut=timedOut,lastNetworkError=error instanceof Error?error.message:String(error),attempt===attempts){let retried=attempts>1?` after ${attempts} attempts`:"";return err(timedOut?unreachable(`timed out after ${formatDuration(opts.timeoutMs)}${retried}`,{url:opts.url,timedOut:!0}):unreachable(`version upload${retried}: ${lastNetworkError}`,{url:opts.url}))}}finally{clearTimeout(timer)}}return err(lastTimedOut?unreachable(`timed out after ${formatDuration(opts.timeoutMs)}`,{url:opts.url,timedOut:!0}):unreachable(`version upload: ${lastNetworkError}`,{url:opts.url}))}function formatDuration(ms){return ms>=1000?`${Math.round(ms/1000)}s`:`${Math.max(1,Math.round(ms))}ms`}var cloudUnhealthy=(detail)=>({kind:"CloudUnhealthy",detail}),noScreens=(root)=>({kind:"NoScreens",root}),noBoardScreens=()=>({kind:"NoBoardScreens"}),bundleInvalid=(detail)=>({kind:"BundleInvalid",detail}),teamNotFound=(requested)=>({kind:"TeamNotFound",requested}),teamAmbiguous=(requested)=>({kind:"TeamAmbiguous",requested});function describePublishError(error){switch(error.kind){case"CloudUnhealthy":return error.detail;case"NoScreens":return`no screens found in ${error.root} \u2014 is this a velloo design folder?`;case"NoBoardScreens":return"the selected boards have no screens.";case"BundleInvalid":return`velloo built an invalid design bundle and did not upload it: ${error.detail}. This is a bug \u2014 please report it.`;case"TeamNotFound":return`no team named or identified by '${error.requested}'`;case"TeamAmbiguous":return`more than one team is named '${error.requested}'; pass its UUID`;case"HttpFailure":{if(error.status===403&&/protected shares/i.test(error.detail))return`${PROTECTED_SHARES_UNAVAILABLE}. Publish publicly, or upgrade at ${PRICING_URL}`;let limit=boardLimitFrom(error);if(limit)return`${describeBoardLimit(limit)}. Run \`velloo publish --list\` to see them, or upgrade at ${PRICING_URL}`;return describeCloudError(error)}default:return describeCloudError(error)}}import{execFileSync}from"child_process";import{readFile}from"fs/promises";import{join}from"path";var DESIGN_BUNDLE_FORMAT=1,BundleScreenshotsSchema=object({cover:string().optional(),screens:record(string(),string()).optional(),boards:record(string(),string()).optional()}),DesignBundleMetaSchema=object({formatVersion:number().int().positive().optional(),title:string().optional(),screens:array(object({id:string(),name:string().optional()})).optional(),boards:array(object({id:string()})).optional(),screenshots:BundleScreenshotsSchema.optional()});var DesignBundleSchema=strictObject({formatVersion:literal(DESIGN_BUNDLE_FORMAT),title:string(),viewport:ViewportSchema,defaultLibrary:string(),libraries:record(string(),LibrarySchema),extensions:record(string(),ExtensionSchema),viewportPresets:array(ViewportPresetSchema),theme:ThemeSchema,themes:record(string(),ThemeSchema),customCss:string(),snippets:array(SnippetSchema),screens:array(ScreenSchema),boards:array(BoardSchema),annotations:record(string(),array(AnnotationSchema)),notes:record(string(),array(CanvasNoteSchema)),live:boolean(),snapshotCssPath:string(),bundlePath:string().optional(),screenshots:object({cover:string(),screens:record(string(),string()),boards:record(string(),string())}).optional()});import{homedir}from"os";import{delimiter,dirname,resolve}from"path";function designGitEnv(folder){let ceilings=[homedir()];if(managedDesignId(folder)||localDesignOf(folder))ceilings.push(dirname(resolve(folder)));let inherited=process.env.GIT_CEILING_DIRECTORIES;if(inherited)ceilings.push(inherited);return{...process.env,GIT_CEILING_DIRECTORIES:ceilings.join(delimiter)}}var MAX_SCREENSHOT_BYTES=4194304,MAX_SCREENSHOT_COUNT=120,DOWNSCALE_WIDTH=1280;function isBrowserMissing(err){return err instanceof Error&&err.name==="BrowserMissingError"}async function captureBundleScreenshots(opts){let{screens,boards,viewport,renderHtml,capture,warn,progress}=opts,selectedScreens=opts.screenIds?screens.filter((screen)=>opts.screenIds?.has(screen.id)):screens,selectedBoards=opts.boardIds?boards.filter((board)=>opts.boardIds?.has(board.id)):boards,manifest={cover:"",screens:{},boards:{}},total=selectedScreens.length+selectedBoards.filter((board)=>board.frames.length>0).length,done=0,advance=()=>{done+=1,progress?.(done,total)},shoot=async(html,vp,fullPage)=>{let png=await capture({html,viewport:vp,fullPage,deviceScaleFactor:1});if(png.byteLength>MAX_SCREENSHOT_BYTES&&DOWNSCALE_WIDTH<vp.w)png=await capture({html,viewport:vp,fullPage,deviceScaleFactor:DOWNSCALE_WIDTH/vp.w});return png.byteLength<=MAX_SCREENSHOT_BYTES?png:null},jobs=[];for(let screen of selectedScreens)jobs.push({run:async()=>{try{let png=await shoot(await renderHtml(screen),viewport,!0);if(!png)return warn(`screenshot of screen "${screen.id}" exceeds 4MB even downscaled \u2014 skipped`),null;return{kind:"screen",id:screen.id,path:`screenshots/${screen.id}.png`,bytes:png}}catch(err){if(isBrowserMissing(err))throw err;return warn(`screenshot of screen "${screen.id}" failed \u2014 skipped (${message(err)})`),null}finally{advance()}}});let screenById=new Map(screens.map((screen)=>[screen.id,screen]));for(let board of selectedBoards){if(board.frames.length===0)continue;jobs.push({run:async()=>{try{let framed=(await Promise.all(board.frames.map(async(frame)=>{let screen=screenById.get(frame.screen);return screen?{frame,html:await renderHtml(screen,board.theme,frame.scheme??"light")}:null}))).filter((entry)=>entry!==null);if(framed.length===0)return null;let composite=buildBoardComposite(framed),png=await shoot(composite.html,composite.viewport,!1);if(!png)return warn(`screenshot of board "${board.id}" exceeds 4MB even downscaled \u2014 skipped`),null;return{kind:"board",id:board.id,path:`screenshots/${board.id}.png`,bytes:png}}catch(err){if(isBrowserMissing(err))throw err;return warn(`screenshot of board "${board.id}" failed \u2014 skipped (${message(err)})`),null}finally{advance()}}})}let shotLimit=MAX_SCREENSHOT_COUNT-1,results=Array.from({length:jobs.length},()=>null),nextJob=0,completedShots=0,reservedShots=0,browserMissing=!1,worker=async()=>{while(!browserMissing&&nextJob<jobs.length&&completedShots+reservedShots<shotLimit){let index=nextJob++;reservedShots+=1;try{let shot=await jobs[index]?.run();if(shot)results[index]=shot,completedShots+=1}catch(err){if(isBrowserMissing(err))browserMissing=!0;else throw err}finally{reservedShots-=1}}},concurrency=Math.max(1,Math.min(MAX_CONCURRENT_RENDERS,Math.floor(opts.concurrency??MAX_CONCURRENT_RENDERS)));if(await Promise.all(Array.from({length:Math.min(concurrency,jobs.length)},worker)),browserMissing)return warn("no headless browser available \u2014 publishing without screenshots"),null;if(nextJob<jobs.length)warn(`screenshot limit (${MAX_SCREENSHOT_COUNT}) reached \u2014 remaining shots skipped`);let files=[];for(let shot of results){if(!shot)continue;if(files.push({path:shot.path,bytes:shot.bytes}),shot.kind==="screen")manifest.screens[shot.id]=shot.path;else manifest.boards[shot.id]=shot.path}let coverSource=selectedBoards.map((b)=>manifest.boards[b.id]).find((p)=>p!==void 0)??selectedScreens.map((s)=>manifest.screens[s.id]).find((p)=>p!==void 0);if(!coverSource)return null;let source=files.find((f)=>f.path===coverSource);if(!source)return null;return manifest.cover="screenshots/cover.png",files.push({path:manifest.cover,bytes:source.bytes}),{manifest,files}}function message(err){let msg=err instanceof Error?err.message:String(err);return msg.split(`
|
|
3
|
-
`)[0]??msg}var normalizedBoardIds=(boardIds)=>[...new Set(boardIds)].sort();function publishSlotMismatches(slot,current){let mismatches=[];if(!slot.context.contextKnown)mismatches.push("older publish has no board-selection context");if(slot.teamId!==current.teamId)mismatches.push("team differs");if(JSON.stringify(normalizedBoardIds(slot.context.boardIds))!==JSON.stringify(normalizedBoardIds(current.boardIds)))mismatches.push("board selection differs");if(slot.context.repo!==current.repo)mismatches.push("repository differs");else if(current.repo!==null){if(!slot.context.branch||!current.branch)mismatches.push("branch is unavailable");else if(slot.context.branch!==current.branch)mismatches.push("branch differs")}return mismatches}function recommendedPublishSlot(slots,current){return exactPublishSlots(slots,current)[0]??null}function exactPublishSlots(slots,current){return slots.filter((slot)=>publishSlotMismatches(slot,current).length===0).sort((left,right)=>publishedAt(right.lastPublishedAt)-publishedAt(left.lastPublishedAt))}var publishedAt=(value)=>{let parsed=value?Date.parse(value):Number.NaN;return Number.isFinite(parsed)?parsed:Number.NEGATIVE_INFINITY},PUBLISH_VIEWPORT={w:1440,h:900};function defaultPublishTitle(folderRoot){return`${localDesignOf(folderRoot)?.projectName??folderRoot.split("/").filter(Boolean).pop()} designs`}async function ensureFolderId(folder,existing,report){if(existing)return existing;let path=join(folder,".design","config.json"),raw=JSON.parse(await readFile(path,"utf8")),folderId=crypto.randomUUID();return await writeJsonAtomic(path,{...raw,folderId}),report({kind:"note",message:"assigned this folder a cloud id (.design/config.json folderId) \u2014 commit it so every clone finds the folder's share links."}),folderId}function reportProvenance(git,report){if(git.repo){report({kind:"info",message:git.branch?`source: ${git.repo} on ${git.branch}`:`source: ${git.repo} (detached HEAD \u2014 no branch recorded)`});return}report({kind:"info",message:git.branch?`source: branch ${git.branch} \u2014 no git remote, publishing without a repository`:"source: not a git repository \u2014 publishing without repository or branch"})}function gitProbe(folder){return{encoding:"utf8",stdio:["ignore","pipe","ignore"],env:designGitEnv(folder)}}function gitCommitSha(folder){try{let probe=gitProbe(folder);if(execFileSync("git",["-C",folder,"status","--porcelain"],probe).trim().length>0)return null;return execFileSync("git",["-C",folder,"rev-parse","HEAD"],probe).trim()}catch{return null}}function normalizeRemote(url){let rest=url.trim().replace(/\.git\/?$/,"");if(/^[./~]/.test(rest)||/^[a-z]:[\\/]/i.test(rest)||rest.startsWith("file://"))return null;let scp=/^(?:[\w.-]+@)?([\w.-]+):(?!\/\/)(.+)$/.exec(rest);if(scp?.[1]&&scp[2])return`${scp[1]}/${scp[2].replace(/^\/+/,"")}`;try{let parsed=new URL(rest.includes("://")?rest:`https://${rest}`);if(!parsed.hostname||!parsed.pathname||parsed.pathname==="/")return null;return`${parsed.hostname}${parsed.pathname.replace(/\/+$/,"")}`}catch{return null}}function gitContext(folder){let probe=gitProbe(folder),run=(args)=>{try{return execFileSync("git",["-C",folder,...args],probe).trim()||null}catch{return null}},branchRaw=run(["rev-parse","--abbrev-ref","HEAD"]),remote=run(["remote","get-url","origin"]);return{repo:remote?normalizeRemote(remote):null,branch:branchRaw==="HEAD"?null:branchRaw}}async function resolveTeam(baseUrl,token,requested){if(!requested)return ok(void 0);let listed=await listTeams(baseUrl,token);if(!listed.ok)return listed;let exact=listed.value.filter((team)=>team.id===requested||team.name.toLowerCase()===requested.toLowerCase());if(exact.length===0)return err(teamNotFound(requested));if(exact.length>1)return err(teamAmbiguous(requested));return ok(exact[0]?.id)}async function listTeams(baseUrl,token){let body=await cloudFetch(`${baseUrl}/v1/teams/mine`,TeamsResponseSchema,{operation:"listing teams",token});return body.ok?ok(body.value.teams):body}function selectBoards(design,boardIds){if(!boardIds||boardIds.length===0)return activeBoards(design).map(([,board])=>board);let wanted=new Set(boardIds);return orderedBoards(design).map(([,board])=>board).filter((board)=>wanted.has(board.id))}async function publishDesign(cloud,pipeline,request,report=()=>{}){let{folder:design}=pipeline,{root,config}=design;report({kind:"step",step:"check",message:"checking the cloud"});let health=await checkCloudHealth(cloud.baseUrl);if(health.status==="unreachable")return err(unreachable(health.reason,{url:cloud.baseUrl}));if(health.status==="unhealthy")return err(cloudUnhealthy(health.detail));if(design.screens.size===0)return err(noScreens(root));report({kind:"step",step:"select",message:"collecting boards"});let boards=selectBoards(design,request.boardIds),screenIds=Boolean(request.boardIds&&request.boardIds.length>0)?new Set(boards.flatMap((b)=>b.frames.map((f)=>f.screen))):null,screens=screenIds?[...design.screens.values()].filter((s)=>screenIds.has(s.id)):[...design.screens.values()];if(screens.length===0)return err(noBoardScreens());let viewport=request.viewport??PUBLISH_VIEWPORT,title=request.title?.trim()||defaultPublishTitle(root),form=new FormData,bundleFiles=0,bundleBytes=0,addFile=(path,data,type)=>{if(typeof data==="string"?data.length===0:data.byteLength===0)return report({kind:"warn",message:`skipped empty file: ${path}`}),!1;return form.append("file",new File([data],path,type?{type}:void 0)),bundleFiles+=1,bundleBytes+=typeof data==="string"?new TextEncoder().encode(data).byteLength:data.byteLength,!0},liveExt=liveExtensions(config.extensions),bundler=Object.keys(liveExt).length>0?pipeline.liveBundler??createPublishBundler(root,config):null;report({kind:"step",step:"styles",message:"compiling styles"});let snapshotCss=await pipeline.snapshotCss(),live=!1,liveCode=null;if(bundler){report({kind:"step",step:"bundle",message:"bundling live components"});let bundle=await bundler.build();for(let e of bundle.errors)report({kind:"warn",message:`live-island: ${e.message}`});if(addFile("bundle.js",bundle.code,"text/javascript"))liveCode=bundle.code,live=!0}report({kind:"step",step:"capture",message:"capturing previews"});let shots=await withAssetServer(root,liveCode,(baseHref)=>{let htmlCache=new Map,renderHtml=async(screen,themeName,scheme="light")=>{let theme=(themeName?design.themes.get(themeName):void 0)??design.theme,key=`${screen.id}\x00${theme.name}\x00${scheme}`,cached=htmlCache.get(key);if(cached)return cached;let rendering=renderScreen(screen,theme,{viewport,snapshotCss,registry:registryForScreen(screen,pipeline.providers,pipeline.defaultProvider,config.extensions??{}),renderPass:renderPassForScreen(screen,pipeline.providers,pipeline.defaultProvider,theme),snippets:design.snippets,customCss:design.customCss,dark:scheme==="dark",baseHref,...live?{liveBundleUrl:"/live/bundle.js"}:{}}).then(({html})=>html);return htmlCache.set(key,rendering),rendering};return captureBundleScreenshots({screens,boards,...request.screenshotSelection?{screenIds:request.screenshotSelection.screenIds,boardIds:request.screenshotSelection.boardIds}:{},viewport,renderHtml,capture:async(req)=>(await captureScreenshot({html:req.html,viewport:req.viewport,fullPage:req.fullPage,deviceScaleFactor:req.deviceScaleFactor})).png,warn:(message)=>report({kind:"warn",message}),progress:(done,total)=>report({kind:"capture",done,total})})});for(let f of shots?.files??[])addFile(f.path,f.bytes,"image/png");let annotations=Object.fromEntries([...design.annotations].filter(([screenId,list])=>list.length>0&&screens.some((s)=>s.id===screenId))),notes=Object.fromEntries([...design.notes].filter(([boardId,list])=>list.length>0&&boards.some((b)=>b.id===boardId))),designDoc={formatVersion:DESIGN_BUNDLE_FORMAT,title,viewport,defaultLibrary:config.defaultLibrary,libraries:config.libraries,extensions:config.extensions??{},viewportPresets:config.viewportPresets??[],theme:design.theme,themes:Object.fromEntries(design.themes),customCss:design.customCss,snippets:[...design.snippets.values()],screens,boards,annotations,notes,live,snapshotCssPath:"snapshot.css",...live?{bundlePath:"bundle.js"}:{},...shots?{screenshots:shots.manifest}:{}},validated=DesignBundleSchema.safeParse(designDoc);if(!validated.success)return err(bundleInvalid(prettifyError(validated.error)));addFile("design.json",JSON.stringify(designDoc),"application/json"),addFile("snapshot.css",snapshotCss||`/* this folder uses no CSS framework */
|
|
4
|
-
`,"text/css");let assetRefs=new Set,assetRe=/\/assets\/[A-Za-z0-9._@\-/]+/g;for(let source of[...screens,...design.snippets.values()])for(let m of JSON.stringify(source).matchAll(assetRe))assetRefs.add(m[0]);for(let ref of assetRefs){let rel=ref.replace(/^\//,"");try{addFile(rel,await readFile(join(root,rel)))}catch{report({kind:"warn",message:`asset not found: ${rel}`})}}let commitSha=gitCommitSha(root);if(commitSha)form.append("commitSha",commitSha);let git=request.provenance??gitContext(root);if(reportProvenance(git,report),git.repo)form.append("gitRepo",git.repo);if(git.branch)form.append("gitBranch",git.branch);let folderId=await ensureFolderId(root,config.folderId,report);report({kind:"step",step:"upload",message:`uploading ${bundleFiles} file${bundleFiles===1?"":"s"} (${formatBytes(bundleBytes)})`});let uploaded=await uploadLinkBundle({baseUrl:cloud.baseUrl,token:cloud.token,link:{...request.destination.slug?{slug:request.destination.slug}:{},folderId,publishMode:request.destination.mode,...request.destination.mode==="update"?{expectedVersionId:request.destination.expectedVersionId}:{},title,visibility:request.visibility,...request.teamId?{teamId:request.teamId}:{},...request.password?{password:request.password}:{},...request.passwordExpiresAt?{passwordExpiresAt:request.passwordExpiresAt}:{}},form});if(!uploaded.ok)return uploaded;let upload=uploaded.value;return ok({shareUrl:upload.shareUrl,visibility:upload.link.visibility,passwordProtected:upload.link.passwordProtected,files:upload.files,bytes:upload.bytes,screenshots:shots?.files.length??0,boards:boards.length,screens:screens.length,commitSha,created:upload.created,...upload.tier!==void 0?{tier:upload.tier}:{},...upload.history!==void 0?{history:upload.history}:{}})}function formatBytes(bytes){if(bytes>=1048576)return`${(bytes/1048576).toFixed(1)} MB`;if(bytes>=1024)return`${Math.round(bytes/1024)} KB`;return`${bytes} B`}function createPublishBundler(root,config){return new LiveBundler(root,()=>config,()=>liveExtensions(config.extensions),!0,!0)}function publishedDesignSubtitle(design){let published=design.lastPublishedAt?`Published ${design.lastPublishedAt}`:"Publish time unavailable",publisher=design.ownerEmail?.trim()?`by ${design.ownerEmail.trim()}`:"publisher unavailable",repo=design.git?.repo?.trim(),branch=design.git?.branch?.trim(),source=repo?`repo ${repo}${branch?` (${branch})`:""}`:"repository unavailable";return`${published} \xB7 ${publisher} \xB7 ${source}`}async function listPublishedDesigns(opts){let body=await cloudFetch(`${opts.baseUrl}/v1/links`,PublishedDesignsResponseSchema,{operation:"listing published designs",token:opts.token});if(!body.ok)return body;return ok((body.value.links??[]).filter((link)=>link.published).map((link)=>({...link,url:link.url.startsWith("http")?link.url:`${opts.baseUrl}${link.url}`})))}async function unpublishDesign(opts){let res=await fetch(`${opts.baseUrl}/v1/links/${encodeURIComponent(opts.slug)}`,{method:"DELETE",headers:{authorization:`Bearer ${opts.token}`}}).catch((error)=>error);if(!(res instanceof Response))return err(unreachable(res,{url:opts.baseUrl}));if(!res.ok)return err(await httpFailureFrom("unpublishing the design",res));return ok(void 0)}
|
|
5
|
-
export{publishedDesignSubtitle,listPublishedDesigns,unpublishDesign,listPublishDestinations,designGitEnv,describePublishError,recommendedPublishSlot,exactPublishSlots,PUBLISH_VIEWPORT,gitContext,resolveTeam,listTeams,publishDesign,createPublishBundler};
|
package/chunk-aapybh30.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isCancel,confirm,select,FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import{capturesDir,sessionStatePath,captureDir,listCaptures,deleteCapture,isSafeCaptureId,HeadedBrowserMissingError,startCaptureSession}from"./chunk-w5rzk6ms.js";import"./chunk-bk8b7f9a.js";import{loadDesignFolder}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import{fail}from"./chunk-s23gtejf.js";import{installChromiumInteractive}from"./chunk-k6ferbam.js";import{openUrl}from"./chunk-hggap8fq.js";import"./chunk-1bywxgc5.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{join}from"path";var import_picocolors=__toESM(require_picocolors(),1);var CTRL_C=3,LOOPBACK=/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?$/i;function normalizeCaptureUrl(input){let raw=input.trim();if(raw==="")return null;let hasScheme=/^[a-z][a-z0-9+.-]*:\/\//i.test(raw),host=raw.split(/[/?#]/,1)[0]??"",candidate=hasScheme?raw:`${LOOPBACK.test(host)?"http":"https"}://${raw}`;try{let url=new URL(candidate);if(url.protocol!=="http:"&&url.protocol!=="https:")return null;if(url.hostname==="")return null;return url.toString()}catch{return null}}function bindKeys(handlers){let stdin=process.stdin;if(!stdin.isTTY)return()=>{};stdin.setRawMode(!0),stdin.resume(),stdin.setEncoding("utf8");let onData=(key)=>{if(key==="c")handlers.page();else if(key==="t")handlers.theme();else if(key==="l")handlers.list();else if(key==="q"||key.charCodeAt(0)===CTRL_C)handlers.quit()};return stdin.on("data",onData),()=>{if(stdin.off("data",onData),stdin.isTTY)stdin.setRawMode(!1);stdin.pause()}}function when(iso){let d=new Date(iso);if(Number.isNaN(d.getTime()))return iso;return d.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function describe(m){let what=m.themeOnly?"theme only":`${m.nodeCount} nodes, ${m.assetCount} assets`;return`${m.title||m.finalUrl||m.url} ${import_picocolors.default.dim(`\u2014 ${what}, ${when(m.capturedAt)}`)}`}function printCaptures(captures,dir){if(console.log(""),captures.length===0){console.log(import_picocolors.default.dim(" No captures yet. Run `velloo capture <url>` to make one.")),console.log("");return}console.log(` ${import_picocolors.default.bold(`${captures.length} capture${captures.length===1?"":"s"}`)}`),console.log(import_picocolors.default.dim(` ${dir}`)),console.log("");for(let m of captures)console.log(` ${import_picocolors.default.cyan(m.id)} ${describe(m)}`),console.log(import_picocolors.default.dim(` ${m.finalUrl||m.url}`));console.log("")}async function browseCaptures(root,folderId){let dir=capturesDir(root,folderId),captures=listCaptures(root,folderId);if(!process.stdin.isTTY||captures.length===0){printCaptures(captures,dir);return}for(;;){if(captures=listCaptures(root,folderId),captures.length===0){console.log(import_picocolors.default.dim(`
|
|
3
|
-
No captures left.
|
|
4
|
-
`));return}let picked=await select({message:`${captures.length} capture${captures.length===1?"":"s"} for this folder`,options:[...captures.map((m)=>({value:m.id,label:describe(m),hint:m.finalUrl||m.url})),{value:"__done",label:import_picocolors.default.dim("Done")}]});if(isCancel(picked)||picked==="__done")return;let manifest=captures.find((m)=>m.id===picked);if(!manifest)continue;let action=await select({message:manifest.title||manifest.id,options:[...manifest.files.includes("page.png")?[{value:"open",label:"Open the screenshot"}]:[],{value:"details",label:"Show what it contains"},{value:"delete",label:import_picocolors.default.red("Delete this capture")},{value:"back",label:import_picocolors.default.dim("Back")}]});if(isCancel(action)||action==="back")continue;if(action==="open"){await openUrl(`file://${join(captureDir(root,manifest.id,folderId),"page.png")}`);continue}if(action==="details"){console.log(""),console.log(` ${import_picocolors.default.bold(manifest.id)}`),console.log(` url ${manifest.finalUrl||manifest.url}`),console.log(` captured ${when(manifest.capturedAt)}`),console.log(` viewport ${manifest.viewport.w}\xD7${manifest.viewport.h}`),console.log(` nodes ${manifest.nodeCount}`),console.log(` assets ${manifest.assetCount}`),console.log(` files ${manifest.files.join(", ")}`),console.log(import_picocolors.default.dim(` ${captureDir(root,manifest.id,folderId)}`)),console.log(""),console.log(import_picocolors.default.dim(` verify a screen against it: compare_to_url { captureId: "${manifest.id}" }`)),console.log("");continue}if(action==="delete"){let sure=await confirm({message:`Delete ${manifest.title||manifest.id}? This can't be undone.`,initialValue:!1});if(isCancel(sure)||!sure)continue;deleteCapture(root,manifest.id,folderId),console.log(import_picocolors.default.dim(` deleted ${manifest.id}`))}}}var capture_default=defineCommand({meta:{name:"capture",description:"open a browser, log in, and capture pages as evidence for the agent"},args:{url:{type:"positional",required:!1,description:"Page to open the browser on, e.g. http://localhost:3000/dashboard"},folder:{type:"string",description:FOLDER_ARG_DESCRIPTION},list:{type:"boolean",default:!1,description:"Browse stored captures instead of opening a browser (interactive on a TTY)"},delete:{type:"string",description:"Delete a capture by id, or `all` to clear every capture for this folder"}},async run({args}){let folder=await resolveDesignFolder(args.folder,"capture"),design=await loadDesignFolder(folder),folderId=design.config.folderId;if(args.delete!==void 0){let id=args.delete.trim();if(id==="all"){let all=listCaptures(design.root,folderId);if(all.length===0){console.log(import_picocolors.default.dim("velloo capture: no captures to delete."));return}if(process.stdin.isTTY){let sure=await confirm({message:`Delete all ${all.length} captures for this folder? This can't be undone.`,initialValue:!1});if(isCancel(sure)||!sure){console.log(import_picocolors.default.dim(" nothing deleted."));return}}for(let m of all)deleteCapture(design.root,m.id,folderId);console.log(`velloo capture: deleted ${all.length} captures.`);return}if(!isSafeCaptureId(id))fail("capture",`not a capture id: ${args.delete}`);if(!deleteCapture(design.root,id,folderId))fail("capture",`no capture "${id}" for this folder \u2014 run \`velloo capture --list\`.`);console.log(`velloo capture: deleted ${id}.`);return}if(args.list){await browseCaptures(design.root,folderId);return}let url;if(args.url!==void 0){let normalized=normalizeCaptureUrl(args.url);if(normalized===null)fail("capture",`not a page that can be captured: ${args.url} (expected an http(s) URL)`);url=normalized}let statePath=url?sessionStatePath(design.root,new URL(url).origin,folderId):void 0;console.log(""),console.log(` ${import_picocolors.default.bold("velloo capture")}`),console.log(import_picocolors.default.dim(` A browser window opens. Log in and navigate wherever you need \u2014 then use the
|
|
5
|
-
`+" velloo toolbar in the page (or the keys below) to capture what the agent should see.")),console.log(""),console.log(import_picocolors.default.dim(` ${import_picocolors.default.cyan("c")} capture page ${import_picocolors.default.cyan("t")} capture theme ${import_picocolors.default.cyan("l")} list ${import_picocolors.default.cyan("q")} done`)),console.log("");let made=[],onCapture=(m)=>{made.push(m);let what=m.themeOnly?"theme":`${m.nodeCount} nodes, ${m.assetCount} assets`;console.log(` ${import_picocolors.default.green("\u2713")} ${m.title||m.url} ${import_picocolors.default.dim(`(${what}) \u2192 ${m.id}`)}`)},start=async()=>startCaptureSession({folderRoot:design.root,...folderId?{folderId}:{},...url?{url}:{},...statePath?{sessionStatePath:statePath}:{},onCapture,onStatus:(message)=>console.log(import_picocolors.default.dim(` ${message}`))}),session;try{session=await start()}catch(err){if(!(err instanceof HeadedBrowserMissingError))throw err;if(!process.stdin.isTTY)fail("capture",err.message);console.log(""),console.log(` ${import_picocolors.default.yellow("\u26A0")} ${err.message}`);let proceed=await confirm({message:"Download the full browser now? (~300MB, one-time)",initialValue:!0});if(isCancel(proceed)||!proceed)fail("capture","no browser available for a capture session.");if(!await installChromiumInteractive())fail("capture","the browser isn't usable yet \u2014 see the output above.");session=await start()}let report=(e)=>{console.log(import_picocolors.default.red(` capture failed: ${e instanceof Error?e.message:String(e)}`))},unbind=bindKeys({page:()=>{session.capturePage().catch(report)},theme:()=>{session.captureTheme().catch(report)},list:()=>{if(console.log(import_picocolors.default.dim(` on: ${session.currentUrl()||"(no page)"}`)),made.length===0)console.log(import_picocolors.default.dim(" nothing captured yet"));for(let m of made)console.log(import_picocolors.default.dim(` ${m.id} ${m.title||m.url}`))},quit:()=>{session.close()}});if(await session.finished,unbind(),console.log(""),made.length===0)console.log(` ${import_picocolors.default.dim("No captures made.")}`);else console.log(` ${import_picocolors.default.green("\u2713")} ${made.length} capture${made.length===1?"":"s"} saved`),console.log(import_picocolors.default.dim(` ${capturesDir(design.root,folderId)}`)),console.log(""),console.log(import_picocolors.default.dim(" The agent can read these with list_captures / get_capture,")),console.log(import_picocolors.default.dim(" and verify a screen against one with compare_to_url { captureId }."));if(statePath)console.log(""),console.log(import_picocolors.default.dim(" Session cookies for this app were saved to:")),console.log(import_picocolors.default.dim(` ${statePath}`)),console.log(import_picocolors.default.dim(` Scoped to that site only (third-party sign-in cookies are dropped), outside your
|
|
6
|
-
repo so it can't be committed or published, and it expires in 14 days.`));console.log("")}});export{capture_default as default};
|
package/chunk-bjnhhsak.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isCancel,select,FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import{closePooledBrowser}from"./chunk-w5rzk6ms.js";import"./chunk-bk8b7f9a.js";import{writeText,findFrame,exportFilename,exportFramePng,exportBoardPng,exportFramePdf,exportBoardPdf,exportScreenHtml,exportScreenPng,exportScreenPdf,exportFrameHtml,exportBoardHtml,screensForExportTarget}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import{fail}from"./chunk-s23gtejf.js";import{captureWithBrowserSetup}from"./chunk-k6ferbam.js";import{confirmRenderFailures}from"./chunk-g02nd9hn.js";import{loadPipeline}from"./chunk-kxk5x7g6.js";import{withAssetServer}from"./chunk-9vg3yafz.js";import"./chunk-1bywxgc5.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."},folder:{type:"string",description:FOLDER_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 resolveDesignFolder(args.folder,"export"),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};
|
package/chunk-dt03awr1.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{CHROMIUM_INSTALL_ARGV,CHROMIUM_FULL_INSTALL_ARGV,CHROMIUM_DEPS_INSTALL_ARGV}from"./chunk-w5rzk6ms.js";import"./chunk-bk8b7f9a.js";import{fail}from"./chunk-s23gtejf.js";import{defineCommand}from"./chunk-2smsg2ct.js";async function run(argv){let code=await Bun.spawn([...argv],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited;if(code!==0)fail("browser",`browser setup exited with status ${code}`)}var browser_default=defineCommand({meta:{name:"browser",description:"Install the optional browser used for screenshots"},args:{action:{type:"positional",required:!1,default:"install",description:"Action (install)"},full:{type:"boolean",default:!1,description:"Install full Chromium instead of the smaller headless shell"},"with-deps":{type:"boolean",default:!1,description:"Also install required Linux system packages (may use sudo)"}},async run({args}){if(args.action!=="install")fail("browser",`unknown action "${args.action}"; expected install`);if(args["with-deps"]&&process.platform==="linux")await run(CHROMIUM_DEPS_INSTALL_ARGV);await run(args.full?CHROMIUM_FULL_INSTALL_ARGV:CHROMIUM_INSTALL_ARGV)}});export{browser_default as default};
|
package/chunk-erwfk47h.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import"./chunk-bk8b7f9a.js";import{localDesignOf}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import{FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import{AGENT_IDS,PROJECT_AGENT_IDS,GLOBAL_AGENT_IDS,resolveProjectRoot,DEFAULT_MCP_URL,MANUAL_AGENT_ID,manualSetupText,askAgentWiring,localDesignScopeProblem,connect}from"./chunk-1gx45384.js";import"./chunk-65wb0g7d.js";import{DesignFolderFormatError,assertFolderFormatCurrent}from"./chunk-k784090q.js";import{fail}from"./chunk-s23gtejf.js";import{createProgress}from"./chunk-79ykzywe.js";import"./chunk-1bywxgc5.js";import"./chunk-2z0k59hz.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{resolve}from"path";var import_picocolors=__toESM(require_picocolors(),1);var connect_default=defineCommand({meta:{name:"connect",description:"Wire the velloo MCP server into your AI coding agent's config"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},agent:{type:"string",description:`Comma-separated agents: ${AGENT_IDS.join(", ")}, manual \u2014 print the config for any other agent (default ${PROJECT_AGENT_IDS.join(",")})`},projectRoot:{type:"string",description:"Where to write the config (default: the velloo.json root that registers the folder, else the nearest package.json above it)"},http:{type:"boolean",default:!1,description:"Wire the HTTP transport (agent dials a running server) instead of stdio"},mcpUrl:{type:"string",description:`MCP server URL for --http (default ${DEFAULT_MCP_URL})`},skill:{type:"boolean",default:!0,description:"Install the velloo-design Claude Code skill into .claude/skills"}},async run({args}){let folder=await resolveDesignFolder(args.folder,"connect",{interactive:!0});try{assertFolderFormatCurrent(folder)}catch(err){if(!(err instanceof DesignFolderFormatError))throw err;console.log(import_picocolors.default.yellow(`\u26A0 ${err.message.slice(8)}`))}let interactive=Boolean(process.stdin.isTTY),agents,manual=!1,local=localDesignOf(folder)!==null;if(args.agent){agents=args.agent.split(",").map((s)=>s.trim()).filter(Boolean);let problem=localDesignScopeProblem(folder,agents);if(problem)fail("connect",problem)}else if(interactive){let wiring=await askAgentWiring({projectRoot:await resolveProjectRoot(folder),globalOnly:local});if(wiring===null)fail("connect","cancelled.");if(wiring.agents.length===0&&!wiring.manual){console.log(import_picocolors.default.dim("No agents selected \u2014 nothing wired."));return}manual=wiring.manual,agents=wiring.agents}else agents=local?GLOBAL_AGENT_IDS:PROJECT_AGENT_IDS;if(agents.includes(MANUAL_AGENT_ID))manual=!0,agents=agents.filter((id)=>id!==MANUAL_AGENT_ID);if(manual){console.log(""),console.log(import_picocolors.default.bold(" Manual MCP setup"));for(let line of manualSetupText().split(`
|
|
3
|
-
`))console.log(` ${line}`);console.log("")}if(agents.length===0)return;let progress=createProgress();progress.start("connecting agent");let result;try{result=await connect({designFolder:folder,agents,projectRoot:args.projectRoot?resolve(args.projectRoot):void 0,transport:args.http?"http":"stdio",mcpUrl:args.mcpUrl,installSkill:args.skill})}catch(error){throw progress.fail("agent connection failed"),error}if(result.unknownAgents.length>0)progress.fail("agent connection failed"),fail("connect",`unknown agent(s): ${result.unknownAgents.join(", ")}. Valid: ${AGENT_IDS.join(", ")}.`);progress.succeed("connected agent"),console.log(""),console.log(import_picocolors.default.green("\u2713 Connected velloo to your agent.")),console.log("");for(let c of result.configs)console.log(` ${c.action==="created"?"wrote ":"updated "} ${import_picocolors.default.cyan(c.path)}`);if(result.plugin)console.log(` plugin ${import_picocolors.default.cyan("velloo@velloo")} ${import_picocolors.default.dim(`(skills + commands + subagents \u2014 local marketplace at ${result.plugin.marketplaceDir})`)}`);for(let s of result.skills??[])console.log(` skill ${import_picocolors.default.cyan(s.path??s.name)}`);if(result.geminiExtension)console.log(` gemini ${import_picocolors.default.cyan(result.geminiExtension.dir)} ${result.geminiExtension.linked?import_picocolors.default.dim("(linked)"):import_picocolors.default.dim(`(link it: gemini extensions link ${result.geminiExtension.dir})`)}`);if(result.cursorRules?.installed&&result.cursorRules.path)console.log(` rule ${import_picocolors.default.cyan(result.cursorRules.path)}`);let folderArg=args.folder?` ${args.folder}`:"";if(console.log(""),console.log(import_picocolors.default.bold(" Next")),result.transport==="http")console.log(` 1. ${import_picocolors.default.cyan(`velloo mcp --http${folderArg}`)} ${import_picocolors.default.dim("\u2014 starts the MCP server your agent dials")}`),console.log(" 2. Restart your agent so it loads the new MCP config.");else console.log(` 1. Restart your agent so it loads the new MCP config ${import_picocolors.default.dim("\u2014 it starts velloo itself")}.`),console.log(` 2. ${import_picocolors.default.cyan(`velloo run${folderArg}`)} ${import_picocolors.default.dim("\u2014 optional: open the canvas to watch")}`);console.log("")}});export{connect_default as default};
|
package/chunk-nfr3q7mg.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{ThemeSchema}from"./chunk-bk8b7f9a.js";import{colorizeDiff,emitTheme,emitNativeTheme,loadDesignFolder,resolveProviders}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import{FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import"./chunk-s23gtejf.js";import{detectHost}from"./chunk-56vqqr8s.js";import"./chunk-1bywxgc5.js";import{defineCommand}from"./chunk-2smsg2ct.js";import{readFile}from"fs/promises";import{isAbsolute,join,resolve}from"path";import{stdin,stdout}from"process";import{createInterface}from"readline/promises";async function readMaybe(path){try{return await readFile(path,"utf8")}catch{return}}async function themeEmitter(folderRoot,theme,outDir,cssOnly,tailwind3){let design=await loadDesignFolder(folderRoot),{defaultProvider}=await resolveProviders(design.config,folderRoot),adapter=defaultProvider;if(adapter.themeToNative&&adapter.themeModule){let toNative=adapter.themeToNative.bind(adapter),spec=adapter.themeModule;return{native:!0,produce:(apply)=>emitNativeTheme(toNative(theme),{spec,outputDir:outDir,apply,...theme.colorsDark?{darkThemeOptions:toNative(theme,!0)}:{},sourceTheme:theme})}}let customCss=await readMaybe(join(folderRoot,"theme","custom.css"));return{native:!1,produce:(apply)=>emitTheme(theme,{outputDir:outDir,apply,cssOnly,...customCss?{customCss}:{},...tailwind3?{tailwindMajor:3}:{}})}}var theme_export_default=defineCommand({meta:{name:"theme:export",description:"Export DTCG tokens.json plus the framework theme in diff mode \u2014 Tailwind v4 globals.css by default, or v3 CSS + preset when detected"},args:{to:{type:"string",required:!0,description:"Target app directory (writes <to>/app/globals.css and <to>/tailwind.config.ts)"},folder:{type:"string",description:FOLDER_ARG_DESCRIPTION},theme:{type:"string",description:"Path to theme JSON (default: <folder>/theme/default.json)"},apply:{type:"boolean",description:"Write files instead of printing diffs. Default: dry-run."},"css-only":{type:"boolean",description:"Skip tailwind.config.ts (CSS-only export)."},"force-v4":{type:"boolean",description:"Emit the v4 artifacts even when the target app looks like Tailwind v3."}},async run({args}){let folderRoot=await resolveDesignFolder(args.folder,"theme:export"),themePath=args.theme?resolve(args.theme):join(folderRoot,"theme","default.json"),outDir=isAbsolute(args.to)?args.to:resolve(args.to),themeJson=JSON.parse(await readFile(themePath,"utf8")),theme=ThemeSchema.parse(themeJson),tailwind3=!args["force-v4"]&&detectHost(outDir).tailwindMajor===3,{native,produce}=await themeEmitter(folderRoot,theme,outDir,Boolean(args["css-only"]),tailwind3);if(!native&&tailwind3)console.log("velloo theme:export: target looks like Tailwind v3 \u2014 emitting velloo-theme.css + velloo.preset (pass --force-v4 for the v4 artifacts).");let result=await produce(Boolean(args.apply)),useColor=stdout.isTTY===!0,anyChange=!1;for(let warning of result.warnings)console.error(`velloo theme:export: warning: ${warning}`);for(let file of result.files){if(file.diff.identical){console.log(`velloo theme:export: ${file.path} is already up to date.`);continue}if(anyChange=!0,file.applied)console.log(`velloo theme:export: wrote ${file.path}`);else{let rendered=useColor?colorizeDiff(file.diff.diff):file.diff.diff;stdout.write(`${rendered}
|
|
3
|
-
`),stdout.write(`Would write to: ${file.path}
|
|
4
|
-
|
|
5
|
-
`)}}for(let note of result.notes)console.log(`velloo theme:export: ${note}`);if(!anyChange||args.apply)return;if(!stdin.isTTY){console.log("(non-TTY) re-run with --apply to write the files.");return}let rl=createInterface({input:stdin,output:stdout}),answer=(await rl.question("Apply all? (y/N) ")).trim().toLowerCase();if(rl.close(),answer==="y"||answer==="yes"){let final=await produce(!0);for(let file of final.files)if(file.applied)console.log(`velloo theme:export: wrote ${file.path}`)}else console.log("velloo theme:export: skipped (no changes written).")}});export{theme_export_default as default};
|
package/chunk-nsqs1bqf.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import"./chunk-bk8b7f9a.js";import"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import"./chunk-65wb0g7d.js";import{assertLoopbackHost,daemonRoot,isLive,ensureDaemon,stopDaemon}from"./chunk-k784090q.js";import{fail}from"./chunk-s23gtejf.js";import{FOLDER_ARG_DESCRIPTION,hasDesignConfig,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import{createProgress}from"./chunk-79ykzywe.js";import{openUrl}from"./chunk-hggap8fq.js";import{findProjects}from"./chunk-1bywxgc5.js";import"./chunk-2z0k59hz.js";import{traceEnabled}from"./chunk-6tx68d90.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{basename,join}from"path";var import_picocolors=__toESM(require_picocolors(),1);function actionForRunKey(key,targetCount=1){if(key==="b")return{kind:"background"};if(key==="q"||key==="\x03")return{kind:"stop"};if(targetCount<=1)return key==="o"?{kind:"open"}:null;if(key==="a"||key==="o")return{kind:"open"};if(/^[1-9]$/.test(key)){let index=Number(key);return index<=targetCount?{kind:"open",index}:null}return null}function shouldStayForeground(opts){return!opts.background&&opts.stdinIsTTY}function bindRunKeys(onKey){let stdin=process.stdin;if(!stdin.isTTY)return()=>{};stdin.setRawMode(!0),stdin.resume(),stdin.setEncoding("utf8");let onData=(chunk)=>{onKey(chunk)};return stdin.on("data",onData),()=>{if(stdin.off("data",onData),stdin.isTTY)stdin.setRawMode(!1);stdin.pause()}}var LIVE_POLL_MS=2000;async function waitInForeground(opts){return await new Promise((resolve)=>{let settled=!1,unbind=()=>{},timer,finish=(outcome)=>{if(settled)return;if(settled=!0,unbind(),timer!==void 0)clearInterval(timer);process.off("SIGINT",onStop),process.off("SIGTERM",onStop),resolve(outcome)},onStop=()=>finish("stop");unbind=bindRunKeys((key)=>{let action=actionForRunKey(key,opts.targetCount??1);if(!action)return;if(action.kind==="open")opts.onOpen(action.index);else finish(action.kind)}),process.on("SIGINT",onStop),process.on("SIGTERM",onStop),timer=setInterval(()=>{opts.isLive().then((live)=>{if(!live)finish("died")})},LIVE_POLL_MS)})}import{resolve,sep}from"path";async function resolveRunTargets(arg,opts={}){let cwd=resolve(opts.cwd??"."),single=async()=>{let folder=await resolveDesignFolder(arg,"run",{interactive:!0,requireConfig:!0,cwd});return[{name:await projectNameFor(folder,cwd),folder}]};if(arg)return single();let found;try{found=await findProjects(cwd)}catch{return single()}if(!found||found.folders.size<2)return single();for(let[name,folder]of found.folders)if(cwd===folder||cwd.startsWith(folder+sep))return[{name,folder}];let targets=[];for(let[name,folder]of found.folders)if(await hasDesignConfig(folder))targets.push({name,folder:await resolveDesignFolder(name,"run",{cwd,requireConfig:!0})});if(targets.length===0)return single();if(targets.length===1)return targets;let defaultProject=found.defaultProject;if(defaultProject)targets.sort((a,b)=>a.name===defaultProject?-1:b.name===defaultProject?1:0);return targets}async function projectNameFor(folder,cwd){try{let found=await findProjects(cwd);if(!found)return;for(let[name,path]of found.folders)if(path===folder)return name}catch{}return}function label(target){return target.name??basename(target.folder)}function labelWidth(running){return Math.max(...running.map(({target})=>label(target).length))}function printBackgroundStay(folderArg){console.log(`velloo: it keeps running in the background \u2014 awake while the canvas is open or an agent is connected. Stop it anytime with \`velloo stop${folderArg}\`.`)}var run_default=defineCommand({meta:{name:"run",description:"Open the canvas for a design folder and stay in the foreground (starts a persistent canvas if none is running)"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},port:{type:"string",description:"Preferred canvas port when starting fresh (default: the port this folder ran on last, else 7300)"},host:{type:"string",description:"Loopback bind hostname: 127.0.0.1 (default), localhost or ::1"},open:{type:"boolean",default:!1,description:"Open the canvas in your browser"},background:{type:"boolean",default:!1,description:"Leave the canvas running and return to the shell (the default when stdin is not a TTY)"}},async run({args}){assertLoopbackHost(args.host??"127.0.0.1");let targets=await resolveRunTargets(args.folder,{}),preferredPort=args.port?Number(args.port):void 0;if(preferredPort!==void 0&&(!Number.isFinite(preferredPort)||preferredPort<0))fail("run",`invalid --port ${JSON.stringify(args.port)}`);let progress=createProgress();progress.start(targets.length>1?"starting canvases":"starting canvas");let spawned=0,running=[];try{for(let[index,target]of targets.entries()){if(targets.length>1)progress.step(`starting ${label(target)}`);let rec=await ensureDaemon(target.folder,{...preferredPort!==void 0&&index===0?{preferredPort}:{},host:args.host,onSpawn:()=>{spawned++,progress.step(`waiting for ${label(target)}`)}});running.push({target,rec})}progress.succeed(spawned===0?targets.length>1?"connected to running canvases":"connected to running canvas":targets.length>1?`started ${targets.length} canvases`:"started canvas")}catch(error){throw progress.fail("could not start canvas"),error}let folderArg=args.folder?` ${args.folder}`:"",first=running[0];if(running.length===1)console.log(`velloo: canvas at ${first.rec.canvasUrl}`);else{console.log("velloo: canvases");for(let{target,rec}of running)console.log(` ${import_picocolors.default.bold(label(target).padEnd(labelWidth(running)))} ${rec.canvasUrl}`)}if(traceEnabled())if(spawned>0)console.log(`velloo: \u29BF trace recording ON \u2014 agent MCP calls tape to ${join(first.target.folder,".velloo","trace")} (view with \`velloo trace\`)`);else console.log(`velloo: VELLOO_TRACE is set, but a canvas was already running \u2014 recording is NOT active on it. Run \`velloo stop${folderArg}\`, then re-run to record. The agent must also connect through this same (trace-enabled) velloo.`);let foreground=shouldStayForeground({background:Boolean(args.background),stdinIsTTY:Boolean(process.stdin.isTTY)});if(foreground){if(console.log(""),running.length>1)running.forEach(({target},i)=>{console.log(` ${import_picocolors.default.cyan(String(i+1))} open ${label(target)}`)}),console.log(` ${import_picocolors.default.cyan("a")} open all`);else console.log(` ${import_picocolors.default.cyan("o")} open the browser`);console.log(` ${import_picocolors.default.cyan("b")} run in the background`),console.log(` ${import_picocolors.default.cyan("q")} stop`),console.log("")}else printBackgroundStay(folderArg);let openTarget=(index)=>{let picked=index===void 0?running:[running[index-1]];for(let entry of picked)if(entry)openUrl(entry.rec.canvasUrl)};if(args.open)openTarget(running.length>1?void 0:1);if(!foreground)return;let outcome=await waitInForeground({isLive:async()=>{for(let{rec}of running)if(!await isLive(rec))return!1;return!0},onOpen:openTarget,targetCount:running.length});if(outcome==="background"){printBackgroundStay(folderArg);return}if(outcome==="died"){console.log("velloo: canvas exited.");return}for(let{target}of running){let root=daemonRoot(target.folder),stopped=await stopDaemon(root);console.log(stopped?`velloo: stopped canvas for ${root}`:`velloo: no canvas running for ${root}`)}}});export{run_default as default};
|
package/chunk-pphgrsxa.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{registry2,loadManifest2}from"./chunk-t2ttkxe9.js";import"./chunk-d385435m.js";import{snapshotVersion2,entryCssPath2,componentsDir2}from"./chunk-jnsfgtn9.js";export{componentsDir2 as componentsDir,entryCssPath2 as entryCssPath,loadManifest2 as loadManifest,registry2 as registry,snapshotVersion2 as snapshotVersion};
|
package/chunk-qpvj6kzq.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{isCancel,confirm,FOLDER_ARG_DESCRIPTION,hasDesignConfig,resolveDesignFolder,resolveDesignLocation}from"./chunk-8ssr8a8w.js";import"./chunk-bk8b7f9a.js";import{managedDesignId,localDesignOf,removeLocalDesign,loadDesignFolder}from"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import"./chunk-65wb0g7d.js";import{daemonRoot,readLock,isLive,stopDaemon}from"./chunk-k784090q.js";import{fail}from"./chunk-s23gtejf.js";import"./chunk-k6ferbam.js";import"./chunk-1yhc252b.js";import{recordedAppRoot,planAppRootChange,applyAppRootChange,promptAppRootChoice,planRelocation,relocateDesign,displayPath,runInit2}from"./chunk-hs2j6s1v.js";import"./chunk-jnsfgtn9.js";import"./chunk-1gx45384.js";import"./chunk-cep3ktr3.js";import"./chunk-b7j86xq7.js";import"./chunk-56vqqr8s.js";import"./chunk-7dggmqwq.js";import"./chunk-y0zxzefg.js";import"./chunk-fgw3hp2v.js";import{findManifest,findProjects,unregisterProject,checkoutRoot,isWithin,registerLocalDesign}from"./chunk-1bywxgc5.js";import"./chunk-2z0k59hz.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 design folders"},async run(){let cwd=resolve("."),found=await findProjects(cwd).catch((err)=>{fail("folder",err.message)});if(!found||found.folders.size===0){let only=await resolveDesignFolder(void 0,"folder",{requireConfig:!0,cwd});console.log("velloo folder: 1 design folder (no velloo.json yet)"),console.log(` ${relative(cwd,only)||only} ${await daemonState(only)}`),console.log(import_picocolors.default.dim(" `velloo folder add` registers a manifest and a second folder."));return}let base=found.repo?.dir??found.local[0]?.root??cwd,localNames=new Set(found.local.map((design)=>design.projectName)),rows=[];for(let[name,folder]of found.folders){let live=await hasDesignConfig(folder);rows.push({name,path:localNames.has(name)?`${displayPath(folder)} (local)`:relative(base,folder)||".",boards:live?await countJson(join(folder,"boards"),".notes.json"):0,state:live?await daemonState(folder):import_picocolors.default.yellow("missing"),live})}let width=Math.max(...rows.map((r)=>r.name.length)),pathWidth=Math.max(...rows.map((r)=>r.path.length));console.log(`velloo folder: ${rows.length} in ${base}`);for(let row of rows){let marker=row.name===found.defaultProject?import_picocolors.default.cyan("\u25CF"):" ",boards=row.live?`${row.boards} board${row.boards===1?"":"s"}`:"\u2014";console.log(` ${marker} ${import_picocolors.default.bold(row.name.padEnd(width))} ${import_picocolors.default.dim(row.path.padEnd(pathWidth))} ${boards.padEnd(9)} ${row.state}`)}}}),add=defineCommand({meta:{name:"add",description:"Scaffold another design folder 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)"},project:{type:"string",description:"Project name for velloo.json"}},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.project?{project:args.project}:{}})}}),remove=defineCommand({meta:{name:"remove",description:"Remove a project; external content is kept unless --delete-content is passed"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},deleteContent:{type:"boolean",description:"Also delete external design content"},yes:{type:"boolean",description:"Skip the confirmation (required without an interactive terminal)"}},async run({args}){let cwd=resolve("."),folder=await resolveDesignFolder(args.folder,"folder",{interactive:!0,requireConfig:!0,cwd}),local=localDesignOf(folder),keepContent=local!==null&&args.deleteContent!==!0;if(!Boolean(process.stdin.isTTY)&&args.yes!==!0)fail("folder","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");if(console.log(`velloo folder: ${folder}`),console.log(import_picocolors.default.dim(` ${boards} board${boards===1?"":"s"}, ${screens} screen${screens===1?"":"s"} \u2014 ${keepContent?"registration removed; content retained.":"deleted from disk."}`)),args.yes!==!0){let approved=await confirm({message:keepContent?"Remove this project registration and retain its external content?":"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 unregisterProject(folder,cwd);if(local)await removeLocalDesign(local.id);if(!keepContent)await rm(folder,{recursive:!0,force:!0});if(console.log(`velloo folder: ${keepContent?"retained content at":"removed"} ${folder}`),local)console.log(import_picocolors.default.dim(` Forgot the local design "${local.projectName}".`));if(dropped?.name)console.log(import_picocolors.default.dim(dropped.removedManifest?` Dropped "${dropped.name}" \u2014 velloo.json had no other projects, so it's gone too.`:` Dropped "${dropped.name}" from velloo.json.`))}}),relocate=defineCommand({meta:{name:"relocate",description:"Preview moving a design between the repository, managed storage and another directory; --yes applies"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},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 relocation"}},async run({args}){let location=await resolveDesignLocation(args.folder,"folder",{requireConfig:!0}),plan=await planRelocation(location.designRoot,resolve("."),args.to,args.external===!0).catch((err)=>fail("folder",err.message)),recorded=plan.destinationLocal?"a local design on this machine (not in velloo.json)":`velloo.json \u2192 ${plan.manifest?.projects[plan.projectName]}`;if(console.log(`Source: ${plan.source}
|
|
3
|
-
Destination: ${plan.destination}
|
|
4
|
-
Project ${plan.projectName}: ${recorded}`),!args.yes){console.log("Preview only. Add --yes to apply relocation.");return}await relocateDesign(plan),console.log(`Relocated ${plan.projectName} to ${plan.destination}. Run velloo connect to refresh existing agent guidance.`)}}),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)"},project:{type:"string",description:"Project name (default: its current one)"},yes:{type:"boolean",description:"Confirm the local binding"}},async run({args}){let cwd=resolve("."),folder=resolve(args.design);if(!await hasDesignConfig(folder))fail("folder",`${folder} is not a velloo design folder (no .design/config.json).`);let root=await checkoutRoot(cwd,cwd);if(isWithin(root,folder))fail("folder",`${folder} is inside this checkout (${root}); a design here belongs in velloo.json \u2014 see \`velloo folder add\`.`);let existing=localDesignOf(folder),appRoot=existing?join(root,relative(existing.root,existing.appRoot)):root,legacy=[...(await findManifest(cwd).catch(()=>null))?.folders??[]].find(([,path])=>existsSync(path)&&realpathSync(path)===realpathSync(folder))?.[0];if(console.log(`Design: ${folder}
|
|
5
|
-
Checkout: ${root}
|
|
6
|
-
Application: ${appRoot}`),legacy)console.log(`velloo.json: drops "${legacy}", which cannot point outside the repo`);if(!args.yes){console.log("Preview only. Add --yes to confirm this local binding.");return}if(await loadDesignFolder(folder,{preferences:!1}),await stopDaemon(daemonRoot(folder)),legacy)await unregisterProject(folder,cwd);let name=await registerLocalDesign({id:existing?.id??managedDesignId(folder)??randomUUID(),root,appRoot:existsSync(appRoot)?appRoot:root,...managedDesignId(folder)?{}:{designPath:folder},requestedName:args.project??existing?.projectName??legacy}).catch((err)=>fail("folder",err.message));console.log(`Bound "${name}" to ${root} on this machine.`)}}),setAppRoot=defineCommand({meta:{name:"set-app-root",description:"Point a design folder at a different application root"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},to:{type:"string",description:"New application root (asked from the repo's apps when omitted)"},yes:{type:"boolean",description:"Apply the displayed change"}},async run({args}){let folder=await resolveDesignFolder(args.folder,"folder",{interactive:!0,requireConfig:!0}),current=await recordedAppRoot(folder);console.log(`Design: ${folder}`),console.log(`Application: ${current.path}${current.exists?current.looksLikeApp?"":import_picocolors.default.yellow(" (no package.json)"):import_picocolors.default.yellow(" (missing)")}`);let target=args.to?resolve(args.to):await promptAppRootChoice(current.path);if(!target){console.log(import_picocolors.default.dim(" No other application found in this repo \u2014 pass --to <path>."));return}let change=await planAppRootChange(folder,target).catch((err)=>fail("folder",err.message));if(resolve(change.to)===resolve(change.from)){console.log(import_picocolors.default.dim(" Already pointing there \u2014 nothing changed."));return}if(!existsSync(change.to))fail("folder",`${change.to} does not exist.`);if(console.log(`New application: ${change.to}`),!existsSync(join(change.to,"package.json")))console.log(import_picocolors.default.yellow(" ! no package.json there \u2014 codegen and live islands will not resolve"));if(change.local)console.log(import_picocolors.default.dim(` local design "${change.local.project}": appRoot \u2192 ${change.to}`));for(let r of change.rewritten)console.log(import_picocolors.default.dim(` ${r.field}: ${r.from} \u2192 ${r.to}`));if(!args.yes){console.log("Preview only. Add --yes to apply.");return}await stopDaemon(daemonRoot(folder)),await applyAppRootChange(folder,change),console.log(`velloo folder: application root is now ${change.to}`)}}),folder_default=defineCommand({meta:{name:"folder",description:"Manage this repo's design folders (list, add, remove)"},subCommands:{list,add,remove,relocate,bind,"set-app-root":setAppRoot},run:({args})=>args._?.length?void 0:list.run?.({args,cmd:list,rawArgs:[]})});export{folder_default as default};
|
package/chunk-qwv7xkms.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{init_default,runInit2}from"./chunk-hs2j6s1v.js";import"./chunk-56vqqr8s.js";import"./chunk-7dggmqwq.js";import"./chunk-k6ferbam.js";import"./chunk-1gx45384.js";import"./chunk-y0zxzefg.js";import"./chunk-8ssr8a8w.js";import"./chunk-fgw3hp2v.js";import"./chunk-b7j86xq7.js";import"./chunk-k784090q.js";import"./chunk-1bywxgc5.js";import"./chunk-329e3phg.js";import"./chunk-w5rzk6ms.js";import"./chunk-2z0k59hz.js";import"./chunk-mq4znqv2.js";import"./chunk-1yhc252b.js";import"./chunk-cep3ktr3.js";import"./chunk-s23gtejf.js";import"./chunk-65wb0g7d.js";import"./chunk-bk8b7f9a.js";import"./chunk-jnsfgtn9.js";export{init_default as default,runInit2 as runInit};
|
package/chunk-tmtzxcs5.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{CURRENT_SCHEMA_VERSION}from"./chunk-bk8b7f9a.js";import{FOLDER_ARG_DESCRIPTION,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import"./chunk-329e3phg.js";import"./chunk-mq4znqv2.js";import"./chunk-w5rzk6ms.js";import{agentRootCandidates,refreshAgentArtifacts}from"./chunk-1gx45384.js";import"./chunk-65wb0g7d.js";import{daemonRoot,stopDaemon}from"./chunk-k784090q.js";import{fail}from"./chunk-s23gtejf.js";import{installedVellooBin,upgradeInstalledVelloo}from"./chunk-cep3ktr3.js";import{createProgress}from"./chunk-79ykzywe.js";import{upgradeFolder}from"./chunk-y0zxzefg.js";import"./chunk-1bywxgc5.js";import"./chunk-2z0k59hz.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";var import_picocolors=__toESM(require_picocolors(),1);async function targetFolder(arg){if(arg)return resolveDesignFolder(arg,"upgrade",{requireConfig:!0});try{return await resolveDesignFolder(void 0,"upgrade",{requireConfig:!0,onFail:()=>{throw Error("no design folder here")}})}catch{return null}}var upgrade_default=defineCommand({meta:{name:"upgrade",description:"Upgrade Velloo and migrate the design folder to the current format"},args:{folder:{type:"positional",required:!1,description:FOLDER_ARG_DESCRIPTION},"dry-run":{type:"boolean",default:!1,description:"Show what would change without writing"},check:{type:"boolean",default:!1,description:"Check for a Velloo update without installing it"},"binary-only":{type:"boolean",default:!1,description:"Upgrade the Velloo installation and leave the design folder alone"},"folder-only":{type:"boolean",default:!1,description:"Migrate the design folder with this Velloo, without self-upgrading first"},skills:{type:"boolean",default:!0,description:"Also refresh the installed agent skills / plugin / rules to this velloo's versions"}},async run({args}){let dryRun=args["dry-run"]||args.check,folder=args["binary-only"]?null:await targetFolder(args.folder),outcome=null;if(!args["folder-only"])try{outcome=await upgradeInstalledVelloo({checkOnly:dryRun})}catch(error){let message=error instanceof Error?error.message:String(error);if(!folder)fail("upgrade",message);console.log(import_picocolors.default.dim(`velloo: skipping the self-upgrade \u2014 ${message}`))}if(!folder)return;if(outcome?.upgraded){let bin=installedVellooBin();if(bin){let argv=[bin,"upgrade",folder,"--folder-only",...args.skills?[]:["--no-skills"]];if(await Bun.spawn(argv,{stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,VELLOO_DISABLE_UPDATE_CHECK:"1"}}).exited!==0)fail("upgrade",`the upgraded velloo could not migrate ${folder}`);return}console.log(import_picocolors.default.dim(`velloo: could not locate the upgraded velloo \u2014 run \`velloo upgrade ${folder}\` again to migrate the folder.`));return}await migrateFolder(folder,{dryRun,skills:args.skills})}});async function migrateFolder(folder,opts){let{dryRun}=opts,progress=createProgress();progress.start(dryRun?"checking upgrade":"preparing upgrade");let stopped=!1,result;try{if(!dryRun)progress.step("stopping running canvas"),stopped=await stopDaemon(daemonRoot(folder));progress.step(dryRun?"checking design folder":"upgrading design folder"),result=await upgradeFolder(folder,{dryRun})}catch(err){progress.fail("upgrade failed"),fail("upgrade",err instanceof Error?err.message:String(err))}let refreshed=[];try{if(opts.skills&&!dryRun){progress.step("refreshing agent guidance");let projectRoots=await agentRootCandidates(folder);({refreshed}=await refreshAgentArtifacts({projectRoots,designFolder:folder}))}progress.succeed(dryRun?"upgrade check complete":"upgrade complete")}catch(error){throw progress.fail("upgrade failed"),error}if(stopped)console.log("velloo: stopped the running canvas for this folder.");if(result.applied.length===0)console.log(`velloo: ${folder} is already at schema version ${CURRENT_SCHEMA_VERSION}.`);else{console.log(`velloo: ${dryRun?"would migrate":"migrated"} ${folder} from schema version ${result.from} to ${result.to}:`);for(let step of result.applied)console.log(` - ${step}`);for(let file of result.changedFiles)console.log(` ${dryRun?"~":"\u2713"} ${file}`);if(!dryRun)console.log("velloo: folder validated against the current schemas.")}if(refreshed.length>0){console.log(""),console.log(import_picocolors.default.green("\u2713 Refreshed agent guidance to this velloo:"));for(let line of refreshed)console.log(` ${import_picocolors.default.cyan(line)}`)}}export{upgrade_default as default};
|
package/chunk-y0zxzefg.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{CURRENT_SCHEMA_VERSION,schemaVersionOf,planMigration}from"./chunk-bk8b7f9a.js";import{loadDesignFolder}from"./chunk-329e3phg.js";import{TOOL_VERSION}from"./chunk-65wb0g7d.js";import{readdir,readFile,writeFile}from"fs/promises";import{join}from"path";function isObject(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}var isAnnotationSidecar=(file)=>file.endsWith(".annotations.json"),isThemeDocument=(file)=>file.endsWith(".json");async function planRewrites(folder,dir,matches,transform){let files=[];try{files=await readdir(join(folder,dir))}catch{return[]}let out=[];for(let file of files.sort()){if(!matches(file))continue;let rel=join(dir,file),prev=await readFile(join(folder,rel),"utf8"),next=`${JSON.stringify(transform(JSON.parse(prev)),null,2)}
|
|
3
|
-
`;if(next!==prev)out.push({rel,next})}return out}async function upgradeFolder(folder,opts={}){let configPath=join(folder,".design","config.json"),rawConfig=JSON.parse(await readFile(configPath,"utf8")),from=schemaVersionOf(rawConfig),run=planMigration(rawConfig);if(run.applied.length===0)return{from,to:CURRENT_SCHEMA_VERSION,applied:[],changedFiles:[]};let rewrites=[...await planRewrites(folder,"screens",isAnnotationSidecar,(parsed)=>Array.isArray(parsed)?parsed.map((e)=>typeof e==="object"&&e!==null?run.annotation(e):e):parsed),...await planRewrites(folder,"theme",isThemeDocument,(parsed)=>isObject(parsed)?run.theme(parsed):parsed)],nextConfig={...run.config,toolVersion:TOOL_VERSION},changedFiles=[join(".design","config.json"),...rewrites.map((r)=>r.rel)];if(opts.dryRun)return{from,to:CURRENT_SCHEMA_VERSION,applied:run.applied,changedFiles};await writeFile(configPath,`${JSON.stringify(nextConfig,null,2)}
|
|
4
|
-
`,"utf8");for(let r of rewrites)await writeFile(join(folder,r.rel),r.next,"utf8");return await loadDesignFolder(folder),{from,to:CURRENT_SCHEMA_VERSION,applied:run.applied,changedFiles}}
|
|
5
|
-
export{upgradeFolder};
|
package/chunk-zf3xc1wz.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import"./chunk-mq4znqv2.js";import"./chunk-bk8b7f9a.js";import{loadCredential}from"./chunk-b7j86xq7.js";import"./chunk-329e3phg.js";import"./chunk-w5rzk6ms.js";import"./chunk-65wb0g7d.js";import{listDaemons}from"./chunk-k784090q.js";import{verifyCredential}from"./chunk-fgw3hp2v.js";import{projectLabel}from"./chunk-1bywxgc5.js";import{defaultCloudUrl}from"./chunk-2z0k59hz.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){let label=await projectLabel(d.root)??d.root;console.log(`${d.canvasUrl} ${label} (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};
|