@frontfriend/tailwind 4.0.6 → 4.0.7

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/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var O=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var Y=O((dn,H)=>{var he="https://app.frontfriend.dev",ye="https://registry-legacy.frontfriend.dev",ve=".cache/frontfriend",Ce={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","safelist.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},we={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};H.exports={DEFAULT_API_URL:he,LEGACY_API_URL:ye,CACHE_DIR_NAME:ve,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:Ce,ENV_VARS:we}});var te=O((un,oe)=>{var F=require("fs"),z=require("path"),Se=require("os"),je=require("https"),xe=require("http"),{URL:Fe}=require("url"),{DEFAULT_API_URL:W}=Y(),K=z.join(Se.homedir(),".frontfriend"),k=z.join(K,"credentials");function ke(){return k}function Z(){try{return F.existsSync(k)?JSON.parse(F.readFileSync(k,"utf8")):null}catch{return null}}function X(e){F.mkdirSync(K,{recursive:!0,mode:448}),F.writeFileSync(k,`${JSON.stringify(e,null,2)}
3
- `,{mode:384});try{F.chmodSync(k,384)}catch{}}function be(){return F.existsSync(k)?(F.unlinkSync(k),!0):!1}function Q(e,n=60*1e3){return!(e!=null&&e.accessToken)||!e.expiresAt||Date.now()+n>=e.expiresAt}function ee(e,n,o){return new Promise((t,s)=>{let r=new Fe(e),i=r.protocol==="https:"?je:xe,f=JSON.stringify(n||{}),l=i.request({hostname:r.hostname,port:r.port,path:`${r.pathname}${r.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(f),...o?{authorization:`Bearer ${o}`}:{}}},u=>{let g="";u.on("data",c=>{g+=c}),u.on("end",()=>{let c=null;try{c=g?JSON.parse(g):null}catch(p){s(p);return}if(u.statusCode>=400){let p=new Error((c==null?void 0:c.error_description)||(c==null?void 0:c.error)||`HTTP ${u.statusCode}`);p.statusCode=u.statusCode,p.body=c,s(p);return}t(c)})});l.on("error",s),l.write(f),l.end()})}async function ne(e,n=W){if(!(e!=null&&e.refreshToken)||!(e!=null&&e.deviceId))return e;let o=await ee(`${n}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:e.refreshToken,device_id:e.deviceId}),t={accessToken:o.access_token,refreshToken:o.refresh_token,deviceId:o.device_id||e.deviceId,expiresAt:Date.now()+(o.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(o.refresh_expires_in||604800)*1e3,ffApiUrl:n};return X(t),t}async function $e(e={}){if(!e.skipCredentials){let n=Z();if(n!=null&&n.accessToken){let o=e.baseURL||n.ffApiUrl||W;if(Q(n))try{let t=await ne(n,o);return(t==null?void 0:t.accessToken)||null}catch{return null}return n.accessToken}}return e.envToken?e.envToken:e.legacyToken?(e.silent||console.warn("\u26A0\uFE0F auth-token in frontfriend.config.js is deprecated. Run `frontfriend login` to store credentials outside the repo."),e.legacyToken):null}oe.exports={getCredentialsPath:ke,readCredentials:Z,writeCredentials:X,deleteCredentials:be,isExpired:Q,postJson:ee,refreshCredentials:ne,resolveAuthToken:$e}});var se=O((gn,Te)=>{Te.exports={name:"@frontfriend/tailwind",version:"4.0.6",description:"Design token management for Tailwind CSS",main:"./dist/index.js",types:"./dist/types/index.d.ts",bin:{frontfriend:"dist/cli.js"},exports:{".":{types:"./dist/types/index.d.ts",browser:"./dist/browser.mjs",import:"./dist/index.mjs",require:"./dist/index.js",default:"./dist/index.js"},"./runtime":{types:"./dist/runtime.d.ts",default:"./dist/runtime.js"},"./next":{types:"./dist/next.d.ts",default:"./dist/next.js"},"./vite":{types:"./dist/vite.d.ts",default:"./dist/vite.mjs"},"./lib/react/utils":{types:"./dist/lib/react/utils.d.ts",default:"./dist/lib/react/utils.mjs"},"./lib/vue/utils":{types:"./dist/lib/vue/utils.d.ts",default:"./dist/lib/vue/utils.mjs"},"./ffdc":{types:"./dist/ffdc.d.ts",default:"./dist/ffdc.js"},"./theme":"./src/theme.css","./theme.css":"./src/theme.css","./components-config-schema":{types:"./dist/components-config-schema.d.ts",require:"./dist/components-config-schema.js",import:"./dist/components-config-schema.js",default:"./dist/components-config-schema.js"}},scripts:{test:"jest",build:"node scripts/build.js",prepublishOnly:"npm run build"},keywords:["tailwindcss","design-tokens","frontfriend"],author:"Donux",license:"SEE LICENSE IN LICENSE",files:["dist/","src/theme.css","scripts/","README.md","LICENSE"],dependencies:{commander:"^11.0.0",dotenv:"^16.0.0",color:"^4.2.3",clsx:"^2.0.0","tailwind-merge":"^2.0.0","tw-animate-css":"^1.3.4"},peerDependencies:{tailwindcss:"^3.0.0 || ^4.0.0",react:"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",vue:">=3.0.0"},devDependencies:{jest:"^29.0.0",esbuild:"^0.19.0",glob:"^10.0.0"}}});var L=O((pn,A)=>{var j=require("fs"),E=require("path");function re(e={}){let n=e.projectRoot||process.cwd(),o=E.join(n,"node_modules",".cache","frontfriend","icons.json"),t=e.outputPath||E.join(n,"types","frontfriend.d.ts");j.existsSync(o)||(console.error('[FrontFriend] Error: icons.json not found. Please run "npx frontfriend init" first.'),process.exit(1));try{let l=function(v){for(let h of Object.values(v))typeof h=="string"?f.add(h):typeof h=="object"&&h!==null&&l(h)},u=function(v,h=" "){let C=[];for(let[P,S]of Object.entries(v))typeof S=="string"?C.push(`${h}${P}: '${S}';`):typeof S=="object"&&S!==null&&(C.push(`${h}${P}: {`),C.push(u(S,h+" ")),C.push(`${h}};`));return C.join(`
4
- `)};var s=l,r=u;let i=JSON.parse(j.readFileSync(o,"utf-8")),f=new Set;l(i);let g=Array.from(f).map(v=>`'${v}'`).join(" | "),c=`// Generated by @frontfriend/tailwind
2
+ var O=(e,o)=>()=>(o||e((o={exports:{}}).exports,o),o.exports);var z=O((uo,Y)=>{var ye="https://app.frontfriend.dev",Ce="https://registry-legacy.frontfriend.dev",ve=".cache/frontfriend",we={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","safelist.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},Se={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};Y.exports={DEFAULT_API_URL:ye,LEGACY_API_URL:Ce,CACHE_DIR_NAME:ve,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:we,ENV_VARS:Se}});var se=O((go,te)=>{var k=require("fs"),W=require("path"),je=require("os"),Fe=require("https"),xe=require("http"),{URL:ke}=require("url"),{DEFAULT_API_URL:K}=z(),Z=W.join(je.homedir(),".frontfriend"),$=W.join(Z,"credentials");function $e(){return $}function X(){try{return k.existsSync($)?JSON.parse(k.readFileSync($,"utf8")):null}catch{return null}}function Q(e){k.mkdirSync(Z,{recursive:!0,mode:448}),k.writeFileSync($,`${JSON.stringify(e,null,2)}
3
+ `,{mode:384});try{k.chmodSync($,384)}catch{}}function be(){return k.existsSync($)?(k.unlinkSync($),!0):!1}function ee(e,o=60*1e3){return!(e!=null&&e.accessToken)||!e.expiresAt||Date.now()+o>=e.expiresAt}function A(e){let o=new Error(`${e}. Run \`frontfriend login\` to re-authenticate.`);return o.code="FF_AUTH_REFRESH_FAILED",o}function oe(e,o,n){return new Promise((t,s)=>{let r=new ke(e),i=r.protocol==="https:"?Fe:xe,d=JSON.stringify(o||{}),f=i.request({hostname:r.hostname,port:r.port,path:`${r.pathname}${r.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(d),...n?{authorization:`Bearer ${n}`}:{}}},a=>{let g="";a.on("data",c=>{g+=c}),a.on("end",()=>{if(a.statusCode>=300&&a.statusCode<400){let p=a.headers.location?` to ${a.headers.location}`:"",C=new Error(`HTTP ${a.statusCode}: redirected${p}`);C.statusCode=a.statusCode,C.body=g,s(C);return}let c=null;try{c=g?JSON.parse(g):null}catch(p){if(a.statusCode>=400){let C=new Error(`HTTP ${a.statusCode}: ${a.statusMessage||"Non-JSON response"}`);C.statusCode=a.statusCode,C.body=g,s(C);return}s(p);return}if(a.statusCode>=400){let p=new Error((c==null?void 0:c.error_description)||(c==null?void 0:c.error)||`HTTP ${a.statusCode}`);p.statusCode=a.statusCode,p.body=c,s(p);return}t(c)})});f.on("error",s),f.write(d),f.end()})}async function ne(e,o=K){if(!(e!=null&&e.refreshToken)||!(e!=null&&e.deviceId))throw A("FrontFriend session expired");let n;try{n=await oe(`${o}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:e.refreshToken,device_id:e.deviceId})}catch(s){throw A((s==null?void 0:s.message)||"Could not refresh FrontFriend session")}if(!(n!=null&&n.access_token)||!(n!=null&&n.refresh_token))throw A("Could not refresh FrontFriend session");let t={accessToken:n.access_token,refreshToken:n.refresh_token,deviceId:n.device_id||e.deviceId,expiresAt:Date.now()+(n.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(n.refresh_expires_in||604800)*1e3,ffApiUrl:o};return Q(t),t}async function Te(e={}){if(!e.skipCredentials){let o=X();if(o!=null&&o.accessToken||o!=null&&o.refreshToken){let n=e.baseURL||o.ffApiUrl||K;return o.accessToken&&!ee(o)?o.accessToken:(await ne(o,n)).accessToken}}return e.envToken?e.envToken:e.legacyToken?(e.silent||console.warn("\u26A0\uFE0F auth-token in frontfriend.config.js is deprecated. Run `frontfriend login` to store credentials outside the repo."),e.legacyToken):null}te.exports={getCredentialsPath:$e,readCredentials:X,writeCredentials:Q,deleteCredentials:be,isExpired:ee,postJson:oe,refreshCredentials:ne,resolveAuthToken:Te,createAuthRefreshError:A}});var re=O((po,_e)=>{_e.exports={name:"@frontfriend/tailwind",version:"4.0.7",description:"Design token management for Tailwind CSS",main:"./dist/index.js",types:"./dist/types/index.d.ts",bin:{frontfriend:"dist/cli.js"},exports:{".":{types:"./dist/types/index.d.ts",browser:"./dist/browser.mjs",import:"./dist/index.mjs",require:"./dist/index.js",default:"./dist/index.js"},"./runtime":{types:"./dist/runtime.d.ts",default:"./dist/runtime.js"},"./next":{types:"./dist/next.d.ts",default:"./dist/next.js"},"./vite":{types:"./dist/vite.d.ts",default:"./dist/vite.mjs"},"./lib/react/utils":{types:"./dist/lib/react/utils.d.ts",default:"./dist/lib/react/utils.mjs"},"./lib/vue/utils":{types:"./dist/lib/vue/utils.d.ts",default:"./dist/lib/vue/utils.mjs"},"./ffdc":{types:"./dist/ffdc.d.ts",default:"./dist/ffdc.js"},"./theme":"./src/theme.css","./theme.css":"./src/theme.css","./components-config-schema":{types:"./dist/components-config-schema.d.ts",require:"./dist/components-config-schema.js",import:"./dist/components-config-schema.js",default:"./dist/components-config-schema.js"}},scripts:{test:"jest",build:"node scripts/build.js",prepublishOnly:"npm run build"},keywords:["tailwindcss","design-tokens","frontfriend"],author:"Donux",license:"SEE LICENSE IN LICENSE",files:["dist/","src/theme.css","scripts/","README.md","LICENSE"],dependencies:{commander:"^11.0.0",dotenv:"^16.0.0",color:"^4.2.3",clsx:"^2.0.0","tailwind-merge":"^2.0.0","tw-animate-css":"^1.3.4"},peerDependencies:{tailwindcss:"^3.0.0 || ^4.0.0",react:"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",vue:">=3.0.0"},devDependencies:{jest:"^29.0.0",esbuild:"^0.19.0",glob:"^10.0.0"}}});var U=O((mo,L)=>{var F=require("fs"),E=require("path");function ie(e={}){let o=e.projectRoot||process.cwd(),n=E.join(o,"node_modules",".cache","frontfriend","icons.json"),t=e.outputPath||E.join(o,"types","frontfriend.d.ts");F.existsSync(n)||(console.error('[FrontFriend] Error: icons.json not found. Please run "npx frontfriend init" first.'),process.exit(1));try{let f=function(v){for(let h of Object.values(v))typeof h=="string"?d.add(h):typeof h=="object"&&h!==null&&f(h)},a=function(v,h=" "){let w=[];for(let[P,j]of Object.entries(v))typeof j=="string"?w.push(`${h}${P}: '${j}';`):typeof j=="object"&&j!==null&&(w.push(`${h}${P}: {`),w.push(a(j,h+" ")),w.push(`${h}};`));return w.join(`
4
+ `)};var s=f,r=a;let i=JSON.parse(F.readFileSync(n,"utf-8")),d=new Set;f(i);let g=Array.from(d).map(v=>`'${v}'`).join(" | "),c=`// Generated by @frontfriend/tailwind
5
5
  // DO NOT EDIT THIS FILE MANUALLY
6
6
 
7
7
  import type { IconSetStructure } from '@frontfriend/tailwind';
@@ -12,7 +12,7 @@ declare module '@frontfriend/tailwind' {
12
12
 
13
13
  // Typed iconSet structure with exact icon names
14
14
  export interface TypedIconSet extends IconSetStructure {
15
- ${u(i)}
15
+ ${a(i)}
16
16
  }
17
17
  }
18
18
 
@@ -36,43 +36,43 @@ declare module '@/src/components/ui/icon' {
36
36
  declare module '@/src/components/ui/icon/Icon.vue' {
37
37
  export type IconName = ${g||"string"};
38
38
  }
39
- `,p=E.dirname(t);j.existsSync(p)||j.mkdirSync(p,{recursive:!0}),j.writeFileSync(t,c),console.log("[FrontFriend] \u2713 Generated types at",E.relative(n,t));let T=E.join(n,"tsconfig.json");if(j.existsSync(T)){let v=JSON.parse(j.readFileSync(T,"utf-8"));v.include||(v.include=[]);let h="types/**/*.d.ts";v.include.includes(h)||(v.include.push(h),j.writeFileSync(T,JSON.stringify(v,null,2)),console.log("[FrontFriend] \u2713 Updated tsconfig.json to include generated types"))}}catch(i){console.error("[FrontFriend] Error generating icon types:",i.message),process.exit(1)}}require.main===A&&re();A.exports={generateIconTypes:re}});var{loadEnvLocal:_e}=require("./lib/core/env-utils");_e();var{Command:Ee}=require("commander"),I=require("./lib/core/config-loader"),D=require("./lib/core/cache-manager"),{APIClient:ae}=require("./lib/core/api-client"),{getCredentialsPath:Ie,writeCredentials:Pe,readCredentials:Oe,deleteCredentials:De,postJson:U}=te(),{ComponentDownloader:Ae}=require("./lib/core/component-downloader"),Le=require("./lib/core/token-processor"),{ConfigError:x,APIError:Ue,CacheError:M}=require("./lib/core/errors"),a=require("path"),d=require("fs"),{spawn:Ne}=require("child_process"),w=new Ee,{version:le}=se(),Re="https://registry.frontfriend.dev/r/v4",ie='@import "@frontfriend/tailwind/theme.css";';function Ve(e){return(e||process.env.FF_REGISTRY_URL||Re).replace(/\/+$/,"")}function $(e){try{return JSON.parse(d.readFileSync(e,"utf8"))}catch{return null}}function q(e,n){d.mkdirSync(a.dirname(e),{recursive:!0}),d.writeFileSync(e,`${JSON.stringify(n,null,2)}
40
- `)}var Me=a.join("node_modules",".cache","frontfriend","migrated-components.json");function qe(e){let n=$(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.vue||o["@vitejs/plugin-vue"]?"vue":"react"}function Ge(e){let n=$(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.next||d.existsSync(a.join(e,"next.config.js"))||d.existsSync(a.join(e,"next.config.mjs"))?"next":o.vite||d.existsSync(a.join(e,"vite.config.ts"))||d.existsSync(a.join(e,"vite.config.js"))?"vite":null}function Je(e,n,o){let t=a.join(e,"components.json");if(!d.existsSync(t))return!1;let s=$(t)||{};s.registries=s.registries||{};let r=`${Ve(o)}/${n}/{name}.json`;return s.registries["@frontfriend"]===r?!1:(s.registries["@frontfriend"]=r,q(t,s),!0)}function Be(e){let n=a.join(e,"package.json"),o=$(n);return o?(o.dependencies=o.dependencies||{},o.dependencies["@frontfriend/tailwind"]?!1:(o.dependencies["@frontfriend/tailwind"]="^4.0.0",q(n,o),!0)):!1}function He(e){let n=a.join(e,"next.config.js");return d.existsSync(n)&&d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/next")?!1:(d.writeFileSync(n,`const frontfriend = require('@frontfriend/tailwind/next');
39
+ `,p=E.dirname(t);F.existsSync(p)||F.mkdirSync(p,{recursive:!0}),F.writeFileSync(t,c),console.log("[FrontFriend] \u2713 Generated types at",E.relative(o,t));let C=E.join(o,"tsconfig.json");if(F.existsSync(C)){let v=JSON.parse(F.readFileSync(C,"utf-8"));v.include||(v.include=[]);let h="types/**/*.d.ts";v.include.includes(h)||(v.include.push(h),F.writeFileSync(C,JSON.stringify(v,null,2)),console.log("[FrontFriend] \u2713 Updated tsconfig.json to include generated types"))}}catch(i){console.error("[FrontFriend] Error generating icon types:",i.message),process.exit(1)}}require.main===L&&ie();L.exports={generateIconTypes:ie}});var{loadEnvLocal:Ee}=require("./lib/core/env-utils");Ee();var{Command:Ie}=require("commander"),I=require("./lib/core/config-loader"),D=require("./lib/core/cache-manager"),{APIClient:le}=require("./lib/core/api-client"),{getCredentialsPath:Pe,writeCredentials:Oe,readCredentials:Ae,deleteCredentials:De,postJson:R}=se(),{ComponentDownloader:Le}=require("./lib/core/component-downloader"),Ue=require("./lib/core/token-processor"),{ConfigError:x,APIError:Re,CacheError:q}=require("./lib/core/errors"),l=require("path"),u=require("fs"),{spawn:Ne}=require("child_process"),S=new Ie,{version:fe}=re(),Ve="https://registry.frontfriend.dev/r/v4",ce='@import "@frontfriend/tailwind/theme.css";';function Me(e){return(e||process.env.FF_REGISTRY_URL||Ve).replace(/\/+$/,"")}function T(e){try{return JSON.parse(u.readFileSync(e,"utf8"))}catch{return null}}function J(e,o){u.mkdirSync(l.dirname(e),{recursive:!0}),u.writeFileSync(e,`${JSON.stringify(o,null,2)}
40
+ `)}var qe=l.join("node_modules",".cache","frontfriend","migrated-components.json");function Je(e){let o=T(l.join(e,"package.json"))||{},n={...o.dependencies||{},...o.devDependencies||{}};return n.vue||n["@vitejs/plugin-vue"]?"vue":"react"}function Ge(e){let o=T(l.join(e,"package.json"))||{},n={...o.dependencies||{},...o.devDependencies||{}};return n.next||u.existsSync(l.join(e,"next.config.js"))||u.existsSync(l.join(e,"next.config.mjs"))?"next":n.vite||u.existsSync(l.join(e,"vite.config.ts"))||u.existsSync(l.join(e,"vite.config.js"))?"vite":null}function He(e,o,n){let t=l.join(e,"components.json");if(!u.existsSync(t))return!1;let s=T(t)||{};s.registries=s.registries||{};let r=`${Me(n)}/${o}/{name}.json`;return s.registries["@frontfriend"]===r?!1:(s.registries["@frontfriend"]=r,J(t,s),!0)}function Be(e){let o=l.join(e,"package.json"),n=T(o);return n?(n.dependencies=n.dependencies||{},n.dependencies["@frontfriend/tailwind"]?!1:(n.dependencies["@frontfriend/tailwind"]="^4.0.0",J(o,n),!0)):!1}function Ye(e){let o=l.join(e,"next.config.js");return u.existsSync(o)&&u.readFileSync(o,"utf8").includes("@frontfriend/tailwind/next")?!1:(u.writeFileSync(o,`const frontfriend = require('@frontfriend/tailwind/next');
41
41
 
42
42
  module.exports = frontfriend({});
43
- `),!0)}function Ye(e){let n=d.existsSync(a.join(e,"vite.config.ts"))?a.join(e,"vite.config.ts"):a.join(e,"vite.config.js");return d.existsSync(n)&&d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/vite")?!1:(d.writeFileSync(n,`import { defineConfig } from 'vite';
43
+ `),!0)}function ze(e){let o=u.existsSync(l.join(e,"vite.config.ts"))?l.join(e,"vite.config.ts"):l.join(e,"vite.config.js");return u.existsSync(o)&&u.readFileSync(o,"utf8").includes("@frontfriend/tailwind/vite")?!1:(u.writeFileSync(o,`import { defineConfig } from 'vite';
44
44
  import frontfriend from '@frontfriend/tailwind/vite';
45
45
 
46
46
  export default defineConfig({
47
47
  plugins: [frontfriend()],
48
48
  });
49
- `),!0)}function ze(e){let t=["app/globals.css","src/app/globals.css","styles/globals.css","src/styles/globals.css","src/index.css"].find(r=>d.existsSync(a.join(e,r)))||"app/globals.css",s=a.join(e,t);return d.mkdirSync(a.dirname(s),{recursive:!0}),d.existsSync(s)||d.writeFileSync(s,""),{fullPath:s,relativePath:t}}function We(e){let{fullPath:n,relativePath:o}=ze(e),t=d.readFileSync(n,"utf8");return t.includes(ie)?{changed:!1,relativePath:o}:(d.writeFileSync(n,`${ie}
50
- ${t}`),{changed:!0,relativePath:o})}function Ke(e,n={}){let o=a.join(e,"components.json");if(!d.existsSync(o))return{isShadcnProject:!1,changes:[]};let t=qe(e),s=Ge(e),r=[];Je(e,t,n.registryUrl)&&r.push(`registered @frontfriend registry for ${t}`),Be(e)&&r.push("added @frontfriend/tailwind dependency"),s==="next"&&He(e)&&r.push("wired Next.js plugin"),s==="vite"&&Ye(e)&&r.push("wired Vite plugin");let i=We(e);return i.changed&&r.push(`imported bundled theme in ${i.relativePath}`),{isShadcnProject:!0,changes:r,framework:t,buildTool:s}}function Ze(e){return new Promise(n=>setTimeout(n,e))}function Xe(e){let n=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",o=process.platform==="win32"?["/c","start","",e]:[e];try{return Ne(n,o,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function Qe(e){e.isShadcnProject&&(console.log("\u{1F9E9} shadcn project wiring"),e.changes.length===0?console.log(" \u2713 Already configured"):e.changes.forEach(n=>console.log(` \u2713 ${n}`)),console.log(` Next: npx shadcn add @frontfriend/button
51
- `))}function en(e,n){let o=e.indexOf(`${n}:`);if(o===-1)return null;let t=e.indexOf("{",o);if(t===-1)return null;let s=0;for(let r=t;r<e.length;r+=1){let i=e[r];if(i==="{"&&(s+=1),i==="}"&&(s-=1),s===0)return e.slice(t+1,r)}return null}function nn(e){let n={},o=/([A-Za-z0-9_-]+):\s*(['"`])([\s\S]*?)\2/g,t;for(;t=o.exec(e||"");)n[t[1]]=t[3].replace(/\s+/g," ").trim();return n}function on(e,n){let o=n;for(;/\s|,/.test(e[o]||"");)o+=1;let t=e[o];if(t==='"'||t==="'"||t==="`"){let r=e.indexOf(t,o+1);return r===-1?null:{name:e.slice(o+1,r),end:r+1}}let s=e.slice(o).match(/^([A-Za-z0-9_-]+)/);return s?{name:s[1],end:o+s[1].length}:null}function tn(e){let n={},o=0;for(;o<(e||"").length;){let t=on(e,o);if(!t){o+=1;continue}for(o=t.end;/\s/.test(e[o]||"");)o+=1;if(e[o]!==":")continue;for(o+=1;/\s/.test(e[o]||"");)o+=1;if(e[o]!=="{")continue;let s=0,r=o;for(;o<e.length;o+=1)if(e[o]==="{"&&(s+=1),e[o]==="}"&&(s-=1),s===0){n[t.name]=nn(e.slice(r+1,o)),o+=1;break}}return n}function N(e,n){if(!e.includes("cva(")||!e.includes("variants:"))return{skipped:!0,reason:`${n} source is not cva-structured`};let o=e.match(/cva\(\s*(['"`])([\s\S]*?)\1\s*,/),t=en(e,"variants"),s=tn(t);if(Object.values(s).every(f=>Object.keys(f).length===0))return{skipped:!0,reason:"no cva variant class maps found"};let r={default:"main",outline:"tertiary",destructive:"destructive",secondary:"secondary",ghost:"ghost",link:"link"},i={root:o?o[2].replace(/\s+/g," ").trim():"",variants:{}};for(let[f,l]of Object.entries(s)){i.variants[f]={};for(let[u,g]of Object.entries(l)){let c=n==="button"&&f==="variant"&&r[u]||u;i.variants[f][c]=g}}return{skipped:!1,config:{[n]:i}}}function R(...e){return e.reduce((n,o)=>({...n,...o||{}}),{})}function sn(e){let n=require("./lib/core/token-processor"),{mergeComponentsConfig:o}=require("./lib/core/default-config"),t=new n,s=o(e),r=t.extractClassesFromComponentsConfig(s);return{componentsConfig:s,icons:{},safelist:r,classesContent:t.generateClassesContent(r),themeCSS:t.generateThemeCSS({}),metadata:{version:"local-components"}}}function fe(e,n){let o=new D(e),t=o.exists()?o.load()||{}:{},s=R(t.componentsConfig,n),r=sn(s);return o.save({...t,...r,icons:t.icons||{}}),r.componentsConfig}function V(e){return a.basename(e).replace(/\.(tsx|ts|jsx|js|vue)$/,"").replace(/[-_]([a-z])/g,(n,o)=>o.toUpperCase())}var rn=["tsx","ts","jsx","js","vue"],de=/\.(tsx|ts|jsx|js|vue)$/;function cn(e){let n={};for(let o of["tsconfig.json","tsconfig.app.json","jsconfig.json"]){let t=$(a.join(e,o)),s=t&&t.compilerOptions&&t.compilerOptions.paths;s&&Object.assign(n,s)}return n}function an(e,n){if(!n)return null;let o=cn(e);for(let[t,s]of Object.entries(o))if(!(!Array.isArray(s)||s.length===0)){if(t.endsWith("/*")){let r=t.slice(0,-1);if(n.startsWith(r)){let i=n.slice(r.length),f=s[0].replace(/\*+$/,"");return a.resolve(e,f,i)}}else if(t===n)return a.resolve(e,s[0])}return n.startsWith("@/")?a.resolve(e,"src",n.slice(2)):a.resolve(e,n)}function ln(e){let n=$(a.join(e,"components.json")),o=n&&n.aliases&&n.aliases.ui,t=[o?an(e,o):null,a.join(e,"src","components","ui"),a.join(e,"components","ui")].filter(Boolean);return[...new Set(t)].filter(s=>d.existsSync(s))}function ce(e,n){for(let t of rn){let s=a.join(e,`${n}.${t}`);if(d.existsSync(s))return s}let o=a.join(e,n);if(d.existsSync(o)&&d.statSync(o).isDirectory()){let t=d.readdirSync(o).filter(i=>de.test(i)),s=t.filter(i=>!/^index\./i.test(i)),r=s.find(i=>i.toLowerCase().startsWith(`${n.toLowerCase()}.`))||s[0]||t.find(i=>/^index\./i.test(i));if(r)return a.join(o,r)}return null}function ue(e,n){let o=ln(e);if(n&&n!=="all"){for(let r of o){let i=ce(r,n);if(i)return[{component:n,inputPath:i}]}return[]}let t=new Set,s=[];for(let r of o)for(let i of d.readdirSync(r,{withFileTypes:!0})){let f,l=null;if(i.isFile()&&de.test(i.name)&&!/^index\./i.test(i.name)?(f=V(i.name),l=a.join(r,i.name)):i.isDirectory()&&(f=V(i.name),l=ce(r,i.name)),!l||!f)continue;let u=f.toLowerCase();t.has(u)||(t.add(u),s.push({component:f,inputPath:l}))}return s}function ge(e){let n={},o=[],t=ue(e,"all");for(let{component:s,inputPath:r}of t){let i=N(d.readFileSync(r,"utf8"),s);if(i.skipped){o.push({component:s,reason:i.reason});continue}Object.assign(n,i.config)}return{config:n,skipped:o}}w.name("frontfriend").description("FrontFriend Tailwind CLI - Manage design tokens and cache").version(le);w.command("login").description("Authenticate FrontFriend CLI with an 8-digit device code").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||"https://app.frontfriend.dev").option("--no-open","Do not open the browser automatically").action(async e=>{try{let n=e.apiUrl.replace(/\/$/,""),o=await U(`${n}/api/auth/device/start`,{}),t=o.interval||5,s=Date.now()+(o.expires_in||600)*1e3;for(console.log("\u{1F510} FrontFriend Login"),console.log(`====================
52
- `),console.log(`Go to ${o.verification_uri} and enter the code:`),console.log(`
53
- ${o.user_code}
54
- `),e.open!==!1&&Xe(o.verification_uri)&&console.log("Opened the browser for you."),console.log(`Waiting for approval...
55
- `);Date.now()<s;){await Ze(t*1e3);let r=await U(`${n}/api/auth/device/poll`,{device_code:o.device_code});if(r.error!=="authorization_pending"){if(r.error==="slow_down"){t=r.interval||t+5;continue}if(r.error)throw new Error(`${r.error}: ${r.error_description||"Authentication failed"}`);Pe({accessToken:r.access_token,refreshToken:r.refresh_token,deviceId:r.device_id,expiresAt:Date.now()+(r.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(r.refresh_expires_in||604800)*1e3,ffApiUrl:n}),console.log("\u2705 Login complete!"),console.log(` Credentials saved to ${Ie()}`),process.exit(0)}}throw new Error("expired_token: the code has expired, run `frontfriend login` again.")}catch(n){console.error("\u274C Login failed:",n.message),process.exit(1)}});w.command("logout").description("Remove FrontFriend CLI credentials").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||"https://app.frontfriend.dev").action(async e=>{let n=Oe(),o=(e.apiUrl||(n==null?void 0:n.ffApiUrl)||"https://app.frontfriend.dev").replace(/\/$/,"");if(n!=null&&n.accessToken&&(n!=null&&n.deviceId))try{await U(`${o}/api/plugin/logout`,{device_id:n.deviceId},n.accessToken)}catch{}let t=De();console.log(t?"\u2705 Logged out. Credentials removed.":"\u2139\uFE0F No stored credentials found."),process.exit(0)});w.command("init").description("Initialize FrontFriend configuration and fetch from API").option("--force","Force refresh even if cache is valid").option("--verbose","Show detailed output including safelist size and token counts").option("--tag <tag>","Fetch specific tag (e.g., dev, next, latest)").option("--version <version>","Fetch specific version (e.g., v1.0.0)").option("--registry-url <url>","Registry base URL for components.json (overrides FF_REGISTRY_URL)").action(async e=>{var n;try{console.log("\u{1F527} FrontFriend Setup"),console.log(`==================
56
- `);let t=await new I().load(),s=Ke(t.appRoot,{registryUrl:e.registryUrl}),r=s.isShadcnProject?ge(t.appRoot):{config:{},skipped:[]};if(Qe(s),!t.ffId)throw s.isShadcnProject&&(fe(t.appRoot,r.config),console.log("\u2705 Local FrontFriend wiring complete!"),console.log(` Local component config cached (${Object.keys(r.config).length||"default"} component${Object.keys(r.config).length===1?"":"s"}).`),console.log(' Add frontfriend.config.js with "ff-id" later to fetch cloud design tokens.'),process.exit(0)),new x(`ff-id not found in frontfriend.config.js
57
- Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let i=e.tag||t.tag,f=e.version||t.version;console.log("\u{1F4CB} Configuration loaded"),console.log(` FF_ID: ${t.ffId}`),console.log(` App Root: ${t.appRoot}`),i&&console.log(` Tag: ${i}`),f&&console.log(` Version: ${f}`),console.log("");let l=new D(t.appRoot);!e.force&&l.exists()&&l.isValid()&&(console.log("\u2705 Cache is valid and up to date"),console.log(" Use --force to refresh anyway"),process.exit(0)),console.log("\u{1F50D} Checking cache..."),e.force?console.log(` Force refresh requested
58
- `):l.exists()?console.log(` Cache expired
49
+ `),!0)}function We(e){let t=["app/globals.css","src/app/globals.css","styles/globals.css","src/styles/globals.css","src/index.css"].find(r=>u.existsSync(l.join(e,r)))||"app/globals.css",s=l.join(e,t);return u.mkdirSync(l.dirname(s),{recursive:!0}),u.existsSync(s)||u.writeFileSync(s,""),{fullPath:s,relativePath:t}}function Ke(e){let{fullPath:o,relativePath:n}=We(e),t=u.readFileSync(o,"utf8");return t.includes(ce)?{changed:!1,relativePath:n}:(u.writeFileSync(o,`${ce}
50
+ ${t}`),{changed:!0,relativePath:n})}function Ze(e,o={}){let n=l.join(e,"components.json");if(!u.existsSync(n))return{isShadcnProject:!1,changes:[]};let t=Je(e),s=Ge(e),r=[];He(e,t,o.registryUrl)&&r.push(`registered @frontfriend registry for ${t}`),Be(e)&&r.push("added @frontfriend/tailwind dependency"),s==="next"&&Ye(e)&&r.push("wired Next.js plugin"),s==="vite"&&ze(e)&&r.push("wired Vite plugin");let i=Ke(e);return i.changed&&r.push(`imported bundled theme in ${i.relativePath}`),{isShadcnProject:!0,changes:r,framework:t,buildTool:s}}function Xe(e){return new Promise(o=>setTimeout(o,e))}function Qe(e){let o=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{return Ne(o,n,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function eo(e){e.isShadcnProject&&(console.log("\u{1F9E9} shadcn project wiring"),e.changes.length===0?console.log(" \u2713 Already configured"):e.changes.forEach(o=>console.log(` \u2713 ${o}`)),console.log(` Next: npx shadcn add @frontfriend/button
51
+ `))}function oo(e,o){let n=e.indexOf(`${o}:`);if(n===-1)return null;let t=e.indexOf("{",n);if(t===-1)return null;let s=0;for(let r=t;r<e.length;r+=1){let i=e[r];if(i==="{"&&(s+=1),i==="}"&&(s-=1),s===0)return e.slice(t+1,r)}return null}function no(e){let o={},n=/([A-Za-z0-9_-]+):\s*(['"`])([\s\S]*?)\2/g,t;for(;t=n.exec(e||"");)o[t[1]]=t[3].replace(/\s+/g," ").trim();return o}function to(e,o){let n=o;for(;/\s|,/.test(e[n]||"");)n+=1;let t=e[n];if(t==='"'||t==="'"||t==="`"){let r=e.indexOf(t,n+1);return r===-1?null:{name:e.slice(n+1,r),end:r+1}}let s=e.slice(n).match(/^([A-Za-z0-9_-]+)/);return s?{name:s[1],end:n+s[1].length}:null}function so(e){let o={},n=0;for(;n<(e||"").length;){let t=to(e,n);if(!t){n+=1;continue}for(n=t.end;/\s/.test(e[n]||"");)n+=1;if(e[n]!==":")continue;for(n+=1;/\s/.test(e[n]||"");)n+=1;if(e[n]!=="{")continue;let s=0,r=n;for(;n<e.length;n+=1)if(e[n]==="{"&&(s+=1),e[n]==="}"&&(s-=1),s===0){o[t.name]=no(e.slice(r+1,n)),n+=1;break}}return o}function N(e,o){if(!e.includes("cva(")||!e.includes("variants:"))return{skipped:!0,reason:`${o} source is not cva-structured`};let n=e.match(/cva\(\s*(['"`])([\s\S]*?)\1\s*,/),t=oo(e,"variants"),s=so(t);if(Object.values(s).every(d=>Object.keys(d).length===0))return{skipped:!0,reason:"no cva variant class maps found"};let r={default:"main",outline:"tertiary",destructive:"destructive",secondary:"secondary",ghost:"ghost",link:"link"},i={root:n?n[2].replace(/\s+/g," ").trim():"",variants:{}};for(let[d,f]of Object.entries(s)){i.variants[d]={};for(let[a,g]of Object.entries(f)){let c=o==="button"&&d==="variant"&&r[a]||a;i.variants[d][c]=g}}return{skipped:!1,config:{[o]:i}}}function V(...e){return e.reduce((o,n)=>({...o,...n||{}}),{})}function ro(e){let o=require("./lib/core/token-processor"),{mergeComponentsConfig:n}=require("./lib/core/default-config"),t=new o,s=n(e),r=t.extractClassesFromComponentsConfig(s);return{componentsConfig:s,icons:{},safelist:r,classesContent:t.generateClassesContent(r),themeCSS:t.generateThemeCSS({}),metadata:{version:"local-components"}}}function de(e,o){let n=new D(e),t=n.exists()?n.load()||{}:{},s=V(t.componentsConfig,o),r=ro(s);return n.save({...t,...r,icons:t.icons||{}}),r.componentsConfig}function M(e){return l.basename(e).replace(/\.(tsx|ts|jsx|js|vue)$/,"").replace(/[-_]([a-z])/g,(o,n)=>n.toUpperCase())}var io=["tsx","ts","jsx","js","vue"],ue=/\.(tsx|ts|jsx|js|vue)$/;function co(e){let o={};for(let n of["tsconfig.json","tsconfig.app.json","jsconfig.json"]){let t=T(l.join(e,n)),s=t&&t.compilerOptions&&t.compilerOptions.paths;s&&Object.assign(o,s)}return o}function ao(e,o){if(!o)return null;let n=co(e);for(let[t,s]of Object.entries(n))if(!(!Array.isArray(s)||s.length===0)){if(t.endsWith("/*")){let r=t.slice(0,-1);if(o.startsWith(r)){let i=o.slice(r.length),d=s[0].replace(/\*+$/,"");return l.resolve(e,d,i)}}else if(t===o)return l.resolve(e,s[0])}return o.startsWith("@/")?l.resolve(e,"src",o.slice(2)):l.resolve(e,o)}function lo(e){let o=T(l.join(e,"components.json")),n=o&&o.aliases&&o.aliases.ui,t=[n?ao(e,n):null,l.join(e,"src","components","ui"),l.join(e,"components","ui")].filter(Boolean);return[...new Set(t)].filter(s=>u.existsSync(s))}function ae(e,o){for(let t of io){let s=l.join(e,`${o}.${t}`);if(u.existsSync(s))return s}let n=l.join(e,o);if(u.existsSync(n)&&u.statSync(n).isDirectory()){let t=u.readdirSync(n).filter(i=>ue.test(i)),s=t.filter(i=>!/^index\./i.test(i)),r=s.find(i=>i.toLowerCase().startsWith(`${o.toLowerCase()}.`))||s[0]||t.find(i=>/^index\./i.test(i));if(r)return l.join(n,r)}return null}function ge(e,o){let n=lo(e);if(o&&o!=="all"){for(let r of n){let i=ae(r,o);if(i)return[{component:o,inputPath:i}]}return[]}let t=new Set,s=[];for(let r of n)for(let i of u.readdirSync(r,{withFileTypes:!0})){let d,f=null;if(i.isFile()&&ue.test(i.name)&&!/^index\./i.test(i.name)?(d=M(i.name),f=l.join(r,i.name)):i.isDirectory()&&(d=M(i.name),f=ae(r,i.name)),!f||!d)continue;let a=d.toLowerCase();t.has(a)||(t.add(a),s.push({component:d,inputPath:f}))}return s}function pe(e){let o={},n=[],t=ge(e,"all");for(let{component:s,inputPath:r}of t){let i=N(u.readFileSync(r,"utf8"),s);if(i.skipped){n.push({component:s,reason:i.reason});continue}Object.assign(o,i.config)}return{config:o,skipped:n}}S.name("frontfriend").description("FrontFriend Tailwind CLI - Manage design tokens and cache").version(fe);S.command("login").description("Authenticate FrontFriend CLI with an 8-digit device code").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||"https://app.frontfriend.dev").option("--no-open","Do not open the browser automatically").action(async e=>{try{let o=e.apiUrl.replace(/\/$/,""),n=await R(`${o}/api/auth/device/start`,{}),t=n.interval||5,s=Date.now()+(n.expires_in||600)*1e3;for(console.log("\u{1F510} FrontFriend Login"),console.log(`====================
52
+ `),console.log(`Go to ${n.verification_uri} and enter the code:`),console.log(`
53
+ ${n.user_code}
54
+ `),e.open!==!1&&Qe(n.verification_uri)&&console.log("Opened the browser for you."),console.log(`Waiting for approval...
55
+ `);Date.now()<s;){await Xe(t*1e3);let r=await R(`${o}/api/auth/device/poll`,{device_code:n.device_code});if(r.error!=="authorization_pending"){if(r.error==="slow_down"){t=r.interval||t+5;continue}if(r.error)throw new Error(`${r.error}: ${r.error_description||"Authentication failed"}`);if(!r.access_token||!r.refresh_token||!r.device_id)throw new Error("Invalid login response from FrontFriend. Run `frontfriend login` again.");Oe({accessToken:r.access_token,refreshToken:r.refresh_token,deviceId:r.device_id,expiresAt:Date.now()+(r.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(r.refresh_expires_in||604800)*1e3,ffApiUrl:o}),console.log("\u2705 Login complete!"),console.log(` Credentials saved to ${Pe()}`),process.exit(0)}}throw new Error("expired_token: the code has expired, run `frontfriend login` again.")}catch(o){console.error("\u274C Login failed:",o.message),process.exit(1)}});S.command("logout").description("Remove FrontFriend CLI credentials").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||"https://app.frontfriend.dev").action(async e=>{let o=Ae(),n=(e.apiUrl||(o==null?void 0:o.ffApiUrl)||"https://app.frontfriend.dev").replace(/\/$/,"");if(o!=null&&o.accessToken&&(o!=null&&o.deviceId))try{await R(`${n}/api/plugin/logout`,{device_id:o.deviceId},o.accessToken)}catch{}let t=De();console.log(t?"\u2705 Logged out. Credentials removed.":"\u2139\uFE0F No stored credentials found."),process.exit(0)});S.command("init").description("Initialize FrontFriend configuration and fetch from API").option("--force","Force refresh even if cache is valid").option("--verbose","Show detailed output including safelist size and token counts").option("--tag <tag>","Fetch specific tag (e.g., dev, next, latest)").option("--version <version>","Fetch specific version (e.g., v1.0.0)").option("--registry-url <url>","Registry base URL for components.json (overrides FF_REGISTRY_URL)").action(async e=>{var o;try{console.log("\u{1F527} FrontFriend Setup"),console.log(`==================
56
+ `);let t=await new I().load(),s=Ze(t.appRoot,{registryUrl:e.registryUrl}),r=s.isShadcnProject?pe(t.appRoot):{config:{},skipped:[]};if(eo(s),!t.ffId)throw s.isShadcnProject&&(de(t.appRoot,r.config),console.log("\u2705 Local FrontFriend wiring complete!"),console.log(` Local component config cached (${Object.keys(r.config).length||"default"} component${Object.keys(r.config).length===1?"":"s"}).`),console.log(' Add frontfriend.config.js with "ff-id" later to fetch cloud design tokens.'),process.exit(0)),new x(`ff-id not found in frontfriend.config.js
57
+ Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let i=e.tag||t.tag,d=e.version||t.version;console.log("\u{1F4CB} Configuration loaded"),console.log(` FF_ID: ${t.ffId}`),console.log(` App Root: ${t.appRoot}`),i&&console.log(` Tag: ${i}`),d&&console.log(` Version: ${d}`),console.log("");let f=new D(t.appRoot);!e.force&&f.exists()&&f.isValid()&&(console.log("\u2705 Cache is valid and up to date"),console.log(" Use --force to refresh anyway"),process.exit(0)),console.log("\u{1F50D} Checking cache..."),e.force?console.log(` Force refresh requested
58
+ `):f.exists()?console.log(` Cache expired
59
59
  `):console.log(` No cache found
60
- `),console.log("\u{1F310} Fetching configuration...");let u=new ae(t.ffId,{baseURL:t["api-url"]||t.apiUrl,authToken:t["auth-token"]||t.authToken});(t["api-url"]||t.apiUrl)&&console.log(` Using API URL: ${t["api-url"]||t.apiUrl}`);let g=new Le,c=null;try{c=await u.fetchProcessedTokens({tag:i,version:f,tailwindV4:g.useTailwindV4})}catch(m){console.log(` \u26A0\uFE0F Failed to fetch pre-processed tokens: ${m.message}`)}if(c){if(console.log(" \u2713 Pre-processed tokens fetched from server"),console.log(" \u2713 Skipping local processing"),Object.keys(r.config).length>0&&(c.componentsConfig=R(c.componentsConfig,r.config),console.log(` \u2713 Preserved host component classes for ${Object.keys(r.config).join(", ")}`)),c.versionMetadata){let m=c.versionMetadata;console.log(" \u2139\uFE0F Version Information:"),m.version&&console.log(` Version: ${m.version}`),m.tag&&console.log(` Tag: ${m.tag}`),m.cached!==void 0&&console.log(` From Cache: ${m.cached?"Yes":"No"}`)}if(console.log(""),(!((n=c.tokens)!=null&&n.fontFamily)||Object.keys(c.tokens.fontFamily).length===0)&&(console.log("\u26A0\uFE0F Warning: No font family utilities found"),console.log(" Font classes like font-primary and font-secondary will not be available"),c.globalTokens?console.log(` Global tokens are present - font processor may need to be updated
60
+ `),console.log("\u{1F310} Fetching configuration...");let a=new le(t.ffId,{baseURL:t["api-url"]||t.apiUrl,authToken:t["auth-token"]||t.authToken});(t["api-url"]||t.apiUrl)&&console.log(` Using API URL: ${t["api-url"]||t.apiUrl}`);let g=new Ue,c=null;try{c=await a.fetchProcessedTokens({tag:i,version:d,tailwindV4:g.useTailwindV4})}catch(m){console.log(` \u26A0\uFE0F Failed to fetch pre-processed tokens: ${m.message}`)}if(c){if(console.log(" \u2713 Pre-processed tokens fetched from server"),console.log(" \u2713 Skipping local processing"),Object.keys(r.config).length>0&&(c.componentsConfig=V(c.componentsConfig,r.config),console.log(` \u2713 Preserved host component classes for ${Object.keys(r.config).join(", ")}`)),c.versionMetadata){let m=c.versionMetadata;console.log(" \u2139\uFE0F Version Information:"),m.version&&console.log(` Version: ${m.version}`),m.tag&&console.log(` Tag: ${m.tag}`),m.cached!==void 0&&console.log(` From Cache: ${m.cached?"Yes":"No"}`)}if(console.log(""),(!((o=c.tokens)!=null&&o.fontFamily)||Object.keys(c.tokens.fontFamily).length===0)&&(console.log("\u26A0\uFE0F Warning: No font family utilities found"),console.log(" Font classes like font-primary and font-secondary will not be available"),c.globalTokens?console.log(` Global tokens are present - font processor may need to be updated
61
61
  `):console.log(` Consider adding font family tokens to your design system
62
- `)),g.useTailwindV4){let m=g.extractClassesFromComponentsConfig(c.componentsConfig),_=[...c.safelist||[],...m||[]];c.safelist=[...new Set(_)].sort(),c.themeCSS||(c.themeCSS=g.generateThemeCSS({variables:c.variables||{},semanticVariables:c.semanticVariables||{},semanticDarkVariables:c.semanticDarkVariables||{},fontFaces:c.fonts||[],keyframes:c.keyframes||{},animations:c.animations||{},custom:c.custom||{}})),(!c.classesContent||Object.keys(r.config).length>0)&&(c.classesContent=g.generateClassesContent(c.safelist))}if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&console.log(` Safelist has ${c.safelist?c.safelist.length:0} items`),l.save(c),console.log(` \u2713 Cache saved successfully
62
+ `)),g.useTailwindV4){let m=g.extractClassesFromComponentsConfig(c.componentsConfig),_=[...c.safelist||[],...m||[]];c.safelist=[...new Set(_)].sort(),c.themeCSS||(c.themeCSS=g.generateThemeCSS({variables:c.variables||{},semanticVariables:c.semanticVariables||{},semanticDarkVariables:c.semanticDarkVariables||{},fontFaces:c.fonts||[],keyframes:c.keyframes||{},animations:c.animations||{},custom:c.custom||{}})),(!c.classesContent||Object.keys(r.config).length>0)&&(c.classesContent=g.generateClassesContent(c.safelist))}if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&console.log(` Safelist has ${c.safelist?c.safelist.length:0} items`),f.save(c),console.log(` \u2713 Cache saved successfully
63
63
  `),console.log("\u2705 Setup complete!"),console.log(" Your FrontFriend configuration has been cached."),console.log(" The Tailwind plugin will now use this cached data."),t.types){console.log(`
64
- \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:m}=L(),_=t.aliases&&t.aliases.types?a.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;m({projectRoot:t.appRoot,outputPath:_})}catch(m){console.log(" \u26A0\uFE0F Type generation failed:",m.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}console.log(` \u2139\uFE0F Pre-processed tokens not available, falling back to local processing
65
- `);let[p,T,v,h,C,P]=await Promise.all([u.fetchTokens(),u.fetchComponentsConfig(),u.fetchFonts(),u.fetchIcons(),u.fetchVersion(),u.fetchCustomCss()]),S=R(T,r.config);if(console.log(" \u2713 Tokens fetched"),p.global||p.colors||p.semantic||p.semanticDark){let m=[p.global?"global":null,p.colors?"colors":null,p.semantic?"semantic":null,p.semanticDark?"semanticDark":null].filter(Boolean).join(", ");console.log(` (Found: ${m})`)}console.log(" \u2713 Components config fetched"),Object.keys(r.config).length>0&&console.log(` \u2713 Preserved host component classes for ${Object.keys(r.config).join(", ")}`),console.log(" \u2713 Fonts fetched"),console.log(" \u2713 Icons fetched"),console.log(" \u2713 Version fetched"),console.log(` \u2713 Custom CSS fetched
66
- `),console.log("\u2699\uFE0F Processing tokens..."),console.log(" Processing raw token data...");let y=await g.process({colors:p.colors||p.global,semantic:p.semantic,semanticDark:p.semanticDark,fonts:v,globalTokens:p.global,animations:p.animations,version:C==null?void 0:C.version,ffId:t.ffId,customCss:P});console.log(" \u2713 Colors processed"),console.log(" \u2713 Semantic tokens processed"),y.fontFaces.length>0&&console.log(` \u2713 ${y.fontFaces.length} font faces processed`),Object.keys(y.animations).length>0&&console.log(` \u2713 ${Object.keys(y.animations).length} animations processed`),console.log(`
67
- `);let pe=g.extractClassesFromComponentsConfig(S),me=[...y.safelist||[],...pe||[]],G=[...new Set(me)].sort(),J,B;g.useTailwindV4&&(console.log("\u{1F3A8} Generating Tailwind v4 CSS artifacts..."),J=g.generateThemeCSS(y),B=g.generateClassesContent(G),console.log(" \u2713 theme.css generated"),console.log(` \u2713 classes.css generated for @source scanning
68
- `));let b={tokens:y.utilities,variables:y.variables,semanticVariables:y.semanticVariables,semanticDarkVariables:y.semanticDarkVariables,fonts:y.fontFaces,icons:h,componentsConfig:S,keyframes:y.keyframes,animations:y.animations,safelist:G,version:C,metadata:y.metadata,custom:y.custom,themeCSS:J,classesContent:B};if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&(console.log(" Cache data summary:"),console.log(` - Tokens: ${Object.keys(b.tokens||{}).length} utilities`),console.log(` - Variables: ${Object.keys(b.variables||{}).length} CSS variables`),console.log(` - Semantic variables: ${Object.keys(b.semanticVariables||{}).length} semantic variables`),console.log(` - Font faces: ${(b.fonts||[]).length} fonts`),console.log(` - Safelist: ${(b.safelist||[]).length} safelist classes`)),l.save(b),console.log(` \u2713 Cache saved successfully
64
+ \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:m}=U(),_=t.aliases&&t.aliases.types?l.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;m({projectRoot:t.appRoot,outputPath:_})}catch(m){console.log(" \u26A0\uFE0F Type generation failed:",m.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}console.log(` \u2139\uFE0F Pre-processed tokens not available, falling back to local processing
65
+ `);let[p,C,v,h,w,P]=await Promise.all([a.fetchTokens(),a.fetchComponentsConfig(),a.fetchFonts(),a.fetchIcons(),a.fetchVersion(),a.fetchCustomCss()]),j=V(C,r.config);if(console.log(" \u2713 Tokens fetched"),p.global||p.colors||p.semantic||p.semanticDark){let m=[p.global?"global":null,p.colors?"colors":null,p.semantic?"semantic":null,p.semanticDark?"semanticDark":null].filter(Boolean).join(", ");console.log(` (Found: ${m})`)}console.log(" \u2713 Components config fetched"),Object.keys(r.config).length>0&&console.log(` \u2713 Preserved host component classes for ${Object.keys(r.config).join(", ")}`),console.log(" \u2713 Fonts fetched"),console.log(" \u2713 Icons fetched"),console.log(" \u2713 Version fetched"),console.log(` \u2713 Custom CSS fetched
66
+ `),console.log("\u2699\uFE0F Processing tokens..."),console.log(" Processing raw token data...");let y=await g.process({colors:p.colors||p.global,semantic:p.semantic,semanticDark:p.semanticDark,fonts:v,globalTokens:p.global,animations:p.animations,version:w==null?void 0:w.version,ffId:t.ffId,customCss:P});console.log(" \u2713 Colors processed"),console.log(" \u2713 Semantic tokens processed"),y.fontFaces.length>0&&console.log(` \u2713 ${y.fontFaces.length} font faces processed`),Object.keys(y.animations).length>0&&console.log(` \u2713 ${Object.keys(y.animations).length} animations processed`),console.log(`
67
+ `);let me=g.extractClassesFromComponentsConfig(j),he=[...y.safelist||[],...me||[]],G=[...new Set(he)].sort(),H,B;g.useTailwindV4&&(console.log("\u{1F3A8} Generating Tailwind v4 CSS artifacts..."),H=g.generateThemeCSS(y),B=g.generateClassesContent(G),console.log(" \u2713 theme.css generated"),console.log(` \u2713 classes.css generated for @source scanning
68
+ `));let b={tokens:y.utilities,variables:y.variables,semanticVariables:y.semanticVariables,semanticDarkVariables:y.semanticDarkVariables,fonts:y.fontFaces,icons:h,componentsConfig:j,keyframes:y.keyframes,animations:y.animations,safelist:G,version:w,metadata:y.metadata,custom:y.custom,themeCSS:H,classesContent:B};if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&(console.log(" Cache data summary:"),console.log(` - Tokens: ${Object.keys(b.tokens||{}).length} utilities`),console.log(` - Variables: ${Object.keys(b.variables||{}).length} CSS variables`),console.log(` - Semantic variables: ${Object.keys(b.semanticVariables||{}).length} semantic variables`),console.log(` - Font faces: ${(b.fonts||[]).length} fonts`),console.log(` - Safelist: ${(b.safelist||[]).length} safelist classes`)),f.save(b),console.log(` \u2713 Cache saved successfully
69
69
  `),console.log("\u2705 Setup complete!"),console.log(" Your FrontFriend configuration has been cached."),console.log(" The Tailwind plugin will now use this cached data."),t.types){console.log(`
70
- \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:m}=L(),_=t.aliases&&t.aliases.types?a.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;m({projectRoot:t.appRoot,outputPath:_})}catch(m){console.log(" \u26A0\uFE0F Type generation failed:",m.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}catch(o){o instanceof x?console.error("\u274C Configuration Error:",o.message):o instanceof Ue?(console.error("\u274C API Error:",o.message),console.error(` Status: ${o.statusCode}`),console.error(` URL: ${o.url}`)):o instanceof M?(console.error("\u274C Cache Error:",o.message),console.error(` Operation: ${o.operation}`)):console.error("\u274C Setup failed:",o.message),process.exit(1)}});w.command("clean").description("Remove cached configuration").action(async()=>{try{console.log(`\u{1F9F9} Cleaning FrontFriend cache...
71
- `);let n=new I().load(),o=new D(n.appRoot);o.exists()?(o.clear(),console.log("\u2705 Cache cleared successfully")):console.log("\u2139\uFE0F No cache found"),process.exit(0)}catch(e){e instanceof M?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Clean failed:",e.message),process.exit(1)}});w.command("status").description("Show cache status and configuration").action(async()=>{try{console.log("\u{1F4CA} FrontFriend Status"),console.log(`===================
72
- `),console.log("Package:"),console.log(` Version: ${le}`),console.log("");let n=await new I().load();console.log("Configuration:"),console.log(` FF_ID: ${n.ffId||"Not set"}`),console.log(` App Root: ${n.appRoot}`),n.tag&&console.log(` Tag: ${n.tag}`),n.version&&console.log(` Version: ${n.version}`),console.log("");let o=new D(n.appRoot),t=o.getCacheDir();if(console.log("Cache:"),console.log(` Directory: ${a.relative(process.cwd(),t)}`),o.exists()){console.log(` Status: ${o.isValid()?"\u2705 Valid":"\u26A0\uFE0F Expired"}`);let s=o.load();if(s&&s.metadata){let r=new Date(s.metadata.timestamp);console.log(` Created: ${r.toLocaleString()}`),console.log(` Format Version: ${s.metadata.version||"Unknown"}`)}s&&s.versionMetadata&&(console.log(" Cached Version Info:"),s.versionMetadata.version&&console.log(` Version: ${s.versionMetadata.version}`),s.versionMetadata.tag&&console.log(` Tag: ${s.versionMetadata.tag}`))}else console.log(" Status: \u274C Not found");process.exit(0)}catch(e){e instanceof x?console.error("\u274C Configuration Error:",e.message):e instanceof M?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Status check failed:",e.message),process.exit(1)}});w.command("migrate").description("Migrate cva-structured shadcn components into FrontFriend config").option("--component <name>",'Component to migrate, or "all" to scan the UI dir',"all").option("--input <path>","Path to the shadcn component source").option("--output <path>","Output JSON path for migrated config",Me).option("--no-push","Do not push migrated config to the configured FrontFriend cloud").action(async e=>{try{let o=await new I().load(),t=o.appRoot,s=e.input&&e.component==="all"?V(e.input):e.component,r;if(e.input){let l=a.resolve(t,e.input);if(!d.existsSync(l))throw new x(`Component source not found: ${a.relative(t,l)}`);let u=d.readFileSync(l,"utf8");r=N(u,s)}else if(s==="all")r=ge(t);else{let l=ue(t,s);if(l.length===0)throw new x(`Component source "${s}" not found under components/ui or src/components/ui`,"component");let u=d.readFileSync(l[0].inputPath,"utf8");r=N(u,s)}if(r.skipped===!0||Object.keys(r.config||{}).length===0){let l=r.reason||"no cva-structured components found";console.log(`\u23ED\uFE0F Skipped ${s}: ${l}`),process.exit(0)}let i=a.resolve(t,e.output);q(i,r.config),fe(t,r.config);let f=!1;e.push&&o.ffId&&(await new ae(o.ffId,{baseURL:o["api-url"]||o.apiUrl,authToken:o["auth-token"]||o.authToken}).pushComponentsConfig(r.config),f=!0),console.log("\u2705 Migration complete!"),console.log(` Component: ${s==="all"?Object.keys(r.config).join(", "):s}`),console.log(` Output: ${a.relative(t,i)}`),console.log(" Local config: cached for the FrontFriend plugin"),console.log(f?" Cloud config: pushed user override":" Cloud config: not pushed (missing ff-id or --no-push)"),process.exit(0)}catch(n){n instanceof x?console.error("\u274C Migration Error:",n.message):console.error("\u274C Migration failed:",n.message),process.exit(1)}});w.command("download").description("Download components from registry").argument("<components...>",'component names to download (or "all" to download all components)').option("-f, --framework <framework>","Framework to download components for (react/vue)").option("-o, --output <path>","Output directory for components").option("--registry <generation>","Registry generation to use (legacy/v4)").option("--overwrite","Overwrite existing files").action(async(e,n)=>{try{console.log(`\u{1F4E6} Downloading components...
70
+ \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:m}=U(),_=t.aliases&&t.aliases.types?l.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;m({projectRoot:t.appRoot,outputPath:_})}catch(m){console.log(" \u26A0\uFE0F Type generation failed:",m.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}catch(n){n instanceof x?console.error("\u274C Configuration Error:",n.message):n instanceof Re?(console.error("\u274C API Error:",n.message),console.error(` Status: ${n.statusCode}`),console.error(` URL: ${n.url}`)):n instanceof q?(console.error("\u274C Cache Error:",n.message),console.error(` Operation: ${n.operation}`)):console.error("\u274C Setup failed:",n.message),process.exit(1)}});S.command("clean").description("Remove cached configuration").action(async()=>{try{console.log(`\u{1F9F9} Cleaning FrontFriend cache...
71
+ `);let o=new I().load(),n=new D(o.appRoot);n.exists()?(n.clear(),console.log("\u2705 Cache cleared successfully")):console.log("\u2139\uFE0F No cache found"),process.exit(0)}catch(e){e instanceof q?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Clean failed:",e.message),process.exit(1)}});S.command("status").description("Show cache status and configuration").action(async()=>{try{console.log("\u{1F4CA} FrontFriend Status"),console.log(`===================
72
+ `),console.log("Package:"),console.log(` Version: ${fe}`),console.log("");let o=await new I().load();console.log("Configuration:"),console.log(` FF_ID: ${o.ffId||"Not set"}`),console.log(` App Root: ${o.appRoot}`),o.tag&&console.log(` Tag: ${o.tag}`),o.version&&console.log(` Version: ${o.version}`),console.log("");let n=new D(o.appRoot),t=n.getCacheDir();if(console.log("Cache:"),console.log(` Directory: ${l.relative(process.cwd(),t)}`),n.exists()){console.log(` Status: ${n.isValid()?"\u2705 Valid":"\u26A0\uFE0F Expired"}`);let s=n.load();if(s&&s.metadata){let r=new Date(s.metadata.timestamp);console.log(` Created: ${r.toLocaleString()}`),console.log(` Format Version: ${s.metadata.version||"Unknown"}`)}s&&s.versionMetadata&&(console.log(" Cached Version Info:"),s.versionMetadata.version&&console.log(` Version: ${s.versionMetadata.version}`),s.versionMetadata.tag&&console.log(` Tag: ${s.versionMetadata.tag}`))}else console.log(" Status: \u274C Not found");process.exit(0)}catch(e){e instanceof x?console.error("\u274C Configuration Error:",e.message):e instanceof q?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Status check failed:",e.message),process.exit(1)}});S.command("migrate").description("Migrate cva-structured shadcn components into FrontFriend config").option("--component <name>",'Component to migrate, or "all" to scan the UI dir',"all").option("--input <path>","Path to the shadcn component source").option("--output <path>","Output JSON path for migrated config",qe).option("--no-push","Do not push migrated config to the configured FrontFriend cloud").action(async e=>{try{let n=await new I().load(),t=n.appRoot,s=e.input&&e.component==="all"?M(e.input):e.component,r;if(e.input){let f=l.resolve(t,e.input);if(!u.existsSync(f))throw new x(`Component source not found: ${l.relative(t,f)}`);let a=u.readFileSync(f,"utf8");r=N(a,s)}else if(s==="all")r=pe(t);else{let f=ge(t,s);if(f.length===0)throw new x(`Component source "${s}" not found under components/ui or src/components/ui`,"component");let a=u.readFileSync(f[0].inputPath,"utf8");r=N(a,s)}if(r.skipped===!0||Object.keys(r.config||{}).length===0){let f=r.reason||"no cva-structured components found";console.log(`\u23ED\uFE0F Skipped ${s}: ${f}`),process.exit(0)}let i=l.resolve(t,e.output);J(i,r.config),de(t,r.config);let d=!1;e.push&&n.ffId&&(await new le(n.ffId,{baseURL:n["api-url"]||n.apiUrl,authToken:n["auth-token"]||n.authToken}).pushComponentsConfig(r.config),d=!0),console.log("\u2705 Migration complete!"),console.log(` Component: ${s==="all"?Object.keys(r.config).join(", "):s}`),console.log(` Output: ${l.relative(t,i)}`),console.log(" Local config: cached for the FrontFriend plugin"),console.log(d?" Cloud config: pushed user override":" Cloud config: not pushed (missing ff-id or --no-push)"),process.exit(0)}catch(o){o instanceof x?console.error("\u274C Migration Error:",o.message):console.error("\u274C Migration failed:",o.message),process.exit(1)}});S.command("download").description("Download components from registry").argument("<components...>",'component names to download (or "all" to download all components)').option("-f, --framework <framework>","Framework to download components for (react/vue)").option("-o, --output <path>","Output directory for components").option("--registry <generation>","Registry generation to use (legacy/v4)").option("--overwrite","Overwrite existing files").action(async(e,o)=>{try{console.log(`\u{1F4E6} Downloading components...
73
73
  `);let t=await new I().load();if(!t.ffId)throw new x(`ff-id not found in frontfriend.config.js
74
- Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let s=new Ae({appRoot:t.appRoot,config:t,framework:n.framework,registryGeneration:n.registry,outputPath:n.output,overwrite:n.overwrite}),r=e;if(e.length===1&&e[0].toLowerCase()==="all"){let f=await s.getAllComponents(),l=await s.getCustomComponents();process.env.FF_DEBUG&&console.log(`Debug: Found ${l.length} custom components: ${l.join(", ")}`),f.length===0&&(console.error("\u274C Failed to fetch component list"),process.exit(1));let u=new Set(l),g=f.filter(c=>!u.has(c));r=[...l,...g],console.log("\u{1F4CB} Configuration"),console.log(` Framework: ${s.framework}`),console.log(` Registry: ${s.registryGeneration}`),console.log(` Output: ${s.outputPath}`),console.log(` Components: All ${r.length} components`),process.env.FF_DEBUG&&l.length>0&&console.log(` Debug: ${l.length} custom components will override standard ones`),console.log("")}else console.log("\u{1F4CB} Configuration"),console.log(` Framework: ${s.framework}`),console.log(` Registry: ${s.registryGeneration}`),console.log(` Output: ${s.outputPath}`),console.log(` Components: ${e.join(", ")}
74
+ Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let s=new Le({appRoot:t.appRoot,config:t,framework:o.framework,registryGeneration:o.registry,outputPath:o.output,overwrite:o.overwrite}),r=e;if(e.length===1&&e[0].toLowerCase()==="all"){let d=await s.getAllComponents(),f=await s.getCustomComponents();process.env.FF_DEBUG&&console.log(`Debug: Found ${f.length} custom components: ${f.join(", ")}`),d.length===0&&(console.error("\u274C Failed to fetch component list"),process.exit(1));let a=new Set(f),g=d.filter(c=>!a.has(c));r=[...f,...g],console.log("\u{1F4CB} Configuration"),console.log(` Framework: ${s.framework}`),console.log(` Registry: ${s.registryGeneration}`),console.log(` Output: ${s.outputPath}`),console.log(` Components: All ${r.length} components`),process.env.FF_DEBUG&&f.length>0&&console.log(` Debug: ${f.length} custom components will override standard ones`),console.log("")}else console.log("\u{1F4CB} Configuration"),console.log(` Framework: ${s.framework}`),console.log(` Registry: ${s.registryGeneration}`),console.log(` Output: ${s.outputPath}`),console.log(` Components: ${e.join(", ")}
75
75
  `);let i=await s.downloadComponents(r);i.successful.length>0&&(console.log(`
76
- \u2705 Download complete!`),console.log(` Downloaded: ${i.successful.length} components`)),i.failed.length>0&&(console.log(""),i.failed.forEach(f=>{f.error.includes("not found")?console.log(`\u274C ${f.error}`):console.log(`\u274C Failed to download ${f.component}: ${f.error}`)})),i.successful.length>0&&i.dependencies.length>0&&(console.log(`
77
- \u{1F4E6} Install dependencies:`),console.log(` npm install ${i.dependencies.join(" ")}`)),i.successful.length===0&&i.failed.length>0&&process.exit(1),process.exit(0)}catch(o){o instanceof x?(console.error("\u274C Configuration Error:",o.message),o.missingKey&&console.error(` Missing key: ${o.missingKey}`)):console.error("\u274C Download failed:",o.message),process.exit(1)}});w.parse(process.argv);process.argv.slice(2).length||(w.outputHelp(),process.exit(0));
76
+ \u2705 Download complete!`),console.log(` Downloaded: ${i.successful.length} components`)),i.failed.length>0&&(console.log(""),i.failed.forEach(d=>{d.error.includes("not found")?console.log(`\u274C ${d.error}`):console.log(`\u274C Failed to download ${d.component}: ${d.error}`)})),i.successful.length>0&&i.dependencies.length>0&&(console.log(`
77
+ \u{1F4E6} Install dependencies:`),console.log(` npm install ${i.dependencies.join(" ")}`)),i.successful.length===0&&i.failed.length>0&&process.exit(1),process.exit(0)}catch(n){n instanceof x?(console.error("\u274C Configuration Error:",n.message),n.missingKey&&console.error(` Missing key: ${n.missingKey}`)):console.error("\u274C Download failed:",n.message),process.exit(1)}});S.parse(process.argv);process.argv.slice(2).length||(S.outputHelp(),process.exit(0));
78
78
  //# sourceMappingURL=cli-temp.js.map
@@ -1,3 +1,3 @@
1
- var j=(s,e)=>()=>(e||s((e={exports:{}}).exports,e),e.exports);var T=j((Ue,I)=>{var oe="https://app.frontfriend.dev",re="https://registry-legacy.frontfriend.dev",ae=".cache/frontfriend",ie={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","safelist.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},ce={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};I.exports={DEFAULT_API_URL:oe,LEGACY_API_URL:re,CACHE_DIR_NAME:ae,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:ie,ENV_VARS:ce}});var J=j((De,x)=>{var _=class extends Error{constructor(e,t,n){super(e),this.name="APIError",this.statusCode=t,this.url=n,this.code=`API_${t}`}},P=class extends Error{constructor(e,t){super(e),this.name="CacheError",this.operation=t,this.code=`CACHE_${t.toUpperCase()}`}},$=class extends Error{constructor(e,t){super(e),this.name="ConfigError",this.field=t,this.code=t?`CONFIG_${String(t).toUpperCase()}`:"CONFIG_ERROR"}},E=class extends Error{constructor(e,t){super(e),this.name="ProcessingError",this.token=t,this.code="PROCESSING_ERROR"}};x.exports={APIError:_,CacheError:P,ConfigError:$,ProcessingError:E}});var R=j((ve,O)=>{var m=require("fs");function le(s){try{let e=m.readFileSync(s,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return null;throw e}}function he(s){try{return m.readFileSync(s,"utf8").replace(/^\uFEFF/,"")}catch(e){if(e.code==="ENOENT")return null;throw e}}function ue(s,e,t=2){let n=JSON.stringify(e,null,t);m.writeFileSync(s,n,"utf8")}function fe(s,e){m.writeFileSync(s,e,"utf8")}function de(s,e){if(e==null||typeof e=="object"&&Object.keys(e).length===0||Array.isArray(e)&&e.length===0){let n=`module.exports = ${Array.isArray(e)?"[]":"{}"};`;m.writeFileSync(s,n,"utf8")}else{let t=`module.exports = ${JSON.stringify(e,null,2)};`;m.writeFileSync(s,t,"utf8")}}function pe(s){return m.existsSync(s)}function me(s){m.mkdirSync(s,{recursive:!0})}function ye(s){m.rmSync(s,{recursive:!0,force:!0})}O.exports={readJsonFileSafe:le,readFileSafe:he,writeJsonFile:ue,writeTextFile:fe,writeModuleExportsFile:de,fileExists:pe,ensureDirectoryExists:me,removeDirectory:ye}});var q=j((Le,M)=>{var y=require("path"),{fileExists:S}=R();function ge(s,e=process.cwd()){let t=e;for(;t!==y.parse(t).root;){let n=y.join(t,s);if(S(n))return n;t=y.dirname(t)}return null}function we(s,e=process.cwd(),t=null){let n=[],o=e,i=10;for(let r=0;r<i;r++){n.push(y.join(o,s)),r<3&&n.push(y.join(o,"../".repeat(r+1)+s));let a=y.dirname(o);if(a===o)break;o=a}n.push(y.join(__dirname,"../../../",s));for(let r of n)if(S(r)&&(!t||t(r)))return r;return null}function ke(s,e=process.cwd()){let t=s.map(n=>y.isAbsolute(n)?n:y.join(e,n));for(let n of t)if(S(n))return n;return null}M.exports={findFileUpward:ge,findDirectoryUpward:we,findDirectoryWithPaths:ke}});var V=j((be,G)=>{var h=require("path"),{findDirectoryUpward:H}=q(),{readJsonFileSafe:g,readFileSafe:B,fileExists:A}=R(),U=class{constructor(e,t={}){if(this.ffId=e,this.tokensBasePath=t.tokensBasePath||this.findTokensPath(),this.folderMap=this.loadFolderMap(),this.projectFolder=this.folderMap[e],!this.projectFolder)throw new Error(`No folder mapping found for ff-id: ${e}`);this.projectPath=h.join(this.tokensBasePath,this.projectFolder)}findTokensPath(){let e=H("apps/tokens",process.cwd(),t=>A(h.join(t,"folderMap.json")));if(e||(e=H("tokens",process.cwd(),t=>A(h.join(t,"folderMap.json")))),!e)throw new Error("Could not find tokens directory with folderMap.json");return e}loadFolderMap(){let e=h.join(this.tokensBasePath,"folderMap.json"),t=g(e);if(!t)throw new Error("Failed to load folderMap.json: File not found");return t}async fetchTokens(){let e=h.join(this.projectPath,"figma"),t={global:[h.join(e,"Global Tokens","Default.json"),h.join(e,"global.json")],colors:[h.join(e,"Global Colors","Default.json"),h.join(e,"Global Colors","Light.json")],semantic:[h.join(e,"Semantic","Light.json"),h.join(e,"Semantic","Default.json")],semanticDark:[h.join(e,"Semantic","Dark.json")]},n={};for(let[o,i]of Object.entries(t)){for(let r of i){let a=g(r);if(a!==null){n[o]=a;break}}n[o]||(n[o]=null)}return n}async fetchProcessedTokens(){let e=h.join(this.projectPath,"cache");if(!A(e))return null;let t=r=>{if(r===null)return null;let a={},u={exports:a};return new Function("module","exports",r)(u,a),u.exports},n={tokens:{fileName:"hashedTokens.js",type:"module"},variables:{fileName:"hashedVariables.js",type:"module"},semanticVariables:{fileName:"hashedSemanticVariables.js",type:"module"},semanticDarkVariables:{fileName:"hashedSemanticDarkVariables.js",type:"module"},safelist:{fileName:"safelist.js",type:"module"},custom:{fileName:"custom.js",type:"module"},fonts:{fileName:"fonts.json",type:"json"},icons:{fileName:"icons.json",type:"json"},componentsConfig:{fileName:"encoded-config.json",type:"json"},version:{fileName:"version.json",type:"json"}},o={};for(let[r,{fileName:a,type:u}]of Object.entries(n)){let c=h.join(e,a),d=u==="module"?t(B(c)):g(c);d!==null&&(o[r]=d)}return Object.values(o).some(r=>r!==null)?o:null}async fetchComponentsConfig(){return g(h.join(this.projectPath,"components-config.json"))}async fetchFonts(){return g(h.join(this.projectPath,"font.json"))}async fetchIcons(){return g(h.join(this.projectPath,"icons.json"))}async fetchVersion(){return g(h.join(this.projectPath,"version.json"))}async fetchCustomCss(){return B(h.join(this.projectPath,"custom.css"))}async fetchPlanMetadata(){return g(h.join(this.projectPath,"metadata.json"))||{planType:"full",allowedComponents:null}}fetchJson(){throw new Error("fetchJson is not implemented in LocalTokenReader. Use specific fetch methods.")}fetchRaw(){throw new Error("fetchRaw is not implemented in LocalTokenReader. Use specific fetch methods.")}};G.exports={LocalTokenReader:U}});var se=j((Ne,te)=>{var w=require("fs"),W=require("path"),Ce=require("os"),je=require("https"),Fe=require("http"),{URL:Te}=require("url"),{DEFAULT_API_URL:Y}=T(),z=W.join(Ce.homedir(),".frontfriend"),k=W.join(z,"credentials");function _e(){return k}function K(){try{return w.existsSync(k)?JSON.parse(w.readFileSync(k,"utf8")):null}catch{return null}}function Q(s){w.mkdirSync(z,{recursive:!0,mode:448}),w.writeFileSync(k,`${JSON.stringify(s,null,2)}
2
- `,{mode:384});try{w.chmodSync(k,384)}catch{}}function Pe(){return w.existsSync(k)?(w.unlinkSync(k),!0):!1}function X(s,e=60*1e3){return!(s!=null&&s.accessToken)||!s.expiresAt||Date.now()+e>=s.expiresAt}function Z(s,e,t){return new Promise((n,o)=>{let i=new Te(s),r=i.protocol==="https:"?je:Fe,a=JSON.stringify(e||{}),u=r.request({hostname:i.hostname,port:i.port,path:`${i.pathname}${i.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(a),...t?{authorization:`Bearer ${t}`}:{}}},c=>{let d="";c.on("data",l=>{d+=l}),c.on("end",()=>{let l=null;try{l=d?JSON.parse(d):null}catch(p){o(p);return}if(c.statusCode>=400){let p=new Error((l==null?void 0:l.error_description)||(l==null?void 0:l.error)||`HTTP ${c.statusCode}`);p.statusCode=c.statusCode,p.body=l,o(p);return}n(l)})});u.on("error",o),u.write(a),u.end()})}async function ee(s,e=Y){if(!(s!=null&&s.refreshToken)||!(s!=null&&s.deviceId))return s;let t=await Z(`${e}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:s.refreshToken,device_id:s.deviceId}),n={accessToken:t.access_token,refreshToken:t.refresh_token,deviceId:t.device_id||s.deviceId,expiresAt:Date.now()+(t.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(t.refresh_expires_in||604800)*1e3,ffApiUrl:e};return Q(n),n}async function $e(s={}){if(!s.skipCredentials){let e=K();if(e!=null&&e.accessToken){let t=s.baseURL||e.ffApiUrl||Y;if(X(e))try{let n=await ee(e,t);return(n==null?void 0:n.accessToken)||null}catch{return null}return e.accessToken}}return s.envToken?s.envToken:s.legacyToken?(s.silent||console.warn("\u26A0\uFE0F auth-token in frontfriend.config.js is deprecated. Run `frontfriend login` to store credentials outside the repo."),s.legacyToken):null}te.exports={getCredentialsPath:_e,readCredentials:K,writeCredentials:Q,deleteCredentials:Pe,isExpired:X,postJson:Z,refreshCredentials:ee,resolveAuthToken:$e}});var D=require("https"),v=require("http"),{URL:b}=require("url"),{DEFAULT_API_URL:Ee,LEGACY_API_URL:C,ENV_VARS:L}=T(),{APIError:f}=J(),{LocalTokenReader:Re}=V(),{resolveAuthToken:Se}=se();function ne(s,e,t,n){return t?s.get(new b(e),{headers:{authorization:`Bearer ${t}`}},n):s.get(e,n)}var N=class{constructor(e,t={}){this.ffId=e,this.baseURL=t.baseURL||process.env[L.FF_API_URL]||Ee,this.legacyAuthToken=t.authToken||null,this.authToken=null,this.skipCredentials=t.skipCredentials||!1,process.env[L.FF_USE_LOCAL]==="true"&&(console.log(" \u{1F3E0} Using local token reader"),this.localReader=new Re(e,t))}async getAuthToken(){return this.authToken=await Se({baseURL:this.baseURL,envToken:process.env[L.FF_AUTH_TOKEN],legacyToken:this.legacyAuthToken,skipCredentials:this.skipCredentials}),this.authToken}async fetchJson(e,t={}){let n=await this.getAuthToken();return new Promise((o,i)=>{let r=e.startsWith("https")?D:v;ne(r,e,n,a=>{let u="";if(a.statusCode>=400){i(new f(`HTTP ${a.statusCode}: ${a.statusMessage}`,a.statusCode,e));return}a.on("data",c=>{u+=c}),a.on("end",()=>{try{let c=JSON.parse(u);t.returnHeaders?o({data:c,headers:a.headers}):o(c)}catch(c){i(new f(`Invalid JSON response: ${c.message}`,a.statusCode,e))}}),a.on("error",c=>{i(new f(`Response error: ${c.message}`,a.statusCode,e))})}).on("error",a=>{i(new f(`Network error: ${a.message}`,0,e))})})}async fetchRaw(e){let t=await this.getAuthToken();return new Promise((n,o)=>{let i=e.startsWith("https")?D:v;ne(i,e,t,r=>{let a="";if(r.statusCode>=400){o(new f(`HTTP ${r.statusCode}: ${r.statusMessage}`,r.statusCode,e));return}r.on("data",u=>{a+=u}),r.on("end",()=>{n(a)}),r.on("error",u=>{o(new f(`Response error: ${u.message}`,r.statusCode,e))})}).on("error",r=>{o(new f(`Network error: ${r.message}`,0,e))})})}async fetchTokens(){if(this.localReader)return this.localReader.fetchTokens();try{let o=`${this.baseURL}/api/design-systems/${this.ffId}/tokens`,i=await this.fetchJson(o);if(i&&i.tokens){let r=i.tokens;return{global:r["Global Tokens/Default"]||r.global||null,colors:r["Global Colors/Default"]||r.colors||null,semantic:r["Semantic/Light"]||r["semantic/light"]||null,semanticDark:r["Semantic/Dark"]||r["semantic/dark"]||null}}}catch(o){if(o.statusCode===400)throw new f("Design system not synced with Figma. Please sync tokens from Figma before using this design system.",400,`${this.baseURL}/api/design-systems/${this.ffId}/tokens`)}let e=C,t={global:`${e}/${this.ffId}/global-tokens/default.json`,colors:`${e}/${this.ffId}/global-colors/default.json`,semantic:`${e}/${this.ffId}/semantic/light.json`,semanticDark:`${e}/${this.ffId}/semantic/dark.json`},n=await Promise.all([this.fetchJson(t.global).catch(o=>o.statusCode===404?null:Promise.reject(o)),this.fetchJson(t.colors).catch(o=>o.statusCode===404?null:Promise.reject(o)),this.fetchJson(t.semantic).catch(o=>o.statusCode===404?null:Promise.reject(o)),this.fetchJson(t.semanticDark).catch(o=>o.statusCode===404?null:Promise.reject(o))]);return{global:n[0],colors:n[1],semantic:n[2],semanticDark:n[3]}}async fetchProcessedTokens(e={}){if(this.localReader)return this.localReader.fetchProcessedTokens();let t=new b(`${this.baseURL}/api/design-systems/${this.ffId}/processed-tokens`);e.tag&&t.searchParams.append("tag",e.tag),e.version&&t.searchParams.append("version",e.version),e.tailwindV4&&t.searchParams.append("tailwind","v4");let n=t.toString();try{let o=await this.fetchJson(n,{returnHeaders:!0});return o.headers&&(o.data.versionMetadata={version:o.headers["x-frontfriend-version"],tag:o.headers["x-frontfriend-tag"],cached:o.headers["x-frontfriend-cached"]==="true"}),o.data}catch(o){if(o.statusCode===404)return null;throw o.statusCode===400?new f("Design system not synced with Figma. Please sync tokens from Figma before using this design system.",400,n):o}}async sendJson(e,t,n){let o=await this.getAuthToken();return new Promise((i,r)=>{let a=new b(e),u=e.startsWith("https")?D:v,c=JSON.stringify(n||{}),d=u.request({hostname:a.hostname,port:a.port,path:`${a.pathname}${a.search}`,method:t,headers:{"content-type":"application/json","content-length":Buffer.byteLength(c),...o?{authorization:`Bearer ${o}`}:{}}},l=>{let p="";if(l.statusCode>=400){r(new f(`HTTP ${l.statusCode}: ${l.statusMessage}`,l.statusCode,e));return}l.on("data",F=>{p+=F}),l.on("end",()=>{if(!p){i(null);return}try{i(JSON.parse(p))}catch(F){r(new f(`Invalid JSON response: ${F.message}`,l.statusCode,e))}})});d.on("error",l=>{r(new f(`Network error: ${l.message}`,0,e))}),d.write(c),d.end()})}async pushComponentsConfig(e){let t=`${this.baseURL}/api/design-systems/${this.ffId}/components-config`;return this.sendJson(t,"PUT",{componentsConfig:e})}async fetchComponentsConfig(){if(this.localReader)return this.localReader.fetchComponentsConfig();let e=`${C}/${this.ffId}/components-config.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchFonts(){if(this.localReader)return this.localReader.fetchFonts();let e=`${C}/${this.ffId}/font.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchIcons(){if(this.localReader)return this.localReader.fetchIcons();let e=`${C}/${this.ffId}/icons.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchVersion(){if(this.localReader)return this.localReader.fetchVersion();let e=`${C}/${this.ffId}/version.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchCustomCss(){if(this.localReader)return this.localReader.fetchCustomCss();let e=`${C}/${this.ffId}/custom.css`;try{return await this.fetchRaw(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchPlanMetadata(){if(this.localReader)return process.env.FF_DEBUG&&console.log(" \u2192 Using local reader for plan metadata"),this.localReader.fetchPlanMetadata();let e=`${this.baseURL}/api/design-systems/${this.ffId}/processed-tokens`;try{process.env.FF_DEBUG&&console.log(` \u2192 Fetching plan metadata from saas app: ${e}`);let t=await this.fetchJson(e);if(t&&t.metadata){let n={planType:t.metadata.planType||"full",allowedComponents:t.metadata.allowedComponents||null};return process.env.FF_DEBUG&&console.log(` \u2192 Found plan metadata in saas app: ${n.planType}, allowed: ${n.allowedComponents?n.allowedComponents.length+" components":"all"}`),n}}catch(t){if(t.statusCode===404){process.env.FF_DEBUG&&console.log(" \u2192 ff-id not found in saas app, trying legacy server");let n=`${C}/${this.ffId}/metadata`;try{process.env.FF_DEBUG&&console.log(` \u2192 Fetching from legacy server: ${n}`);let o=await this.fetchJson(n),i={planType:o.planType||"full",allowedComponents:o.allowedComponents||null};return process.env.FF_DEBUG&&console.log(` \u2192 Found in legacy server: ${i.planType}, allowed: ${i.allowedComponents?i.allowedComponents.length+" components":"all"}`),i}catch(o){if(o.statusCode===404)return process.env.FF_DEBUG&&console.log(" \u2192 ff-id not found in any server - access denied"),{planType:"denied",allowedComponents:[],error:"Design system not found. Please ensure your ff-id is valid."};throw o}}throw t}}};module.exports={APIClient:N};
1
+ var T=(s,e)=>()=>(e||s((e={exports:{}}).exports,e),e.exports);var E=T((Le,O)=>{var ce="https://app.frontfriend.dev",le="https://registry-legacy.frontfriend.dev",he=".cache/frontfriend",ue={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","safelist.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},fe={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};O.exports={DEFAULT_API_URL:ce,LEGACY_API_URL:le,CACHE_DIR_NAME:he,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:ue,ENV_VARS:fe}});var q=T((Ne,M)=>{var $=class extends Error{constructor(e,t,o){super(e),this.name="APIError",this.statusCode=t,this.url=o,this.code=`API_${t}`}},P=class extends Error{constructor(e,t){super(e),this.name="CacheError",this.operation=t,this.code=`CACHE_${t.toUpperCase()}`}},R=class extends Error{constructor(e,t){super(e),this.name="ConfigError",this.field=t,this.code=t?`CONFIG_${String(t).toUpperCase()}`:"CONFIG_ERROR"}},S=class extends Error{constructor(e,t){super(e),this.name="ProcessingError",this.token=t,this.code="PROCESSING_ERROR"}};M.exports={APIError:$,CacheError:P,ConfigError:R,ProcessingError:S}});var A=T((Ie,H)=>{var y=require("fs");function de(s){try{let e=y.readFileSync(s,"utf8");return JSON.parse(e)}catch(e){if(e.code==="ENOENT")return null;throw e}}function pe(s){try{return y.readFileSync(s,"utf8").replace(/^\uFEFF/,"")}catch(e){if(e.code==="ENOENT")return null;throw e}}function me(s,e,t=2){let o=JSON.stringify(e,null,t);y.writeFileSync(s,o,"utf8")}function ye(s,e){y.writeFileSync(s,e,"utf8")}function we(s,e){if(e==null||typeof e=="object"&&Object.keys(e).length===0||Array.isArray(e)&&e.length===0){let o=`module.exports = ${Array.isArray(e)?"[]":"{}"};`;y.writeFileSync(s,o,"utf8")}else{let t=`module.exports = ${JSON.stringify(e,null,2)};`;y.writeFileSync(s,t,"utf8")}}function ge(s){return y.existsSync(s)}function Ce(s){y.mkdirSync(s,{recursive:!0})}function ke(s){y.rmSync(s,{recursive:!0,force:!0})}H.exports={readJsonFileSafe:de,readFileSafe:pe,writeJsonFile:me,writeTextFile:ye,writeModuleExportsFile:we,fileExists:ge,ensureDirectoryExists:Ce,removeDirectory:ke}});var B=T((xe,G)=>{var w=require("path"),{fileExists:U}=A();function Fe(s,e=process.cwd()){let t=e;for(;t!==w.parse(t).root;){let o=w.join(t,s);if(U(o))return o;t=w.dirname(t)}return null}function Te(s,e=process.cwd(),t=null){let o=[],n=e,c=10;for(let r=0;r<c;r++){o.push(w.join(n,s)),r<3&&o.push(w.join(n,"../".repeat(r+1)+s));let a=w.dirname(n);if(a===n)break;n=a}o.push(w.join(__dirname,"../../../",s));for(let r of o)if(U(r)&&(!t||t(r)))return r;return null}function je(s,e=process.cwd()){let t=s.map(o=>w.isAbsolute(o)?o:w.join(e,o));for(let o of t)if(U(o))return o;return null}G.exports={findFileUpward:Fe,findDirectoryUpward:Te,findDirectoryWithPaths:je}});var z=T((Je,Y)=>{var h=require("path"),{findDirectoryUpward:V}=B(),{readJsonFileSafe:g,readFileSafe:W,fileExists:D}=A(),v=class{constructor(e,t={}){if(this.ffId=e,this.tokensBasePath=t.tokensBasePath||this.findTokensPath(),this.folderMap=this.loadFolderMap(),this.projectFolder=this.folderMap[e],!this.projectFolder)throw new Error(`No folder mapping found for ff-id: ${e}`);this.projectPath=h.join(this.tokensBasePath,this.projectFolder)}findTokensPath(){let e=V("apps/tokens",process.cwd(),t=>D(h.join(t,"folderMap.json")));if(e||(e=V("tokens",process.cwd(),t=>D(h.join(t,"folderMap.json")))),!e)throw new Error("Could not find tokens directory with folderMap.json");return e}loadFolderMap(){let e=h.join(this.tokensBasePath,"folderMap.json"),t=g(e);if(!t)throw new Error("Failed to load folderMap.json: File not found");return t}async fetchTokens(){let e=h.join(this.projectPath,"figma"),t={global:[h.join(e,"Global Tokens","Default.json"),h.join(e,"global.json")],colors:[h.join(e,"Global Colors","Default.json"),h.join(e,"Global Colors","Light.json")],semantic:[h.join(e,"Semantic","Light.json"),h.join(e,"Semantic","Default.json")],semanticDark:[h.join(e,"Semantic","Dark.json")]},o={};for(let[n,c]of Object.entries(t)){for(let r of c){let a=g(r);if(a!==null){o[n]=a;break}}o[n]||(o[n]=null)}return o}async fetchProcessedTokens(){let e=h.join(this.projectPath,"cache");if(!D(e))return null;let t=r=>{if(r===null)return null;let a={},u={exports:a};return new Function("module","exports",r)(u,a),u.exports},o={tokens:{fileName:"hashedTokens.js",type:"module"},variables:{fileName:"hashedVariables.js",type:"module"},semanticVariables:{fileName:"hashedSemanticVariables.js",type:"module"},semanticDarkVariables:{fileName:"hashedSemanticDarkVariables.js",type:"module"},safelist:{fileName:"safelist.js",type:"module"},custom:{fileName:"custom.js",type:"module"},fonts:{fileName:"fonts.json",type:"json"},icons:{fileName:"icons.json",type:"json"},componentsConfig:{fileName:"encoded-config.json",type:"json"},version:{fileName:"version.json",type:"json"}},n={};for(let[r,{fileName:a,type:u}]of Object.entries(o)){let i=h.join(e,a),d=u==="module"?t(W(i)):g(i);d!==null&&(n[r]=d)}return Object.values(n).some(r=>r!==null)?n:null}async fetchComponentsConfig(){return g(h.join(this.projectPath,"components-config.json"))}async fetchFonts(){return g(h.join(this.projectPath,"font.json"))}async fetchIcons(){return g(h.join(this.projectPath,"icons.json"))}async fetchVersion(){return g(h.join(this.projectPath,"version.json"))}async fetchCustomCss(){return W(h.join(this.projectPath,"custom.css"))}async fetchPlanMetadata(){return g(h.join(this.projectPath,"metadata.json"))||{planType:"full",allowedComponents:null}}fetchJson(){throw new Error("fetchJson is not implemented in LocalTokenReader. Use specific fetch methods.")}fetchRaw(){throw new Error("fetchRaw is not implemented in LocalTokenReader. Use specific fetch methods.")}};Y.exports={LocalTokenReader:v}});var re=T((Oe,oe)=>{var C=require("fs"),K=require("path"),_e=require("os"),Ee=require("https"),$e=require("http"),{URL:Pe}=require("url"),{DEFAULT_API_URL:Q}=E(),X=K.join(_e.homedir(),".frontfriend"),k=K.join(X,"credentials");function Re(){return k}function Z(){try{return C.existsSync(k)?JSON.parse(C.readFileSync(k,"utf8")):null}catch{return null}}function ee(s){C.mkdirSync(X,{recursive:!0,mode:448}),C.writeFileSync(k,`${JSON.stringify(s,null,2)}
2
+ `,{mode:384});try{C.chmodSync(k,384)}catch{}}function Se(){return C.existsSync(k)?(C.unlinkSync(k),!0):!1}function te(s,e=60*1e3){return!(s!=null&&s.accessToken)||!s.expiresAt||Date.now()+e>=s.expiresAt}function j(s){let e=new Error(`${s}. Run \`frontfriend login\` to re-authenticate.`);return e.code="FF_AUTH_REFRESH_FAILED",e}function se(s,e,t){return new Promise((o,n)=>{let c=new Pe(s),r=c.protocol==="https:"?Ee:$e,a=JSON.stringify(e||{}),u=r.request({hostname:c.hostname,port:c.port,path:`${c.pathname}${c.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(a),...t?{authorization:`Bearer ${t}`}:{}}},i=>{let d="";i.on("data",l=>{d+=l}),i.on("end",()=>{if(i.statusCode>=300&&i.statusCode<400){let p=i.headers.location?` to ${i.headers.location}`:"",m=new Error(`HTTP ${i.statusCode}: redirected${p}`);m.statusCode=i.statusCode,m.body=d,n(m);return}let l=null;try{l=d?JSON.parse(d):null}catch(p){if(i.statusCode>=400){let m=new Error(`HTTP ${i.statusCode}: ${i.statusMessage||"Non-JSON response"}`);m.statusCode=i.statusCode,m.body=d,n(m);return}n(p);return}if(i.statusCode>=400){let p=new Error((l==null?void 0:l.error_description)||(l==null?void 0:l.error)||`HTTP ${i.statusCode}`);p.statusCode=i.statusCode,p.body=l,n(p);return}o(l)})});u.on("error",n),u.write(a),u.end()})}async function ne(s,e=Q){if(!(s!=null&&s.refreshToken)||!(s!=null&&s.deviceId))throw j("FrontFriend session expired");let t;try{t=await se(`${e}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:s.refreshToken,device_id:s.deviceId})}catch(n){throw j((n==null?void 0:n.message)||"Could not refresh FrontFriend session")}if(!(t!=null&&t.access_token)||!(t!=null&&t.refresh_token))throw j("Could not refresh FrontFriend session");let o={accessToken:t.access_token,refreshToken:t.refresh_token,deviceId:t.device_id||s.deviceId,expiresAt:Date.now()+(t.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(t.refresh_expires_in||604800)*1e3,ffApiUrl:e};return ee(o),o}async function Ae(s={}){if(!s.skipCredentials){let e=Z();if(e!=null&&e.accessToken||e!=null&&e.refreshToken){let t=s.baseURL||e.ffApiUrl||Q;return e.accessToken&&!te(e)?e.accessToken:(await ne(e,t)).accessToken}}return s.envToken?s.envToken:s.legacyToken?(s.silent||console.warn("\u26A0\uFE0F auth-token in frontfriend.config.js is deprecated. Run `frontfriend login` to store credentials outside the repo."),s.legacyToken):null}oe.exports={getCredentialsPath:Re,readCredentials:Z,writeCredentials:ee,deleteCredentials:Se,isExpired:te,postJson:se,refreshCredentials:ne,resolveAuthToken:Ae,createAuthRefreshError:j}});var b=require("https"),L=require("http"),{URL:I}=require("url"),{DEFAULT_API_URL:Ue,LEGACY_API_URL:F,ENV_VARS:N}=E(),{APIError:f}=q(),{LocalTokenReader:De}=z(),{resolveAuthToken:ve}=re(),_="Authentication required. Run `frontfriend login` to re-authenticate.";function ae(s,e,t,o){return t?s.get(new I(e),{headers:{authorization:`Bearer ${t}`}},o):s.get(e,o)}function x(s,e=""){var o;let t=((o=s.headers)==null?void 0:o.location)||"";return s.statusCode===401||s.statusCode===403||s.statusCode>=300&&s.statusCode<400&&t.includes("/sign-in")||String(e).trim().startsWith("/sign-in")}function ie(s,e,t=""){return x(s,t)?new f(_,s.statusCode,e):new f(`HTTP ${s.statusCode}: ${s.statusMessage}`,s.statusCode,e)}var J=class{constructor(e,t={}){this.ffId=e,this.baseURL=t.baseURL||process.env[N.FF_API_URL]||Ue,this.legacyAuthToken=t.authToken||null,this.authToken=null,this.skipCredentials=t.skipCredentials||!1,process.env[N.FF_USE_LOCAL]==="true"&&(console.log(" \u{1F3E0} Using local token reader"),this.localReader=new De(e,t))}async getAuthToken(){return this.authToken=await ve({baseURL:this.baseURL,envToken:process.env[N.FF_AUTH_TOKEN],legacyToken:this.legacyAuthToken,skipCredentials:this.skipCredentials}),this.authToken}async fetchJson(e,t={}){let o=await this.getAuthToken();return new Promise((n,c)=>{let r=e.startsWith("https")?b:L;ae(r,e,o,a=>{let u="";if(a.statusCode>=300){c(ie(a,e));return}a.on("data",i=>{u+=i}),a.on("end",()=>{try{let i=JSON.parse(u);t.returnHeaders?n({data:i,headers:a.headers}):n(i)}catch(i){if(x(a,u)){c(new f(_,a.statusCode,e));return}c(new f(`Invalid JSON response: ${i.message}`,a.statusCode,e))}}),a.on("error",i=>{c(new f(`Response error: ${i.message}`,a.statusCode,e))})}).on("error",a=>{c(new f(`Network error: ${a.message}`,0,e))})})}async fetchRaw(e){let t=await this.getAuthToken();return new Promise((o,n)=>{let c=e.startsWith("https")?b:L;ae(c,e,t,r=>{let a="";if(r.statusCode>=400){n(new f(`HTTP ${r.statusCode}: ${r.statusMessage}`,r.statusCode,e));return}r.on("data",u=>{a+=u}),r.on("end",()=>{o(a)}),r.on("error",u=>{n(new f(`Response error: ${u.message}`,r.statusCode,e))})}).on("error",r=>{n(new f(`Network error: ${r.message}`,0,e))})})}async fetchTokens(){if(this.localReader)return this.localReader.fetchTokens();try{let n=`${this.baseURL}/api/design-systems/${this.ffId}/tokens`,c=await this.fetchJson(n);if(c&&c.tokens){let r=c.tokens;return{global:r["Global Tokens/Default"]||r.global||null,colors:r["Global Colors/Default"]||r.colors||null,semantic:r["Semantic/Light"]||r["semantic/light"]||null,semanticDark:r["Semantic/Dark"]||r["semantic/dark"]||null}}}catch(n){if(n.statusCode===400)throw new f("Design system not synced with Figma. Please sync tokens from Figma before using this design system.",400,`${this.baseURL}/api/design-systems/${this.ffId}/tokens`)}let e=F,t={global:`${e}/${this.ffId}/global-tokens/default.json`,colors:`${e}/${this.ffId}/global-colors/default.json`,semantic:`${e}/${this.ffId}/semantic/light.json`,semanticDark:`${e}/${this.ffId}/semantic/dark.json`},o=await Promise.all([this.fetchJson(t.global).catch(n=>n.statusCode===404?null:Promise.reject(n)),this.fetchJson(t.colors).catch(n=>n.statusCode===404?null:Promise.reject(n)),this.fetchJson(t.semantic).catch(n=>n.statusCode===404?null:Promise.reject(n)),this.fetchJson(t.semanticDark).catch(n=>n.statusCode===404?null:Promise.reject(n))]);return{global:o[0],colors:o[1],semantic:o[2],semanticDark:o[3]}}async fetchProcessedTokens(e={}){if(this.localReader)return this.localReader.fetchProcessedTokens();let t=new I(`${this.baseURL}/api/design-systems/${this.ffId}/processed-tokens`);e.tag&&t.searchParams.append("tag",e.tag),e.version&&t.searchParams.append("version",e.version),e.tailwindV4&&t.searchParams.append("tailwind","v4");let o=t.toString();try{let n=await this.fetchJson(o,{returnHeaders:!0});return n.headers&&(n.data.versionMetadata={version:n.headers["x-frontfriend-version"],tag:n.headers["x-frontfriend-tag"],cached:n.headers["x-frontfriend-cached"]==="true"}),n.data}catch(n){if(n.statusCode===404)return null;throw n.statusCode===400?new f("Design system not synced with Figma. Please sync tokens from Figma before using this design system.",400,o):n}}async sendJson(e,t,o){let n=await this.getAuthToken();if(!n)throw new f(_,401,e);return new Promise((c,r)=>{let a=new I(e),u=e.startsWith("https")?b:L,i=JSON.stringify(o||{}),d=u.request({hostname:a.hostname,port:a.port,path:`${a.pathname}${a.search}`,method:t,headers:{"content-type":"application/json","content-length":Buffer.byteLength(i),...n?{authorization:`Bearer ${n}`}:{}}},l=>{let p="";if(l.statusCode>=300){r(ie(l,e));return}l.on("data",m=>{p+=m}),l.on("end",()=>{if(!p){c(null);return}try{c(JSON.parse(p))}catch(m){if(x(l,p)){r(new f(_,l.statusCode,e));return}r(new f(`Invalid JSON response: ${m.message}`,l.statusCode,e))}})});d.on("error",l=>{r(new f(`Network error: ${l.message}`,0,e))}),d.write(i),d.end()})}async pushComponentsConfig(e){let t=`${this.baseURL}/api/design-systems/${this.ffId}/components-config`;return this.sendJson(t,"PUT",{componentsConfig:e})}async fetchComponentsConfig(){if(this.localReader)return this.localReader.fetchComponentsConfig();let e=`${F}/${this.ffId}/components-config.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchFonts(){if(this.localReader)return this.localReader.fetchFonts();let e=`${F}/${this.ffId}/font.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchIcons(){if(this.localReader)return this.localReader.fetchIcons();let e=`${F}/${this.ffId}/icons.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchVersion(){if(this.localReader)return this.localReader.fetchVersion();let e=`${F}/${this.ffId}/version.json`;try{return await this.fetchJson(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchCustomCss(){if(this.localReader)return this.localReader.fetchCustomCss();let e=`${F}/${this.ffId}/custom.css`;try{return await this.fetchRaw(e)}catch(t){if(t.statusCode===404)return null;throw t}}async fetchPlanMetadata(){if(this.localReader)return process.env.FF_DEBUG&&console.log(" \u2192 Using local reader for plan metadata"),this.localReader.fetchPlanMetadata();let e=`${this.baseURL}/api/design-systems/${this.ffId}/processed-tokens`;try{process.env.FF_DEBUG&&console.log(` \u2192 Fetching plan metadata from saas app: ${e}`);let t=await this.fetchJson(e);if(t&&t.metadata){let o={planType:t.metadata.planType||"full",allowedComponents:t.metadata.allowedComponents||null};return process.env.FF_DEBUG&&console.log(` \u2192 Found plan metadata in saas app: ${o.planType}, allowed: ${o.allowedComponents?o.allowedComponents.length+" components":"all"}`),o}}catch(t){if(t.statusCode===404){process.env.FF_DEBUG&&console.log(" \u2192 ff-id not found in saas app, trying legacy server");let o=`${F}/${this.ffId}/metadata`;try{process.env.FF_DEBUG&&console.log(` \u2192 Fetching from legacy server: ${o}`);let n=await this.fetchJson(o),c={planType:n.planType||"full",allowedComponents:n.allowedComponents||null};return process.env.FF_DEBUG&&console.log(` \u2192 Found in legacy server: ${c.planType}, allowed: ${c.allowedComponents?c.allowedComponents.length+" components":"all"}`),c}catch(n){if(n.statusCode===404)return process.env.FF_DEBUG&&console.log(" \u2192 ff-id not found in any server - access denied"),{planType:"denied",allowedComponents:[],error:"Design system not found. Please ensure your ff-id is valid."};throw n}}throw t}}};module.exports={APIClient:J};
3
3
  //# sourceMappingURL=api-client.js.map