@iconia/react 0.1.0-dev.2b3c0be → 0.1.0-dev.2b7ace2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli/index.js +15 -16
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -1,27 +1,26 @@
1
1
  #!/usr/bin/env node
2
- var K=new AbortController;process.on("SIGINT",()=>{K.abort(),process.stderr.write(`
3
- `),process.exit(130)});import{Command as Qo}from"commander";import{Command as jo}from"commander";import l from"fs";import uo from"path";import S from"picocolors";var Uo=`import type { IconiaConfig } from '@iconia/react';
2
+ import{Command as Qo}from"commander";import{Command as Ro}from"commander";import N from"fs";import jo from"path";import v from"picocolors";var Uo=`import type { IconiaConfig } from '@iconia/react';
4
3
 
5
4
  const config: IconiaConfig = {
6
5
  apiKey: process.env.ICONIA_API_KEY ?? '',
7
- collections: [],
6
+ collections: ['my-icons'],
8
7
  };
9
8
 
10
9
  export default config;
11
- `,X=new jo("init").description("Create an iconia.config.ts file in the current directory").action(()=>{let o=uo.resolve(process.cwd(),"iconia.config.ts");if(l.existsSync(o)){console.log(S.yellow("iconia.config.ts already exists. Skipping."));return}l.writeFileSync(o,Uo),console.log(S.green("✓ Created iconia.config.ts")),console.log(`
12
- Next steps:`),console.log(` 1. Set ${S.cyan("ICONIA_API_KEY")} in your environment`),console.log(` 2. Edit ${S.cyan("iconia.config.ts")} to add your collections`),console.log(` 3. Run ${S.cyan("npx iconia pull")} to fetch icons`),console.log(`
13
- Import icons: ${S.cyan("import { MyIcon } from '@iconia/react/my-collection'")}`)});import{Command as vo}from"commander";import v from"picocolors";import So from"ora";import{z as H}from"zod";import D from"path";var po=H.object({apiKey:H.string().min(1,"apiKey is required"),collections:H.array(H.string()).default([])}),Lo="https://api.iconia.io";async function U(){let o=D.resolve(process.cwd(),"iconia.config.ts"),r=D.resolve(process.cwd(),"iconia.config.js"),i;try{let f=await import(o);i=f.default??f}catch{try{let f=await import(r);i=f.default??f}catch{throw Error("Could not find iconia.config.ts or iconia.config.js\nRun `npx @iconia/react init` to create one.")}}let n=po.safeParse(i);if(!n.success){let f=n.error.issues.map((a)=>` - ${a.path.join(".")}: ${a.message}`).join(`
10
+ `,X=new Ro("init").description("Create an iconia.config.ts file in the current directory").action(()=>{let o=jo.resolve(process.cwd(),"iconia.config.ts");if(N.existsSync(o)){console.log(v.yellow("iconia.config.ts already exists. Skipping."));return}N.writeFileSync(o,Uo),console.log(v.green("✓ Created iconia.config.ts")),console.log(`
11
+ Next steps:`),console.log(` 1. Set ${v.cyan("ICONIA_API_KEY")} in your environment`),console.log(` 2. Edit ${v.cyan("iconia.config.ts")} to add your collections`),console.log(` 3. Run ${v.cyan("npx iconia pull")} to fetch icons`),console.log(`
12
+ Import icons: ${v.cyan("import { MyIcon } from '@iconia/react/my-collection'")}`)});import{Command as Vo}from"commander";import V from"picocolors";import vo from"ora";import{z as Y}from"zod";import D from"path";var uo=Y.object({apiKey:Y.string().min(1,"apiKey is required"),collections:Y.array(Y.string()).default([])}),Lo="https://api.iconia.io";async function u(){let o=D.resolve(process.cwd(),"iconia.config.ts"),r=D.resolve(process.cwd(),"iconia.config.js"),i;try{let f=await import(o);i=f.default??f}catch{try{let f=await import(r);i=f.default??f}catch{throw Error("Could not find iconia.config.ts or iconia.config.js\nRun `npx @iconia/react init` to create one.")}}let n=uo.safeParse(i);if(!n.success){let f=n.error.issues.map((m)=>` - ${m.path.join(".")}: ${m.message}`).join(`
14
13
  `);throw Error(`Invalid iconia config:
15
- ${f}`)}let t=i.__internal?.endpoint??Lo;return{...n.data,apiUrl:t}}function G(o){return{Authorization:`ApiKey ${o.apiKey}`,"Content-Type":"application/json"}}async function M(o,r=3){for(let i=0;i<=r;i++){let n=await o(K.signal);if(n.status!==429||i===r)return n;let c=parseInt(n.headers.get("Retry-After")??"60",10);process.stderr.write(`
16
- ⏳ Rate limited — waiting ${c}s before retry ${i+1}/${r}...
17
- `),await new Promise((t)=>{let f=()=>{clearTimeout(a),process.exit(130)},a=setTimeout(()=>{process.removeListener("SIGINT",f),t()},c*1000);process.once("SIGINT",f),K.signal.addEventListener("abort",f,{once:!0})})}return o(K.signal)}async function x(o){let r=await M((n)=>fetch(new URL("/v1/collections",o.apiUrl).toString(),{headers:G(o),signal:n}));if(!r.ok){let n={};try{n=await r.json()}catch{}throw Error(`API error ${r.status}: ${n.error??r.statusText}`)}return(await r.json()).collections}async function V(o,r){let i=new URL("/v1/collections/icons",o.apiUrl);i.searchParams.set("collections",r.join(","));let n=await M((t)=>fetch(i.toString(),{headers:G(o),signal:t}));if(!n.ok){let t={};try{t=await n.json()}catch{}throw Error(`API error ${n.status}: ${t.error??n.statusText}`)}return(await n.json()).icons}async function g(o,r){let i=await M((n)=>fetch(new URL("/v1/icons",o.apiUrl).toString(),{method:"POST",headers:G(o),body:JSON.stringify(r),signal:n}));if(!i.ok){let n={};try{n=await i.json()}catch{}throw Error(n.error??i.statusText)}return!0}import L from"fs";import O from"path";import{fileURLToPath as Eo}from"url";import bo from"picocolors";import{optimize as _o}from"svgo";function Co(o){return _o(o,{plugins:["removeDoctype","removeXMLProcInst","removeComments","removeMetadata","removeTitle","removeDesc"]}).data.replace(/<svg([^>]*)>/i,(i,n)=>`<svg${n.replace(/\s+(width|height)=['"][^'"]*['"]/gi,"")}>`)}function oo(o){let r={},i=/([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,n;while((n=i.exec(o))!==null){let c=n[1].replace(/^xlink:/,"").replace(/-([a-z])/g,(t,f)=>f.toUpperCase());r[c]=n[2]??n[3]??""}return r}function ro(o){let r=[],i=0;while(i<o.length){let n=o.indexOf("<",i);if(n===-1)break;let c=o[n+1];if(c==="/"||c==="!"||c==="?"){let d=o.indexOf(">",n);i=d===-1?o.length:d+1;continue}let t=n+1,f=!1,a="";while(t<o.length){let d=o[t];if(f){if(d===a)f=!1}else if(d==='"'||d==="'")f=!0,a=d;else if(d===">")break;t++}if(t>=o.length)break;let s=o.slice(n+1,t),m=s.trimEnd().endsWith("/"),y=m?s.slice(0,s.lastIndexOf("/")).trim():s.trim(),e=y.search(/\s/),w=e===-1?y:y.slice(0,e);if(!w){i=t+1;continue}let j=e===-1?"":y.slice(e+1),E=oo(j);if(i=t+1,m)r.push([w,E]);else{let d=`<${w}`,b=`</${w}>`,F=1,R=i;while(F>0&&R<o.length){let u=o.indexOf(d,R),$=o.indexOf(b,R);if($===-1)break;if(u!==-1&&u<$)F++,R=u+d.length;else if(F--,F===0){let Fo=o.slice(i,$),N=ro(Fo),Ro=N.length>0?[w,E,N]:[w,E];r.push(Ro),i=$+b.length}else R=$+b.length}if(F>0)r.push([w,E])}}return r}function io(o){let r=Co(o),i=r.match(/<svg([^>]*)>/i),n=oo(i?.[1]??"");delete n.xmlns,delete n.xmlnsXlink;let{viewBox:c}=n,t=c?{viewBox:c}:{},a=r.match(/<svg[^>]*>([\s\S]*)<\/svg>/i)?.[1]?.trim()??"";return{iconNode:ro(a),svgAttrs:t}}function A(o){return o.replace(/[-_\s]+(.)/g,(r,i)=>i.toUpperCase()).replace(/^(.)/,(r,i)=>i.toUpperCase())}function no(o){if(o.length===0)return"";let r=["import { forwardRef, createElement } from 'react';","","const _r = (n) => n.map(([t, a, c], i) => createElement(t, { key: i, ...a }, ...(c ? _r(c) : [])));",""];for(let{name:i,iconNode:n,svgAttrs:c}of o){let t=A(i),f={viewBox:"0 0 24 24",...c},a=JSON.stringify(n),s=JSON.stringify(f);r.push(`export const ${t} = /*#__PURE__*/forwardRef(({ children, ...props }, ref) =>`,` createElement('svg', { ref, xmlns: 'http://www.w3.org/2000/svg', ...${s}, ...props },`,` ..._r(${a}),`," children"," )",");",`${t}.displayName = '${t}';`,"")}return r.join(`
18
- `)}function to(o){let r=["import type { ForwardRefExoticComponent, SVGProps, RefAttributes } from 'react';","","type IconComponent = ForwardRefExoticComponent<SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>>;",""];for(let i of o)r.push(`export declare const ${A(i)}: IconComponent;`);return r.push(""),r.join(`
19
- `)}function k(){return O.resolve(O.dirname(Eo(import.meta.url)),"..")}function P(o,r){let i=[];for(let c of r)try{let{iconNode:t,svgAttrs:f}=io(c.svgContent);i.push({name:c.name,iconNode:t,svgAttrs:f})}catch(t){console.warn(bo.yellow(` ⚠ Skipped ${c.name}: ${t.message}`))}if(i.length===0)return 0;let n=k();return L.writeFileSync(O.join(n,`${o}.js`),no(i),"utf-8"),L.writeFileSync(O.join(n,`${o}.d.ts`),to(i.map((c)=>c.name)),"utf-8"),i.length}function T(){let o=O.join(k(),"..","package.json");try{let r=JSON.parse(L.readFileSync(o,"utf-8")),i=r.exports??{};if(i["./*"]?.import?.startsWith("./dist/"))return;r.exports={".":i["."]??{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.cjs"},"./*":{import:"./dist/*.js",types:"./dist/*.d.ts"}},L.writeFileSync(o,JSON.stringify(r,null,2)+`
20
- `,"utf-8")}catch{}}function co(o){let r=k(),i=O.join(r,`${o}.js`),n=O.join(r,`${o}.d.ts`);if(L.existsSync(i))L.unlinkSync(i);if(L.existsSync(n))L.unlinkSync(n)}import fo from"fs";import Ko from"path";var Oo=".iconia-lock.json";function ao(){return Ko.resolve(process.cwd(),Oo)}function _(){try{let o=fo.readFileSync(ao(),"utf-8");return JSON.parse(o)}catch{return{version:1,collections:{}}}}function C(o){fo.writeFileSync(ao(),JSON.stringify(o,null,2),"utf-8")}function z(o,r,i){return{...o,collections:{...o.collections,[r]:{icons:Object.fromEntries(i.map((n)=>[n.slug,n.fingerprint]))}}}}function mo(o,r){let{[r]:i,...n}=o.collections;return{...o,collections:n}}var eo=new vo("pull").description("Fetch icons and regenerate all collection files (replaces existing)").option("-c, --collection <slug>","Pull only this collection").action(async(o)=>{let r=So("Loading config...").start(),i;try{i=await U()}catch(m){r.fail(v.red(m.message)),process.exit(1)}let n=o.collection?[o.collection]:i.collections;if(n.length===0){r.warn(v.yellow("No collections in config. Add one with `iconia add <slug>`."));return}if(o.collection&&!i.collections.includes(o.collection))r.fail(v.red(`Collection '${o.collection}' is not in your config.`)),process.exit(1);r.text=`Fetching icons for ${n.join(", ")}...`;let c;try{c=await V(i,n)}catch(m){r.fail(v.red(`Failed to fetch icons: ${m.message}`)),process.exit(1)}if(c.length===0){r.warn(v.yellow("No icons found."));return}r.text=`Generating ${c.length} icon${c.length!==1?"s":""}...`;let t=new Map;for(let m of c){let y=t.get(m.collectionSlug)??[];y.push(m),t.set(m.collectionSlug,y)}let f=_(),a=0,s=[];for(let[m,y]of t){let e=P(m,y);if(e===0)continue;a+=e,s.push(m),f=z(f,m,y.map((w)=>({slug:w.slug,fingerprint:w.fingerprint})))}if(C(f),T(),r.succeed(v.green(`Generated ${a} icon${a!==1?"s":""} across ${s.length} collection${s.length!==1?"s":""}`)),s.length>0){let m=s[0]??"",y=A(t.get(m)?.[0]?.name??"MyIcon");console.log(`
14
+ ${f}`)}let c=i.__internal?.endpoint??Lo;return{...n.data,apiUrl:c}}function Z(o){return{Authorization:`ApiKey ${o.apiKey}`,"Content-Type":"application/json"}}async function G(o,r=3){for(let i=0;i<=r;i++){let n=await o();if(n.status!==429||i===r)return n;let t=parseInt(n.headers.get("Retry-After")??"60",10);process.stderr.write(`
15
+ ⏳ Rate limited — waiting ${t}s before retry ${i+1}/${r}...
16
+ `),await new Promise((c)=>{let f=()=>{clearTimeout(m),process.exit(130)},m=setTimeout(()=>{process.removeListener("SIGINT",f),c()},t*1000);process.once("SIGINT",f)})}return o()}async function l(o){let r=await G(()=>fetch(new URL("/v1/collections",o.apiUrl).toString(),{headers:Z(o)}));if(!r.ok){let n={};try{n=await r.json()}catch{}throw Error(`API error ${r.status}: ${n.error??r.statusText}`)}return(await r.json()).collections}async function P(o,r){let i=new URL("/v1/collections/icons",o.apiUrl);i.searchParams.set("collections",r.join(","));let n=await G(()=>fetch(i.toString(),{headers:Z(o)}));if(!n.ok){let c={};try{c=await n.json()}catch{}throw Error(`API error ${n.status}: ${c.error??n.statusText}`)}return(await n.json()).icons}async function x(o,r){let i=await G(()=>fetch(new URL("/v1/icons",o.apiUrl).toString(),{method:"POST",headers:Z(o),body:JSON.stringify(r)}));if(!i.ok){let n={};try{n=await i.json()}catch{}throw Error(n.error??i.statusText)}return!0}import _ from"fs";import O from"path";import{fileURLToPath as Eo}from"url";import Ko from"picocolors";import{optimize as _o}from"svgo";function Co(o){return _o(o,{plugins:["removeDoctype","removeXMLProcInst","removeComments","removeMetadata","removeTitle","removeDesc"]}).data.replace(/<svg([^>]*)>/i,(i,n)=>`<svg${n.replace(/\s+(width|height)=['"][^'"]*['"]/gi,"")}>`)}function g(o){let r={},i=/([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,n;while((n=i.exec(o))!==null){let t=n[1].replace(/^xlink:/,"").replace(/-([a-z])/g,(c,f)=>f.toUpperCase());r[t]=n[2]??n[3]??""}return r}function oo(o){let r=[],i=0;while(i<o.length){let n=o.indexOf("<",i);if(n===-1)break;let t=o[n+1];if(t==="/"||t==="!"||t==="?"){let I=o.indexOf(">",n);i=I===-1?o.length:I+1;continue}let c=n+1,f=!1,m="";while(c<o.length){let I=o[c];if(f){if(I===m)f=!1}else if(I==='"'||I==="'")f=!0,m=I;else if(I===">")break;c++}if(c>=o.length)break;let $=o.slice(n+1,c),a=$.trimEnd().endsWith("/"),e=a?$.slice(0,$.lastIndexOf("/")).trim():$.trim(),y=e.search(/\s/),w=y===-1?e:e.slice(0,y);if(!w){i=c+1;continue}let j=y===-1?"":e.slice(y+1),K=g(j);if(i=c+1,a)r.push([w,K]);else{let I=`<${w}`,p=`</${w}>`,F=1,R=i;while(F>0&&R<o.length){let U=o.indexOf(I,R),s=o.indexOf(p,R);if(s===-1)break;if(U!==-1&&U<s)F++,R=U+I.length;else if(F--,F===0){let Io=o.slice(i,s),k=oo(Io),Fo=k.length>0?[w,K,k]:[w,K];r.push(Fo),i=s+p.length}else R=s+p.length}if(F>0)r.push([w,K])}}return r}function ro(o){let r=Co(o),i=r.match(/<svg([^>]*)>/i),n=g(i?.[1]??"");delete n.xmlns,delete n.xmlnsXlink;let{viewBox:t}=n,c=t?{viewBox:t}:{},m=r.match(/<svg[^>]*>([\s\S]*)<\/svg>/i)?.[1]?.trim()??"";return{iconNode:oo(m),svgAttrs:c}}function b(o){return o.replace(/[-_\s]+(.)/g,(r,i)=>i.toUpperCase()).replace(/^(.)/,(r,i)=>i.toUpperCase())}function io(o){if(o.length===0)return"";let r=["import { forwardRef, createElement } from 'react';","","const _r = (n) => n.map(([t, a, c], i) => createElement(t, { key: i, ...a }, ...(c ? _r(c) : [])));",""];for(let{name:i,iconNode:n,svgAttrs:t}of o){let c=b(i),f={viewBox:"0 0 24 24",...t},m=JSON.stringify(n),$=JSON.stringify(f);r.push(`export const ${c} = /*#__PURE__*/forwardRef(({ children, ...props }, ref) =>`,` createElement('svg', { ref, xmlns: 'http://www.w3.org/2000/svg', ...${$}, ...props },`,` ..._r(${m}),`," children"," )",");",`${c}.displayName = '${c}';`,"")}return r.join(`
17
+ `)}function no(o){let r=["import type { ForwardRefExoticComponent, SVGProps, RefAttributes } from 'react';","","type IconComponent = ForwardRefExoticComponent<SVGProps<SVGSVGElement> & RefAttributes<SVGSVGElement>>;",""];for(let i of o)r.push(`export declare const ${b(i)}: IconComponent;`);return r.push(""),r.join(`
18
+ `)}function M(){return O.resolve(O.dirname(Eo(import.meta.url)),"..")}function z(o,r){let i=[];for(let t of r)try{let{iconNode:c,svgAttrs:f}=ro(t.svgContent);i.push({name:t.name,iconNode:c,svgAttrs:f})}catch(c){console.warn(Ko.yellow(` ⚠ Skipped ${t.name}: ${c.message}`))}if(i.length===0)return 0;let n=M();return _.writeFileSync(O.join(n,`${o}.js`),io(i),"utf-8"),_.writeFileSync(O.join(n,`${o}.d.ts`),no(i.map((t)=>t.name)),"utf-8"),i.length}function H(){let o=O.join(M(),"..","package.json");try{let r=JSON.parse(_.readFileSync(o,"utf-8")),i=r.exports??{};if(i["./*"]?.import?.startsWith("./dist/"))return;r.exports={".":i["."]??{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.cjs"},"./*":{import:"./dist/*.js",types:"./dist/*.d.ts"}},_.writeFileSync(o,JSON.stringify(r,null,2)+`
19
+ `,"utf-8")}catch{}}function to(o){let r=M(),i=O.join(r,`${o}.js`),n=O.join(r,`${o}.d.ts`);if(_.existsSync(i))_.unlinkSync(i);if(_.existsSync(n))_.unlinkSync(n)}import co from"fs";import po from"path";var Oo=".iconia-lock.json";function fo(){return po.resolve(process.cwd(),Oo)}function C(){try{let o=co.readFileSync(fo(),"utf-8");return JSON.parse(o)}catch{return{version:1,collections:{}}}}function E(o){co.writeFileSync(fo(),JSON.stringify(o,null,2),"utf-8")}function J(o,r,i){return{...o,collections:{...o.collections,[r]:{icons:Object.fromEntries(i.map((n)=>[n.slug,n.fingerprint]))}}}}function mo(o,r){let{[r]:i,...n}=o.collections;return{...o,collections:n}}var ao=new Vo("pull").description("Fetch icons and regenerate all collection files (replaces existing)").option("-c, --collection <slug>","Pull only this collection").action(async(o)=>{let r=vo("Loading config...").start(),i;try{i=await u()}catch(a){r.fail(V.red(a.message)),process.exit(1)}let n=o.collection?[o.collection]:i.collections;if(n.length===0){r.warn(V.yellow("No collections in config. Add one with `iconia add <slug>`."));return}if(o.collection&&!i.collections.includes(o.collection))r.fail(V.red(`Collection '${o.collection}' is not in your config.`)),process.exit(1);r.text=`Fetching icons for ${n.join(", ")}...`;let t;try{t=await P(i,n)}catch(a){r.fail(V.red(`Failed to fetch icons: ${a.message}`)),process.exit(1)}if(t.length===0){r.warn(V.yellow("No icons found."));return}r.text=`Generating ${t.length} icon${t.length!==1?"s":""}...`;let c=new Map;for(let a of t){let e=c.get(a.collectionSlug)??[];e.push(a),c.set(a.collectionSlug,e)}let f=C(),m=0,$=[];for(let[a,e]of c){let y=z(a,e);if(y===0)continue;m+=y,$.push(a),f=J(f,a,e.map((w)=>({slug:w.slug,fingerprint:w.fingerprint})))}if(E(f),H(),r.succeed(V.green(`Generated ${m} icon${m!==1?"s":""} across ${$.length} collection${$.length!==1?"s":""}`)),$.length>0){let a=$[0]??"",e=b(c.get(a)?.[0]?.name??"MyIcon");console.log(`
21
20
  Import icons:
22
- ${v.cyan(`import { ${y} } from '@iconia/react/${m}'`)}`)}});import{Command as Vo}from"commander";import p from"picocolors";import Ao from"ora";import Y from"fs";import yo from"path";function h(){let o=yo.resolve(process.cwd(),"iconia.config.ts"),r=yo.resolve(process.cwd(),"iconia.config.js");if(Y.existsSync(o))return o;if(Y.existsSync(r))return r;return null}function Q(o){let n=Y.readFileSync(o,"utf-8").match(/collections:\s*\[([\s\S]*?)\]/)?.[1];if(!n)return null;let c=[],t=/['"]([^'"]+)['"]/g,f;while((f=t.exec(n))!==null){let a=f[1];if(a)c.push(a)}return c}function W(o,r){let i=Y.readFileSync(o,"utf-8"),n=r.length===0?"[]":`[
23
- ${r.map((t)=>` '${t}'`).join(`,
21
+ ${V.cyan(`import { ${e} } from '@iconia/react/${a}'`)}`)}});import{Command as Po}from"commander";import L from"picocolors";import bo from"ora";import S from"fs";import yo from"path";function h(){let o=yo.resolve(process.cwd(),"iconia.config.ts"),r=yo.resolve(process.cwd(),"iconia.config.js");if(S.existsSync(o))return o;if(S.existsSync(r))return r;return null}function Q(o){let n=S.readFileSync(o,"utf-8").match(/collections:\s*\[([\s\S]*?)\]/)?.[1];if(!n)return null;let t=[],c=/['"]([^'"]+)['"]/g,f;while((f=c.exec(n))!==null){let m=f[1];if(m)t.push(m)}return t}function T(o,r){let i=S.readFileSync(o,"utf-8"),n=r.length===0?"[]":`[
22
+ ${r.map((c)=>` '${c}'`).join(`,
24
23
  `)},
25
- ]`,c=i.replace(/collections:\s*\[[\s\S]*?\]/,`collections: ${n}`);if(c===i)return!1;return Y.writeFileSync(o,c,"utf-8"),!0}var wo=new Vo("add").description("Add a collection to your project (updates config and downloads icons)").argument("<slug>","Collection slug").action(async(o)=>{let r=Ao("Loading config...").start(),i;try{i=await U()}catch(a){r.fail(p.red(a.message)),process.exit(1)}if(i.collections.includes(o))r.info(p.yellow(`Collection '${o}' is already in your config. Running pull...`));else{r.text="Verifying collection...";let a;try{a=await x(i)}catch(j){r.fail(p.red(`Failed to fetch collections: ${j.message}`)),process.exit(1)}if(!a.find((j)=>j.slug===o))r.fail(p.red(`Collection '${o}' not found. Available: ${a.map((j)=>j.slug).join(", ")||"none"}`)),process.exit(1);let m=h();if(!m)r.fail(p.red("Config file not found. Run `npx @iconia/react init` first.")),process.exit(1);let e=[...Q(m)??i.collections,o];if(!W(m,e))r.warn(p.yellow(`Could not update config automatically. Add '${o}' to collections in iconia.config.ts manually.`));else r.text=`Added '${o}' to config. Fetching icons...`}r.text=`Fetching icons for '${o}'...`;let n;try{n=await V(i,[o])}catch(a){r.fail(p.red(`Failed to fetch icons: ${a.message}`)),process.exit(1)}if(n.length===0){r.warn(p.yellow(`No icons in collection '${o}'.`));return}r.text=`Generating ${n.length} icon${n.length!==1?"s":""}...`;let c=P(o,n),t=_();t=z(t,o,n.map((a)=>({slug:a.slug,fingerprint:a.fingerprint}))),C(t),r.succeed(p.green(`Added '${o}' — ${c} icon${c!==1?"s":""} generated`));let f=A(n[0]?.name??"Icon");console.log(`
24
+ ]`,t=i.replace(/collections:\s*\[[\s\S]*?\]/,`collections: ${n}`);if(t===i)return!1;return S.writeFileSync(o,t,"utf-8"),!0}var eo=new Po("add").description("Add a collection to your project (updates config and downloads icons)").argument("<slug>","Collection slug").action(async(o)=>{let r=bo("Loading config...").start(),i;try{i=await u()}catch(m){r.fail(L.red(m.message)),process.exit(1)}if(i.collections.includes(o))r.info(L.yellow(`Collection '${o}' is already in your config. Running pull...`));else{r.text="Verifying collection...";let m;try{m=await l(i)}catch(j){r.fail(L.red(`Failed to fetch collections: ${j.message}`)),process.exit(1)}if(!m.find((j)=>j.slug===o))r.fail(L.red(`Collection '${o}' not found. Available: ${m.map((j)=>j.slug).join(", ")||"none"}`)),process.exit(1);let a=h();if(!a)r.fail(L.red("Config file not found. Run `npx @iconia/react init` first.")),process.exit(1);let y=[...Q(a)??i.collections,o];if(!T(a,y))r.warn(L.yellow(`Could not update config automatically. Add '${o}' to collections in iconia.config.ts manually.`));else r.text=`Added '${o}' to config. Fetching icons...`}r.text=`Fetching icons for '${o}'...`;let n;try{n=await P(i,[o])}catch(m){r.fail(L.red(`Failed to fetch icons: ${m.message}`)),process.exit(1)}if(n.length===0){r.warn(L.yellow(`No icons in collection '${o}'.`));return}r.text=`Generating ${n.length} icon${n.length!==1?"s":""}...`;let t=z(o,n),c=C();c=J(c,o,n.map((m)=>({slug:m.slug,fingerprint:m.fingerprint}))),E(c),r.succeed(L.green(`Added '${o}' — ${t} icon${t!==1?"s":""} generated`));let f=b(n[0]?.name??"Icon");console.log(`
26
25
  Import icons:
27
- ${p.cyan(`import { ${f} } from '@iconia/react/${o}'`)}`)});import{Command as Po}from"commander";import Z from"picocolors";var so=new Po("remove").description("Remove a collection from your project (updates config and deletes generated files)").argument("<slug>","Collection slug").action(async(o)=>{let r;try{r=await U()}catch(n){console.error(Z.red(n.message)),process.exit(1)}if(!r.collections.includes(o))console.warn(Z.yellow(`Collection '${o}' is not in your config.`));else{let n=h();if(n){let t=(Q(n)??r.collections).filter((a)=>a!==o);if(!W(n,t))console.warn(Z.yellow(`Could not update config automatically. Remove '${o}' from collections in iconia.config.ts manually.`))}}co(o);let i=_();i=mo(i,o),C(i),console.log(Z.green(`✓ Removed collection '${o}'`))});import{Command as zo}from"commander";import I from"picocolors";import Jo from"ora";var $o=new zo("sync").description("Sync icons: add new, update changed, remove deleted — without full re-fetch").option("-c, --collection <slug>","Sync only this collection").action(async(o)=>{let r=Jo("Loading config...").start(),i;try{i=await U()}catch(e){r.fail(I.red(e.message)),process.exit(1)}let n=o.collection?[o.collection]:i.collections;if(n.length===0){r.warn(I.yellow("No collections in config. Add one with `iconia add <slug>`."));return}if(o.collection&&!i.collections.includes(o.collection))r.fail(I.red(`Collection '${o.collection}' is not in your config.`)),process.exit(1);r.text=`Fetching icons for ${n.join(", ")}...`;let c;try{c=await V(i,n)}catch(e){r.fail(I.red(`Failed to fetch icons: ${e.message}`)),process.exit(1)}let t=new Map;for(let e of c){let w=t.get(e.collectionSlug)??[];w.push(e),t.set(e.collectionSlug,w)}let f=_(),a=0,s=0,m=0,y=0;for(let e of n){let w=t.get(e)??[],j=f.collections[e]?.icons??{},E=new Map(w.map(($)=>[$.slug,$])),d=new Set(Object.keys(j)),b=new Set(E.keys()),F=[...b].filter(($)=>!d.has($)),R=[...d].filter(($)=>!b.has($)),u=[...b].filter(($)=>d.has($)&&j[$]!==E.get($).fingerprint);if(F.length===0&&R.length===0&&u.length===0){console.log(I.dim(` ${e}: up to date`));continue}if(F.length>0)console.log(I.green(` ${e}: +${F.length} added`)+I.dim(` (${F.slice(0,5).join(", ")}${F.length>5?"…":""})`));if(u.length>0)console.log(I.blue(` ${e}: ~${u.length} updated`)+I.dim(` (${u.slice(0,5).join(", ")}${u.length>5?"…":""})`));if(R.length>0)console.log(I.red(` ${e}: -${R.length} removed`)+I.dim(` (${R.slice(0,5).join(", ")}${R.length>5?"…":""})`));if(w.length>0)P(e,w);f=z(f,e,w.map(($)=>({slug:$.slug,fingerprint:$.fingerprint}))),a+=F.length,s+=u.length,m+=R.length,y++}if(C(f),y>0)T();if(y===0)r.succeed(I.green("Everything is up to date."));else r.succeed(I.green(`Sync complete: ${a} added, ${s} updated, ${m} removed across ${y} collection${y!==1?"s":""}`))});import{Command as qo}from"commander";import B from"fs";import q from"path";import J from"picocolors";import Yo from"ora";function Ho(o){return q.basename(o,q.extname(o)).toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function To(o){return o.split("-").map((r)=>r.charAt(0).toUpperCase()+r.slice(1)).join(" ")}function ho(o){let r=B.statSync(o);if(r.isFile()){if(!o.endsWith(".svg"))throw Error(`File '${o}' is not an SVG.`);return[o]}if(r.isDirectory())return B.readdirSync(o).filter((i)=>i.endsWith(".svg")).map((i)=>q.join(o,i));throw Error(`'${o}' is not a file or directory.`)}var Io=new qo("upload").description("Upload SVG file(s) to an Iconia collection").argument("<path>","SVG file or directory of SVGs").requiredOption("-c, --collection <slug>","Target collection slug").option("--tags <tags>","Comma-separated tags to apply to all uploaded icons").action(async(o,r)=>{let i=Yo({text:"Loading config...",discardStdin:!1}).start(),n;try{n=await U()}catch(m){i.fail(J.red(m.message)),process.exit(1)}let c;try{c=ho(q.resolve(process.cwd(),o))}catch(m){i.fail(J.red(m.message)),process.exit(1)}if(c.length===0){i.warn(J.yellow("No SVG files found."));return}let t=r.tags?r.tags.split(",").map((m)=>m.trim()).filter(Boolean):[];i.text=`Uploading ${c.length} file${c.length!==1?"s":""} to '${r.collection}'...`;let f=0,a=0,s=[];for(let m of c){if(K.signal.aborted)break;let y=Ho(m);if(!y){s.push(`${q.basename(m)}: could not derive a valid slug`),a++;continue}let e=B.readFileSync(m,"utf-8");try{await g(n,{collectionSlug:r.collection,name:To(y),slug:y,svgContent:e,tags:t}),f++,i.text=`Uploading... (${f}/${c.length})`}catch(w){s.push(`${q.basename(m)}: ${w.message}`),a++}}if(a===0)i.succeed(J.green(`Uploaded ${f} icon${f!==1?"s":""} to '${r.collection}'`));else{i.warn(J.yellow(`Uploaded ${f}, failed ${a}`));for(let m of s)console.log(J.dim(` ✗ ${m}`))}});var Wo=new Qo("iconia").version("0.1.0").description("CLI for fetching and generating React icon components from Iconia").addCommand(X).addCommand(wo).addCommand(so).addCommand(eo).addCommand($o).addCommand(Io);Wo.parse(process.argv);
26
+ ${L.cyan(`import { ${f} } from '@iconia/react/${o}'`)}`)});import{Command as zo}from"commander";import W from"picocolors";var wo=new zo("remove").description("Remove a collection from your project (updates config and deletes generated files)").argument("<slug>","Collection slug").action(async(o)=>{let r;try{r=await u()}catch(n){console.error(W.red(n.message)),process.exit(1)}if(!r.collections.includes(o))console.warn(W.yellow(`Collection '${o}' is not in your config.`));else{let n=h();if(n){let c=(Q(n)??r.collections).filter((m)=>m!==o);if(!T(n,c))console.warn(W.yellow(`Could not update config automatically. Remove '${o}' from collections in iconia.config.ts manually.`))}}to(o);let i=C();i=mo(i,o),E(i),console.log(W.green(`✓ Removed collection '${o}'`))});import{Command as Jo}from"commander";import d from"picocolors";import qo from"ora";var $o=new Jo("sync").description("Sync icons: add new, update changed, remove deleted — without full re-fetch").option("-c, --collection <slug>","Sync only this collection").action(async(o)=>{let r=qo("Loading config...").start(),i;try{i=await u()}catch(y){r.fail(d.red(y.message)),process.exit(1)}let n=o.collection?[o.collection]:i.collections;if(n.length===0){r.warn(d.yellow("No collections in config. Add one with `iconia add <slug>`."));return}if(o.collection&&!i.collections.includes(o.collection))r.fail(d.red(`Collection '${o.collection}' is not in your config.`)),process.exit(1);r.text=`Fetching icons for ${n.join(", ")}...`;let t;try{t=await P(i,n)}catch(y){r.fail(d.red(`Failed to fetch icons: ${y.message}`)),process.exit(1)}let c=new Map;for(let y of t){let w=c.get(y.collectionSlug)??[];w.push(y),c.set(y.collectionSlug,w)}let f=C(),m=0,$=0,a=0,e=0;for(let y of n){let w=c.get(y)??[],j=f.collections[y]?.icons??{},K=new Map(w.map((s)=>[s.slug,s])),I=new Set(Object.keys(j)),p=new Set(K.keys()),F=[...p].filter((s)=>!I.has(s)),R=[...I].filter((s)=>!p.has(s)),U=[...p].filter((s)=>I.has(s)&&j[s]!==K.get(s).fingerprint);if(F.length===0&&R.length===0&&U.length===0){console.log(d.dim(` ${y}: up to date`));continue}if(F.length>0)console.log(d.green(` ${y}: +${F.length} added`)+d.dim(` (${F.slice(0,5).join(", ")}${F.length>5?"…":""})`));if(U.length>0)console.log(d.blue(` ${y}: ~${U.length} updated`)+d.dim(` (${U.slice(0,5).join(", ")}${U.length>5?"…":""})`));if(R.length>0)console.log(d.red(` ${y}: -${R.length} removed`)+d.dim(` (${R.slice(0,5).join(", ")}${R.length>5?"…":""})`));if(w.length>0)z(y,w);f=J(f,y,w.map((s)=>({slug:s.slug,fingerprint:s.fingerprint}))),m+=F.length,$+=U.length,a+=R.length,e++}if(E(f),e>0)H();if(e===0)r.succeed(d.green("Everything is up to date."));else r.succeed(d.green(`Sync complete: ${m} added, ${$} updated, ${a} removed across ${e} collection${e!==1?"s":""}`))});import{Command as Ao}from"commander";import B from"fs";import A from"path";import q from"picocolors";import So from"ora";function Yo(o){return A.basename(o,A.extname(o)).toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function Ho(o){return o.split("-").map((r)=>r.charAt(0).toUpperCase()+r.slice(1)).join(" ")}function ho(o){let r=B.statSync(o);if(r.isFile()){if(!o.endsWith(".svg"))throw Error(`File '${o}' is not an SVG.`);return[o]}if(r.isDirectory())return B.readdirSync(o).filter((i)=>i.endsWith(".svg")).map((i)=>A.join(o,i));throw Error(`'${o}' is not a file or directory.`)}var so=new Ao("upload").description("Upload SVG file(s) to an Iconia collection").argument("<path>","SVG file or directory of SVGs").requiredOption("-c, --collection <slug>","Target collection slug").option("--tags <tags>","Comma-separated tags to apply to all uploaded icons").action(async(o,r)=>{let i=So("Loading config...").start(),n;try{n=await u()}catch(a){i.fail(q.red(a.message)),process.exit(1)}let t;try{t=ho(A.resolve(process.cwd(),o))}catch(a){i.fail(q.red(a.message)),process.exit(1)}if(t.length===0){i.warn(q.yellow("No SVG files found."));return}let c=r.tags?r.tags.split(",").map((a)=>a.trim()).filter(Boolean):[];i.text=`Uploading ${t.length} file${t.length!==1?"s":""} to '${r.collection}'...`;let f=0,m=0,$=[];for(let a of t){let e=Yo(a);if(!e){$.push(`${A.basename(a)}: could not derive a valid slug`),m++;continue}let y=B.readFileSync(a,"utf-8");try{await x(n,{collectionSlug:r.collection,name:Ho(e),slug:e,svgContent:y,tags:c}),f++,i.text=`Uploading... (${f}/${t.length})`}catch(w){$.push(`${A.basename(a)}: ${w.message}`),m++}}if(m===0)i.succeed(q.green(`Uploaded ${f} icon${f!==1?"s":""} to '${r.collection}'`));else{i.warn(q.yellow(`Uploaded ${f}, failed ${m}`));for(let a of $)console.log(q.dim(` ✗ ${a}`))}});var To=new Qo("iconia").version("0.1.0").description("CLI for fetching and generating React icon components from Iconia").addCommand(X).addCommand(eo).addCommand(wo).addCommand(ao).addCommand($o).addCommand(so);To.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iconia/react",
3
- "version": "0.1.0-dev.2b3c0be",
3
+ "version": "0.1.0-dev.2b7ace2",
4
4
  "description": "Fetch and generate React icon components from your Iconia collections",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",