jsrepo 1.26.6 → 1.28.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/dist/index.js +73 -53
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,64 +1,84 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import Le from'node:fs';import {fileURLToPath}from'node:url';import {Command,program,Option,Argument}from'commander';import q from'pathe';import {outro,spinner,confirm,isCancel,cancel,multiselect,text,select,log,password,intro}from'@clack/prompts';import E from'chalk';import {resolveCommand}from'package-manager-detector/commands';import {detect}from'package-manager-detector/detect';import*as k from'valibot';import {getTsconfig,createPathsMatcher}from'get-tsconfig';import nt from'node-fetch';import {Octokit}from'octokit';import {builtinModules}from'node:module';import {Biome,Distribution}from'@biomejs/js-api';import {walk}from'estree-walker';import*as qr from'parse5';import*as Be from'prettier';import*as Kr from'svelte/compiler';import {Project}from'ts-morph';import Go from'validate-npm-package-name';import*as zt from'vue/compiler-sfc';import Wo from'node:os';import _o from'ansi-regex';import Mr from'semver';import ln from'conf';import {execa}from'execa';import {detect as detect$1,resolveCommand as resolveCommand$1,detectSync}from'package-manager-detector';import wn from'escape-string-regexp';import {diffLines,diffChars}from'diff';var D=E.gray("\u2502"),Rt=E.gray("\u2500"),tr=E.gray("\u2510"),rr=E.gray("\u2518"),or=E.gray("\u251C"),Ir=E.gray("\u250C"),Tr=E.gray("\u2514"),Ce=E.bgRgb(245,149,66).black(" WARN "),pt=E.bgBlueBright.white(" INFO "),Dt=E.bgRedBright.white(" ERROR "),me=E.hex("#f7df1e")("jsrepo");var At=class{_result;constructor(t){this._result=t;}match(t,r){return this._result.ok?t(this._result.val):r(this._result.err)}map(t){return this.match(r=>j(t(r)),r=>x(r))}mapOr(t,r){return this.match(o=>r(o),o=>t)}mapOrElse(t,r){return this.match(o=>r(o),o=>t(o))}mapErr(t){return this.match(r=>j(r),r=>x(t(r)))}mapErrOr(t,r){return this.match(o=>t,o=>r(o))}mapErrOrElse(t,r){return this.match(o=>t(o),o=>r(o))}isOk(){return this.match(()=>true,()=>false)}isErr(){return this.match(()=>false,()=>true)}unwrap(){return this.match(t=>t,()=>{throw new Error("Attempted to call `.unwrap()` on a non `Ok` value.")})}unwrapErr(){return this.match(()=>{throw new Error("Attempted to call `.unwrapErr()` on a non `Err` value.")},t=>t)}unwrapOr(t){return this.match(r=>r,r=>t)}unwrapErrOr(t){return this.match(()=>t,r=>r)}unwrapOrElse(t){return this.match(r=>r,r=>t(r))}unwrapErrOrElse(t){return this.match(r=>t(r),r=>r)}expect(t){return this.match(r=>r,()=>{throw new Error(t)})}expectErr(t){return this.match(()=>{throw new Error(t)},r=>r)}},j=e=>new At({ok:true,val:e}),x=e=>new At({ok:false,err:e});var Or=(e,t)=>{let r=[];for(let[o,n]of e)r.push(t(o,n));return r};var ae=(...e)=>e.map(t=>Io(t)).filter(Boolean).join("/"),Io=e=>{let t=To(e);return Oo(t)};var To=e=>{let t=e;return t.startsWith("/")&&(t=t.slice(1)),t};var Oo=e=>{let t=e;return t.endsWith("/")&&(t=t.slice(0,t.length-1)),t},Nr=e=>{let t=e;return t.endsWith("/")||(t=`${t}/`),t};var No=/^(@[^\/]+\/[^@\/]+)(?:@([^\/]+))?(\/.*)?$/,Po=/^([^@\/]+)(?:@([^\/]+))?(\/.*)?$/,Lt=e=>{let t=No.exec(e)||Po.exec(e);return t?j({name:t[1]||"",version:t[2]||"latest",path:t[3]||""}):x(`invalid package name: ${e}`)};var Pr=k.union([k.literal("off"),k.literal("warn"),k.literal("error")]),Do={"no-unpinned-dependency":{description:"Require all dependencies to have a pinned version.",check:e=>{let t=[];for(let r of [...e.dependencies,...e.devDependencies])r.includes("@")||t.push(`Couldn't find a version to use for ${E.bold(r)}`);return t.length>0?t:undefined}},"require-local-dependency-exists":{description:"Require all local dependencies to exist.",check:(e,{categories:t})=>{let r=[];for(let o of e.localDependencies){let[n,s]=o.split("/"),i=t.find(p=>p.name.trim()===n.trim()),a=`${E.bold(`${e.category}/${e.name}`)} depends on local dependency ${E.bold(o)} which doesn't exist`;if(!i){r.push(a);continue}i.blocks.find(p=>p.name===s)===undefined&&r.push(a);}return r.length>0?r:undefined}},"no-category-index-file-dependency":{description:"Disallow depending on the index file of a category.",check:(e,{categories:t})=>{let r=[];for(let o of e.localDependencies){let[n,s]=o.split("/");if(s!=="index")continue;let i=t.find(p=>p.name===n);!i||!i.blocks.find(p=>p.name===s)||r.push(`${E.bold(`${e.category}/${e.name}`)} depends on ${E.bold(`${n}/${s}`)}`);}return r.length>0?r:undefined}},"max-local-dependencies":{description:"Enforces a limit on the amount of local dependencies a block can have.",check:(e,{options:t})=>{let r=[],o;return typeof t[0]!="number"?o=5:o=t[0],e.localDependencies.length>o&&r.push(`${E.bold(`${e.category}/${e.name}`)} has too many local dependencies (${E.bold(e.localDependencies.length)}) limit (${E.bold(o)})`),r.length>0?r:undefined}},"no-circular-dependency":{description:"Disallow circular dependencies.",check:(e,{categories:t})=>{let r=[],o=`${e.category}/${e.name}`,n=Bt(o,e,t);return n&&r.push(`There is a circular dependency in ${E.bold(o)}: ${E.bold(n.join(" -> "))}`),r.length>0?r:undefined}},"no-unused-block":{description:"Disallow unused blocks. (Not listed and not a dependency of another block)",check:(e,{categories:t})=>{if(e.list)return;let r=`${e.category}/${e.name}`,o=t.flatMap(n=>n.blocks).filter(n=>n.list);for(let n of o)if(Bt(r,n,t))return;return [`${E.bold(r)} is unused and will be ${E.bold.red("removed")}`]}},"no-framework-dependency":{description:"Disallow frameworks (Svelte, Vue, React) as dependencies.",check:e=>{let t=[],r=new Set(["svelte","vue","nuxt","react","react-dom","next","@remix-run/react","@builder.io/qwik","astro","solid-js","@angular/core","@angular/common","@angular/forms","@angular/platform-browser","@angular/platform-browser-dynamic","@angular/router"]),o=[...e.devDependencies,...e.dependencies].map(n=>Lt(n).unwrap().name).filter(n=>r.has(n));if(o.length>0)for(let n of o)t.push(`${E.bold(`${e.category}/${e.name}`)} depends on ${E.bold(n)} causing it to be installed when added`);return t.length>0?t:undefined}}},Ao=k.union([k.literal("no-category-index-file-dependency"),k.literal("no-unpinned-dependency"),k.literal("require-local-dependency-exists"),k.literal("max-local-dependencies"),k.literal("no-circular-dependency"),k.literal("no-unused-block"),k.literal("no-framework-dependency")]),Dr=k.record(Ao,k.union([Pr,k.tupleWithRest([Pr,k.union([k.string(),k.number()])],k.union([k.string(),k.number()]))])),nr={"no-category-index-file-dependency":"warn","no-unpinned-dependency":"warn","require-local-dependency-exists":"error","max-local-dependencies":["warn",10],"no-circular-dependency":"error","no-unused-block":"warn","no-framework-dependency":"warn"},Ar=(e,t,r=nr)=>{let o=[],n=[];for(let s of e)for(let i of s.blocks)for(let[a,p]of Object.entries(Do)){let d=r[a],c,u=[];if(Array.isArray(d)?(c=d[0],u.push(...d.slice(1))):c=d,c==="off")continue;let f=p.check(i,{categories:e,options:u,config:t});if(f){if(c==="error"){n.push(...f.map(h=>`${D} ${Dt} ${E.red(h)} ${E.gray(a)}`));continue}o.push(...f.map(h=>`${D} ${Ce} ${h} ${E.gray(a)}`));}}return {warnings:o,errors:n}},Bt=(e,t,r,o=[])=>{let n=[...o,`${t.category}/${t.name}`];for(let s of t.localDependencies){if(s===e)return n;if(o.includes(s))return;let[i,a]=s.split("/"),p=r.find(c=>c.name===i)?.blocks.find(c=>c.name===a);if(!p)continue;let d=Bt(e,p,r,n);if(d)return [...d,e]}},Lr=(e,t)=>{for(let r of t)for(let o of r.blocks){if(!o.list)continue;if(Bt(e,o,t))return true}return false};var ot="jsrepo.json",Ke="jsrepo-build-config.json",sr=k.union([k.literal("prettier"),k.literal("biome")]),Bo=k.objectWithRest({"*":k.string()},k.string()),ir=k.object({$schema:k.string(),repos:k.optional(k.array(k.string()),[]),includeTests:k.boolean(),paths:Bo,watermark:k.optional(k.boolean(),true),formatter:k.optional(sr)}),Pe=e=>{if(!Le.existsSync(q.join(e,ot)))return x("Could not find your configuration file! Please run `init`.");let t=k.safeParse(ir,JSON.parse(Le.readFileSync(q.join(e,ot)).toString()));return t.success?j(t.output):x(`There was an error reading your \`${ot}\` file!`)},Fo=k.object({$schema:k.string(),dirs:k.array(k.string()),outputDir:k.optional(k.string()),includeBlocks:k.optional(k.array(k.string()),[]),includeCategories:k.optional(k.array(k.string()),[]),excludeBlocks:k.optional(k.array(k.string()),[]),excludeCategories:k.optional(k.array(k.string()),[]),doNotListBlocks:k.optional(k.array(k.string()),[]),doNotListCategories:k.optional(k.array(k.string()),[]),listBlocks:k.optional(k.array(k.string()),[]),listCategories:k.optional(k.array(k.string()),[]),excludeDeps:k.optional(k.array(k.string()),[]),preview:k.optional(k.boolean()),rules:k.optional(Dr)}),_t=e=>{if(!Le.existsSync(q.join(e,Ke)))return j(null);let t=k.safeParse(Fo,JSON.parse(Le.readFileSync(q.join(e,Ke)).toString()));return t.success?j(t.output):x(`There was an error reading your \`${Ke}\` file!`)},De=(e,t)=>{let r=getTsconfig(t,"tsconfig.json"),o=null;r||(r=getTsconfig(t,"jsconfig.json")),r&&(o=createPathsMatcher(r));let n;if(e["*"].startsWith("."))n={"*":q.relative(t,q.join(q.resolve(t),e["*"]))};else {if(o===null)return x("Cannot resolve aliases because we couldn't find a tsconfig!");n={"*":Fr(e["*"],o,t)};}for(let[s,i]of Object.entries(e))if(s!=="*"){if(i.startsWith(".")){n[s]=q.relative(t,q.join(q.resolve(t),i));continue}if(o===null)return x("Cannot resolve aliases because we couldn't find a tsconfig!");n[s]=Fr(i,o,t);}return j(n)},Fr=(e,t,r)=>{let o=t(e);return q.relative(r,o[0])};var Ae=e=>e.replace(_o(),"");var jt=(e,t,r=" ")=>{if(Ae(e).length>t)throw new Error("String length is greater than the length provided.");return r.repeat(t-Ae(e).length)+e},_r=(e,t,r=" ")=>e+r.repeat(t),Wr=(e,t,r=" ")=>{if(Ae(e).length>t)throw new Error("String length is greater than the length provided.");return e+r.repeat(t-Ae(e).length)},Vr=(e,t,r=" ")=>{if(Ae(e).length>t)throw new Error("String length is greater than the length provided.");let o=t-Ae(e).length,n=Math.floor(o/2),s=Math.ceil(o/2);return r.repeat(n)+e+r.repeat(s)};var Vo=/\n|\r\n/g,ee=e=>e.split(Vo),Y=(e,{lineNumbers:t=false,prefix:r}={})=>{let o=e;if(t){let n=e.length.toString().length+1;o=o.map((s,i)=>`${jt(`${i+1}`,n)} ${s}`);}return r!==undefined&&(o=o.map((n,s)=>`${r(s,e.length)}${n}`)),o.join(Wo.EOL)};var lr=(e,t)=>{let r=q.join(e,"package.json");if(Le.existsSync(r))return r;if(e===t)return;let o=e.split(/[\/\\]/);return lr(o.slice(0,o.length-1).join("/"),t)},Mo=e=>{if(!Le.existsSync(e))return x(`${e} doesn't exist`);let t=Le.readFileSync(e).toString();return j(JSON.parse(t))},Jr=e=>e[0]==="^"?e.slice(1):e,Wt=(e,t,{cwd:r})=>{let o=e,n=t,s=Mo(q.join(r,"package.json"));if(!s.isErr()){let i=s.unwrap();if(i.dependencies)for(let a of o){let[p,d]=a.split("@"),c=i.dependencies[p];if(d===undefined&&c){o.delete(a);continue}c&&Mr.satisfies(Jr(c),d)&&o.delete(a);}if(i.devDependencies)for(let a of n){let[p,d]=a.split("@"),c=i.devDependencies[p];if(d===undefined&&c){n.delete(a);continue}c&&Mr.satisfies(Jr(c),d)&&n.delete(a);}}return {dependencies:o,devDependencies:n}};var Ho={matches:e=>e.endsWith(".css"),resolveDependencies:()=>j({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>`/*
|
|
3
|
-
${
|
|
4
|
-
*/`,format:async(e,{formatter:t,prettierOptions:r,biomeOptions:o,filePath:n})=>{if(!t)return e;if(t==="prettier")return await
|
|
5
|
-
`)):
|
|
6
|
-
${
|
|
7
|
-
-->`,format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await
|
|
8
|
-
${
|
|
9
|
-
*/`,format:async(e,{formatter:t,prettierOptions:r,biomeOptions:o,filePath:n})=>{if(!t)return e;if(t==="prettier")return await
|
|
10
|
-
${
|
|
11
|
-
*/`,format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await
|
|
12
|
-
`)):
|
|
13
|
-
${
|
|
14
|
-
-->`,format:async(e,{formatter:t,filePath:r,prettierOptions:o})=>t&&t==="prettier"&&o&&o.plugins?.find(n=>n==="prettier-plugin-svelte")?await
|
|
15
|
-
${
|
|
16
|
-
-->`,format:async e=>e},
|
|
17
|
-
`)):
|
|
18
|
-
${
|
|
19
|
-
*/`,format:async(e,{formatter:t,filePath:r,prettierOptions:o,biomeOptions:n})=>{if(!t)return e;if(t==="prettier")return await
|
|
20
|
-
`)):
|
|
21
|
-
${
|
|
22
|
-
-->`,format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await
|
|
23
|
-
${n||e} references code not contained in ${
|
|
2
|
+
import Be from'node:fs';import {fileURLToPath}from'node:url';import {Command,program,Option,Argument}from'commander';import Y from'pathe';import {outro,spinner,confirm,isCancel,cancel,multiselect,text,select,log,password,intro}from'@clack/prompts';import T from'chalk';import {resolveCommand}from'package-manager-detector/commands';import {detect}from'package-manager-detector/detect';import*as b from'valibot';import {getTsconfig,createPathsMatcher}from'get-tsconfig';import nt from'node-fetch';import {Octokit}from'octokit';import {builtinModules}from'node:module';import {Biome,Distribution}from'@biomejs/js-api';import {walk}from'estree-walker';import*as Qr from'parse5';import*as Fe from'prettier';import*as eo from'svelte/compiler';import {Project}from'ts-morph';import tn from'validate-npm-package-name';import*as Ht from'vue/compiler-sfc';import qo from'node:os';import Ko from'ansi-regex';import Hr from'semver';import vn from'conf';import {execa}from'execa';import {detect as detect$1,resolveCommand as resolveCommand$1,detectSync}from'package-manager-detector';import Sn from'escape-string-regexp';import ts from'ignore';import {diffLines,diffChars}from'diff';import Ls from'@anthropic-ai/sdk';import Ws from'ollama';import Vs from'openai';var D=T.gray("\u2502"),jt=T.gray("\u2500"),nr=T.gray("\u2510"),sr=T.gray("\u2518"),ir=T.gray("\u251C"),Ar=T.gray("\u250C"),Dr=T.gray("\u2514"),xe=T.bgRgb(245,149,66).black(" WARN "),mt=T.bgBlueBright.white(" INFO "),Lt=T.bgRedBright.white(" ERROR "),ge=T.hex("#f7df1e")("jsrepo");var Bt=class{_result;constructor(t){this._result=t;}match(t,r){return this._result.ok?t(this._result.val):r(this._result.err)}map(t){return this.match(r=>C(t(r)),r=>j(r))}mapOr(t,r){return this.match(o=>r(o),o=>t)}mapOrElse(t,r){return this.match(o=>r(o),o=>t(o))}mapErr(t){return this.match(r=>C(r),r=>j(t(r)))}mapErrOr(t,r){return this.match(o=>t,o=>r(o))}mapErrOrElse(t,r){return this.match(o=>t(o),o=>r(o))}isOk(){return this.match(()=>true,()=>false)}isErr(){return this.match(()=>false,()=>true)}unwrap(){return this.match(t=>t,()=>{throw new Error("Attempted to call `.unwrap()` on a non `Ok` value.")})}unwrapErr(){return this.match(()=>{throw new Error("Attempted to call `.unwrapErr()` on a non `Err` value.")},t=>t)}unwrapOr(t){return this.match(r=>r,r=>t)}unwrapErrOr(t){return this.match(()=>t,r=>r)}unwrapOrElse(t){return this.match(r=>r,r=>t(r))}unwrapErrOrElse(t){return this.match(r=>t(r),r=>r)}expect(t){return this.match(r=>r,()=>{throw new Error(t)})}expectErr(t){return this.match(()=>{throw new Error(t)},r=>r)}},C=e=>new Bt({ok:true,val:e}),j=e=>new Bt({ok:false,err:e});var Lr=(e,t)=>{let r=[];for(let[o,n]of e)r.push(t(o,n));return r};var ne=(...e)=>e.map(t=>Fo(t)).filter(Boolean).join("/"),Fo=e=>{let t=_o(e);return Wo(t)};var _o=e=>{let t=e;return t.startsWith("/")&&(t=t.slice(1)),t};var Wo=e=>{let t=e;return t.endsWith("/")&&(t=t.slice(0,t.length-1)),t},Br=e=>{let t=e;return t.endsWith("/")||(t=`${t}/`),t};var Vo=/^(@[^\/]+\/[^@\/]+)(?:@([^\/]+))?(\/.*)?$/,Mo=/^([^@\/]+)(?:@([^\/]+))?(\/.*)?$/,Ft=e=>{let t=Vo.exec(e)||Mo.exec(e);return t?C({name:t[1]||"",version:t[2]||"latest",path:t[3]||""}):j(`invalid package name: ${e}`)};var Fr=b.union([b.literal("off"),b.literal("warn"),b.literal("error")]),Jo={"no-unpinned-dependency":{description:"Require all dependencies to have a pinned version.",check:e=>{let t=[];for(let r of [...e.dependencies,...e.devDependencies])r.includes("@")||t.push(`Couldn't find a version to use for ${T.bold(r)}`);return t.length>0?t:undefined}},"require-local-dependency-exists":{description:"Require all local dependencies to exist.",check:(e,{categories:t})=>{let r=[];for(let o of e.localDependencies){let[n,s]=o.split("/"),i=t.find(p=>p.name.trim()===n.trim()),a=`${T.bold(`${e.category}/${e.name}`)} depends on local dependency ${T.bold(o)} which doesn't exist`;if(!i){r.push(a);continue}i.blocks.find(p=>p.name===s)===undefined&&r.push(a);}return r.length>0?r:undefined}},"no-category-index-file-dependency":{description:"Disallow depending on the index file of a category.",check:(e,{categories:t})=>{let r=[];for(let o of e.localDependencies){let[n,s]=o.split("/");if(s!=="index")continue;let i=t.find(p=>p.name===n);!i||!i.blocks.find(p=>p.name===s)||r.push(`${T.bold(`${e.category}/${e.name}`)} depends on ${T.bold(`${n}/${s}`)}`);}return r.length>0?r:undefined}},"max-local-dependencies":{description:"Enforces a limit on the amount of local dependencies a block can have.",check:(e,{options:t})=>{let r=[],o;return typeof t[0]!="number"?o=5:o=t[0],e.localDependencies.length>o&&r.push(`${T.bold(`${e.category}/${e.name}`)} has too many local dependencies (${T.bold(e.localDependencies.length)}) limit (${T.bold(o)})`),r.length>0?r:undefined}},"no-circular-dependency":{description:"Disallow circular dependencies.",check:(e,{categories:t})=>{let r=[],o=`${e.category}/${e.name}`,n=_t(o,e,t);return n&&r.push(`There is a circular dependency in ${T.bold(o)}: ${T.bold(n.join(" -> "))}`),r.length>0?r:undefined}},"no-unused-block":{description:"Disallow unused blocks. (Not listed and not a dependency of another block)",check:(e,{categories:t})=>{if(e.list)return;let r=`${e.category}/${e.name}`,o=t.flatMap(n=>n.blocks).filter(n=>n.list);for(let n of o)if(_t(r,n,t))return;return [`${T.bold(r)} is unused and will be ${T.bold.red("removed")}`]}},"no-framework-dependency":{description:"Disallow frameworks (Svelte, Vue, React) as dependencies.",check:e=>{let t=[],r=new Set(["svelte","vue","nuxt","react","react-dom","next","@remix-run/react","@builder.io/qwik","astro","solid-js","@angular/core","@angular/common","@angular/forms","@angular/platform-browser","@angular/platform-browser-dynamic","@angular/router"]),o=[...e.devDependencies,...e.dependencies].map(n=>Ft(n).unwrap().name).filter(n=>r.has(n));if(o.length>0)for(let n of o)t.push(`${T.bold(`${e.category}/${e.name}`)} depends on ${T.bold(n)} causing it to be installed when added`);return t.length>0?t:undefined}}},zo=b.union([b.literal("no-category-index-file-dependency"),b.literal("no-unpinned-dependency"),b.literal("require-local-dependency-exists"),b.literal("max-local-dependencies"),b.literal("no-circular-dependency"),b.literal("no-unused-block"),b.literal("no-framework-dependency")]),_r=b.record(zo,b.union([Fr,b.tupleWithRest([Fr,b.union([b.string(),b.number()])],b.union([b.string(),b.number()]))])),ar={"no-category-index-file-dependency":"warn","no-unpinned-dependency":"warn","require-local-dependency-exists":"error","max-local-dependencies":["warn",10],"no-circular-dependency":"error","no-unused-block":"warn","no-framework-dependency":"warn"},Wr=(e,t,r=ar)=>{let o=[],n=[];for(let s of e)for(let i of s.blocks)for(let[a,p]of Object.entries(Jo)){let d=r[a],c,g=[];if(Array.isArray(d)?(c=d[0],g.push(...d.slice(1))):c=d,c==="off")continue;let l=p.check(i,{categories:e,options:g,config:t});if(l){if(c==="error"){n.push(...l.map(h=>`${D} ${Lt} ${T.red(h)} ${T.gray(a)}`));continue}o.push(...l.map(h=>`${D} ${xe} ${h} ${T.gray(a)}`));}}return {warnings:o,errors:n}},_t=(e,t,r,o=[])=>{let n=[...o,`${t.category}/${t.name}`];for(let s of t.localDependencies){if(s===e)return n;if(o.includes(s))return;let[i,a]=s.split("/"),p=r.find(c=>c.name===i)?.blocks.find(c=>c.name===a);if(!p)continue;let d=_t(e,p,r,n);if(d)return [...d,e]}},Vr=(e,t)=>{for(let r of t)for(let o of r.blocks){if(!o.list)continue;if(_t(e,o,t))return true}return false};var ot="jsrepo.json",Ze="jsrepo-build-config.json",cr=b.union([b.literal("prettier"),b.literal("biome")]),Uo=b.objectWithRest({"*":b.string()},b.string()),lr=b.object({$schema:b.string(),repos:b.optional(b.array(b.string()),[]),includeTests:b.boolean(),paths:Uo,watermark:b.optional(b.boolean(),true),formatter:b.optional(cr)}),Ae=e=>{if(!Be.existsSync(Y.join(e,ot)))return j("Could not find your configuration file! Please run `init`.");let t=b.safeParse(lr,JSON.parse(Be.readFileSync(Y.join(e,ot)).toString()));return t.success?C(t.output):j(`There was an error reading your \`${ot}\` file!`)},Ho=b.object({$schema:b.string(),dirs:b.array(b.string()),outputDir:b.optional(b.string()),includeBlocks:b.optional(b.array(b.string()),[]),includeCategories:b.optional(b.array(b.string()),[]),excludeBlocks:b.optional(b.array(b.string()),[]),excludeCategories:b.optional(b.array(b.string()),[]),doNotListBlocks:b.optional(b.array(b.string()),[]),doNotListCategories:b.optional(b.array(b.string()),[]),listBlocks:b.optional(b.array(b.string()),[]),listCategories:b.optional(b.array(b.string()),[]),excludeDeps:b.optional(b.array(b.string()),[]),preview:b.optional(b.boolean()),rules:b.optional(_r)}),Vt=e=>{if(!Be.existsSync(Y.join(e,Ze)))return C(null);let t=b.safeParse(Ho,JSON.parse(Be.readFileSync(Y.join(e,Ze)).toString()));return t.success?C(t.output):j(`There was an error reading your \`${Ze}\` file!`)},De=(e,t)=>{let r=getTsconfig(t,"tsconfig.json"),o=null;r||(r=getTsconfig(t,"jsconfig.json")),r&&(o=createPathsMatcher(r));let n;if(e["*"].startsWith("."))n={"*":Y.relative(t,Y.join(Y.resolve(t),e["*"]))};else {if(o===null)return j("Cannot resolve aliases because we couldn't find a tsconfig!");n={"*":Jr(e["*"],o,t)};}for(let[s,i]of Object.entries(e))if(s!=="*"){if(i.startsWith(".")){n[s]=Y.relative(t,Y.join(Y.resolve(t),i));continue}if(o===null)return j("Cannot resolve aliases because we couldn't find a tsconfig!");n[s]=Jr(i,o,t);}return C(n)},Jr=(e,t,r)=>{let o=t(e);return Y.relative(r,o[0])};var Le=e=>e.replace(Ko(),"");var St=(e,t,r=" ")=>{if(Le(e).length>t)throw new Error("String length is greater than the length provided.");return r.repeat(t-Le(e).length)+e},zr=(e,t,r=" ")=>e+r.repeat(t),Gr=(e,t,r=" ")=>{if(Le(e).length>t)throw new Error("String length is greater than the length provided.");return e+r.repeat(t-Le(e).length)},Ur=(e,t,r=" ")=>{if(Le(e).length>t)throw new Error("String length is greater than the length provided.");let o=t-Le(e).length,n=Math.floor(o/2),s=Math.ceil(o/2);return r.repeat(n)+e+r.repeat(s)};var Yo=/\n|\r\n/g,q=e=>e.split(Yo),Q=(e,{lineNumbers:t=false,prefix:r}={})=>{let o=e;if(t){let n=e.length.toString().length+1;o=o.map((s,i)=>`${St(`${i+1}`,n)} ${s}`);}return r!==undefined&&(o=o.map((n,s)=>`${r(s,e.length)}${n}`)),o.join(qo.EOL)};var dr=(e,t)=>{let r=Y.join(e,"package.json");if(Be.existsSync(r))return r;if(e===t)return;let o=e.split(/[\/\\]/);return dr(o.slice(0,o.length-1).join("/"),t)},Zo=e=>{if(!Be.existsSync(e))return j(`${e} doesn't exist`);let t=Be.readFileSync(e).toString();return C(JSON.parse(t))},Kr=e=>e[0]==="^"?e.slice(1):e,Jt=(e,t,{cwd:r})=>{let o=e,n=t,s=Zo(Y.join(r,"package.json"));if(!s.isErr()){let i=s.unwrap();if(i.dependencies)for(let a of o){let[p,d]=a.split("@"),c=i.dependencies[p];if(d===undefined&&c){o.delete(a);continue}c&&Hr.satisfies(Kr(c),d)&&o.delete(a);}if(i.devDependencies)for(let a of n){let[p,d]=a.split("@"),c=i.devDependencies[p];if(d===undefined&&c){n.delete(a);continue}c&&Hr.satisfies(Kr(c),d)&&n.delete(a);}}return {dependencies:o,devDependencies:n}};var rn={matches:e=>e.endsWith(".css"),resolveDependencies:()=>C({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>`/*
|
|
3
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
4
|
+
*/`,format:async(e,{formatter:t,prettierOptions:r,biomeOptions:o,filePath:n})=>{if(!t)return e;if(t==="prettier")return await Fe.format(e,{filepath:n,...r});let s=await Biome.create({distribution:Distribution.NODE});return o&&s.applyConfiguration(o),s.formatContent(e,{filePath:n}).content}},on={matches:e=>e.endsWith(".html"),resolveDependencies:({filePath:e,isSubDir:t,excludeDeps:r,dirs:o,cwd:n})=>{let s=Be.readFileSync(e).toString(),i=Qr.parse(s),a=[],p=(c,g)=>{if(c&&(g(c),c.childNodes&&c.childNodes.length>0))for(let l of c.childNodes)p(l,g);};for(let c of i.childNodes)p(c,g=>{if(g.tagName==="script")for(let l of g.attrs)l.name==="src"&&a.push(l.value);if(g.tagName==="link"&&g.attrs.find(l=>l.name==="rel"&&l.value==="stylesheet"))for(let l of g.attrs)l.name==="href"&&!l.value.startsWith("http")&&a.push(l.value);});let d=qt({moduleSpecifiers:a,filePath:e,isSubDir:t,dirs:o,cwd:n,doNotInstall:["svelte","@sveltejs/kit",...r]});return d.isErr()?j(d.unwrapErr().map(c=>Kt(c)).join(`
|
|
5
|
+
`)):C(d.unwrap())},comment:e=>`<!--
|
|
6
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
7
|
+
-->`,format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await Fe.format(e,{parser:"html",...r}):e},fr={matches:e=>e.endsWith(".json"),resolveDependencies:()=>C({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>e,format:async(e,{formatter:t,prettierOptions:r,biomeOptions:o,filePath:n})=>{if(!t)return e;if(t==="prettier")return await Fe.format(e,{filepath:n,...r});let s=await Biome.create({distribution:Distribution.NODE});return o&&s.applyConfiguration(o),s.formatContent(e,{filePath:n}).content}},nn={matches:e=>e.endsWith(".jsonc"),resolveDependencies:()=>C({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>`/*
|
|
8
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
9
|
+
*/`,format:async(e,{formatter:t,prettierOptions:r,biomeOptions:o,filePath:n})=>{if(!t)return e;if(t==="prettier")return await Fe.format(e,{filepath:n,...r});let s=await Biome.create({distribution:Distribution.NODE});return o&&s.applyConfiguration({...o,json:{parser:{allowComments:true}}}),s.formatContent(e,{filePath:n}).content}},sn={matches:e=>e.endsWith(".sass")||e.endsWith(".scss"),resolveDependencies:()=>C({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>`/*
|
|
10
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
11
|
+
*/`,format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await Fe.format(e,{parser:"scss",...r}):e},an={matches:e=>e.endsWith(".svelte"),resolveDependencies:({filePath:e,isSubDir:t,excludeDeps:r,dirs:o,cwd:n})=>{let s=Be.readFileSync(e).toString(),i=eo.parse(s,{modern:true,filename:e});if(!i.instance&&!i.module)return C({dependencies:[],devDependencies:[],local:[],imports:{}});let a=[],p=c=>{(c.type==="ImportDeclaration"||c.type==="ExportAllDeclaration"||c.type==="ExportNamedDeclaration")&&typeof c.source?.value=="string"&&a.push(c.source.value);};i.instance&&walk(i.instance,{enter:p}),i.module&&walk(i.module,{enter:p});let d=qt({moduleSpecifiers:a,filePath:e,isSubDir:t,dirs:o,cwd:n,doNotInstall:["svelte","@sveltejs/kit",...r]});return d.isErr()?j(d.unwrapErr().map(c=>Kt(c)).join(`
|
|
12
|
+
`)):C(d.unwrap())},comment:e=>`<!--
|
|
13
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
14
|
+
-->`,format:async(e,{formatter:t,filePath:r,prettierOptions:o})=>t&&t==="prettier"&&o&&o.plugins?.find(n=>n==="prettier-plugin-svelte")?await Fe.format(e,{filepath:r,...o}):e},cn={matches:e=>e.endsWith(".svg"),resolveDependencies:()=>C({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>`<!--
|
|
15
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
16
|
+
-->`,format:async e=>e},ln={matches:e=>e.endsWith(".ts")||e.endsWith(".js")||e.endsWith(".tsx")||e.endsWith(".jsx"),resolveDependencies:({filePath:e,isSubDir:t,excludeDeps:r,dirs:o,cwd:n})=>{let i=new Project().addSourceFileAtPath(e),a=i.getImportDeclarations().map(c=>c.getModuleSpecifierValue()),p=i.getExportDeclarations().map(c=>c.getModuleSpecifierValue()).filter(c=>c!==undefined);a.push(...p);let d=qt({moduleSpecifiers:a,filePath:e,isSubDir:t,dirs:o,cwd:n,doNotInstall:r});return d.isErr()?j(d.unwrapErr().map(c=>Kt(c)).join(`
|
|
17
|
+
`)):C(d.unwrap())},comment:e=>`/*
|
|
18
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
19
|
+
*/`,format:async(e,{formatter:t,filePath:r,prettierOptions:o,biomeOptions:n})=>{if(!t)return e;if(t==="prettier")return await Fe.format(e,{filepath:r,...o});let s=await Biome.create({distribution:Distribution.NODE});return n&&s.applyConfiguration(n),s.formatContent(e,{filePath:r}).content}},pn={matches:e=>e.endsWith(".vue"),resolveDependencies:({filePath:e,isSubDir:t,excludeDeps:r,dirs:o,cwd:n})=>{let s=Be.readFileSync(e).toString(),i=Ht.parse(s,{filename:e});if(!i.descriptor.script?.content&&!i.descriptor.scriptSetup?.content)return C({dependencies:[],devDependencies:[],local:[],imports:{}});let a;try{a=Ht.compileScript(i.descriptor,{id:"shut-it"});}catch(c){return j(`Compile error: ${c}`)}if(!a.imports)return C({dependencies:[],devDependencies:[],local:[],imports:{}});let p=Object.values(a.imports).map(c=>c.source),d=qt({moduleSpecifiers:p,filePath:e,isSubDir:t,dirs:o,cwd:n,doNotInstall:["vue","nuxt",...r]});return d.isErr()?j(d.unwrapErr().map(c=>Kt(c)).join(`
|
|
20
|
+
`)):C(d.unwrap())},comment:e=>`<!--
|
|
21
|
+
${Q(q(e),{prefix:()=>" "})}
|
|
22
|
+
-->`,format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await Fe.format(e,{parser:"vue",...r}):e},dn={matches:e=>e.endsWith(".yml")||e.endsWith(".yaml"),resolveDependencies:()=>C({dependencies:[],local:[],devDependencies:[],imports:{}}),comment:e=>Q(q(e),{prefix:()=>"# "}),format:async(e,{formatter:t,prettierOptions:r})=>t&&t==="prettier"?await Fe.format(e,{parser:"yaml",...r}):e},Kt=e=>`${Q(q(e),{prefix:t=>t===0?`${D} ${Lt} `:`${D} `})}`,qt=({moduleSpecifiers:e,isSubDir:t,filePath:r,doNotInstall:o,dirs:n,cwd:s})=>{let i=[],a=new Set,p=new Set,d={};for(let l of e){if(l.startsWith(".")){let S=to(l,t,{filePath:r,dirs:n,cwd:s});if(S.isErr()){i.push(S.unwrapErr());continue}let $=S.unwrap();$&&(p.add($.dependency),d[l]=$.template);continue}let h=fn(l,t,{filePath:r,dirs:n,cwd:s});if(h.isErr()){i.push(h.unwrapErr());continue}let R=h.unwrap();R?(p.add(R.dependency),d[l]=R.template):a.add(l);}if(i.length>0)return j(i);let{devDependencies:c,dependencies:g}=gn(Array.from(a),r,{doNotInstall:o||[]});return C({dependencies:g,devDependencies:c,local:Array.from(p),imports:d})},to=(e,t,{filePath:r,dropExtension:o=true,alias:n,dirs:s,cwd:i})=>{if(t&&(e.startsWith("./")||e==="."))return C(undefined);let a=t?Y.join(r,"../../"):Y.join(r,"../"),p=Y.join(Y.join(r,"../"),e),d=Y.join(a,"../");if(p.startsWith(d))return C(Xr(p.slice(d.length),o));for(let c of s){let g=Y.resolve(Y.join(i,c)),l=Y.resolve(p);if(l.startsWith(g))return C(Xr(l.slice(g.length+1),o))}return j(`${r}:
|
|
23
|
+
${n||e} references code not contained in ${T.bold(s.join(", "))} and cannot be resolved.`)},Xr=(e,t=true)=>{let[r,o,...n]=e.split("/");o===undefined&&(o="index");let s=o;t&&s.includes(".")&&(s=s.slice(0,s.length-Y.parse(s).ext.length));let i=`${r}/${s}`,a=`{{${i}}}`;return n.length===0?s.length!==o.length&&(a+=Y.parse(o).ext):a+=`/${n.join("/")}`,{dependency:i,template:a}},fn=(e,t,{filePath:r,dirs:o,cwd:n})=>{let s;try{if(s=getTsconfig(r,"tsconfig.json"),!s&&(s=getTsconfig(r,"jsconfig.json"),!s))return C(void 0)}catch(a){return j(`Error while trying to get ${T.bold("tsconfig.json")}: ${a}`)}let i=createPathsMatcher(s);if(i){let a=i(e);for(let p of a){let d=un(p);if(!d)continue;let c=Y.relative(Y.resolve(Y.join(r,"../")),d.prettyPath),g=mn(d.prettyPath,d.path,[".js",".ts"]),l=to(c,t,{filePath:r,alias:e,dropExtension:g,dirs:o,cwd:n,modIsFile:d.type==="file"});if(l.isErr())return j(l.unwrapErr());if(l.unwrap())return C(l.unwrap());break}}return C(undefined)},mn=(e,t,r=[".ts",".js",""])=>{if(e===t)return true;let o=Y.parse(e),n=Y.parse(t),s=Y.join(o.dir,o.name),i=Y.join(n.dir,n.name);return s!==i?false:!!(r.includes(o.ext)&&r.includes(n.ext))},un=e=>{if(Be.existsSync(e))return {path:e,prettyPath:e,type:Be.statSync(e).isDirectory()?"directory":"file"};let t=Y.join(e,"../");if(!Be.existsSync(t))return;let r=Y.parse(e);if(r.ext===".js"){let n=`${e.slice(0,e.length-3)}.ts`;if(Be.existsSync(n))return {path:n,prettyPath:e,type:"file"}}let o=Be.readdirSync(t);for(let n of o){let s=Y.parse(n);if(s.name===r.base){let i=Y.join(t,n),a=i.slice(0,i.length-s.ext.length);return {path:i,prettyPath:a,type:Be.statSync(i).isDirectory()?"directory":"file"}}}},gn=(e,t,{doNotInstall:r}={doNotInstall:[]})=>{let o=new Set(r),n=e.filter(p=>!builtinModules.includes(p)&&!p.startsWith("node:")),s=dr(Y.dirname(t),""),i=new Set,a=new Set;if(s){let{devDependencies:p,dependencies:d}=JSON.parse(Be.readFileSync(s,"utf-8"));for(let c of n){let g=Ft(c);if(g.isErr()){console.warn(`${D} ${xe} Skipped adding import \`${T.cyan(c)}\`. Reason: Couldn't parse package name`);continue}let l=g.unwrap();if(!tn(l.name).validForNewPackages){console.warn(`${D} ${xe} Skipped adding import \`${T.cyan(c)}\`. Reason: Not a valid package name`);continue}if(o.has(l.name))continue;let h;if(d!==undefined&&(h=d[l.name]),h!==undefined){i.add(`${l.name}@${h}`);continue}if(p!==undefined&&(h=p[l.name]),h!==undefined){a.add(`${l.name}@${h}`);continue}i.add(l.name);}}return {dependencies:Array.from(i),devDependencies:Array.from(a)}},ut=[rn,on,fr,nn,sn,an,cn,ln,pn,dn];var hn=b.object({name:b.string(),category:b.string(),localDependencies:b.array(b.string()),dependencies:b.array(b.string()),devDependencies:b.array(b.string()),tests:b.boolean(),list:b.optional(b.boolean(),true),directory:b.string(),subdirectory:b.boolean(),files:b.array(b.string()),_imports_:b.record(b.string(),b.string())}),ht=b.object({name:b.string(),blocks:b.array(hn)}),ro=[".test.ts","_test.ts",".test.js","_test.js"],Se=e=>ro.find(t=>e.endsWith(t))!==undefined,oo=(e,{cwd:t,ignore:r,config:{excludeDeps:o,includeBlocks:n,includeCategories:s,excludeBlocks:i,excludeCategories:a,dirs:p,doNotListBlocks:d,doNotListCategories:c,listBlocks:g,listCategories:l}})=>{let h;try{h=Be.readdirSync(e);}catch{program.error(T.red(`Couldn't read the ${T.bold(e)} directory.`));}let R=[];for(let S of h){let $=Y.join(e,S);if(r.ignores(Y.relative(t,$))||Be.statSync($).isFile())continue;let m=Y.basename(S);if(a.length>0&&a.find(L=>L.trim()===m.trim())||s.length>0&&!s.find(L=>L.trim()===m.trim()))continue;let O=true;c.includes(m)&&(O=false),l.length>0&&!l.includes(m)&&(O=false);let V={name:m,blocks:[]},z=Be.readdirSync($);for(let L of z){let u=Y.join($,L);if(Be.statSync(u).isFile()){if(Se(L))continue;let w=yn(L),A=true;if(d.includes(w)&&(A=false),g.length>0&&!g.includes(w)&&(A=false),i.length>0&&i.find(k=>k.trim()===w.trim())||n.length>0&&!n.find(k=>k.trim()===w.trim()))continue;let x=ut.find(k=>k.matches(L));if(!x){console.warn(`${D} ${xe} Skipped \`${T.bold(u)}\` \`*${T.bold(Y.parse(L).ext)}\` files are not currently supported!`);continue}let U=z.find(k=>ro.find(F=>k===`${w}${F}`)),{dependencies:ce,devDependencies:f,local:y,imports:v}=x.resolveDependencies({filePath:u,isSubDir:false,excludeDeps:o,cwd:t,dirs:p}).match(k=>k,k=>{program.error(T.red(k));}),E={name:w,directory:Y.relative(t,$),category:m,tests:U!==undefined,subdirectory:false,list:O?A:false,files:[L],localDependencies:y,_imports_:v,dependencies:ce,devDependencies:f};U!==undefined&&E.files.push(U),V.blocks.push(E);}else {let w=L,A=true;if(d.includes(w)&&(A=false),g.length>0&&!g.includes(w)&&(A=false),i.length>0&&i.find(k=>k.trim()===w.trim())||n.length>0&&!n.find(k=>k.trim()===w.trim()))continue;let x=Be.readdirSync(u),U=x.findIndex(k=>Se(k))!==-1,ce=new Set,f=new Set,y=new Set,v={};for(let k of x){if(Se(k))continue;if(Be.statSync(Y.join(u,k)).isDirectory()){console.warn(`${D} ${xe} Skipped \`${T.bold(Y.join(u,k))}\` subdirectories are not currently supported!`);continue}let F=ut.find(I=>I.matches(k));if(!F){console.warn(`${D} ${xe} Skipped \`${Y.join(u,k)}\` \`*${T.bold(Y.parse(k).ext)}\` files are not currently supported!`);continue}let{local:_,dependencies:X,devDependencies:W,imports:le}=F.resolveDependencies({filePath:Y.join(u,k),isSubDir:true,excludeDeps:o,cwd:t,dirs:p}).match(I=>I,I=>{program.error(T.red(I));});for(let I of _)I!==`${m}/${w}`&&ce.add(I);for(let I of X)f.add(I);for(let I of W)y.add(I);for(let[I,K]of Object.entries(le))v[I]=K;}let E={name:w,directory:Y.relative(t,u),category:m,tests:U,subdirectory:true,list:O?A:false,files:[...x],localDependencies:Array.from(ce.keys()),dependencies:Array.from(f.keys()),devDependencies:Array.from(y.keys()),_imports_:v};V.blocks.push(E);}}R.push(V);}return R},yn=e=>Y.parse(Y.basename(e)).name,no=e=>{let t=[];for(let o of e){let n=[];for(let s of o.blocks){let i=`${s.category}/${s.name}`;!s.list&&!Vr(i,e)||n.push(s);}n.length>0&&t.push({name:o.name,blocks:n});}return [t,0]};var he="jsrepo-manifest.json";var te=()=>new vn({projectName:"jsrepo"});var Qe=(e,t)=>j(`There was an error fetching the \`${T.bold(t)}\` from ${T.bold(e.url)}.
|
|
24
24
|
|
|
25
|
-
${
|
|
26
|
-
1. The \`${
|
|
27
|
-
2. Your repository path is incorrect (wrong branch, wrong tag) default branches other than ${
|
|
25
|
+
${T.bold("This may be for one of the following reasons:")}
|
|
26
|
+
1. The \`${T.bold(t)}\` or containing repository doesn't exist
|
|
27
|
+
2. Your repository path is incorrect (wrong branch, wrong tag) default branches other than ${T.bold("default")} must be specified \`${T.bold(e.provider.refSpecifierExample())}\`
|
|
28
28
|
3. You are using an expired access token or a token that doesn't have access to this repository
|
|
29
|
-
`),
|
|
29
|
+
`),we={name:()=>"github",defaultBranch:()=>"main",refSpecifierExample:()=>"github/<owner>/<repo>/tree/<ref>",parseBlockSpecifier:e=>{let[t,r,o,...n]=e.split("/"),s;return n.length>2?s=`github/${r}/${o}/${n.slice(0,n.length-2).join("/")}`:s=`github/${r}/${o}`,[s,n.slice(n.length-2).join("/")]},resolveRaw:async(e,t)=>{let r=await we.info(e);return new URL(t,`https://raw.githubusercontent.com/${r.owner}/${r.repoName}/refs/${r.refs}/${r.ref}/`)},fetchRaw:async(e,t,{verbose:r}={})=>{let o=await we.info(e),n=await we.resolveRaw(o,t);r?.(`Trying to fetch from ${n}`);try{let s=te().get(`${we.name()}-token`),i=new Headers;s!==void 0&&i.append("Authorization",`token ${s}`);let a=await nt(n,{headers:i});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?C(await a.text()):Qe(o,t)}catch(s){return r?.(`error in response ${s} `),Qe(o,t)}},fetchManifest:async e=>{let t=await we.fetchRaw(e,he);if(t.isErr())return j(t.unwrapErr());let r=b.safeParse(b.array(ht),JSON.parse(t.unwrap()));return r.success?C(r.output):j(`Error parsing categories: ${r.issues}`)},info:async e=>{if(typeof e!="string")return e;let t=e.replaceAll(/(https:\/\/github.com\/)|(github\/)/g,""),[r,o,...n]=t.split("/"),s=we.defaultBranch(),i=te().get(`${we.name()}-token`),a=new Octokit({auth:i});if(n[0]==="tree")s=n[1];else try{let{data:d}=await a.rest.repos.get({owner:r,repo:o});s=d.default_branch;}catch{}let p="heads";if(s!==we.defaultBranch())try{let{data:d}=await a.rest.git.listMatchingRefs({owner:r,repo:o,ref:"tags"});d.some(c=>c.ref===`refs/tags/${s}`)&&(p="tags");}catch{p="heads";}return {refs:p,url:e,name:we.name(),repoName:o,owner:r,ref:s,provider:we}},matches:e=>e.toLowerCase().startsWith("https://github.com")||e.toLowerCase().startsWith("github")},ze={name:()=>"gitlab",defaultBranch:()=>"main",refSpecifierExample:()=>"gitlab/<owner>/<repo>/-/tree/<ref>",parseBlockSpecifier:e=>{let[t,r,o,...n]=e.split("/"),s;return n.length>2?s=`gitlab/${r}/${o}/${n.slice(0,n.length-2).join("/")}`:s=`gitlab/${r}/${o}`,[s,n.slice(n.length-2).join("/")]},resolveRaw:async(e,t)=>{let r=await ze.info(e);return new URL(`${encodeURIComponent(t)}/raw?ref=${r.ref}`,`https://gitlab.com/api/v4/projects/${encodeURIComponent(`${r.owner}/${r.repoName}`)}/repository/files/`)},fetchRaw:async(e,t,{verbose:r}={})=>{let o=await we.info(e),n=await ze.resolveRaw(o,t);r?.(`Trying to fetch from ${n}`);try{let s=te().get(`${ze.name()}-token`),i=new Headers;s!==void 0&&i.append("PRIVATE-TOKEN",`${s}`);let a=await nt(n,{headers:i});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?C(await a.text()):Qe(o,t)}catch{return Qe(o,t)}},fetchManifest:async e=>{let t=await ze.fetchRaw(e,he);if(t.isErr())return j(t.unwrapErr());let r=b.safeParse(b.array(ht),JSON.parse(t.unwrap()));return r.success?C(r.output):j(`Error parsing categories: ${r.issues}`)},info:async e=>{if(typeof e!="string")return e;let t=e.replaceAll(/(https:\/\/gitlab.com\/)|(gitlab\/)/g,""),[r,o,...n]=t.split("/"),s=ze.defaultBranch(),i="heads";if(n[0]==="-"&&n[1]==="tree")if(n[2].includes("?")){let[a,p]=n[2].split("?");s=a,p.startsWith("ref_type=")&&p.slice(10)==="tags"&&(i="tags");}else s=n[2];else try{let a=te().get(`${ze.name()}-token`),p=new Headers;a!==void 0&&p.append("Authorization",`Bearer ${a}`);let d=await nt(`https://gitlab.com/api/v4/projects/${encodeURIComponent(`${r}/${o}`)}`,{headers:p});d.ok&&(s=(await d.json()).default_branch);}catch{}return {refs:i,url:e,name:ze.name(),repoName:o,owner:r,ref:s,provider:ze}},matches:e=>e.toLowerCase().startsWith("https://gitlab.com")||e.toLowerCase().startsWith("gitlab")},_e={name:()=>"bitbucket",defaultBranch:()=>"master",refSpecifierExample:()=>"bitbucket/<owner>/<repo>/src/<ref>",parseBlockSpecifier:e=>{let[t,r,o,...n]=e.split("/"),s;return n.length>2?s=`azure/${r}/${o}/${n.slice(0,n.length-2).join("/")}`:s=`azure/${r}/${o}`,[s,n.slice(n.length-2).join("/")]},resolveRaw:async(e,t)=>{let r=await _e.info(e);return new URL(t,`https://api.bitbucket.org/2.0/repositories/${r.owner}/${r.repoName}/src/${r.ref}/`)},fetchRaw:async(e,t,{verbose:r}={})=>{let o=await _e.info(e),n=await _e.resolveRaw(o,t);r?.(`Trying to fetch from ${n}`);try{let s=te().get(`${_e.name()}-token`),i=new Headers;s!==void 0&&i.append("Authorization",`Bearer ${s}`);let a=await nt(n,{headers:i});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?C(await a.text()):Qe(o,t)}catch{return Qe(o,t)}},fetchManifest:async e=>{let t=await _e.fetchRaw(e,he);if(t.isErr())return j(t.unwrapErr());let r=b.safeParse(b.array(ht),JSON.parse(t.unwrap()));return r.success?C(r.output):j(`Error parsing categories: ${r.issues}`)},info:async e=>{if(typeof e!="string")return e;let t=e.replaceAll(/(https:\/\/bitbucket.org\/)|(bitbucket\/)/g,""),[r,o,...n]=t.split("/"),s="heads",i=_e.defaultBranch();if(n[0]==="src")i=n[1];else try{let a=te().get(`${_e.name()}-token`),p=new Headers;a!==void 0&&p.append("Authorization",`Bearer ${a}`);let d=await nt(`https://api.bitbucket.org/2.0/repositories/${r}/${o}`,{headers:p});d.ok&&(i=(await d.json()).mainbranch.name);}catch{}return {refs:s,url:e,name:_e.name(),repoName:o,owner:r,ref:i,provider:_e}},matches:e=>e.toLowerCase().startsWith("https://bitbucket.org")||e.toLowerCase().startsWith("bitbucket")},Ge={name:()=>"azure",defaultBranch:()=>"main",refSpecifierExample:()=>"azure/<org>/<project>/<repo>/(tags|heads)/<ref>",parseBlockSpecifier:e=>{let[t,r,o,n,...s]=e.split("/"),i;return s.length>2?i=`${t}/${r}/${o}/${n}${s.slice(0,s.length-2).join("/")}`:i=`${t}/${r}/${o}/${n}`,[i,s.slice(s.length-2).join("/")]},resolveRaw:async(e,t)=>{let r=await Ge.info(e),o=r.refs==="tags"?"tag":"branch";return new URL(`https://dev.azure.com/${r.owner}/${r.projectName}/_apis/git/repositories/${r.repoName}/items?path=${t}&api-version=7.2-preview.1&versionDescriptor.version=${r.ref}&versionDescriptor.versionType=${o}`)},fetchRaw:async(e,t,{verbose:r}={})=>{let o=await Ge.info(e),n=await Ge.resolveRaw(o,t);r?.(`Trying to fetch from ${n}`);try{let s=te().get(`${Ge.name()}-token`),i=new Headers;s!==void 0&&i.append("Authorization",`Bearer ${s}`);let a=await nt(n,{headers:i});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?C(await a.text()):Qe(o,t)}catch(s){return r?.(`error in response ${s} `),Qe(o,t)}},fetchManifest:async e=>{let t=await Ge.fetchRaw(e,he);if(t.isErr())return j(t.unwrapErr());let r=b.safeParse(b.array(ht),JSON.parse(t.unwrap()));return r.success?C(r.output):j(`Error parsing categories: ${r.issues}`)},info:async e=>{if(typeof e!="string")return e;let t=e.replaceAll(/(azure\/)/g,""),[r,o,n,...s]=t.split("/"),i=Ge.defaultBranch(),a="heads";return ["tags","heads"].includes(s[0])&&(a=s[0],s[1]&&s[1]!==""&&(i=s[1])),{refs:a,url:e,name:Ge.name(),projectName:o,repoName:n,owner:r,ref:i,provider:Ge}},matches:e=>e.toLowerCase().startsWith("azure")},so=(e,t,r)=>j(`There was an error fetching ${T.bold(new URL(t,e).toString())}
|
|
30
30
|
|
|
31
|
-
${
|
|
31
|
+
${T.bold(r)}`),Ie={name:()=>"http",defaultBranch:()=>"",refSpecifierExample:()=>"",parseBlockSpecifier:e=>{let t=new URL(e),r=t.pathname.split("/");return [new URL(r.slice(0,r.length-2).join("/"),t.origin).toString(),r.slice(r.length-2).join("/")]},info:async e=>typeof e!="string"?e:{name:Ie.name(),url:Br(e),provider:Ie,owner:"",ref:"",refs:"heads",repoName:"",projectName:""},resolveRaw:async(e,t)=>{let r=await Ie.info(e);return new URL(t,r.url)},fetchRaw:async(e,t,{verbose:r}={})=>{let o=await Ie.info(e),n=await Ie.resolveRaw(o,t);r?.(`Trying to fetch from ${n}`);try{let s=await nt(n);return r?.(`Got a response from ${n} ${s.status} ${s.statusText}`),s.ok?C(await s.text()):so(o.url,t,`The server responded with: ${s.status}: ${s.statusText}`)}catch(s){return r?.(`error in response ${s} `),so(o.url,t,String(s))}},fetchManifest:async e=>{let t=await Ie.fetchRaw(e,he);if(t.isErr())return j(t.unwrapErr());let r=b.safeParse(b.array(ht),JSON.parse(t.unwrap()));return r.success?C(r.output):j(`Error parsing categories: ${r.issues}`)},matches:e=>e.startsWith("http")},ee=[we,ze,_e,Ge,Ie],It=async e=>{let t=ee.find(r=>r.matches(e));return t?C(await t.info(e)):j(`Only ${ee.map((r,o)=>`${o===ee.length-1?"and ":""}${T.bold(r.name())}`).join(", ")} registries are supported at this time!`)},vt=async(...e)=>{let t=new Map;for(let{path:r,info:o}of e){let n=await o.provider.fetchManifest(o);if(n.isErr())return j({message:n.unwrapErr(),repo:r});let s=n.unwrap();for(let i of s)for(let a of i.blocks){let[p,d]=o.provider.parseBlockSpecifier(ne(o.url,a.category,a.name));t.set(ne(p,d),{...a,sourceRepo:o});}}return C(t)},wt=async(...e)=>{let t=[];for(let r of e){let o=await It(r);if(o.isErr())return j({message:o.unwrapErr(),repo:r});let n=o.unwrap();t.push({path:r,info:n});}return C(t)};var st=async(e,t,r,o=new Map)=>{let n=new Map;for(let s of e){let i,a=ee.find(d=>s.startsWith(d.name()));if(a){let[d,c]=a.parseBlockSpecifier(s);i=t.get(ne(d,c));}else {if(r.length===0)return j(T.red(`If your config doesn't contain repos then you must provide the repo in the block specifier ex: \`${T.bold(`github/ieedan/std/${s}`)}\`!`));for(let{info:d}of r){let[c,g]=d.provider.parseBlockSpecifier(ne(d.url,s)),l=t.get(ne(c,g));if(l!==undefined){i=l;break}}}if(!i)return j(`Invalid block! ${T.bold(s)} does not exist!`);let p=`${i.category}/${i.name}`;if(n.set(p,{name:i.name,subDependency:false,block:i}),i.localDependencies&&i.localDependencies.length>0){let d=await st(i.localDependencies.filter(c=>!n.has(c)&&!o.has(c)),t,r,n);if(d.isErr())return j(d.unwrapErr());for(let c of d.unwrap())n.set(`${c.block.category}/${c.block.name}`,c);}}return C(Lr(n,(s,i)=>i))},it=(e,t,r)=>{let o=[],n=De(t.paths,r);n.isErr()&&program.error(T.red(n.unwrapErr()));let s=n.unwrap();for(let[i,a]of e){let p;s[a.category]!==undefined?p=Y.join(r,s[a.category]):p=Y.join(r,s["*"],a.category);let d=Y.join(p,a.files[0]);a.subdirectory&&(d=Y.join(p,a.name)),Be.existsSync(d)&&o.push({specifier:`${a.category}/${a.name}`,path:d,block:a});}return o};var bn={"no-workspace":"--no-workspace","install-as-dev-dependency":"-D"},Rn={"install-as-dev-dependency":"-D"},Cn={"no-workspace":"--workspaces=false","install-as-dev-dependency":"-D"},io={"no-workspace":"--ignore-workspace","install-as-dev-dependency":"-D"},ao={"no-workspace":"--focus","install-as-dev-dependency":"-D"},ur={bun:bn,npm:Cn,pnpm:io,deno:Rn,yarn:ao,"yarn@berry":ao,"pnpm@6":io};var Te=async({pm:e,deps:t,dev:r,cwd:o,ignoreWorkspace:n=false})=>{let s=[...t];r&&s.push(ur[e]["install-as-dev-dependency"]);let i=ur[e]["no-workspace"];n&&i&&s.push(i);let a=resolveCommand$1(e,"add",s);if(a==null)return j(T.red(`Could not resolve add command for '${e}'.`));try{return await execa(a.command,[...a.args],{cwd:o}),C(t)}catch{return j(T.red(`Failed to install ${T.bold(t.join(", "))}! Failed while running '${T.bold(`${a.command} ${a.args.join(" ")}`)}'`))}},En=/\{\{([^\/]+)\/([^\}]+)\}\}/g,co=({template:e,config:t,destPath:r,cwd:o})=>{let n=Y.join(r,"../");return e.replace(En,(s,i,a)=>{if(t.paths[i]===undefined){if(t.paths["*"].startsWith(".")){let p=Y.relative(n,Y.join(o,t.paths["*"],i,a));return p.startsWith(".")?p:`./${p}`}return Y.join(t.paths["*"],i,a)}if(t.paths[i].startsWith(".")){let p=Y.relative(n,Y.join(o,t.paths[i],a));return p.startsWith(".")?p:`./${p}`}return Y.join(t.paths[i],a)})};var Qt=async({file:e,config:t,imports:r,watermark:o,prettierOptions:n,biomeOptions:s,cwd:i,verbose:a})=>{let p=ut.find(c=>c.matches(e.destPath)),d=e.content;if(p){t.watermark&&(d=`${p.comment(o)}
|
|
32
32
|
|
|
33
|
-
${d}`),a?.(`Formatting ${
|
|
33
|
+
${d}`),a?.(`Formatting ${T.bold(e.destPath)}`);try{d=await p.format(d,{filePath:e.destPath,formatter:t.formatter,prettierOptions:n,biomeOptions:s});}catch(c){return j(`Error formatting ${T.bold(e.destPath)} ${c}`)}}for(let[c,g]of Object.entries(r)){let l=co({template:g,config:t,destPath:e.destPath,cwd:i}),h=new RegExp(`(['"])${Sn(c)}\\1`,"g");d=d.replaceAll(h,`$1${l}$1`);}return C(d)},po=async({file:e,config:t,prettierOptions:r,biomeOptions:o})=>{let n=ut.find(i=>i.matches(e.destPath)),s=e.content;if(n)try{s=await n.format(e.content,{filePath:e.destPath,formatter:t.formatter,prettierOptions:r,biomeOptions:o});}catch{return s}return s};var $t=async({formatter:e,cwd:t})=>{let r=null;e==="prettier"&&(r=await Fe.resolveConfig(Y.join(t,".prettierrc")));let o=null;if(e==="biome"){let n=Y.join(t,"biome.json");Be.existsSync(n)&&(o=JSON.parse(Be.readFileSync(n).toString()));}return {biomeOptions:o,prettierOptions:r}};var er=(e,t)=>`jsrepo ${e}
|
|
34
34
|
Installed from ${t}
|
|
35
|
-
${new Date().toLocaleDateString().replaceAll("/","-")}`;var
|
|
36
|
-
`;return o+=`${
|
|
35
|
+
${new Date().toLocaleDateString().replaceAll("/","-")}`;var Pt=async(e,{verbose:t=undefined})=>{let r=spinner();for(let o of e){t?t(o.loadingMessage):r.start(o.loadingMessage);try{await o.run();}catch(n){r.stop(`Error while ${o.loadingMessage}`),console.error(n);}t?t(o.completedMessage):r.stop(o.completedMessage);}},tr=async({tasks:e,startMessage:t,stopMessage:r,verbose:o})=>{let n=spinner(),s=i=>{o?o(i):n.message(i);};o?o(t):n.start(t),await Promise.all([...e.map(i=>i.run({message:s}))]),o?o(r):n.stop(r);},kt=e=>{let t=20;e.map(n=>{let s=zr(Le(n),4);s.length>t&&(t=s.length);});let r="Next Steps",o=`${D}
|
|
36
|
+
`;return o+=`${ir} ${r} ${jt.repeat(t-r.length-1)}${nr}
|
|
37
37
|
`,o+=`${D} ${" ".repeat(t)} ${D}
|
|
38
|
-
`,e.map(n=>{o+=`${D} ${
|
|
38
|
+
`,e.map(n=>{o+=`${D} ${Gr(n,t-1)} ${D}
|
|
39
39
|
`;}),o+=`${D} ${" ".repeat(t)} ${D}
|
|
40
|
-
`,o+=`${
|
|
41
|
-
`,o},
|
|
42
|
-
`;a+=`${
|
|
40
|
+
`,o+=`${ir}${jt.repeat(t+2)}${sr}
|
|
41
|
+
`,o},ho=(e,t=3)=>{let r=e.slice(0,t),o=e.length-r.length;return `${r.join(", ")}${o>0?` and ${o} other(s)`:""}`},Nn=(e,t,r)=>{let o=detectSync({cwd:process.cwd()})?.agent??"npm",n=resolveCommand$1(o,"global",["jsrepo@latest"]),s=[`Update available! ${T.redBright(t)} -> ${T.greenBright(r)}`,`${T.cyan("Changelog")}: https://github.com/ieedan/jsrepo/releases/tag/${e}@${r}`,`Run ${T.cyan(`${n?.command} ${n?.args.join(" ")}`)} to update!`,"",`${T.yellowBright("Star")} on GitHub for updates: https://github.com/ieedan/jsrepo`],i=30;s.map(p=>{let d=Le(p);d.length+4>i&&(i=d.length+4);});let a=`
|
|
42
|
+
`;a+=`${Ar}${jt.repeat(i)}${nr}
|
|
43
43
|
`,a+=`${D}${" ".repeat(i)}${D}
|
|
44
|
-
`;for(let p of s)a+=`${D}${
|
|
44
|
+
`;for(let p of s)a+=`${D}${Ur(p,i)}${D}
|
|
45
45
|
`;return a+=`${D}${" ".repeat(i)}${D}
|
|
46
|
-
`,a+=`${
|
|
47
|
-
`,
|
|
48
|
-
`),process.stdout.write(
|
|
49
|
-
`));continue}let n=await confirm({message:`Remove ${r.name()} token?`,initialValue:true});isCancel(n)&&(cancel("Canceled!"),process.exit(0)),n&&t.delete(o);}return}if(wt.length>1){let r=await select({message:"Which provider is this token for?",options:wt.map(o=>({label:o.name(),value:o.name()})),initialValue:wt[0].name()});isCancel(r)&&(cancel("Canceled!"),process.exit(0)),e.provider=r;}else e.provider=wt[0].name();if(e.token===undefined){let r=await password({message:"Paste your token",validate(o){if(o.trim()==="")return "Please provide a value"}});(isCancel(r)||!r)&&(cancel("Canceled!"),process.exit(0)),e.token=r;}t.set(`${e.provider}-token`,e.token);};var Gn=k.object({dirs:k.optional(k.array(k.string())),outputDir:k.optional(k.string()),includeBlocks:k.optional(k.array(k.string())),includeCategories:k.optional(k.array(k.string())),excludeBlocks:k.optional(k.array(k.string())),excludeCategories:k.optional(k.array(k.string())),excludeDeps:k.optional(k.array(k.string())),listBlocks:k.optional(k.array(k.string())),listCategories:k.optional(k.array(k.string())),doNotListBlocks:k.optional(k.array(k.string())),doNotListCategories:k.optional(k.array(k.string())),preview:k.optional(k.boolean()),output:k.boolean(),verbose:k.boolean(),cwd:k.string()}),yr=new Command("build").description(`Builds the provided --dirs in the project root into a \`${ge}\` file.`).option("--dirs [dirs...]","The directories containing the blocks.").option("--output-dir <dir>","The directory to output the registry to. (Copies jsrepo-manifest.json + all required files)").option("--include-blocks [blockNames...]","Include only the blocks with these names.").option("--include-categories [categoryNames...]","Include only the categories with these names.").option("--exclude-blocks [blockNames...]","Do not include the blocks with these names.").option("--exclude-categories [categoryNames...]","Do not include the categories with these names.").option("--list-blocks [blockNames...]","List only the blocks with these names.").option("--list-categories [categoryNames...]","List only the categories with these names.").option("--do-not-list-blocks [blockNames...]","Do not list the blocks with these names.").option("--do-not-list-categories [categoryNames...]","Do not list the categories with these names.").option("--exclude-deps [deps...]","Dependencies that should not be added.").option("--preview","Display a preview of the blocks list.").option("--no-output",`Do not output a \`${ge}\` file.`).option("--verbose","Include debug logs.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async e=>{let t=k.parse(Gn,e);pe(te),await Hn(t),outro(E.green("All done!"));}),Hn=async e=>{let t=spinner(),r=[],o=_t(e.cwd).match(c=>{if(c===null)return {$schema:"",dirs:e.dirs??[],outputDir:e.outputDir,doNotListBlocks:e.doNotListBlocks??[],doNotListCategories:e.doNotListCategories??[],listBlocks:e.listBlocks??[],listCategories:e.listCategories??[],excludeDeps:e.excludeDeps??[],includeBlocks:e.includeBlocks??[],includeCategories:e.includeCategories??[],excludeBlocks:e.excludeBlocks??[],excludeCategories:e.excludeCategories??[],preview:e.preview};let u=c;return e.dirs&&(u.dirs=e.dirs),e.outputDir&&(u.outputDir=e.outputDir),e.doNotListBlocks&&(u.doNotListBlocks=e.doNotListBlocks),e.doNotListCategories&&(u.doNotListCategories=e.doNotListCategories),e.listBlocks&&(u.listBlocks=e.listBlocks),e.listCategories&&(u.listCategories=e.listCategories),e.includeBlocks&&(u.includeBlocks=e.includeBlocks),e.includeCategories&&(u.includeCategories=e.includeCategories),e.excludeBlocks&&(u.excludeBlocks=e.excludeBlocks),e.excludeCategories&&(u.excludeCategories=e.excludeCategories),e.excludeDeps&&(u.excludeDeps=e.excludeDeps),e.preview!==undefined&&(u.preview=e.preview),u.rules={...nr,...u.rules},u},c=>program.error(E.red(c))),n;o.outputDir?n=q.join(e.cwd,o.outputDir):n=e.cwd;let s=q.join(n,ge);if(e.output&&Le.existsSync(s)){if(o.outputDir){let c=JSON.parse(Le.readFileSync(s).toString());for(let u of c)for(let f of u.blocks){let h=q.join(n,f.directory);Le.existsSync(h)&&Le.rmSync(h,{recursive:true});}}Le.rmSync(s);}for(let c of o.dirs){let u=q.join(e.cwd,c);t.start(`Building ${E.cyan(u)}`);let f=Xr(u,{cwd:e.cwd,config:o});for(let h of f){if(r.find(R=>R.name===h.name)!==undefined){console.warn(`${D} ${Ce} Skipped adding \`${E.cyan(`${c}/${h.name}`)}\` because a category with the same name already exists!`);continue}r.push(h);}t.stop(`Built ${E.cyan(u)}`);}t.start("Checking manifest");let{warnings:i,errors:a}=Ar(r,o,o.rules);t.stop("Completed checking manifest."),(i.length>0||a.length>0)&&console.log(D);for(let c of i)console.log(c);if(a.length>0){for(let c of a)console.log(c);program.error(E.red(`Completed checking manifest with ${E.bold(`${a.length} error(s)`)} and ${E.bold(`${i.length} warning(s)`)}`));}let[p,d]=Qr(r);if(r=p,d>0&&log.step(`Removed ${d} unused block${d>1?"s":""}.`),o.preview){let c=r.flatMap(u=>u.blocks.filter(f=>f.list).map(f=>`${E.cyan(f.category)}/${f.name}`));log.message(`${E.yellow("Preview")}:`);for(let u of c)console.log(`${D} \u25FB ${u}`);}if(e.output){if(o.outputDir){t.start(`Copying registry files to \`${E.cyan(n)}\``);for(let c of r)for(let u of c.blocks){let f=q.join(e.cwd,u.directory),h=q.join(n,u.directory);Le.existsSync(h)||Le.mkdirSync(h,{recursive:true});for(let R of u.files)Le.copyFileSync(q.join(f,R),q.join(h,R));}t.stop(`Copied registry files to \`${E.cyan(n)}\``);}t.start(`Writing output to \`${E.cyan(s)}\``),Le.writeFileSync(s,JSON.stringify(r,null," ")),t.stop(`Wrote output to \`${E.cyan(s)}\``);}};var ts=k.objectWithRest({repo:k.optional(k.string()),allow:k.boolean(),cwd:k.string()},k.unknown()),$r=new Command("exec").alias("x").description("Execute a block as a script.").addArgument(new Argument("script","Name of the script you want to execute. ex: (general/hello, github/ieedan/std/general/hello)").argOptional()).option("--repo <repo>","Repository to download and run the script from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",false).option("--cwd <path>","The current working directory.",process.cwd()).allowExcessArguments().allowUnknownOption().action(async(e,t,r)=>{let o=k.parse(ts,t);pe(te),await rs(e,o,r);}),rs=async(e,t,r)=>{let o=e,n=spinner(),s=Pe(t.cwd),i=s.isErr(),a;s.isErr()?a={$schema:"",includeTests:false,watermark:true,paths:{"*":"./"},repos:[]}:a=s.unwrap();let p=a.repos;if(t.repo&&(p=[t.repo]),o&&Q.find(l=>o?.startsWith(l.name()))){let[l,C,v,...$]=o.split("/"),P;if($.length>2?P=`${l}/${C}/${v}/${$.slice(0,$.length-2).join("/")}`:P=`${l}/${C}/${v}`,!p.find(J=>J===P)){if(!t.allow){let J=await confirm({message:`Allow ${me} to download and run code from ${E.cyan(P)}?`,initialValue:true});(isCancel(J)||!J)&&(cancel("Canceled!"),process.exit(0));}p=[P];}}if(!t.allow&&t.repo){let l=await confirm({message:`Allow ${me} to download and run code from ${E.cyan(t.repo)}?`,initialValue:true});(isCancel(l)||!l)&&(cancel("Canceled!"),process.exit(0));}p.length===0&&(i&&program.error(E.red(`Fully quality your script ex: (github/ieedan/std/scripts/build) or provide the \`${E.bold("--repo")}\` flag to specify a registry.`)),program.error(E.red(`There were no repos present in your config and you didn't provide the \`${E.bold("--repo")}\` flag with a repo.`))),n.start(`Fetching scripts from ${E.cyan(p.join(", "))}`);let d=(await gt(...p)).match(l=>l,({repo:l,message:C})=>{n.stop(`Failed to get info for ${E.cyan(l)}`),program.error(E.red(C));}),c=(await ut(...d)).match(l=>l,({repo:l,message:C})=>{n.stop(`Failed fetching scripts from ${E.cyan(l)}`),program.error(E.red(C));});if(n.stop(`Retrieved scripts from ${E.cyan(p.join(", "))}`),!o){let l=await select({message:"Select which script to run.",options:Array.from(c.entries()).filter(([C,v])=>v.list).map(([C,v])=>{let $;return p.length>1?$=`${E.cyan(`${v.sourceRepo.name}/${v.sourceRepo.owner}/${v.sourceRepo.repoName}/${v.category}`)}/${v.name}`:$=`${E.cyan(v.category)}/${v.name}`,{label:$,value:C}})});isCancel(l)&&(cancel("Canceled!"),process.exit(0)),o=l;}let u=(await st([o],c,d)).match(l=>l,l=>program.error(l)),f="temp-jsrepo-exec",h=`./${f}/${encodeURIComponent(o)}`,R=q.join(process.cwd(),h);a.paths["*"]=h,Le.mkdirSync(R,{recursive:true});let T=(await detect({cwd:process.cwd()}))?.agent??"npm",y=[],m=new Set,N=new Set,M=De(a.paths,t.cwd);M.isErr()&&program.error(E.red(M.unwrapErr()));let B=M.unwrap(),g=[];for(let{block:l}of u){let C=`${l.sourceRepo.url}/${l.category}/${l.name}`,v=`${l.category}/${l.name}`,$=l.sourceRepo,P=q.join(t.cwd,B["*"],l.category);g.push(v),y.push({run:async({message:J})=>{J(`Adding ${E.cyan(C)}`),Le.mkdirSync(P,{recursive:true});let z=[],X=async W=>{let L=await $.provider.fetchRaw($,W);return L.isErr()&&(n.stop(E.red(`Error fetching ${E.bold(W)}`)),program.error(E.red(`There was an error trying to get ${C}`))),L.unwrap()};for(let W of l.files){if(!a.includeTests&&Ee(W))continue;let L=q.join(l.directory,W),_;l.subdirectory?_=q.join(P,l.name,W):_=q.join(P,W);let ie=await X(L),Ne=_.slice(0,_.length-W.length);Le.mkdirSync(Ne,{recursive:true}),z.push({content:ie,destPath:_});}for(let W of z)Le.writeFileSync(W.destPath,W.content);if(a.includeTests&&l.tests){let{devDependencies:W}=JSON.parse(Le.readFileSync(q.join(t.cwd,"package.json")).toString());(W===undefined||W.vitest===undefined)&&m.add("vitest");}for(let W of l.devDependencies)m.add(W);for(let W of l.dependencies)N.add(W);}});}if(await Xt({startMessage:"Adding blocks",stopMessage:`Added ${E.cyan(g.join(", "))}`,tasks:y}),N.size>0||m.size>0){let l={name:"temp-package",type:"module",version:"0.0.1"},C=q.join(R,"package.json");Le.writeFileSync(C,JSON.stringify(l,null," ")),N.size>0&&(t.verbose||n.start(`Installing dependencies with ${E.cyan(T)}`),(await Ie({pm:T,deps:Array.from(N),dev:false,cwd:R,ignoreWorkspace:true})).match(v=>{t.verbose||n.stop(`Installed ${E.cyan(v.join(", "))}`);},v=>{t.verbose||n.stop("Failed to install dependencies"),program.error(v);})),m.size>0&&(t.verbose||n.start(`Installing dependencies with ${E.cyan(T)}`),(await Ie({pm:T,deps:Array.from(m),dev:true,cwd:R,ignoreWorkspace:true})).match(v=>{t.verbose||n.stop(`Installed ${E.cyan(v.join(", "))}`);},v=>{t.verbose||n.stop("Failed to install dev dependencies"),program.error(v);}));}let S=r.parent.rawArgs.findIndex(l=>l==="--"),b=[];S!==-1&&(b=r.parent.rawArgs.slice(S+1)),console.clear();let A=u[0],Z;A.block.subdirectory?Z=q.join(R,`${A.block.category}/${A.block.name}/index.js`):Z=q.join(R,`${A.block.category}/${A.block.name}.js`);let le=resolveCommand(T,"execute",["tsx",Z,...b]);le||program.error(E.red("Error resolving run command!"));try{await execa(le.command,le.args,{cwd:process.cwd(),stdin:process.stdin,stdout:process.stdout});}finally{Le.rmSync(q.join(process.cwd(),f),{recursive:true,force:true});}};var ls=k.object({repos:k.optional(k.array(k.string())),watermark:k.boolean(),tests:k.optional(k.boolean()),formatter:k.optional(sr),project:k.optional(k.boolean()),registry:k.optional(k.boolean()),script:k.string(),yes:k.boolean(),cwd:k.string()}),Rr=new Command("init").description("Initializes your project with a configuration file.").argument("[registries...]","Registries to install the blocks from.",[]).option("--repos [repos...]","Repository to install the blocks from. (DEPRECATED)").option("--no-watermark","Will not add a watermark to each file upon adding it to your project.").option("--tests","Will include tests with the blocks.").addOption(new Option("--formatter <formatter>","What formatter to use when adding or updating blocks.").choices(["prettier","biome"])).option("-P, --project","Takes you through the steps to initialize a project.").option("-R, --registry","Takes you through the steps to initialize a registry.").option("--script <name>","The name of the build script. (For Registry setup)","build:registry").option("-y, --yes","Skip confirmation prompt.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async(e,t)=>{let r=k.parse(ls,t);if(pe(te),r.registry!==undefined&&r.project!==undefined&&program.error(E.red(`You cannot provide both ${E.bold("--project")} and ${E.bold("--registry")} at the same time.`)),r.repos!==undefined&&log.warn(`The ${E.gray("`--repos`")} flag is deprecated! Instead supply registries as arguments. ${E.cyan(`\`jsrepo init ${r.repos.join(" ")}\``)}`),r.registry===undefined&&r.project===undefined&&e.length===0){let o=await select({message:"Initialize a project or registry?",options:[{value:"project",label:"project"},{value:"registry",label:"registry"}],initialValue:"project"});isCancel(o)&&(cancel("Canceled!"),process.exit(0)),r.project=o==="project";}r.project||e.length>0?await ds(e,r):await ps(r),outro(E.green("All done!"));}),ds=async(e,t)=>{let r=Pe(t.cwd),o=spinner(),n,s=await text({message:"Please enter a default path to install the blocks",validate(f){if(f.trim()==="")return "Please provide a value"},placeholder:"./src/blocks",initialValue:r.isOk()?r.unwrap().paths["*"]:undefined});isCancel(s)&&(cancel("Canceled!"),process.exit(0)),r.isOk()?n={...r.unwrap().paths,"*":s}:n={"*":s};let i=[...r.isOk()?r.unwrap().repos:[],...e,...t.repos??[]];if(i.length>0)for(let f of i){if(r.isOk()&&r.unwrap().repos.find(h=>h===f)){let h=await confirm({message:`Configure ${f}?`,initialValue:t.yes});if(isCancel(h)&&(cancel("Canceled!"),process.exit(0)),!h)continue}log.info(`Configuring ${E.cyan(f)}`),n=await ho(f,n);}for(;;){let f=await confirm({message:`Add ${i.length>0?"another":"a"} repo?`,initialValue:i.length===0});if(isCancel(f)&&(cancel("Canceled!"),process.exit(0)),!f)break;let h=await text({message:"Where should we download the blocks from?",placeholder:"github/ieedan/std",validate:R=>{if(R.trim().length===0)return "Please provide a value";if(!Q.find(T=>T.matches(R)))return `Invalid provider! Valid providers (${Q.map(T=>T.name()).join(", ")})`}});isCancel(h)&&(cancel("Canceled!"),process.exit(0)),n=await ho(h,n),i.push(h);}if(!t.formatter){let f=r.isErr()?"none":r.unwrap().formatter??"none";Le.existsSync(q.join(t.cwd,".prettierrc"))&&(f="prettier"),Le.existsSync(q.join(t.cwd,"biome.json"))&&(f="biome");let h=await select({message:"What formatter would you like to use?",options:["Prettier","Biome","None"].map(R=>({value:R.toLowerCase(),label:R})),initialValue:f});isCancel(h)&&(cancel("Canceled!"),process.exit(0)),h!=="none"&&(t.formatter=h);}let a={$schema:`https://unpkg.com/jsrepo@${te.package.version}/schemas/project-config.json`,repos:i,includeTests:r.isOk()&&t.tests===undefined?r.unwrap().includeTests:t.tests??false,watermark:t.watermark,formatter:t.formatter,paths:n};o.start(`Writing config to \`${ot}\``);let{prettierOptions:p,biomeOptions:d}=await ht({formatter:a.formatter,cwd:t.cwd}),c=q.join(t.cwd,ot),u=await dr.format(JSON.stringify(a,null," "),{biomeOptions:d,prettierOptions:p,filePath:c,formatter:a.formatter});Le.existsSync(t.cwd)||Le.mkdirSync(t.cwd,{recursive:true}),Le.writeFileSync(c,u),o.stop(`Wrote config to \`${ot}\`.`);},ho=async(e,t)=>{let r=spinner(),o=ce(),n=Q.find(c=>c.matches(e));n||program.error(E.red(`Invalid provider! Valid providers (${Q.map(c=>c.name()).join(", ")})`));let s=`${n.name()}-token`;if(!o.get(s)&&n.name()!==Se.name()){let c=await confirm({message:"Would you like to add an auth token?",initialValue:false});if(isCancel(c)&&(cancel("Canceled!"),process.exit(0)),c){let u=await password({message:"Paste your token",validate(f){if(f.trim()==="")return "Please provide a value"}});isCancel(u)&&(cancel("Canceled!"),process.exit(0)),o.set(s,u);}}r.start(`Fetching categories from ${E.cyan(e)}`);let a=await n.fetchManifest(e);r.stop(`Fetched categories from ${E.cyan(e)}`),a.isErr()&&program.error(E.red(a.unwrapErr()));let p=a.unwrap(),d=await multiselect({message:"Which category paths would you like to configure?",options:p.map(c=>({label:c.name,value:c.name})),required:false});if(isCancel(d)&&(cancel("Canceled!"),process.exit(0)),d.length>0)for(let c of d){let u=t[c],f=await text({message:`Where should ${c} be added in your project?`,validate(h){if(h.trim()==="")return "Please provide a value"},placeholder:u||`./src/${c}`,defaultValue:u,initialValue:u});isCancel(f)&&(cancel("Canceled!"),process.exit(0)),t[c]=f;}return t},ps=async e=>{let t=spinner(),r=q.join(e.cwd,"package.json");Le.existsSync(r)||program.error(E.red(`Couldn't find your ${E.bold("package.json")}!`));let o=_t(e.cwd).match(y=>y,y=>program.error(E.red(y))),n=o===null;for(o||(o={$schema:"",dirs:[],doNotListBlocks:[],doNotListCategories:[],listBlocks:[],listCategories:[],excludeDeps:[],includeBlocks:[],includeCategories:[],excludeBlocks:[],excludeCategories:[],preview:false}),o.$schema=`https://unpkg.com/jsrepo@${te.package.version}/schemas/registry-config.json`;;){if(o.dirs.length>0){let m=await confirm({message:"Add another blocks directory?",initialValue:false});if(isCancel(m)&&(cancel("Canceled!"),process.exit(0)),!m)break}let y=await text({message:"Where are your blocks located?",placeholder:"./src",defaultValue:"./src",initialValue:"./src",validate:m=>{if(m.trim().length===0)return "Please provide a value!"}});isCancel(y)&&(cancel("Canceled!"),process.exit(0)),o.dirs.push(y);}let s=JSON.parse(Le.readFileSync(r).toString());for(;!e.yes&&s.scripts&&s.scripts[e.script];){let y=await confirm({message:`The \`${E.cyan(e.script)}\` already exists overwrite?`,initialValue:false});if(isCancel(y)&&(cancel("Canceled!"),process.exit(0)),y)break;{let m=await text({message:"What would you like to call the script?",placeholder:"build:registry",validate:N=>{if(N.trim().length===0)return "Please provide a value!"}});isCancel(m)&&(cancel("Canceled!"),process.exit(0)),e.script=m;}}let i=s.devDependencies&&s.devDependencies.jsrepo!==undefined,a=e.yes||i;if(!e.yes&&!i){let y=await confirm({message:`Add ${me} as a dev dependency?`,initialValue:true});isCancel(y)&&(cancel("Canceled!"),process.exit(0)),a=y;}let p=!n;if(!e.yes&&n){let y=await confirm({message:`Create a \`${E.cyan(Ke)}\` file?`,initialValue:true});isCancel(y)&&(cancel("Canceled!"),process.exit(0)),p=y;}let d=(await detect$1({cwd:"cwd"}))?.agent??"npm",c="";if(a)c+="jsrepo build";else {let y=resolveCommand$1(d,"execute",["jsrepo","build"]);y||program.error(E.red(`Error resolving execute command for ${d}`)),c+=`${y.command} ${y.args.join(" ")} `;}p||(c+=` --dirs ${o.dirs.join(" ")} `),s.scripts===undefined&&(s.scripts={}),s.scripts[e.script]=c;let u=[];u.push({loadingMessage:`Adding \`${E.cyan(e.script)}\` to scripts in package.json`,completedMessage:`Added \`${E.cyan(e.script)}\` to scripts in package.json`,run:async()=>{try{Le.writeFileSync(r,JSON.stringify(s,null," "));}catch(y){program.error(E.red(`Error writing to \`${E.bold(r)}\`. Error: ${y}`));}}}),p&&u.push({loadingMessage:`Writing config to \`${E.cyan(Ke)}\``,completedMessage:`Wrote config to \`${E.cyan(Ke)}\``,run:async()=>{let y=q.join(e.cwd,Ke);try{Le.writeFileSync(q.join(y),JSON.stringify(o,null," "));}catch(m){program.error(E.red(`Error writing to \`${E.bold(y)}\`. Error: ${m}`));}}}),await Tt(u,{});let f=i;if(a&&!i){let y=e.yes;if(!e.yes){let m=await confirm({message:"Install dependencies?",initialValue:true});isCancel(m)&&(cancel("Canceled!"),process.exit(0)),y=m;}y&&(t.start(`Installing ${me}`),(await Ie({pm:d,deps:["jsrepo"],dev:true,cwd:e.cwd})).match(()=>t.stop(`Installed ${me}.`),N=>{t.stop(`Failed to install ${me}.`),program.error(N);}),f=true);}let h=[];if(!f&&a){let y=resolveCommand$1(d,"add",["jsrepo","-D"]);h.push(`Install ${me} as a dev dependency \`${E.cyan(`${y?.command} ${y?.args.join(" ")}`)}\``);}h.push(`Add categories to \`${E.cyan(o.dirs.join(", "))}\`.`);let R=resolveCommand$1(d,"run",[e.script]);h.push(`Run \`${E.cyan(`${R?.command} ${R?.args.join(" ")}`)}\` to build the registry.`),h=h.map((y,m)=>`${m+1}. ${y}`);let T=yt(h);process.stdout.write(T);};var Rs=k.object({repo:k.optional(k.string()),allow:k.boolean(),debug:k.boolean(),verbose:k.boolean(),cwd:k.string()}),jr=new Command("test").description("Tests local blocks against most recent remote tests.").addArgument(new Argument("[blocks...]","The blocks you want to test.").default([])).option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",false).option("--debug","Leaves the temp test file around for debugging upon failure.",false).option("--verbose","Include debug logs.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async(e,t)=>{let r=k.parse(Rs,t);pe(te),await Cs(e,r),outro(E.green("All done!"));}),Cs=async(e,t)=>{let r=m=>{t.verbose&&console.info(`${pt} ${m}`);};r(`Attempting to test ${JSON.stringify(e)}`);let o=Pe(t.cwd).match(m=>m,m=>program.error(E.red(m))),n=spinner(),s=new Map,i=o.repos;if(t.repo&&(i=[t.repo]),!t.allow&&t.repo){let m=await confirm({message:`Allow ${E.cyan("jsrepo")} to download and run code from ${E.cyan(t.repo)}?`,initialValue:true});(isCancel(m)||!m)&&(cancel("Canceled!"),process.exit(0));}r(`Fetching blocks from ${E.cyan(i.join(", "))}`),t.verbose||n.start(`Fetching blocks from ${E.cyan(i.join(", "))}`);for(let m of i){let N=(await St(m)).match(g=>g,g=>program.error(E.red(g))),M=await N.provider.fetchManifest(N);r(`Got info for provider ${E.cyan(N.name)}`),M.isErr()&&(t.verbose||n.stop(`Error fetching ${E.cyan(m)}`),program.error(E.red(`There was an error fetching the \`${ge}\` from the repository ${E.cyan(m)} make sure the target repository has a \`${ge}\` in its root?`)));let B=M.unwrap();for(let g of B)for(let w of g.blocks)s.set(ae(N.url,g.name,w.name),{...w,sourceRepo:N});}r(`Retrieved blocks from ${E.cyan(i.join(", "))}`),t.verbose||n.stop(`Retrieved blocks from ${E.cyan(i.join(", "))}`);let a=q.resolve(q.join(t.cwd,`blocks-tests-temp-${Date.now()}`));r(`Trying to create the temp directory ${E.bold(a)}.`),Le.mkdirSync(a,{recursive:true});let p=()=>{Le.rmSync(a,{recursive:true,force:true});},d=it(s,o,t.cwd).map(m=>m.specifier),c=e;e.length===0&&(c=d),c.length===0&&(p(),program.error(E.red("There were no blocks found in your project!")));let u=[];for(let m of c){let N,M=Q.find(B=>m.startsWith(B.name()));if(M){let[B]=M.parseBlockSpecifier(m),g=(await St(B)).match(S=>S,S=>program.error(E.red(S))),w=(await g.provider.fetchManifest(g)).match(S=>S,S=>program.error(E.red(S)));for(let S of w)for(let b of S.blocks)s.set(ae(B,b.category,b.name),{...b,sourceRepo:g});N=s.get(m);}else for(let B of i){let g=(await St(B)).unwrap(),[w]=g.provider.parseBlockSpecifier(g.url),[S,b]=m.split("/"),A=s.get(ae(w,S,b));if(A!==undefined){N=A;break}}N||program.error(E.red(`Invalid block! ${E.bold(m)} does not exist!`)),u.push({name:m,block:N});}let f=De(o.paths,t.cwd);f.isErr()&&program.error(E.red(f.unwrapErr()));let h=f.unwrap();for(let{block:m}of u){let N=m.sourceRepo,M=ae(m.sourceRepo.url,m.category,m.name);if(t.verbose||n.start(`Setting up test file for ${E.cyan(M)}`),!m.tests){n.stop(`No tests found for ${E.cyan(M)}`);continue}let B;h[m.category]!==undefined?B=q.join(t.cwd,h[m.category]):B=q.join(t.cwd,h["*"],m.category),B=q.relative(a,B);let g=async b=>{let A=await N.provider.fetchRaw(N,b);return A.isErr()&&(n.stop(E.red(`Error fetching ${E.bold(b)}`)),program.error(E.red(`There was an error trying to get ${M}`))),A.unwrap()};r(`Downloading and copying test files for ${M}`);let w=[];for(let b of m.files.filter(A=>Ee(A))){let A=await g(q.join(m.directory,b)),Z=q.join(a,b);Le.writeFileSync(Z,A),w.push(Z);}let S=new Project;for(let b of w){r(`Opening test file ${b}`);let A=S.addSourceFileAtPath(b);for(let Z of A.getImportDeclarations()){let le=Z.getModuleSpecifierValue(),l;le.startsWith(".")&&(m.subdirectory?l=q.join(B,m.name,le):l=q.join(B,le)),l&&Z.setModuleSpecifier(l.replaceAll(/\\/g,"/"));}}S.saveSync(),r(`Completed ${E.cyan.bold(M)} test file`),t.verbose||n.stop(`Completed setup for ${E.bold(M)}`);}r("Beginning testing");let R=await detect({cwd:t.cwd});R==null&&program.error(E.red("Could not detect package manager"));let T=resolveCommand(R.agent,"execute",["vitest","run",a]);T==null&&program.error(E.red(`Could not resolve add command for '${R.agent}'.`));let y=`${T.command} ${T.args.join(" ")}`;r(`Running ${E.cyan(y)} on ${E.cyan(t.cwd)}`);try{await execa(T.command,T.args,{cwd:t.cwd,stdin:process.stdin,stdout:process.stdout}),p();}catch(m){t.debug?console.info(`${E.bold("--debug")} flag provided. Skipping cleanup. Run '${E.bold(y)}' to retry tests.
|
|
50
|
-
`):p(),program.error(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
`,a+=`${Dr}${jt.repeat(i)}${sr}
|
|
47
|
+
`,Q(q(a),{prefix:()=>" "})},me=({package:e})=>{console.clear(),e.latestVersion&&Hr.lt(e.version,e.latestVersion)&&console.info(Nn(e.name,e.version,e.latestVersion)),intro(`${T.bgHex("#f7df1e").black(` ${e.name} `)}${T.gray(` v${e.version} `)}`);};var Mn=b.object({repo:b.optional(b.string()),allow:b.boolean(),yes:b.boolean(),verbose:b.boolean(),cwd:b.string()}),gr=new Command("add").description("Add blocks to your project.").argument("[blocks...]","Names of the blocks you want to add to your project. ex: (utils/math, github/ieedan/std/utils/math)").option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",false).option("-y, --yes","Skip confirmation prompt.",false).option("--verbose","Include debug logs.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async(e,t)=>{let r=b.parse(Mn,t);me(re),await Jn(e,r),outro(T.green("All done!"));}),Jn=async(e,t)=>{let r=f=>{t.verbose&&console.info(`${mt} ${f}`);};r(`Attempting to add ${JSON.stringify(e)}`);let o=spinner(),n=Ae(t.cwd),s=n.isErr(),i;if(n.isErr()){let f=t.yes;if(!t.yes){let y=await confirm({message:`You don't have ${ge} initialized in your project. Do you want to continue?`,initialValue:false});isCancel(y)&&(cancel("Canceled!"),process.exit(0)),f=y;}f||(cancel("Canceled!"),process.exit(0)),i={$schema:"",includeTests:false,watermark:true,paths:{"*":"./src/blocks"},repos:[]};}else i=n.unwrap();let a=i.repos,p=new Set,d=false;t.repo&&(a=[t.repo]);for(let f of e){let y=ee.find(k=>f.startsWith(k.name()));if(!y){d=true;continue}let[v]=y.parseBlockSpecifier(f);if(!(!i.repos.find(k=>k===v)&&!p.has(v))){if(!t.allow){let k=await confirm({message:`Allow ${ge} to download and run code from ${T.cyan(v)}?`,initialValue:true});(isCancel(k)||!k)&&(cancel("Canceled!"),process.exit(0));}a.push(v);}p.add(v);}if(!d&&e.length>0&&(a=Array.from(p)),!t.allow&&t.repo){let f=await confirm({message:`Allow ${ge} to download and run code from ${T.cyan(t.repo)}?`,initialValue:true});(isCancel(f)||!f)&&(cancel("Canceled!"),process.exit(0));}a.length===0&&(s&&program.error(T.red(`Fully quality blocks ex: (github/ieedan/std/utils/math) or provide the \`${T.bold("--repo")}\` flag to specify a registry.`)),program.error(T.red(`There were no repos present in your config and you didn't provide the \`${T.bold("--repo")}\` flag with a repo.`))),r(`Resolving ${T.cyan(a.join(", "))}`),t.verbose||o.start(`Fetching blocks from ${T.cyan(a.join(", "))}`);let c=(await wt(...a)).match(f=>f,({repo:f,message:y})=>{o.stop(`Failed to get info for ${T.cyan(f)}`),program.error(T.red(y));});r(`Resolved ${T.cyan(a.join(", "))}`),r(`Fetching blocks from ${T.cyan(a.join(", "))}`);let g=(await vt(...c)).match(f=>f,({repo:f,message:y})=>{o.stop(`Failed fetching blocks from ${T.cyan(f)}`),program.error(T.red(y));});t.verbose||o.stop(`Retrieved blocks from ${T.cyan(a.join(", "))}`),r(`Retrieved blocks from ${T.cyan(a.join(", "))}`);let l=it(g,i,t.cwd).map(f=>f.specifier),h=e;if(h.length===0){let f=await multiselect({message:"Select which blocks to add.",options:Array.from(g.entries()).filter(([y,v])=>v.list).map(([y,v])=>{let E=`${v.category}/${v.name}`,k=l.findIndex(_=>_===E)!==-1,F;return a.length>1?F=`${T.cyan(`${v.sourceRepo.name}/${v.sourceRepo.owner}/${v.sourceRepo.repoName}/${v.category}`)}/${v.name}`:F=`${T.cyan(v.category)}/${v.name}`,{label:k?T.gray(F):F,value:y,hint:k?"Installed":undefined}}),required:true});isCancel(f)&&(cancel("Canceled!"),process.exit(0)),h=f;}r(`Installing blocks ${T.cyan(h.join(", "))}`);let R=(await st(h,g,c)).match(f=>f,f=>program.error(f)),S=(await detect({cwd:t.cwd}))?.agent??"npm",$=[],m=new Set,O=new Set,V=te();if(s){let f=`${t.cwd}-zero-config`,y=b.safeParse(lr,V.get(f)),v=y.success?y.output:i,E=Array.from(new Set(R.map(_=>_.block.category)));for(let _ of E){let X=await text({message:`Where would you like to add ${T.cyan(_)}?`,placeholder:v?v.paths[_]:`./src/${_}`,initialValue:v?v.paths[_]:`./src/${_}`,defaultValue:v?v.paths[_]:`./src/${_}`,validate(W){if(W.trim()==="")return "Please provide a value"}});isCancel(X)&&(cancel("Canceled!"),process.exit(0)),i.paths[_]=X;}if(!t.yes){let _=await confirm({message:"Include tests?",initialValue:v.includeTests});isCancel(_)&&(cancel("Canceled!"),process.exit(0)),i.includeTests=_;let X=await confirm({message:"Add watermark?",initialValue:v.watermark});isCancel(X)&&(cancel("Canceled!"),process.exit(0)),i.watermark=X;}let k="none";Be.existsSync(Y.join(t.cwd,".prettierrc"))&&(k="prettier"),Be.existsSync(Y.join(t.cwd,"biome.json"))&&(k="biome");let F=await select({message:"What formatter would you like to use?",options:["Prettier","Biome","None"].map(_=>({value:_.toLowerCase(),label:_})),initialValue:k==="none"?v.formatter?v.formatter:"none":k});isCancel(F)&&(cancel("Canceled!"),process.exit(0)),F!=="none"&&(i.formatter=F),V.set(f,i),l=it(g,i,t.cwd).map(_=>_.specifier);}let{prettierOptions:z,biomeOptions:L}=await $t({formatter:i.formatter,cwd:t.cwd}),u=De(i.paths,t.cwd);u.isErr()&&program.error(T.red(u.unwrapErr()));let w=u.unwrap(),A=[],x;for(let{block:f}of R){let y=ne(f.sourceRepo.url,f.category,f.name),v=`${f.category}/${f.name}`,E=er(re.package.version,f.sourceRepo.url),k=f.sourceRepo;r(`Setting up ${y}`);let F;if(w[f.category]!==undefined?F=Y.join(t.cwd,w[f.category]):F=Y.join(t.cwd,w["*"],f.category),l.find(X=>v===X)&&!t.yes&&!x){if(x===undefined){let X=R.map(le=>`${le.block.category}/${le.block.name}`).filter(le=>l.find(I=>I===le));log.warn(`The following components ${T.bold.yellow("already exist")}: ${T.cyan(ho(X))}`);let W=await confirm({message:`Would you like to ${T.bold.red("overwrite")} all existing components?`,active:"Yes, overwrite everything",inactive:"No, let me decide individually",initialValue:false});isCancel(W)&&(cancel("Canceled!"),process.exit(0)),x=W;}if(!x){let X=await confirm({message:`${T.cyan(v)} already exists in your project would you like to overwrite it?`,initialValue:false});if(isCancel(X)&&(cancel("Canceled!"),process.exit(0)),!X)continue}}A.push(v),$.push({run:async({message:X})=>{X(`Adding ${T.cyan(y)}`),r(`Creating directory ${T.bold(F)}`),Be.mkdirSync(F,{recursive:true}),r(`Created directory ${T.bold(F)}`);let W=[],le=async I=>{let K=await k.provider.fetchRaw(k,I,{verbose:r});return K.isErr()&&(o.stop(T.red(`Error fetching ${T.bold(I)}`)),program.error(T.red(`There was an error trying to get ${y}`))),K.unwrap()};for(let I of f.files){if(!i.includeTests&&Se(I))continue;let K=Y.join(f.directory,I),de;f.subdirectory?de=Y.join(F,f.name,I):de=Y.join(F,I),r(`Adding ${T.bold(K)}`);let Ne=await le(K),ft=de.slice(0,de.length-I.length);r(`Creating directory ${T.bold(ft)}`),Be.mkdirSync(ft,{recursive:true}),r(`Created directory ${T.bold(ft)}`),W.push({content:Ne,destPath:de}),r(`Got ${T.bold(K)}`);}for(let I of W){let K=await Qt({file:I,biomeOptions:L,prettierOptions:z,config:i,imports:f._imports_,watermark:E,verbose:r,cwd:t.cwd});K.isErr()&&program.error(T.red(K.unwrapErr())),r(`Writing to ${T.bold(I.destPath)}`),Be.writeFileSync(I.destPath,K.unwrap());}if(i.includeTests&&f.tests){r("Trying to include tests");let{devDependencies:I}=JSON.parse(Be.readFileSync(Y.join(t.cwd,"package.json")).toString());(I===undefined||I.vitest===undefined)&&m.add("vitest");}for(let I of f.devDependencies)m.add(I);for(let I of f.dependencies)O.add(I);}});}await tr({startMessage:"Adding blocks",stopMessage:`Added ${T.cyan(A.join(", "))}`,tasks:$,verbose:t.verbose?r:undefined});let U=Jt(O,m,{cwd:t.cwd});if(O=U.dependencies,m=U.devDependencies,O.size>0||m.size>0){let f=t.yes;if(!t.yes){let E=await confirm({message:"Would you like to install dependencies?",initialValue:true});isCancel(E)&&(cancel("Canceled!"),process.exit(0)),f=E;}f&&(O.size>0&&(t.verbose||o.start(`Installing dependencies with ${T.cyan(S)}`),(await Te({pm:S,deps:Array.from(O),dev:false,cwd:t.cwd})).match(E=>{t.verbose||o.stop(`Installed ${T.cyan(E.join(", "))}`);},E=>{t.verbose||o.stop("Failed to install dependencies"),program.error(E);})),m.size>0&&(t.verbose||o.start(`Installing dependencies with ${T.cyan(S)}`),(await Te({pm:S,deps:Array.from(m),dev:true,cwd:t.cwd})).match(E=>{t.verbose||o.stop(`Installed ${T.cyan(E.join(", "))}`);},E=>{t.verbose||o.stop("Failed to install dev dependencies"),program.error(E);})));let y=[];if(!f){if(O.size>0){let E=resolveCommand(S,"add",[...O]);y.push(`Install dependencies \`${T.cyan(`${E?.command} ${E?.args.join(" ")}`)}\``);}if(m.size>0){let E=resolveCommand(S,"add",[...m,"-D"]);y.push(`Install dev dependencies \`${T.cyan(`${E?.command} ${E?.args.join(" ")}`)}\``);}}y=y.map((E,k)=>`${k+1}. ${E}`),f||y.push(""),y.push("Import and use the blocks!");let v=kt(y);process.stdout.write(v);}};var Yn=b.object({token:b.optional(b.string()),provider:b.optional(b.string()),logout:b.boolean()}),Rt=ee.filter(e=>e.name()!==Ie.name()),vr=new Command("auth").description("Provide a token for access to private repositories.").option("--token <token>","The token to use for authenticating to your provider.").addOption(new Option("--provider <name>","The provider this token belongs to.").choices(Rt.map(e=>e.name()))).option("--logout","Erase tokens from each provider from storage.",false).action(async e=>{let t=b.parse(Yn,e);me(re),await Zn(t),outro(T.green("All done!"));}),Zn=async e=>{let t=te();if(e.logout){for(let r of Rt){let o=`${r.name()}-token`;if(t.get(o)===undefined){process.stdout.write(`${D}
|
|
48
|
+
`),process.stdout.write(T.gray(`${D} Already logged out of ${r.name()}.
|
|
49
|
+
`));continue}let n=await confirm({message:`Remove ${r.name()} token?`,initialValue:true});isCancel(n)&&(cancel("Canceled!"),process.exit(0)),n&&t.delete(o);}return}if(Rt.length>1){let r=await select({message:"Which provider is this token for?",options:Rt.map(o=>({label:o.name(),value:o.name()})),initialValue:Rt[0].name()});isCancel(r)&&(cancel("Canceled!"),process.exit(0)),e.provider=r;}else e.provider=Rt[0].name();if(e.token===undefined){let r=await password({message:"Paste your token",validate(o){if(o.trim()==="")return "Please provide a value"}});(isCancel(r)||!r)&&(cancel("Canceled!"),process.exit(0)),e.token=r;}t.set(`${e.provider}-token`,e.token);};var rs=[".git","node_modules"],os=b.object({dirs:b.optional(b.array(b.string())),outputDir:b.optional(b.string()),includeBlocks:b.optional(b.array(b.string())),includeCategories:b.optional(b.array(b.string())),excludeBlocks:b.optional(b.array(b.string())),excludeCategories:b.optional(b.array(b.string())),excludeDeps:b.optional(b.array(b.string())),listBlocks:b.optional(b.array(b.string())),listCategories:b.optional(b.array(b.string())),doNotListBlocks:b.optional(b.array(b.string())),doNotListCategories:b.optional(b.array(b.string())),preview:b.optional(b.boolean()),output:b.boolean(),verbose:b.boolean(),cwd:b.string()}),wr=new Command("build").description(`Builds the provided --dirs in the project root into a \`${he}\` file.`).option("--dirs [dirs...]","The directories containing the blocks.").option("--output-dir <dir>","The directory to output the registry to. (Copies jsrepo-manifest.json + all required files)").option("--include-blocks [blockNames...]","Include only the blocks with these names.").option("--include-categories [categoryNames...]","Include only the categories with these names.").option("--exclude-blocks [blockNames...]","Do not include the blocks with these names.").option("--exclude-categories [categoryNames...]","Do not include the categories with these names.").option("--list-blocks [blockNames...]","List only the blocks with these names.").option("--list-categories [categoryNames...]","List only the categories with these names.").option("--do-not-list-blocks [blockNames...]","Do not list the blocks with these names.").option("--do-not-list-categories [categoryNames...]","Do not list the categories with these names.").option("--exclude-deps [deps...]","Dependencies that should not be added.").option("--preview","Display a preview of the blocks list.").option("--no-output",`Do not output a \`${he}\` file.`).option("--verbose","Include debug logs.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async e=>{let t=b.parse(os,e);me(re),await ns(t),outro(T.green("All done!"));}),ns=async e=>{let t=spinner(),r=[],o=Vt(e.cwd).match(g=>{if(g===null)return {$schema:"",dirs:e.dirs??[],outputDir:e.outputDir,doNotListBlocks:e.doNotListBlocks??[],doNotListCategories:e.doNotListCategories??[],listBlocks:e.listBlocks??[],listCategories:e.listCategories??[],excludeDeps:e.excludeDeps??[],includeBlocks:e.includeBlocks??[],includeCategories:e.includeCategories??[],excludeBlocks:e.excludeBlocks??[],excludeCategories:e.excludeCategories??[],preview:e.preview};let l=g;return e.dirs&&(l.dirs=e.dirs),e.outputDir&&(l.outputDir=e.outputDir),e.doNotListBlocks&&(l.doNotListBlocks=e.doNotListBlocks),e.doNotListCategories&&(l.doNotListCategories=e.doNotListCategories),e.listBlocks&&(l.listBlocks=e.listBlocks),e.listCategories&&(l.listCategories=e.listCategories),e.includeBlocks&&(l.includeBlocks=e.includeBlocks),e.includeCategories&&(l.includeCategories=e.includeCategories),e.excludeBlocks&&(l.excludeBlocks=e.excludeBlocks),e.excludeCategories&&(l.excludeCategories=e.excludeCategories),e.excludeDeps&&(l.excludeDeps=e.excludeDeps),e.preview!==undefined&&(l.preview=e.preview),l.rules={...ar,...l.rules},l},g=>program.error(T.red(g))),n;o.outputDir?n=Y.join(e.cwd,o.outputDir):n=e.cwd;let s=Y.join(n,he);if(e.output&&Be.existsSync(s)){if(o.outputDir){let g=JSON.parse(Be.readFileSync(s).toString());for(let l of g)for(let h of l.blocks){let R=Y.join(n,h.directory);Be.existsSync(R)&&Be.rmSync(R,{recursive:true});}}Be.rmSync(s);}let i=ts();try{let g=Be.readFileSync(Y.join(e.cwd,".gitignore")).toString();i.add(g);}catch{}i.add(rs);for(let g of o.dirs){let l=Y.join(e.cwd,g);t.start(`Building ${T.cyan(l)}`);let h=oo(l,{cwd:e.cwd,ignore:i,config:o});for(let R of h){if(r.find(S=>S.name===R.name)!==undefined){console.warn(`${D} ${xe} Skipped adding \`${T.cyan(`${g}/${R.name}`)}\` because a category with the same name already exists!`);continue}r.push(R);}t.stop(`Built ${T.cyan(l)}`);}t.start("Checking manifest");let{warnings:a,errors:p}=Wr(r,o,o.rules);t.stop("Completed checking manifest."),(a.length>0||p.length>0)&&console.log(D);for(let g of a)console.log(g);if(p.length>0){for(let g of p)console.log(g);program.error(T.red(`Completed checking manifest with ${T.bold(`${p.length} error(s)`)} and ${T.bold(`${a.length} warning(s)`)}`));}let[d,c]=no(r);if(r=d,c>0&&log.step(`Removed ${c} unused block${c>1?"s":""}.`),o.preview){let g=r.flatMap(l=>l.blocks.filter(h=>h.list).map(h=>`${T.cyan(h.category)}/${h.name}`));log.message(`${T.yellow("Preview")}:`);for(let l of g)console.log(`${D} \u25FB ${l}`);}if(e.output){if(o.outputDir){t.start(`Copying registry files to \`${T.cyan(n)}\``);for(let g of r)for(let l of g.blocks){let h=Y.join(e.cwd,l.directory),R=Y.join(n,l.directory);Be.existsSync(R)||Be.mkdirSync(R,{recursive:true});for(let S of l.files)Be.copyFileSync(Y.join(h,S),Y.join(R,S));}t.stop(`Copied registry files to \`${T.cyan(n)}\``);}t.start(`Writing output to \`${T.cyan(s)}\``),Be.writeFileSync(s,JSON.stringify(r,null," ")),t.stop(`Wrote output to \`${T.cyan(s)}\``);}};var fs=b.objectWithRest({repo:b.optional(b.string()),allow:b.boolean(),cwd:b.string()},b.unknown()),br=new Command("exec").alias("x").description("Execute a block as a script.").addArgument(new Argument("script","Name of the script you want to execute. ex: (general/hello, github/ieedan/std/general/hello)").argOptional()).option("--repo <repo>","Repository to download and run the script from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",false).option("--cwd <path>","The current working directory.",process.cwd()).allowExcessArguments().allowUnknownOption().action(async(e,t,r)=>{let o=b.parse(fs,t);me(re),await ms(e,o,r);}),ms=async(e,t,r)=>{let o=e,n=spinner(),s=Ae(t.cwd),i=s.isErr(),a;s.isErr()?a={$schema:"",includeTests:false,watermark:true,paths:{"*":"./"},repos:[]}:a=s.unwrap();let p=a.repos;if(t.repo&&(p=[t.repo]),o&&ee.find(f=>o?.startsWith(f.name()))){let[f,y,v,...E]=o.split("/"),k;if(E.length>2?k=`${f}/${y}/${v}/${E.slice(0,E.length-2).join("/")}`:k=`${f}/${y}/${v}`,!p.find(F=>F===k)){if(!t.allow){let F=await confirm({message:`Allow ${ge} to download and run code from ${T.cyan(k)}?`,initialValue:true});(isCancel(F)||!F)&&(cancel("Canceled!"),process.exit(0));}p=[k];}}if(!t.allow&&t.repo){let f=await confirm({message:`Allow ${ge} to download and run code from ${T.cyan(t.repo)}?`,initialValue:true});(isCancel(f)||!f)&&(cancel("Canceled!"),process.exit(0));}p.length===0&&(i&&program.error(T.red(`Fully quality your script ex: (github/ieedan/std/scripts/build) or provide the \`${T.bold("--repo")}\` flag to specify a registry.`)),program.error(T.red(`There were no repos present in your config and you didn't provide the \`${T.bold("--repo")}\` flag with a repo.`))),n.start(`Fetching scripts from ${T.cyan(p.join(", "))}`);let d=(await wt(...p)).match(f=>f,({repo:f,message:y})=>{n.stop(`Failed to get info for ${T.cyan(f)}`),program.error(T.red(y));}),c=(await vt(...d)).match(f=>f,({repo:f,message:y})=>{n.stop(`Failed fetching scripts from ${T.cyan(f)}`),program.error(T.red(y));});if(n.stop(`Retrieved scripts from ${T.cyan(p.join(", "))}`),!o){let f=await select({message:"Select which script to run.",options:Array.from(c.entries()).filter(([y,v])=>v.list).map(([y,v])=>{let E;return p.length>1?E=`${T.cyan(`${v.sourceRepo.name}/${v.sourceRepo.owner}/${v.sourceRepo.repoName}/${v.category}`)}/${v.name}`:E=`${T.cyan(v.category)}/${v.name}`,{label:E,value:y}})});isCancel(f)&&(cancel("Canceled!"),process.exit(0)),o=f;}let g=(await st([o],c,d)).match(f=>f,f=>program.error(f)),l="temp-jsrepo-exec",h=`./${l}/${encodeURIComponent(o)}`,R=Y.join(process.cwd(),h);a.paths["*"]=h,Be.mkdirSync(R,{recursive:true});let S=(await detect({cwd:process.cwd()}))?.agent??"npm",$=[],m=new Set,O=new Set,V=De(a.paths,t.cwd);V.isErr()&&program.error(T.red(V.unwrapErr()));let z=V.unwrap(),L=[];for(let{block:f}of g){let y=`${f.sourceRepo.url}/${f.category}/${f.name}`,v=`${f.category}/${f.name}`,E=f.sourceRepo,k=Y.join(t.cwd,z["*"],f.category);L.push(v),$.push({run:async({message:F})=>{F(`Adding ${T.cyan(y)}`),Be.mkdirSync(k,{recursive:true});let _=[],X=async W=>{let le=await E.provider.fetchRaw(E,W);return le.isErr()&&(n.stop(T.red(`Error fetching ${T.bold(W)}`)),program.error(T.red(`There was an error trying to get ${y}`))),le.unwrap()};for(let W of f.files){if(!a.includeTests&&Se(W))continue;let le=Y.join(f.directory,W),I;f.subdirectory?I=Y.join(k,f.name,W):I=Y.join(k,W);let K=await X(le),de=I.slice(0,I.length-W.length);Be.mkdirSync(de,{recursive:true}),_.push({content:K,destPath:I});}for(let W of _)Be.writeFileSync(W.destPath,W.content);if(a.includeTests&&f.tests){let{devDependencies:W}=JSON.parse(Be.readFileSync(Y.join(t.cwd,"package.json")).toString());(W===undefined||W.vitest===undefined)&&m.add("vitest");}for(let W of f.devDependencies)m.add(W);for(let W of f.dependencies)O.add(W);}});}if(await tr({startMessage:"Adding blocks",stopMessage:`Added ${T.cyan(L.join(", "))}`,tasks:$}),O.size>0||m.size>0){let f={name:"temp-package",type:"module",version:"0.0.1"},y=Y.join(R,"package.json");Be.writeFileSync(y,JSON.stringify(f,null," ")),O.size>0&&(t.verbose||n.start(`Installing dependencies with ${T.cyan(S)}`),(await Te({pm:S,deps:Array.from(O),dev:false,cwd:R,ignoreWorkspace:true})).match(v=>{t.verbose||n.stop(`Installed ${T.cyan(v.join(", "))}`);},v=>{t.verbose||n.stop("Failed to install dependencies"),program.error(v);})),m.size>0&&(t.verbose||n.start(`Installing dependencies with ${T.cyan(S)}`),(await Te({pm:S,deps:Array.from(m),dev:true,cwd:R,ignoreWorkspace:true})).match(v=>{t.verbose||n.stop(`Installed ${T.cyan(v.join(", "))}`);},v=>{t.verbose||n.stop("Failed to install dev dependencies"),program.error(v);}));}let w=r.parent.rawArgs.findIndex(f=>f==="--"),A=[];w!==-1&&(A=r.parent.rawArgs.slice(w+1)),console.clear();let x=g[0],U;x.block.subdirectory?U=Y.join(R,`${x.block.category}/${x.block.name}/index.js`):U=Y.join(R,`${x.block.category}/${x.block.name}.js`);let ce=resolveCommand(S,"execute",["tsx",U,...A]);ce||program.error(T.red("Error resolving run command!"));try{await execa(ce.command,ce.args,{cwd:process.cwd(),stdin:process.stdin,stdout:process.stdout});}finally{Be.rmSync(Y.join(process.cwd(),l),{recursive:true,force:true});}};var $s=b.object({repos:b.optional(b.array(b.string())),watermark:b.boolean(),tests:b.optional(b.boolean()),formatter:b.optional(cr),project:b.optional(b.boolean()),registry:b.optional(b.boolean()),script:b.string(),yes:b.boolean(),cwd:b.string()}),xr=new Command("init").description("Initializes your project with a configuration file.").argument("[registries...]","Registries to install the blocks from.",[]).option("--repos [repos...]","Repository to install the blocks from. (DEPRECATED)").option("--no-watermark","Will not add a watermark to each file upon adding it to your project.").option("--tests","Will include tests with the blocks.").addOption(new Option("--formatter <formatter>","What formatter to use when adding or updating blocks.").choices(["prettier","biome"])).option("-P, --project","Takes you through the steps to initialize a project.").option("-R, --registry","Takes you through the steps to initialize a registry.").option("--script <name>","The name of the build script. (For Registry setup)","build:registry").option("-y, --yes","Skip confirmation prompt.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async(e,t)=>{let r=b.parse($s,t);if(me(re),r.registry!==undefined&&r.project!==undefined&&program.error(T.red(`You cannot provide both ${T.bold("--project")} and ${T.bold("--registry")} at the same time.`)),r.repos!==undefined&&log.warn(`The ${T.gray("`--repos`")} flag is deprecated! Instead supply registries as arguments. ${T.cyan(`\`jsrepo init ${r.repos.join(" ")}\``)}`),r.registry===undefined&&r.project===undefined&&e.length===0){let o=await select({message:"Initialize a project or registry?",options:[{value:"project",label:"project"},{value:"registry",label:"registry"}],initialValue:"project"});isCancel(o)&&(cancel("Canceled!"),process.exit(0)),r.project=o==="project";}r.project||e.length>0?await ks(e,r):await bs(r),outro(T.green("All done!"));}),ks=async(e,t)=>{let r=Ae(t.cwd),o=spinner(),n,s=await text({message:"Please enter a default path to install the blocks",validate(l){if(l.trim()==="")return "Please provide a value"},placeholder:"./src/blocks",initialValue:r.isOk()?r.unwrap().paths["*"]:undefined});isCancel(s)&&(cancel("Canceled!"),process.exit(0)),r.isOk()?n={...r.unwrap().paths,"*":s}:n={"*":s};let i=[...r.isOk()?r.unwrap().repos:[],...e,...t.repos??[]];if(i.length>0)for(let l of i){if(r.isOk()&&r.unwrap().repos.find(h=>h===l)){let h=await confirm({message:`Configure ${l}?`,initialValue:t.yes});if(isCancel(h)&&(cancel("Canceled!"),process.exit(0)),!h)continue}log.info(`Configuring ${T.cyan(l)}`),n=await bo(l,n);}for(;;){let l=await confirm({message:`Add ${i.length>0?"another":"a"} repo?`,initialValue:i.length===0});if(isCancel(l)&&(cancel("Canceled!"),process.exit(0)),!l)break;let h=await text({message:"Where should we download the blocks from?",placeholder:"github/ieedan/std",validate:R=>{if(R.trim().length===0)return "Please provide a value";if(!ee.find(S=>S.matches(R)))return `Invalid provider! Valid providers (${ee.map(S=>S.name()).join(", ")})`}});isCancel(h)&&(cancel("Canceled!"),process.exit(0)),n=await bo(h,n),i.push(h);}if(!t.formatter){let l=r.isErr()?"none":r.unwrap().formatter??"none";Be.existsSync(Y.join(t.cwd,".prettierrc"))&&(l="prettier"),Be.existsSync(Y.join(t.cwd,"biome.json"))&&(l="biome");let h=await select({message:"What formatter would you like to use?",options:["Prettier","Biome","None"].map(R=>({value:R.toLowerCase(),label:R})),initialValue:l});isCancel(h)&&(cancel("Canceled!"),process.exit(0)),h!=="none"&&(t.formatter=h);}let a={$schema:`https://unpkg.com/jsrepo@${re.package.version}/schemas/project-config.json`,repos:i,includeTests:r.isOk()&&t.tests===undefined?r.unwrap().includeTests:t.tests??false,watermark:t.watermark,formatter:t.formatter,paths:n};o.start(`Writing config to \`${ot}\``);let{prettierOptions:p,biomeOptions:d}=await $t({formatter:a.formatter,cwd:t.cwd}),c=Y.join(t.cwd,ot),g=await fr.format(JSON.stringify(a,null," "),{biomeOptions:d,prettierOptions:p,filePath:c,formatter:a.formatter});Be.existsSync(t.cwd)||Be.mkdirSync(t.cwd,{recursive:true}),Be.writeFileSync(c,g),o.stop(`Wrote config to \`${ot}\`.`);},bo=async(e,t)=>{let r=spinner(),o=te(),n=ee.find(c=>c.matches(e));n||program.error(T.red(`Invalid provider! Valid providers (${ee.map(c=>c.name()).join(", ")})`));let s=`${n.name()}-token`;if(!o.get(s)&&n.name()!==Ie.name()){let c=await confirm({message:"Would you like to add an auth token?",initialValue:false});if(isCancel(c)&&(cancel("Canceled!"),process.exit(0)),c){let g=await password({message:"Paste your token",validate(l){if(l.trim()==="")return "Please provide a value"}});isCancel(g)&&(cancel("Canceled!"),process.exit(0)),o.set(s,g);}}r.start(`Fetching categories from ${T.cyan(e)}`);let a=await n.fetchManifest(e);r.stop(`Fetched categories from ${T.cyan(e)}`),a.isErr()&&program.error(T.red(a.unwrapErr()));let p=a.unwrap(),d=await multiselect({message:"Which category paths would you like to configure?",options:p.map(c=>({label:c.name,value:c.name})),required:false});if(isCancel(d)&&(cancel("Canceled!"),process.exit(0)),d.length>0)for(let c of d){let g=t[c],l=await text({message:`Where should ${c} be added in your project?`,validate(h){if(h.trim()==="")return "Please provide a value"},placeholder:g||`./src/${c}`,defaultValue:g,initialValue:g});isCancel(l)&&(cancel("Canceled!"),process.exit(0)),t[c]=l;}return t},bs=async e=>{let t=spinner(),r=Y.join(e.cwd,"package.json");Be.existsSync(r)||program.error(T.red(`Couldn't find your ${T.bold("package.json")}!`));let o=Vt(e.cwd).match($=>$,$=>program.error(T.red($))),n=o===null;for(o||(o={$schema:"",dirs:[],doNotListBlocks:[],doNotListCategories:[],listBlocks:[],listCategories:[],excludeDeps:[],includeBlocks:[],includeCategories:[],excludeBlocks:[],excludeCategories:[],preview:false}),o.$schema=`https://unpkg.com/jsrepo@${re.package.version}/schemas/registry-config.json`;;){if(o.dirs.length>0){let m=await confirm({message:"Add another blocks directory?",initialValue:false});if(isCancel(m)&&(cancel("Canceled!"),process.exit(0)),!m)break}let $=await text({message:"Where are your blocks located?",placeholder:"./src",defaultValue:"./src",initialValue:"./src",validate:m=>{if(m.trim().length===0)return "Please provide a value!"}});isCancel($)&&(cancel("Canceled!"),process.exit(0)),o.dirs.push($);}let s=JSON.parse(Be.readFileSync(r).toString());for(;!e.yes&&s.scripts&&s.scripts[e.script];){let $=await confirm({message:`The \`${T.cyan(e.script)}\` already exists overwrite?`,initialValue:false});if(isCancel($)&&(cancel("Canceled!"),process.exit(0)),$)break;{let m=await text({message:"What would you like to call the script?",placeholder:"build:registry",validate:O=>{if(O.trim().length===0)return "Please provide a value!"}});isCancel(m)&&(cancel("Canceled!"),process.exit(0)),e.script=m;}}let i=s.devDependencies&&s.devDependencies.jsrepo!==undefined,a=e.yes||i;if(!e.yes&&!i){let $=await confirm({message:`Add ${ge} as a dev dependency?`,initialValue:true});isCancel($)&&(cancel("Canceled!"),process.exit(0)),a=$;}let p=!n;if(!e.yes&&n){let $=await confirm({message:`Create a \`${T.cyan(Ze)}\` file?`,initialValue:true});isCancel($)&&(cancel("Canceled!"),process.exit(0)),p=$;}let d=(await detect$1({cwd:"cwd"}))?.agent??"npm",c="";if(a)c+="jsrepo build";else {let $=resolveCommand$1(d,"execute",["jsrepo","build"]);$||program.error(T.red(`Error resolving execute command for ${d}`)),c+=`${$.command} ${$.args.join(" ")} `;}p||(c+=` --dirs ${o.dirs.join(" ")} `),s.scripts===undefined&&(s.scripts={}),s.scripts[e.script]=c;let g=[];g.push({loadingMessage:`Adding \`${T.cyan(e.script)}\` to scripts in package.json`,completedMessage:`Added \`${T.cyan(e.script)}\` to scripts in package.json`,run:async()=>{try{Be.writeFileSync(r,JSON.stringify(s,null," "));}catch($){program.error(T.red(`Error writing to \`${T.bold(r)}\`. Error: ${$}`));}}}),p&&g.push({loadingMessage:`Writing config to \`${T.cyan(Ze)}\``,completedMessage:`Wrote config to \`${T.cyan(Ze)}\``,run:async()=>{let $=Y.join(e.cwd,Ze);try{Be.writeFileSync(Y.join($),JSON.stringify(o,null," "));}catch(m){program.error(T.red(`Error writing to \`${T.bold($)}\`. Error: ${m}`));}}}),await Pt(g,{});let l=i;if(a&&!i){let $=e.yes;if(!e.yes){let m=await confirm({message:"Install dependencies?",initialValue:true});isCancel(m)&&(cancel("Canceled!"),process.exit(0)),$=m;}$&&(t.start(`Installing ${ge}`),(await Te({pm:d,deps:["jsrepo"],dev:true,cwd:e.cwd})).match(()=>t.stop(`Installed ${ge}.`),O=>{t.stop(`Failed to install ${ge}.`),program.error(O);}),l=true);}let h=[];if(!l&&a){let $=resolveCommand$1(d,"add",["jsrepo","-D"]);h.push(`Install ${ge} as a dev dependency \`${T.cyan(`${$?.command} ${$?.args.join(" ")}`)}\``);}h.push(`Add categories to \`${T.cyan(o.dirs.join(", "))}\`.`);let R=resolveCommand$1(d,"run",[e.script]);h.push(`Run \`${T.cyan(`${R?.command} ${R?.args.join(" ")}`)}\` to build the registry.`),h=h.map(($,m)=>`${m+1}. ${$}`);let S=kt(h);process.stdout.write(S);};var As=b.object({repo:b.optional(b.string()),allow:b.boolean(),debug:b.boolean(),verbose:b.boolean(),cwd:b.string()}),Er=new Command("test").description("Tests local blocks against most recent remote tests.").addArgument(new Argument("[blocks...]","The blocks you want to test.").default([])).option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",false).option("--debug","Leaves the temp test file around for debugging upon failure.",false).option("--verbose","Include debug logs.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async(e,t)=>{let r=b.parse(As,t);me(re),await Ds(e,r),outro(T.green("All done!"));}),Ds=async(e,t)=>{let r=m=>{t.verbose&&console.info(`${mt} ${m}`);};r(`Attempting to test ${JSON.stringify(e)}`);let o=Ae(t.cwd).match(m=>m,m=>program.error(T.red(m))),n=spinner(),s=new Map,i=o.repos;if(t.repo&&(i=[t.repo]),!t.allow&&t.repo){let m=await confirm({message:`Allow ${T.cyan("jsrepo")} to download and run code from ${T.cyan(t.repo)}?`,initialValue:true});(isCancel(m)||!m)&&(cancel("Canceled!"),process.exit(0));}r(`Fetching blocks from ${T.cyan(i.join(", "))}`),t.verbose||n.start(`Fetching blocks from ${T.cyan(i.join(", "))}`);for(let m of i){let O=(await It(m)).match(L=>L,L=>program.error(T.red(L))),V=await O.provider.fetchManifest(O);r(`Got info for provider ${T.cyan(O.name)}`),V.isErr()&&(t.verbose||n.stop(`Error fetching ${T.cyan(m)}`),program.error(T.red(`There was an error fetching the \`${he}\` from the repository ${T.cyan(m)} make sure the target repository has a \`${he}\` in its root?`)));let z=V.unwrap();for(let L of z)for(let u of L.blocks)s.set(ne(O.url,L.name,u.name),{...u,sourceRepo:O});}r(`Retrieved blocks from ${T.cyan(i.join(", "))}`),t.verbose||n.stop(`Retrieved blocks from ${T.cyan(i.join(", "))}`);let a=Y.resolve(Y.join(t.cwd,`blocks-tests-temp-${Date.now()}`));r(`Trying to create the temp directory ${T.bold(a)}.`),Be.mkdirSync(a,{recursive:true});let p=()=>{Be.rmSync(a,{recursive:true,force:true});},d=it(s,o,t.cwd).map(m=>m.specifier),c=e;e.length===0&&(c=d),c.length===0&&(p(),program.error(T.red("There were no blocks found in your project!")));let g=[];for(let m of c){let O,V=ee.find(z=>m.startsWith(z.name()));if(V){let[z]=V.parseBlockSpecifier(m),L=(await It(z)).match(w=>w,w=>program.error(T.red(w))),u=(await L.provider.fetchManifest(L)).match(w=>w,w=>program.error(T.red(w)));for(let w of u)for(let A of w.blocks)s.set(ne(z,A.category,A.name),{...A,sourceRepo:L});O=s.get(m);}else for(let z of i){let L=(await It(z)).unwrap(),[u]=L.provider.parseBlockSpecifier(L.url),[w,A]=m.split("/"),x=s.get(ne(u,w,A));if(x!==undefined){O=x;break}}O||program.error(T.red(`Invalid block! ${T.bold(m)} does not exist!`)),g.push({name:m,block:O});}let l=De(o.paths,t.cwd);l.isErr()&&program.error(T.red(l.unwrapErr()));let h=l.unwrap();for(let{block:m}of g){let O=m.sourceRepo,V=ne(m.sourceRepo.url,m.category,m.name);if(t.verbose||n.start(`Setting up test file for ${T.cyan(V)}`),!m.tests){n.stop(`No tests found for ${T.cyan(V)}`);continue}let z;h[m.category]!==undefined?z=Y.join(t.cwd,h[m.category]):z=Y.join(t.cwd,h["*"],m.category),z=Y.relative(a,z);let L=async A=>{let x=await O.provider.fetchRaw(O,A);return x.isErr()&&(n.stop(T.red(`Error fetching ${T.bold(A)}`)),program.error(T.red(`There was an error trying to get ${V}`))),x.unwrap()};r(`Downloading and copying test files for ${V}`);let u=[];for(let A of m.files.filter(x=>Se(x))){let x=await L(Y.join(m.directory,A)),U=Y.join(a,A);Be.writeFileSync(U,x),u.push(U);}let w=new Project;for(let A of u){r(`Opening test file ${A}`);let x=w.addSourceFileAtPath(A);for(let U of x.getImportDeclarations()){let ce=U.getModuleSpecifierValue(),f;ce.startsWith(".")&&(m.subdirectory?f=Y.join(z,m.name,ce):f=Y.join(z,ce)),f&&U.setModuleSpecifier(f.replaceAll(/\\/g,"/"));}}w.saveSync(),r(`Completed ${T.cyan.bold(V)} test file`),t.verbose||n.stop(`Completed setup for ${T.bold(V)}`);}r("Beginning testing");let R=await detect({cwd:t.cwd});R==null&&program.error(T.red("Could not detect package manager"));let S=resolveCommand(R.agent,"execute",["vitest","run",a]);S==null&&program.error(T.red(`Could not resolve add command for '${R.agent}'.`));let $=`${S.command} ${S.args.join(" ")}`;r(`Running ${T.cyan($)} on ${T.cyan(t.cwd)}`);try{await execa(S.command,S.args,{cwd:t.cwd,stdin:process.stdin,stdout:process.stdout}),p();}catch(m){t.debug?console.info(`${T.bold("--debug")} flag provided. Skipping cleanup. Run '${T.bold($)}' to retry tests.
|
|
50
|
+
`):p(),program.error(T.red(`Tests failed! Error ${m}`));}};var Ir={"Claude 3.5 Sonnet":{updateFile:async({originalFile:e,newFile:t,loading:r,verbose:o})=>{let n=await Sr("Anthropic");o||r.start("Asking Claude 3.5 Sonnet");let s=rr({originalFile:e,newFile:t});o?.(`Prompting Claude 3.5 Sonnet with:
|
|
51
|
+
${JSON.stringify(s,null," ")}`);let i=await Ms({model:"claude-3-5-sonnet-latest",prompt:s,apiKey:n,maxTokens:(e.content.length+t.content.length)*2});return o||r.stop("Claude 3.5 Sonnet updated the file"),i?or(i):t.content}},"ChatGPT 4o":{updateFile:async({originalFile:e,newFile:t,loading:r,verbose:o})=>{let n=await Sr("OpenAI");o||r.start("Asking ChatGPT 4o");let s=rr({originalFile:e,newFile:t});o?.(`Prompting ChatGPT 4o with:
|
|
52
|
+
${JSON.stringify(s,null," ")}`);let i=await xo({model:"gpt-4o",prompt:s,apiKey:n,maxTokens:(e.content.length+t.content.length)*2});return o||r.stop("ChatGPT 4o updated the file"),i?or(i):t.content}},"ChatGPT 4o-mini":{updateFile:async({originalFile:e,newFile:t,loading:r,verbose:o})=>{let n=await Sr("OpenAI");o||r.start("Asking ChatGPT 4o-mini");let s=rr({originalFile:e,newFile:t});o?.(`Prompting ChatGPT 4o with:
|
|
53
|
+
${JSON.stringify(s,null," ")}`);let i=await xo({model:"gpt-4o-mini",prompt:s,apiKey:n,maxTokens:(e.content.length+t.content.length)*2});return o||r.stop("ChatGPT 4o-mini updated the file"),i?or(i):t.content}},Phi4:{updateFile:async({originalFile:e,newFile:t,loading:r,verbose:o})=>{o||r.start("Asking Phi4");let n=rr({originalFile:e,newFile:t});o?.(`Prompting Phi4 with:
|
|
54
|
+
${JSON.stringify(n,null," ")}`);let s=await Js({model:"phi4",prompt:n});return o||r.stop("Phi4 updated the file"),s?or(s):t.content}}},xo=async({prompt:e,maxTokens:t,model:r,apiKey:o})=>{let i=(await new Vs({apiKey:o}).chat.completions.create({model:r,max_completion_tokens:t,messages:[{role:"system",content:e.system},{role:"user",content:e.message}]})).choices[0];return i.message.content===null?null:i.message.content},Ms=async({prompt:e,maxTokens:t,model:r,apiKey:o})=>{let i=(await new Ls({apiKey:o}).messages.create({model:r,max_tokens:Math.min(t,8192),temperature:.5,system:e.system,messages:[{role:"user",content:[{type:"text",text:e.message}]}]})).content[0];return i.type!=="text"?null:i.text},Js=async({prompt:e,model:t})=>(await Ws.chat({model:t,messages:[{role:"system",content:e.system},{role:"user",content:e.message}]})).message.content,rr=({originalFile:e,newFile:t})=>({system:"You will respond only with the resulting code. DO NOT format the code with markdown, DO NOT put the code inside of triple quotes, only return the code as a raw string.",message:`Help me merge these two files. DO NOT make unnecessary changes.
|
|
55
|
+
I expect the original code to maintain the same behavior as it currently has while including any added functionality from the new file.
|
|
56
|
+
This means stuff like defaults or configuration should normally stay intact unless the new behaviors in the new file depend on those defaults or configuration.
|
|
57
|
+
This is my current file ${e.path}:
|
|
58
|
+
\`\`\`
|
|
59
|
+
${e.content}
|
|
60
|
+
\`\`\`
|
|
61
|
+
|
|
62
|
+
This is the file that has changes I want to update with ${t.path}:
|
|
63
|
+
\`\`\`
|
|
64
|
+
${t.content}
|
|
65
|
+
\`\`\`
|
|
66
|
+
`}),or=e=>{let t=e.trim();if(t.startsWith("```")&&(t=q(t).slice(1).join(`
|
|
67
|
+
`).trim()),t.endsWith("```")){let r=q(t);t=r.slice(0,r.length-1).join(`
|
|
68
|
+
`).trim();}return t},Sr=async e=>{let t=`${e}-api-key`,r=te(),o=r.get(t,null);if(!o){let n=await password({message:`Paste your ${e} API key:`,validate(s){if(s.trim()==="")return "Please provide an API key"}});(isCancel(n)||!n)&&(cancel("Canceled!"),process.exit(0)),o=n;}return r.set(t,o),o};var jo=(e,t)=>{let r=0;for(let o of e)r=r+t(o);return r};var Eo=e=>/^\s+$/g.test(e),xt=e=>{let t=e.length-1;for(;Eo(e[t])&&t>=0;){if(e[t]===`
|
|
69
|
+
`)return e[t-1]==="\r"?e.slice(0,t-1):e.slice(0,t);t--;}return e},So=({from:e,to:t,changes:r,expand:o=false,maxUnchanged:n=5,colorRemoved:s=T.redBright,colorAdded:i=T.greenBright,colorCharsRemoved:a=T.bgRedBright,colorCharsAdded:p=T.bgGreenBright,prefix:d,onUnchanged:c,intro:g})=>{let l="",h=jo(r,$=>$.count??0).toString().length+1,R=0;if(r.length===1&&!r[0].added&&!r[0].removed)return c({from:e,to:t,changes:r,expand:o,maxUnchanged:n,colorAdded:i,colorRemoved:s,prefix:d,onUnchanged:c,intro:g});l+=g({from:e,to:t,changes:r,expand:o,maxUnchanged:n,colorAdded:i,colorRemoved:s,prefix:d,onUnchanged:c,intro:g});let S=$=>T.gray(`${d?.()??""}${St(`${$+1+R} `,h)} `);for(let $=0;$<r.length;$++){let m=r[$],O=r[$-1]?.added||r[$-1]?.removed,V=r[$+1]?.added||r[$+1]?.removed;if(!m.added&&!m.removed){if(!o&&m.count!==undefined&&m.count>n){let u=R,w=q(xt(m.value)),A=0;if(V&&(A+=n),O&&(A+=n),A>=w.length){l+=`${Q(w,{prefix:S})}
|
|
70
|
+
`,R+=w.length;continue}if(O&&(l+=`${Q(w.slice(0,n),{prefix:S})}
|
|
71
|
+
`),w.length>A){let x=w.length-A;l+=`${Q(q(T.gray(`+ ${x} more unchanged (${T.italic("-E to expand")})`)),{prefix:()=>`${d?.()??""}${St(" ",h)} `})}
|
|
72
|
+
`;}V&&(R=R+w.length-n,l+=`${Q(w.slice(w.length-n),{prefix:S})}
|
|
73
|
+
`),R=u+m.count;continue}l+=`${Q(q(xt(m.value)),{prefix:S})}
|
|
74
|
+
`,R+=m.count??0;continue}let z=u=>u.added?i(xt(u.value)):u.removed?s(xt(u.value)):u.value,L=u=>u.added?p(xt(u.value)):u.removed?a(xt(u.value)):u.value;if(m.removed&&m.count===1&&r[$+1]?.added&&r[$+1]?.count===1){let w=diffChars(m.value,r[$+1].value).map(A=>L(A)).join("");l+=`${S(0)}${w}`,R+=1,$++;}else Eo(m.value)?(l+=`${Q(q(L(m)),{prefix:u=>`${S(u)}${L({removed:true,value:" ",added:false})}`})}
|
|
75
|
+
`,m.removed||(R+=m.count??0)):(l+=`${Q(q(z(m)),{prefix:S})}
|
|
76
|
+
`,m.removed||(R+=m.count??0));}return l};var Xs=b.object({all:b.boolean(),expand:b.boolean(),maxUnchanged:b.number(),no:b.boolean(),repo:b.optional(b.string()),allow:b.boolean(),yes:b.boolean(),verbose:b.boolean(),cwd:b.string()}),Tr=new Command("update").description("Update blocks to the code in the remote repository.").argument("[blocks...]","Names of the blocks you want to update. ex: (utils/math)").option("--all","Update all installed components.",false).option("-E, --expand","Expands the diff so you see everything.",false).option("--max-unchanged <number>","Maximum unchanged lines that will show without being collapsed.",e=>Number.parseInt(e),3).option("-n, --no","Do update any blocks.",false).option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",false).option("-y, --yes","Skip confirmation prompt.",false).option("--verbose","Include debug logs.",false).option("--cwd <path>","The current working directory.",process.cwd()).action(async(e,t)=>{let r=b.parse(Xs,t);me(re),await Qs(e,r),outro(T.green("All done!"));}),Qs=async(e,t)=>{let r=u=>{t.verbose&&console.info(`${mt} ${u}`);};r(`Attempting to update ${JSON.stringify(e)}`);let o=spinner(),n=Ae(t.cwd).match(u=>u,u=>program.error(T.red(u))),s=n.repos;t.repo&&(s=[t.repo]);for(let u of e)ee.find(w=>u.startsWith(w.name()))&&program.error(T.red(`Invalid value provided for block names \`${T.bold(u)}\`. Block names are expected to be provided in the format of \`${T.bold("<category>/<name>")}\``));if(!t.allow&&t.repo){let u=await confirm({message:`Allow ${T.cyan("jsrepo")} to download and run code from ${T.cyan(t.repo)}?`,initialValue:true});(isCancel(u)||!u)&&(cancel("Canceled!"),process.exit(0));}r(`Resolving ${T.cyan(s.join(", "))}`),t.verbose||o.start(`Fetching blocks from ${T.cyan(s.join(", "))}`);let i=(await wt(...s)).match(u=>u,({repo:u,message:w})=>{o.stop(`Failed to get info for ${T.cyan(u)}`),program.error(T.red(w));});r(`Resolved ${T.cyan(s.join(", "))}`),r(`Fetching blocks from ${T.cyan(s.join(", "))}`);let a=(await vt(...i)).match(u=>u,({repo:u,message:w})=>{o.stop(`Failed fetching blocks from ${T.cyan(u)}`),program.error(T.red(w));});t.verbose||o.stop(`Retrieved blocks from ${T.cyan(s.join(", "))}`),r(`Retrieved blocks from ${T.cyan(s.join(", "))}`);let p=it(a,n,t.cwd);p.length===0&&program.error(T.red(`You haven't installed any blocks yet. Did you mean to \`${T.bold("add")}\`?`));let d=e;if(t.all&&(d=p.map(u=>u.specifier)),d.length===0){let u=await multiselect({message:`Which blocks would you like to ${t.no?"diff":"update"}?`,options:p.filter(w=>w.block.list).map(w=>({label:`${T.cyan(w.block.category)}/${w.block.name}`,value:w.specifier})),required:true});isCancel(u)&&(cancel("Canceled!"),process.exit(0)),d=u;}r(`Preparing to update ${T.cyan(d.join(", "))}`);let c=(await st(d,a,i)).match(u=>u,program.error),g=(await detect({cwd:t.cwd}))?.agent??"npm",l=[],h=new Set,R=new Set,{prettierOptions:S,biomeOptions:$}=await $t({formatter:n.formatter,cwd:t.cwd}),m=De(n.paths,t.cwd);m.isErr()&&program.error(T.red(m.unwrapErr()));let O=m.unwrap(),V="Claude 3.5 Sonnet";for(let{block:u}of c){let w=ne(u.sourceRepo.url,u.category,u.name),A=er(re.package.version,u.sourceRepo.url),x=u.sourceRepo;r(`Attempting to add ${w}`);let U;O[u.category]!==undefined?U=Y.join(t.cwd,O[u.category]):U=Y.join(t.cwd,O["*"],u.category);let ce=[],f=async y=>{let v=await x.provider.fetchRaw(x,y,{verbose:r});return v.isErr()&&(o.stop(T.red(`Error fetching ${T.bold(y)}`)),program.error(T.red(`There was an error trying to get ${w}`))),v.unwrap()};for(let y of u.files){if(!n.includeTests&&Se(y))continue;let v=Y.join(u.directory,y),E;u.subdirectory?E=Y.join(U,u.name,y):E=Y.join(U,y);let k=await f(v);Be.mkdirSync(E.slice(0,E.length-y.length),{recursive:true}),ce.push({content:k,destPath:E,fileName:y});}process.stdout.write(`${D}
|
|
59
77
|
`),process.stdout.write(`${D} ${w}
|
|
60
|
-
`);for(let
|
|
61
|
-
`);let
|
|
62
|
-
`,intro:({from:
|
|
63
|
-
${
|
|
64
|
-
`}});if(process.stdout.write(
|
|
78
|
+
`);for(let y of ce){let v=await Qt({file:y,biomeOptions:$,prettierOptions:S,config:n,imports:u._imports_,watermark:A,verbose:r,cwd:t.cwd});v.isErr()&&program.error(T.red(v.unwrapErr()));let E=v.unwrap(),k=v.unwrap(),F=t.yes;if(!t.yes){process.stdout.write(`${D}
|
|
79
|
+
`);let _="";Be.existsSync(y.destPath)&&(_=Be.readFileSync(y.destPath).toString());let X=ne(x.url,y.fileName),W=Y.relative(t.cwd,y.destPath);for(;;){let le=diffLines(_,k),I=So({from:X,to:W,changes:le,expand:t.expand,maxUnchanged:t.maxUnchanged,prefix:()=>`${D} `,onUnchanged:({from:K,to:de,prefix:Ne})=>`${Ne?.()??""}${T.cyan(K)} \u2192 ${T.gray(de)} ${T.gray("(unchanged)")}
|
|
80
|
+
`,intro:({from:K,to:de,changes:Ne,prefix:ft})=>{let Or=Ne.filter(Nr=>Nr.added||Nr.removed).length;return `${ft?.()??""}${T.cyan(K)} \u2192 ${T.gray(de)} (${Or} change${Or===1?"":"s"})
|
|
81
|
+
${ft?.()??""}
|
|
82
|
+
`}});if(process.stdout.write(I),(le.length>1||_==="")&&(F=t.yes,!t.yes&&!t.no)){let K=await select({message:"Accept changes?",options:[{label:"Accept",value:"accept"},{label:"Reject",value:"reject"},{label:`\u2728 ${T.yellow("Update with AI")} \u2728`,value:"update"}]});if(isCancel(K)&&(cancel("Canceled!"),process.exit(0)),K==="update"){let de=await select({message:"Select a model",options:Object.keys(Ir).map(Ne=>({label:Ne,value:Ne}))});isCancel(de)&&(cancel("Canceled!"),process.exit(0)),V=de;try{k=await Ir[V].updateFile({originalFile:{content:_,path:W},newFile:{content:E,path:X},loading:o,verbose:t.verbose?r:void 0});}catch(Ne){o.stop(),log.error(T.red(`Error getting completions: ${Ne}`)),process.stdout.write(`${D}
|
|
83
|
+
`);continue}k=await po({file:{content:k,destPath:y.destPath},biomeOptions:$,prettierOptions:S,config:n}),process.stdout.write(`${D}
|
|
84
|
+
`);continue}F=K==="accept";break}break}}F&&await Pt([{loadingMessage:`Writing changes to ${T.cyan(y.destPath)}`,completedMessage:`Wrote changes to ${T.cyan(y.destPath)}.`,run:async()=>Be.writeFileSync(y.destPath,k)}],{verbose:t.verbose?r:undefined});}if(n.includeTests&&u.tests){r("Trying to include tests");let{devDependencies:y}=JSON.parse(Be.readFileSync(Y.join(t.cwd,"package.json")).toString());(y===undefined||y.vitest===undefined)&&h.add("vitest");}for(let y of u.devDependencies)h.add(y);for(let y of u.dependencies)R.add(y);}await Pt(l,{verbose:t.verbose?r:undefined});let z=Jt(R,h,{cwd:t.cwd});if(R=z.dependencies,h=z.devDependencies,R.size>0||h.size>0){let u=t.yes;if(!t.yes&&!t.no){let x=await confirm({message:"Would you like to install dependencies?",initialValue:true});isCancel(x)&&(cancel("Canceled!"),process.exit(0)),u=x;}u&&(R.size>0&&(t.verbose||o.start(`Installing dependencies with ${T.cyan(g)}`),(await Te({pm:g,deps:Array.from(R),dev:false,cwd:t.cwd})).match(x=>{t.verbose||o.stop(`Installed ${T.cyan(x.join(", "))}`);},x=>{t.verbose||o.stop("Failed to install dependencies"),program.error(x);})),h.size>0&&(t.verbose||o.start(`Installing dependencies with ${T.cyan(g)}`),(await Te({pm:g,deps:Array.from(h),dev:true,cwd:t.cwd})).match(x=>{t.verbose||o.stop(`Installed ${T.cyan(x.join(", "))}`);},x=>{t.verbose||o.stop("Failed to install dev dependencies"),program.error(x);})));let w=[];if(!u){if(R.size>0){let x=resolveCommand(g,"add",[...R]);w.push(`Install dependencies \`${T.cyan(`${x?.command} ${x?.args.join(" ")}`)}\``);}if(h.size>0){let x=resolveCommand(g,"add",[...h,"-D"]);w.push(`Install dev dependencies \`${T.cyan(`${x?.command} ${x?.args.join(" ")}`)}\``);}}w=w.map((x,U)=>`${U+1}. ${x}`),u||w.push(""),w.push("Import and use the blocks!");let A=kt(w);process.stdout.write(A);}};var Pr="latest-version",ti=60*60*1e3,Oo=async()=>{try{let e=te(),t,r=e.get(Pr);if(r){if(r.expiration>Date.now())return t=r.version,C(t);e.delete(Pr);}let o=new AbortController,n=setTimeout(()=>{o.abort();},1e3),s=await fetch("https://raw.githubusercontent.com/ieedan/jsrepo/refs/heads/main/packages/cli/package.json",{signal:o.signal});if(clearTimeout(n),!s.ok)return j("Error getting version");let{version:i}=await s.json();return t=i,e.set(Pr,{expiration:Date.now()+ti,version:t}),C(t)}catch(e){return j(`Error getting version: ${e}`)}};var No=e=>{let t=fileURLToPath(import.meta.url);return Y.join(t,"../..",e)},{version:Ao,name:Do,description:Lo,repository:ii}=JSON.parse(Be.readFileSync(No("package.json"),"utf-8")),ai=(await Oo()).match(e=>e,()=>{}),re={package:{name:Do,description:Lo,version:Ao,repository:ii,latestVersion:ai},resolveRelativeToRoot:No},Bo=program.name(Do).description(Lo).version(Ao).addCommand(gr).addCommand(vr).addCommand(wr).addCommand(br).addCommand(xr).addCommand(Er).addCommand(Tr);Bo.parse();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsrepo",
|
|
3
3
|
"description": "A CLI to add shared code from remote repositories.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.28.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://jsrepo.dev",
|
|
7
7
|
"author": {
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"vitest": "^2.1.8"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"@anthropic-ai/sdk": "^0.33.1",
|
|
47
48
|
"@biomejs/js-api": "^0.7.1",
|
|
48
49
|
"@biomejs/wasm-nodejs": "^1.9.4",
|
|
49
50
|
"@clack/prompts": "^0.9.1",
|
|
@@ -56,8 +57,11 @@
|
|
|
56
57
|
"estree-walker": "^3.0.3",
|
|
57
58
|
"execa": "^9.5.2",
|
|
58
59
|
"get-tsconfig": "^4.8.1",
|
|
60
|
+
"ignore": "^7.0.3",
|
|
59
61
|
"node-fetch": "^3.3.2",
|
|
60
62
|
"octokit": "^4.1.0",
|
|
63
|
+
"ollama": "^0.5.12",
|
|
64
|
+
"openai": "^4.79.1",
|
|
61
65
|
"package-manager-detector": "^0.2.8",
|
|
62
66
|
"parse5": "^7.2.1",
|
|
63
67
|
"pathe": "^2.0.1",
|