@frontfriend/tailwind 4.0.18 → 4.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/browser.mjs +1 -1
  2. package/dist/browser.mjs.map +3 -3
  3. package/dist/cli.js +37 -36
  4. package/dist/component-recipes.d.ts +14 -0
  5. package/dist/components-config-schema.js +1 -1
  6. package/dist/components-config-schema.js.map +3 -3
  7. package/dist/ffdc.d.ts +11 -1
  8. package/dist/ffdc.js +1 -1
  9. package/dist/ffdc.js.map +4 -4
  10. package/dist/index.js +3 -3
  11. package/dist/index.js.map +4 -4
  12. package/dist/index.mjs +1 -1
  13. package/dist/index.mjs.map +3 -3
  14. package/dist/lib/core/api-client.js +2 -2
  15. package/dist/lib/core/api-client.js.map +3 -3
  16. package/dist/lib/core/cache-manager.js +6 -4
  17. package/dist/lib/core/cached-components-config.js +2 -0
  18. package/dist/lib/core/cached-components-config.js.map +7 -0
  19. package/dist/lib/core/component-downloader.js +3 -3
  20. package/dist/lib/core/component-downloader.js.map +3 -3
  21. package/dist/lib/core/component-recipes.js +8 -0
  22. package/dist/lib/core/component-recipes.js.map +7 -0
  23. package/dist/lib/core/components-config-schema.js +1 -1
  24. package/dist/lib/core/components-config-schema.js.map +3 -3
  25. package/dist/lib/core/constants.js +1 -1
  26. package/dist/lib/core/constants.js.map +3 -3
  27. package/dist/lib/core/credentials.js +2 -2
  28. package/dist/lib/core/credentials.js.map +3 -3
  29. package/dist/next.js +1 -1
  30. package/dist/next.js.map +4 -4
  31. package/dist/runtime.js +1 -1
  32. package/dist/runtime.js.map +3 -3
  33. package/dist/types/index.d.ts +15 -1
  34. package/dist/vite.js +6 -19
  35. package/dist/vite.js.map +4 -4
  36. package/dist/vite.mjs +4 -4
  37. package/dist/vite.mjs.map +3 -3
  38. package/package.json +7 -1
  39. package/scripts/build.js +32 -9
  40. package/src/theme.css +3 -9
  41. package/dist/lib/core/default-config-data.js +0 -2
  42. package/dist/lib/core/default-config-data.js.map +0 -7
  43. package/dist/lib/core/default-config.js +0 -2
  44. package/dist/lib/core/default-config.js.map +0 -7
  45. package/scripts/master-components-config.json +0 -1678
  46. package/scripts/update-default-config-data.js +0 -891
package/dist/browser.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var o=typeof window<"u"&&typeof window.document<"u";function i(t=""){let e=new Map;return new Proxy({},{get(r,n){return n===Symbol.toPrimitive||n==="valueOf"?()=>t:n==="toString"||n===Symbol.toStringTag?()=>t:n==="constructor"?Object:(e.has(n)||e.set(n,i(t)),e.get(n))},has(){return!0},ownKeys(){return[]},getOwnPropertyDescriptor(){return{enumerable:!0,configurable:!0}}})}function u(t){return t==="__FF_CONFIG__"&&typeof __FF_CONFIG__<"u"?__FF_CONFIG__:t==="__FF_ICONS__"&&typeof __FF_ICONS__<"u"?__FF_ICONS__:typeof globalThis<"u"&&globalThis[t]?globalThis[t]:o&&window[t]?window[t]:null}function _(t){return!t||typeof t!="object"?i():t}var c=new Proxy({},{get(t,e){if(e===Symbol.toPrimitive||e==="valueOf")return()=>"";if(e==="toString"||e===Symbol.toStringTag)return()=>"[object Object]";if(e==="constructor")return Object;let r=u("__FF_CONFIG__");return r&&e in r?r[e]:i()},has(){return!0},ownKeys(){return[]},getOwnPropertyDescriptor(){return{enumerable:!0,configurable:!0}}}),s=new Proxy({},{get(t,e){if(e===Symbol.toPrimitive||e==="valueOf")return()=>"";if(e==="toString"||e===Symbol.toStringTag)return()=>"[object Object]";if(e==="constructor")return Object;let r=u("__FF_ICONS__");return r&&e in r?r[e]:i()},has(){return!0},ownKeys(){return[]},getOwnPropertyDescriptor(){return{enumerable:!0,configurable:!0}}}),g={};function y(t){return typeof t=="string"&&t.trim().length>0}function f(){return{}}export{g as componentsConfigSchema,c as config,f as default,_ as ffdc,s as iconSet,y as isCSSClassString};
1
+ var y=typeof window<"u"&&typeof window.document<"u";function f(t=""){let e=new Map;return new Proxy({},{get(n,r){return r===Symbol.toPrimitive||r==="valueOf"?()=>t:r==="toString"||r===Symbol.toStringTag?()=>t:r==="constructor"?Object:(e.has(r)||e.set(r,f(t)),e.get(r))},has(){return!0},ownKeys(){return[]},getOwnPropertyDescriptor(){return{enumerable:!0,configurable:!0}}})}function o(t){return t==="__FF_CONFIG__"&&typeof __FF_CONFIG__<"u"?__FF_CONFIG__:t==="__FF_ICONS__"&&typeof __FF_ICONS__<"u"?__FF_ICONS__:typeof globalThis<"u"&&globalThis[t]?globalThis[t]:y&&window[t]?window[t]:null}function u(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function s(t,e){if(!u(t)||!u(e))return e===void 0?t:e;let n={...t};for(let[r,i]of Object.entries(e))n[r]=r in n?s(n[r],i):i;return n}function c(t,e,n=[],r=[]){if(t===void 0||e===void 0)return r;if(!u(t)||!u(e))return r.push(n.join(".")),r;for(let i of Object.keys(t))i in e&&c(t[i],e[i],[...n,i],r);return r}function _(t,e=[]){if(!u(t)||!("styles"in t||"behavior"in t))return t;let n=c(t.styles,t.behavior,e);if(n.length>0)throw new Error(`Component config styles/behavior conflict at ${n.join(", ")}`);return s(t.styles||{},t.behavior||{})}function a(t){let e=!1,n={};for(let[r,i]of Object.entries(t))n[r]=_(i,[r]),n[r]!==i&&(e=!0);return e?n:t}function g(t){return!t||typeof t!="object"?f():a(t)}var d=new Proxy({},{get(t,e){if(e===Symbol.toPrimitive||e==="valueOf")return()=>"";if(e==="toString"||e===Symbol.toStringTag)return()=>"[object Object]";if(e==="constructor")return Object;let n=o("__FF_CONFIG__");return n&&e in n?_(n[e],[String(e)]):f()},has(){return!0},ownKeys(){return[]},getOwnPropertyDescriptor(){return{enumerable:!0,configurable:!0}}}),O=new Proxy({},{get(t,e){if(e===Symbol.toPrimitive||e==="valueOf")return()=>"";if(e==="toString"||e===Symbol.toStringTag)return()=>"[object Object]";if(e==="constructor")return Object;let n=o("__FF_ICONS__");return n&&e in n?n[e]:null},has(t,e){let n=o("__FF_ICONS__");return n?e in n:!1},ownKeys(){let t=o("__FF_ICONS__");return t?Object.keys(t):[]},getOwnPropertyDescriptor(t,e){let n=o("__FF_ICONS__");if(n&&e in n)return{enumerable:!0,configurable:!0,value:n[e]}}}),l={};function F(t){return typeof t=="string"&&t.trim().length>0}function b(){return{}}export{l as componentsConfigSchema,d as config,b as default,g as ffdc,O as iconSet,F as isCSSClassString};
2
2
  //# sourceMappingURL=browser.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../browser.mjs"],
4
- "sourcesContent": ["// Browser-safe FrontFriend runtime used by Vite-built component consumers.\n\nconst isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';\n\nfunction createDeepProxy(fallbackValue = '') {\n const cache = new Map();\n\n return new Proxy({}, {\n get(target, prop) {\n if (prop === Symbol.toPrimitive || prop === 'valueOf') {\n return () => fallbackValue;\n }\n if (prop === 'toString' || prop === Symbol.toStringTag) {\n return () => fallbackValue;\n }\n if (prop === 'constructor') {\n return Object;\n }\n if (!cache.has(prop)) {\n cache.set(prop, createDeepProxy(fallbackValue));\n }\n return cache.get(prop);\n },\n has() {\n return true;\n },\n ownKeys() {\n return [];\n },\n getOwnPropertyDescriptor() {\n return { enumerable: true, configurable: true };\n },\n });\n}\n\nfunction readGlobal(name) {\n if (name === '__FF_CONFIG__' && typeof __FF_CONFIG__ !== 'undefined') {\n return __FF_CONFIG__;\n }\n if (name === '__FF_ICONS__' && typeof __FF_ICONS__ !== 'undefined') {\n return __FF_ICONS__;\n }\n if (typeof globalThis !== 'undefined' && globalThis[name]) {\n return globalThis[name];\n }\n if (isBrowser && window[name]) {\n return window[name];\n }\n return null;\n}\n\nexport function ffdc(config) {\n if (!config || typeof config !== 'object') {\n return createDeepProxy();\n }\n return config;\n}\n\nexport const config = new Proxy({}, {\n get(target, prop) {\n if (prop === Symbol.toPrimitive || prop === 'valueOf') return () => '';\n if (prop === 'toString' || prop === Symbol.toStringTag) return () => '[object Object]';\n if (prop === 'constructor') return Object;\n\n const currentConfig = readGlobal('__FF_CONFIG__');\n if (currentConfig && prop in currentConfig) {\n return currentConfig[prop];\n }\n return createDeepProxy();\n },\n has() {\n return true;\n },\n ownKeys() {\n return [];\n },\n getOwnPropertyDescriptor() {\n return { enumerable: true, configurable: true };\n },\n});\n\nexport const iconSet = new Proxy({}, {\n get(target, prop) {\n if (prop === Symbol.toPrimitive || prop === 'valueOf') return () => '';\n if (prop === 'toString' || prop === Symbol.toStringTag) return () => '[object Object]';\n if (prop === 'constructor') return Object;\n\n const icons = readGlobal('__FF_ICONS__');\n if (icons && prop in icons) {\n return icons[prop];\n }\n return createDeepProxy();\n },\n has() {\n return true;\n },\n ownKeys() {\n return [];\n },\n getOwnPropertyDescriptor() {\n return { enumerable: true, configurable: true };\n },\n});\n\nexport const componentsConfigSchema = {};\n\nexport function isCSSClassString(value) {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nexport default function frontfriend() {\n return {};\n}\n"],
5
- "mappings": "AAEA,IAAMA,EAAY,OAAO,OAAW,KAAe,OAAO,OAAO,SAAa,IAE9E,SAASC,EAAgBC,EAAgB,GAAI,CAC3C,IAAMC,EAAQ,IAAI,IAElB,OAAO,IAAI,MAAM,CAAC,EAAG,CACnB,IAAIC,EAAQC,EAAM,CAChB,OAAIA,IAAS,OAAO,aAAeA,IAAS,UACnC,IAAMH,EAEXG,IAAS,YAAcA,IAAS,OAAO,YAClC,IAAMH,EAEXG,IAAS,cACJ,QAEJF,EAAM,IAAIE,CAAI,GACjBF,EAAM,IAAIE,EAAMJ,EAAgBC,CAAa,CAAC,EAEzCC,EAAM,IAAIE,CAAI,EACvB,EACA,KAAM,CACJ,MAAO,EACT,EACA,SAAU,CACR,MAAO,CAAC,CACV,EACA,0BAA2B,CACzB,MAAO,CAAE,WAAY,GAAM,aAAc,EAAK,CAChD,CACF,CAAC,CACH,CAEA,SAASC,EAAWC,EAAM,CACxB,OAAIA,IAAS,iBAAmB,OAAO,cAAkB,IAChD,cAELA,IAAS,gBAAkB,OAAO,aAAiB,IAC9C,aAEL,OAAO,WAAe,KAAe,WAAWA,CAAI,EAC/C,WAAWA,CAAI,EAEpBP,GAAa,OAAOO,CAAI,EACnB,OAAOA,CAAI,EAEb,IACT,CAEO,SAASC,EAAKC,EAAQ,CAC3B,MAAI,CAACA,GAAU,OAAOA,GAAW,SACxBR,EAAgB,EAElBQ,CACT,CAEO,IAAMA,EAAS,IAAI,MAAM,CAAC,EAAG,CAClC,IAAIL,EAAQC,EAAM,CAChB,GAAIA,IAAS,OAAO,aAAeA,IAAS,UAAW,MAAO,IAAM,GACpE,GAAIA,IAAS,YAAcA,IAAS,OAAO,YAAa,MAAO,IAAM,kBACrE,GAAIA,IAAS,cAAe,OAAO,OAEnC,IAAMK,EAAgBJ,EAAW,eAAe,EAChD,OAAII,GAAiBL,KAAQK,EACpBA,EAAcL,CAAI,EAEpBJ,EAAgB,CACzB,EACA,KAAM,CACJ,MAAO,EACT,EACA,SAAU,CACR,MAAO,CAAC,CACV,EACA,0BAA2B,CACzB,MAAO,CAAE,WAAY,GAAM,aAAc,EAAK,CAChD,CACF,CAAC,EAEYU,EAAU,IAAI,MAAM,CAAC,EAAG,CACnC,IAAIP,EAAQC,EAAM,CAChB,GAAIA,IAAS,OAAO,aAAeA,IAAS,UAAW,MAAO,IAAM,GACpE,GAAIA,IAAS,YAAcA,IAAS,OAAO,YAAa,MAAO,IAAM,kBACrE,GAAIA,IAAS,cAAe,OAAO,OAEnC,IAAMO,EAAQN,EAAW,cAAc,EACvC,OAAIM,GAASP,KAAQO,EACZA,EAAMP,CAAI,EAEZJ,EAAgB,CACzB,EACA,KAAM,CACJ,MAAO,EACT,EACA,SAAU,CACR,MAAO,CAAC,CACV,EACA,0BAA2B,CACzB,MAAO,CAAE,WAAY,GAAM,aAAc,EAAK,CAChD,CACF,CAAC,EAEYY,EAAyB,CAAC,EAEhC,SAASC,EAAiBC,EAAO,CACtC,OAAO,OAAOA,GAAU,UAAYA,EAAM,KAAK,EAAE,OAAS,CAC5D,CAEe,SAARC,GAA+B,CACpC,MAAO,CAAC,CACV",
6
- "names": ["isBrowser", "createDeepProxy", "fallbackValue", "cache", "target", "prop", "readGlobal", "name", "ffdc", "config", "currentConfig", "iconSet", "icons", "componentsConfigSchema", "isCSSClassString", "value", "frontfriend"]
4
+ "sourcesContent": ["// Browser-safe FrontFriend runtime used by Vite-built component consumers.\n\nconst isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';\n\nfunction createDeepProxy(fallbackValue = '') {\n const cache = new Map();\n\n return new Proxy({}, {\n get(target, prop) {\n if (prop === Symbol.toPrimitive || prop === 'valueOf') {\n return () => fallbackValue;\n }\n if (prop === 'toString' || prop === Symbol.toStringTag) {\n return () => fallbackValue;\n }\n if (prop === 'constructor') {\n return Object;\n }\n if (!cache.has(prop)) {\n cache.set(prop, createDeepProxy(fallbackValue));\n }\n return cache.get(prop);\n },\n has() {\n return true;\n },\n ownKeys() {\n return [];\n },\n getOwnPropertyDescriptor() {\n return { enumerable: true, configurable: true };\n },\n });\n}\n\nfunction readGlobal(name) {\n if (name === '__FF_CONFIG__' && typeof __FF_CONFIG__ !== 'undefined') {\n return __FF_CONFIG__;\n }\n if (name === '__FF_ICONS__' && typeof __FF_ICONS__ !== 'undefined') {\n return __FF_ICONS__;\n }\n if (typeof globalThis !== 'undefined' && globalThis[name]) {\n return globalThis[name];\n }\n if (isBrowser && window[name]) {\n return window[name];\n }\n return null;\n}\n\nfunction isPlainObject(value) {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction mergeConfigTrees(left, right) {\n if (!isPlainObject(left) || !isPlainObject(right)) return right === undefined ? left : right;\n const result = { ...left };\n for (const [key, value] of Object.entries(right)) {\n result[key] = key in result ? mergeConfigTrees(result[key], value) : value;\n }\n return result;\n}\n\nfunction findTreeConflicts(left, right, path = [], conflicts = []) {\n if (left === undefined || right === undefined) return conflicts;\n if (!isPlainObject(left) || !isPlainObject(right)) {\n conflicts.push(path.join('.'));\n return conflicts;\n }\n for (const key of Object.keys(left)) {\n if (key in right) findTreeConflicts(left[key], right[key], [...path, key], conflicts);\n }\n return conflicts;\n}\n\nfunction normalizeV4Component(envelope, path = []) {\n if (!isPlainObject(envelope) || !('styles' in envelope || 'behavior' in envelope)) {\n return envelope;\n }\n const conflicts = findTreeConflicts(envelope.styles, envelope.behavior, path);\n if (conflicts.length > 0) {\n throw new Error(`Component config styles/behavior conflict at ${conflicts.join(', ')}`);\n }\n return mergeConfigTrees(envelope.styles || {}, envelope.behavior || {});\n}\n\nfunction normalizeV4Config(config) {\n let changed = false;\n const result = {};\n for (const [name, envelope] of Object.entries(config)) {\n result[name] = normalizeV4Component(envelope, [name]);\n if (result[name] !== envelope) changed = true;\n }\n return changed ? result : config;\n}\n\nexport function ffdc(config) {\n if (!config || typeof config !== 'object') {\n return createDeepProxy();\n }\n return normalizeV4Config(config);\n}\n\nexport const config = new Proxy({}, {\n get(target, prop) {\n if (prop === Symbol.toPrimitive || prop === 'valueOf') return () => '';\n if (prop === 'toString' || prop === Symbol.toStringTag) return () => '[object Object]';\n if (prop === 'constructor') return Object;\n\n const currentConfig = readGlobal('__FF_CONFIG__');\n if (currentConfig && prop in currentConfig) {\n return normalizeV4Component(currentConfig[prop], [String(prop)]);\n }\n return createDeepProxy();\n },\n has() {\n return true;\n },\n ownKeys() {\n return [];\n },\n getOwnPropertyDescriptor() {\n return { enumerable: true, configurable: true };\n },\n});\n\n// Unlike `config` (whose values feed class strings, where an empty-ish deep\n// proxy is a safe placeholder), iconSet values are icon NAMES the components\n// look up in an icon library \u2014 a truthy proxy placeholder would defeat their\n// `iconSet?.x?.y ?? fallback` chains. Mirror runtime.js: null for misses.\nexport const iconSet = new Proxy({}, {\n get(target, prop) {\n if (prop === Symbol.toPrimitive || prop === 'valueOf') return () => '';\n if (prop === 'toString' || prop === Symbol.toStringTag) return () => '[object Object]';\n if (prop === 'constructor') return Object;\n\n const icons = readGlobal('__FF_ICONS__');\n if (icons && prop in icons) {\n return icons[prop];\n }\n return null;\n },\n has(target, prop) {\n const icons = readGlobal('__FF_ICONS__');\n return icons ? prop in icons : false;\n },\n ownKeys() {\n const icons = readGlobal('__FF_ICONS__');\n return icons ? Object.keys(icons) : [];\n },\n getOwnPropertyDescriptor(target, prop) {\n const icons = readGlobal('__FF_ICONS__');\n if (icons && prop in icons) {\n return { enumerable: true, configurable: true, value: icons[prop] };\n }\n return undefined;\n },\n});\n\nexport const componentsConfigSchema = {};\n\nexport function isCSSClassString(value) {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nexport default function frontfriend() {\n return {};\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["isBrowser", "createDeepProxy", "fallbackValue", "cache", "target", "prop", "readGlobal", "name", "isPlainObject", "value", "mergeConfigTrees", "left", "right", "result", "key", "findTreeConflicts", "path", "conflicts", "normalizeV4Component", "envelope", "normalizeV4Config", "config", "changed", "ffdc", "currentConfig", "iconSet", "icons", "componentsConfigSchema", "isCSSClassString", "frontfriend"]
7
7
  }
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- var L=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var O=L((jn,ee)=>{var Ee="https://app.dev.frontfriend.dev",Le="https://registry-legacy.frontfriend.dev",Ae=".cache/frontfriend",Pe={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"]},De={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};ee.exports={DEFAULT_API_URL:Ee,LEGACY_API_URL:Le,CACHE_DIR_NAME:Ae,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:Pe,ENV_VARS:De}});var fe=L((kn,le)=>{var b=require("fs"),ne=require("path"),Re=require("os"),Ue=require("https"),Oe=require("http"),{URL:Ne}=require("url"),{DEFAULT_API_URL:oe}=O(),te=ne.join(Re.homedir(),".frontfriend"),T=ne.join(te,"credentials");function qe(){return T}function se(){try{return b.existsSync(T)?JSON.parse(b.readFileSync(T,"utf8")):null}catch{return null}}function re(e){b.mkdirSync(te,{recursive:!0,mode:448}),b.writeFileSync(T,`${JSON.stringify(e,null,2)}
3
- `,{mode:384});try{b.chmodSync(T,384)}catch{}}function Me(){return b.existsSync(T)?(b.unlinkSync(T),!0):!1}function ie(e,n=60*1e3){return!(e!=null&&e.accessToken)||!e.expiresAt||Date.now()+n>=e.expiresAt}function D(e){let n=new Error(`${e}. Run \`frontfriend login\` to re-authenticate.`);return n.code="FF_AUTH_REFRESH_FAILED",n}function ce(e,n,o){return new Promise((t,s)=>{let r=new Ne(e),i=r.protocol==="https:"?Ue:Oe,f=JSON.stringify(n||{}),c=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}`}:{}}},l=>{let u="";l.on("data",g=>{u+=g}),l.on("end",()=>{if(l.statusCode>=300&&l.statusCode<400){let p=l.headers.location?` to ${l.headers.location}`:"",m=new Error(`HTTP ${l.statusCode}: redirected${p}`);m.statusCode=l.statusCode,m.body=u,s(m);return}let g=null;try{g=u?JSON.parse(u):null}catch{let m=l.headers["content-type"]||"unknown content-type",y=new Error(`Expected JSON from FrontFriend API at ${e}, but received ${m} (HTTP ${l.statusCode}). Check FF_API_URL or pass --api-url with the FrontFriend app URL.`);if(y.statusCode=l.statusCode,y.body=u,l.statusCode>=400){s(y);return}s(y);return}if(l.statusCode>=400){let p=new Error((g==null?void 0:g.error_description)||(g==null?void 0:g.error)||`HTTP ${l.statusCode}`);p.statusCode=l.statusCode,p.body=g,s(p);return}t(g)})});c.on("error",s),c.write(f),c.end()})}async function ae(e,n=oe){if(!(e!=null&&e.refreshToken)||!(e!=null&&e.deviceId))throw D("FrontFriend session expired");let o;try{o=await ce(`${n}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:e.refreshToken,device_id:e.deviceId})}catch(s){throw D((s==null?void 0:s.message)||"Could not refresh FrontFriend session")}if(!(o!=null&&o.access_token)||!(o!=null&&o.refresh_token))throw D("Could not refresh FrontFriend session");let 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 re(t),t}async function Ve(e={}){if(!e.skipCredentials){let n=se();if(n!=null&&n.accessToken||n!=null&&n.refreshToken){let o=e.baseURL||n.ffApiUrl||oe;return n.accessToken&&!ie(n)?n.accessToken:(await ae(n,o)).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}le.exports={getCredentialsPath:qe,readCredentials:se,writeCredentials:re,deleteCredentials:Me,isExpired:ie,postJson:ce,refreshCredentials:ae,resolveAuthToken:Ve,createAuthRefreshError:D}});var ue=L(($n,de)=>{var N={lucide:["lucide-react"],tabler:["@tabler/icons-react"],hugeicons:["@hugeicons/react","@hugeicons/core-free-icons"],phosphor:["@phosphor-icons/react"],remixicon:["@remixicon/react"]};function Je(e,n){let o=e&&e.iconLibrary||n||"lucide";return N[o]?o:"lucide"}function Ge(e,n){return typeof e!="string"?e:e.replace(/(from\s+["']\.\/adapters\/)[a-z]+(["'])/,`$1${n}$2`)}function He(e,n){return(e||[]).filter(o=>{let t=String(o).replace(/\.(tsx|ts|jsx|js)$/,"");return!!N[t]&&t!==n})}de.exports={ICON_LIBRARY_DEPS:N,resolveIconLibraryName:Je,swapIconAdapterImport:Ge,adapterFilesToPrune:He}});var ge=L((bn,Be)=>{Be.exports={name:"@frontfriend/tailwind",version:"4.0.18",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","tw-animate-css":"^1.3.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 M=L((Tn,q)=>{var x=require("fs"),A=require("path");function pe(e={}){let n=e.projectRoot||process.cwd(),o=A.join(n,"node_modules",".cache","frontfriend","icons.json"),t=e.outputPath||A.join(n,"types","frontfriend.d.ts");x.existsSync(o)||(console.error('[FrontFriend] Error: icons.json not found. Please run "npx frontfriend init" first.'),process.exit(1));try{let c=function(y){for(let w of Object.values(y))typeof w=="string"?f.add(w):typeof w=="object"&&w!==null&&c(w)},l=function(y,w=" "){let j=[];for(let[k,$]of Object.entries(y))typeof $=="string"?j.push(`${w}${k}: '${$}';`):typeof $=="object"&&$!==null&&(j.push(`${w}${k}: {`),j.push(l($,w+" ")),j.push(`${w}};`));return j.join(`
4
- `)};var s=c,r=l;let i=JSON.parse(x.readFileSync(o,"utf-8")),f=new Set;c(i);let u=Array.from(f).map(y=>`'${y}'`).join(" | "),g=`// Generated by @frontfriend/tailwind
2
+ var L=(e,o)=>()=>(o||e((o={exports:{}}).exports,o),o.exports);var M=L((_o,ee)=>{var Pe="https://app.dev.frontfriend.dev",Re="https://registry-legacy.frontfriend.dev",De=".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","versionMetadata.json","metadata.json"]},Oe={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};function Ne(e){if(!e)return null;try{let o=new URL(e);return o.hostname.startsWith("app.")?`${o.protocol}//${o.hostname.replace(/^app\./,"registry.")}`:null}catch{return null}}ee.exports={DEFAULT_API_URL:Pe,LEGACY_API_URL:Re,CACHE_DIR_NAME:De,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:Ue,ENV_VARS:Oe,deriveRegistryFromApiUrl:Ne}});var fe=L((Lo,le)=>{var $=require("fs"),oe=require("path"),qe=require("os"),Me=require("https"),Ve=require("http"),{URL:Je}=require("url"),{DEFAULT_API_URL:ne}=M(),te=oe.join(qe.homedir(),".frontfriend"),b=oe.join(te,"credentials");function Be(){return b}function se(){try{return $.existsSync(b)?JSON.parse($.readFileSync(b,"utf8")):null}catch{return null}}function re(e){$.mkdirSync(te,{recursive:!0,mode:448}),$.writeFileSync(b,`${JSON.stringify(e,null,2)}
3
+ `,{mode:384});try{$.chmodSync(b,384)}catch{}}function Ge(){return $.existsSync(b)?($.unlinkSync(b),!0):!1}function ie(e,o=60*1e3){return!(e!=null&&e.accessToken)||!e.expiresAt||Date.now()+o>=e.expiresAt}function R(e){let o=new Error(`${e}. Run \`frontfriend login\` to re-authenticate.`);return o.code="FF_AUTH_REFRESH_FAILED",o}function ce(e,o,n){return new Promise((t,s)=>{let i=new Je(e),r=i.protocol==="https:"?Me:Ve,c=JSON.stringify(o||{}),a=r.request({hostname:i.hostname,port:i.port,path:`${i.pathname}${i.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(c),...n?{authorization:`Bearer ${n}`}:{}}},f=>{let u="";f.on("data",g=>{u+=g}),f.on("end",()=>{if(f.statusCode>=300&&f.statusCode<400){let h=f.headers.location?` to ${f.headers.location}`:"",p=new Error(`HTTP ${f.statusCode}: redirected${h}`);p.statusCode=f.statusCode,p.body=u,s(p);return}let g=null;try{g=u?JSON.parse(u):null}catch{let p=f.headers["content-type"]||"unknown content-type",m=new Error(`Expected JSON from FrontFriend API at ${e}, but received ${p} (HTTP ${f.statusCode}). Check FF_API_URL or pass --api-url with the FrontFriend app URL.`);if(m.statusCode=f.statusCode,m.body=u,f.statusCode>=400){s(m);return}s(m);return}if(f.statusCode>=400){let h=new Error((g==null?void 0:g.error_description)||(g==null?void 0:g.error)||`HTTP ${f.statusCode}`);h.statusCode=f.statusCode,h.body=g,s(h);return}t(g)})});a.on("error",s),a.write(c),a.end()})}async function ae(e,o=ne){if(!(e!=null&&e.refreshToken)||!(e!=null&&e.deviceId))throw R("FrontFriend session expired");let n;try{n=await ce(`${o}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:e.refreshToken,device_id:e.deviceId})}catch(s){throw R((s==null?void 0:s.message)||"Could not refresh FrontFriend session")}if(!(n!=null&&n.access_token)||!(n!=null&&n.refresh_token))throw R("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 re(t),t}async function He(e={}){if(!e.skipCredentials){let o=se();if(o!=null&&o.accessToken||o!=null&&o.refreshToken){let n=e.baseURL||o.ffApiUrl||ne;return o.accessToken&&!ie(o)?o.accessToken:(await ae(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}le.exports={getCredentialsPath:Be,readCredentials:se,writeCredentials:re,deleteCredentials:Ge,isExpired:ie,postJson:ce,refreshCredentials:ae,resolveAuthToken:He,createAuthRefreshError:R}});var ue=L((Eo,de)=>{var V={lucide:["lucide-react"],tabler:["@tabler/icons-react"],hugeicons:["@hugeicons/react","@hugeicons/core-free-icons"],phosphor:["@phosphor-icons/react"],remixicon:["@remixicon/react"]};function Ye(e,o){let n=e&&e.iconLibrary||o||"lucide";return V[n]?n:"lucide"}function Ke(e,o){return typeof e!="string"?e:e.replace(/(from\s+["']\.\/adapters\/)[a-z]+(["'])/,`$1${o}$2`)}function We(e,o){return(e||[]).filter(n=>{let t=String(n).replace(/\.(tsx|ts|jsx|js)$/,"");return!!V[t]&&t!==o})}de.exports={ICON_LIBRARY_DEPS:V,resolveIconLibraryName:Ye,swapIconAdapterImport:Ke,adapterFilesToPrune:We}});var ge=L((Ao,ze)=>{ze.exports={name:"@frontfriend/tailwind",version:"4.0.21",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"},"./component-recipes":{types:"./dist/component-recipes.d.ts",require:"./dist/lib/core/component-recipes.js",import:"./dist/lib/core/component-recipes.js",default:"./dist/lib/core/component-recipes.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","tw-animate-css":"^1.3.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 B=L((Po,J)=>{var j=require("fs"),E=require("path");function pe(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");j.existsSync(n)||(console.error('[FrontFriend] Error: icons.json not found. Please run "npx frontfriend init" first.'),process.exit(1));try{let a=function(m){for(let w of Object.values(m))typeof w=="string"?c.add(w):typeof w=="object"&&w!==null&&a(w)},f=function(m,w=" "){let k=[];for(let[P,F]of Object.entries(m))typeof F=="string"?k.push(`${w}${P}: '${F}';`):typeof F=="object"&&F!==null&&(k.push(`${w}${P}: {`),k.push(f(F,w+" ")),k.push(`${w}};`));return k.join(`
4
+ `)};var s=a,i=f;let r=JSON.parse(j.readFileSync(n,"utf-8")),c=new Set;a(r);let u=Array.from(c).map(m=>`'${m}'`).join(" | "),g=`// 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
- ${l(i)}
15
+ ${f(r)}
16
16
  }
17
17
  }
18
18
 
@@ -36,48 +36,49 @@ declare module '@/src/components/ui/icon' {
36
36
  declare module '@/src/components/ui/icon/Icon.vue' {
37
37
  export type IconName = ${u||"string"};
38
38
  }
39
- `,p=A.dirname(t);x.existsSync(p)||x.mkdirSync(p,{recursive:!0}),x.writeFileSync(t,g),console.log("[FrontFriend] \u2713 Generated types at",A.relative(n,t));let m=A.join(n,"tsconfig.json");if(x.existsSync(m)){let y=JSON.parse(x.readFileSync(m,"utf-8"));y.include||(y.include=[]);let w="types/**/*.d.ts";y.include.includes(w)||(y.include.push(w),x.writeFileSync(m,JSON.stringify(y,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===q&&pe();q.exports={generateIconTypes:pe}});var{loadEnvLocal:Ye}=require("./lib/core/env-utils");Ye();var{Command:We}=require("commander"),_=require("./lib/core/config-loader"),R=require("./lib/core/cache-manager"),{APIClient:G}=require("./lib/core/api-client"),{getCredentialsPath:Ke,writeCredentials:ze,readCredentials:Xe,deleteCredentials:Ze,postJson:V}=fe(),{ComponentDownloader:Qe}=require("./lib/core/component-downloader"),en=require("./lib/core/token-processor"),{ICON_LIBRARY_DEPS:ye,resolveIconLibraryName:nn,swapIconAdapterImport:on,adapterFilesToPrune:tn}=ue(),{DEFAULT_API_URL:J}=O(),{ConfigError:C,APIError:H,CacheError:B}=require("./lib/core/errors"),a=require("path"),d=require("fs"),{spawn:sn}=require("child_process"),v=new We,{version:we}=ge(),rn="https://registry.frontfriend.dev/r/v4",me='@import "@frontfriend/tailwind/theme.css";',Se=["app/globals.css","src/app/globals.css","styles/globals.css","src/styles/globals.css","src/styles.css","src/index.css","src/style.css"];function cn(e){let n=(e||process.env.FF_REGISTRY_URL||rn).replace(/\/+$/,"");return/\/r\/(legacy|v4)$/i.test(n)?n:`${n}/r/v4`}function F(e){try{return JSON.parse(d.readFileSync(e,"utf8"))}catch{return null}}function U(e,n){d.mkdirSync(a.dirname(e),{recursive:!0}),d.writeFileSync(e,`${JSON.stringify(n,null,2)}
40
- `)}var ve=a.join("node_modules",".cache","frontfriend","migrated-components.json");function Y(e){let n=F(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.vue||o["@vitejs/plugin-vue"]||o.nuxt?"vue":"react"}function an(e){let n=F(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 ln(e,n,o){let t=a.join(e,"components.json");if(!d.existsSync(t))return!1;let s=F(t)||{};s.registries=s.registries||{};let r=`${cn(o)}/${n}/{name}.json`,i=ye[s.iconLibrary]?s.iconLibrary:void 0,f=i&&i!=="lucide"?{url:r,params:{iconLibrary:i}}:r;return JSON.stringify(s.registries["@frontfriend"])===JSON.stringify(f)?!1:(s.registries["@frontfriend"]=f,U(t,s),!0)}function fn(e){let n=a.join(e,"package.json"),o=F(n);return o?(o.dependencies=o.dependencies||{},o.dependencies["@frontfriend/tailwind"]?!1:(o.dependencies["@frontfriend/tailwind"]="^4.0.0",U(n,o),!0)):!1}function dn(e){let n=["next.config.js","next.config.mjs","next.config.ts"].map(o=>a.join(e,o)).find(o=>d.existsSync(o));return n?d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/next")?"present":"manual":(d.writeFileSync(a.join(e,"next.config.js"),`const frontfriend = require('@frontfriend/tailwind/next');
39
+ `,h=E.dirname(t);j.existsSync(h)||j.mkdirSync(h,{recursive:!0}),j.writeFileSync(t,g),console.log("[FrontFriend] \u2713 Generated types at",E.relative(o,t));let p=E.join(o,"tsconfig.json");if(j.existsSync(p)){let m=JSON.parse(j.readFileSync(p,"utf-8"));m.include||(m.include=[]);let w="types/**/*.d.ts";m.include.includes(w)||(m.include.push(w),j.writeFileSync(p,JSON.stringify(m,null,2)),console.log("[FrontFriend] \u2713 Updated tsconfig.json to include generated types"))}}catch(r){console.error("[FrontFriend] Error generating icon types:",r.message),process.exit(1)}}require.main===J&&pe();J.exports={generateIconTypes:pe}});var{loadEnvLocal:Xe}=require("./lib/core/env-utils");Xe();var{Command:Ze}=require("commander"),T=require("./lib/core/config-loader"),D=require("./lib/core/cache-manager"),{assertComponentsConfig:me,loadCachedComponents:Qe,SAAS_ERROR_MESSAGE:he}=require("./lib/core/cached-components-config"),{APIClient:U}=require("./lib/core/api-client"),{getCredentialsPath:eo,writeCredentials:oo,readCredentials:no,deleteCredentials:to,postJson:G}=fe(),{ComponentDownloader:so}=require("./lib/core/component-downloader"),ro=require("./lib/core/token-processor"),{ICON_LIBRARY_DEPS:ve,resolveIconLibraryName:io,swapIconAdapterImport:co,adapterFilesToPrune:ao}=ue(),{DEFAULT_API_URL:H,deriveRegistryFromApiUrl:lo}=M(),{ConfigError:C,APIError:O,CacheError:Y}=require("./lib/core/errors"),l=require("path"),d=require("fs"),{spawn:fo}=require("child_process"),S=new Ze,{version:Ce}=ge(),uo="https://registry.frontfriend.dev/r/v4",ye='@import "@frontfriend/tailwind/theme.css";',Se=["app/globals.css","src/app/globals.css","styles/globals.css","src/styles/globals.css","src/styles.css","src/index.css","src/style.css"];function go(e,o){let n=(e||process.env.FF_REGISTRY_URL||lo(o)||uo).replace(/\/+$/,"");return/\/r\/(legacy|v4)$/i.test(n)?n:`${n}/r/v4`}function x(e){try{return JSON.parse(d.readFileSync(e,"utf8"))}catch{return null}}function N(e,o){d.mkdirSync(l.dirname(e),{recursive:!0}),d.writeFileSync(e,`${JSON.stringify(o,null,2)}
40
+ `)}var Fe=l.join("node_modules",".cache","frontfriend","migrated-components.json");function q(e){let o=x(l.join(e,"package.json"))||{},n={...o.dependencies||{},...o.devDependencies||{}};return n.vue||n["@vitejs/plugin-vue"]||n.nuxt?"vue":"react"}function po(e){let o=x(l.join(e,"package.json"))||{},n={...o.dependencies||{},...o.devDependencies||{}};return n.next||d.existsSync(l.join(e,"next.config.js"))||d.existsSync(l.join(e,"next.config.mjs"))?"next":n.vite||d.existsSync(l.join(e,"vite.config.ts"))||d.existsSync(l.join(e,"vite.config.js"))?"vite":null}function mo(e,o,n,t){let s=l.join(e,"components.json");if(!d.existsSync(s))return!1;let i=x(s)||{};i.registries=i.registries||{};let r=`${go(n,t)}/${o}/{name}.json`,c=ve[i.iconLibrary]?i.iconLibrary:void 0,a=c&&c!=="lucide"?{url:r,params:{iconLibrary:c}}:r;return JSON.stringify(i.registries["@frontfriend"])===JSON.stringify(a)?!1:(i.registries["@frontfriend"]=a,N(s,i),!0)}function ho(e){let o=l.join(e,"package.json"),n=x(o);return n?(n.dependencies=n.dependencies||{},n.dependencies["@frontfriend/tailwind"]?!1:(n.dependencies["@frontfriend/tailwind"]="^4.0.0",N(o,n),!0)):!1}function yo(e){let o=["next.config.js","next.config.mjs","next.config.ts"].map(n=>l.join(e,n)).find(n=>d.existsSync(n));return o?d.readFileSync(o,"utf8").includes("@frontfriend/tailwind/next")?"present":"manual":(d.writeFileSync(l.join(e,"next.config.js"),`const frontfriend = require('@frontfriend/tailwind/next');
41
41
 
42
42
  module.exports = frontfriend({});
43
- `),"created")}function un(e){let n=["vite.config.ts","vite.config.js","vite.config.mjs"].map(o=>a.join(e,o)).find(o=>d.existsSync(o));return n?d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/vite")?"present":"manual":(d.writeFileSync(a.join(e,"vite.config.ts"),`import { defineConfig } from 'vite';
43
+ `),"created")}function wo(e){let o=["vite.config.ts","vite.config.js","vite.config.mjs"].map(n=>l.join(e,n)).find(n=>d.existsSync(n));return o?d.readFileSync(o,"utf8").includes("@frontfriend/tailwind/vite")?"present":"manual":(d.writeFileSync(l.join(e,"vite.config.ts"),`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
- `),"created")}function Ce(e){let n=Se.find(o=>d.existsSync(a.join(e,o)));return n?a.join(e,n):null}function gn(e){let o=Se.find(s=>d.existsSync(a.join(e,s)))||"app/globals.css",t=a.join(e,o);return d.mkdirSync(a.dirname(t),{recursive:!0}),d.existsSync(t)||d.writeFileSync(t,""),{fullPath:t,relativePath:o}}function pn(e){let{fullPath:n,relativePath:o}=gn(e),t=d.readFileSync(n,"utf8");return t.includes(me)?{changed:!1,relativePath:o}:(d.writeFileSync(n,`${me}
50
- ${t}`),{changed:!0,relativePath:o})}function mn(e,n={}){let o=a.join(e,"components.json");if(!d.existsSync(o))return{isShadcnProject:!1,changes:[]};let t=Y(e),s=an(e),r=[],i=[];if(ln(e,t,n.registryUrl)&&r.push(`registered @frontfriend registry for ${t}`),fn(e)&&r.push("added @frontfriend/tailwind dependency"),s==="next"){let c=dn(e);c==="created"&&r.push("created next.config.js with the FrontFriend plugin"),c==="manual"&&i.push('wrap your existing next.config with `require("@frontfriend/tailwind/next")(...)`')}if(s==="vite"){let c=un(e);c==="created"&&r.push("created vite.config.ts with the FrontFriend plugin"),c==="manual"&&i.push("add `frontfriend()` from `@frontfriend/tailwind/vite` to your existing vite.config plugins array")}let f=pn(e);return f.changed&&r.push(`imported bundled theme in ${f.relativePath}`),{isShadcnProject:!0,changes:r,manualSteps:i,framework:t,buildTool:s}}function hn(e){return new Promise(n=>setTimeout(n,e))}function yn(e){let n=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",o=process.platform==="win32"?["/c","start","",e]:[e];try{return sn(n,o,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function wn(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}`)),e.manualSteps&&e.manualSteps.length>0&&(console.log(" \u26A0 Manual steps required (existing config left untouched):"),e.manualSteps.forEach(n=>console.log(` \u2022 ${n}`))),console.log(` Next: npx shadcn add @frontfriend/button
51
- `))}function P(e){return a.basename(e).replace(/\.(tsx|ts|jsx|js|vue)$/,"").replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[_\s]+/g,"-").toLowerCase()}var Fe=["tsx","ts","jsx","js","vue"],W=/\.(tsx|ts|jsx|js|vue)$/;function Sn(e){let n={};for(let o of["tsconfig.json","tsconfig.app.json","jsconfig.json"]){let t=F(a.join(e,o)),s=t&&t.compilerOptions&&t.compilerOptions.paths;s&&Object.assign(n,s)}return n}function vn(e,n){if(!n)return null;let o=Sn(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 xe(e){let n=F(a.join(e,"components.json")),o=n&&n.aliases&&n.aliases.ui,t=[o?vn(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 je(e,n){let o=F(a.join(e,"components.json")),t=nn(o,n),s=xe(e).flatMap(g=>[a.join(g,"icon","index.tsx"),a.join(g,"icon","Icon.vue")]).find(g=>d.existsSync(g));if(!s)return{changed:!1,iconLibrary:t};let r=d.readFileSync(s,"utf8"),i=on(r,t),f=i!==r;f&&d.writeFileSync(s,i);let c=a.join(a.dirname(s),"adapters");if(d.existsSync(c))for(let g of tn(d.readdirSync(c),t))d.rmSync(a.join(c,g),{force:!0}),f=!0;let l=a.join(e,"package.json"),u=F(l);if(u){u.dependencies=u.dependencies||{};let g=!1;for(let p of ye[t])u.dependencies[p]||(u.dependencies[p]="latest",g=!0);g&&U(l,u)}return{changed:f,iconLibrary:t}}function Cn(e,n){for(let t of Fe){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=>W.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 he(e,n,o){for(let r of Fe){let i=a.join(e,`${n}.${r}`);if(d.existsSync(i))return{inputPath:i,source:d.readFileSync(i,"utf8")}}let t=a.join(e,n);if(!d.existsSync(t)||!d.statSync(t).isDirectory())return null;if(o==="vue"){let r=d.readdirSync(t).filter(l=>W.test(l)).sort(),i=r.filter(l=>/^index\.(tsx?|jsx?)$/i.test(l)),f=r.filter(l=>/\.vue$/i.test(l)),c=[...i,...f];if(c.length>0){let l=c.map(g=>d.readFileSync(a.join(t,g),"utf8")).join(`
52
- `),u=f.find(g=>g.toLowerCase().startsWith(`${n.toLowerCase()}.`))||f[0]||i[0];return{inputPath:a.join(t,u),source:l}}}let s=Cn(e,n);return s?{inputPath:s,source:d.readFileSync(s,"utf8")}:null}function ke(e,n,o){let t=xe(e);if(n&&n!=="all"){for(let i of t){let f=he(i,n,o);if(f)return[{component:n,...f}]}return[]}let s=new Set,r=[];for(let i of t)for(let f of d.readdirSync(i,{withFileTypes:!0})){let c=null;if((f.isFile()&&W.test(f.name)&&!/^index\./i.test(f.name)||f.isDirectory())&&(c=P(f.name)),!c)continue;let l=c.toLowerCase();if(s.has(l))continue;let u=he(i,c,o);u&&(s.add(l),r.push({component:c,...u}))}return r}v.name("frontfriend").description("FrontFriend Tailwind CLI - Manage design tokens and cache").version(we);v.command("login").description("Authenticate FrontFriend CLI with an 8-digit device code").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||J).option("--no-open","Do not open the browser automatically").action(async e=>{try{let n=e.apiUrl.replace(/\/$/,""),o=await V(`${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(`====================
53
- `),console.log(`Go to ${o.verification_uri} and enter the code:`),console.log(`
54
- ${o.user_code}
55
- `),e.open!==!1&&yn(o.verification_uri)&&console.log("Opened the browser for you."),console.log(`Waiting for approval...
56
- `);Date.now()<s;){await hn(t*1e3);let r=await V(`${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"}`);if(!r.access_token||!r.refresh_token||!r.device_id)throw new Error("Invalid login response from FrontFriend. Run `frontfriend login` again.");ze({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 ${Ke()}`),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)}});v.command("logout").description("Remove FrontFriend CLI credentials").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||J).action(async e=>{let n=Xe(),o=(e.apiUrl||(n==null?void 0:n.ffApiUrl)||J).replace(/\/$/,"");if(n!=null&&n.accessToken&&(n!=null&&n.deviceId))try{await V(`${o}/api/plugin/logout`,{device_id:n.deviceId},n.accessToken)}catch{}let t=Ze();console.log(t?"\u2705 Logged out. Credentials removed.":"\u2139\uFE0F No stored credentials found."),process.exit(0)});v.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(`==================
57
- `);let t=await new _().load(),s=d.existsSync(a.join(t.appRoot,"components.json")),r=a.join(t.appRoot,ve);s&&!d.existsSync(r)&&!e.force&&(console.log("\u{1F6D1} shadcn project detected (components.json) that has not been migrated yet."),console.log(""),console.log(" Run `npx frontfriend migrate` first: it reads your components' classes and"),console.log(" pushes them to your design system, so FrontFriend components keep your app's look."),console.log(""),console.log(" Or run `npx frontfriend init --force` to skip this and use the design system's styling."),process.exit(1));let i=mn(t.appRoot,{registryUrl:e.registryUrl});if(wn(i),!t.ffId)throw i.isShadcnProject&&(console.log("\u2705 Local FrontFriend wiring complete!"),console.log(' Add frontfriend.config.js with "ff-id" later to fetch cloud design tokens.'),process.exit(0)),new C(`ff-id not found in frontfriend.config.js
58
- Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let f=e.tag||t.tag,c=e.version||t.version;console.log("\u{1F4CB} Configuration loaded"),console.log(` FF_ID: ${t.ffId}`),console.log(` App Root: ${t.appRoot}`),f&&console.log(` Tag: ${f}`),c&&console.log(` Version: ${c}`),console.log("");let l=new R(t.appRoot);!e.force&&l.exists()&&l.isValid()&&!l.isLocalOnly()&&(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
59
- `):l.exists()?l.isLocalOnly()?console.log(` Local migrate cache found \u2014 fetching the design system
49
+ `),"created")}function xe(e){let o=Se.find(n=>d.existsSync(l.join(e,n)));return o?l.join(e,o):null}function vo(e){let n=Se.find(s=>d.existsSync(l.join(e,s)))||"app/globals.css",t=l.join(e,n);return d.mkdirSync(l.dirname(t),{recursive:!0}),d.existsSync(t)||d.writeFileSync(t,""),{fullPath:t,relativePath:n}}function Co(e){let{fullPath:o,relativePath:n}=vo(e),t=d.readFileSync(o,"utf8");return t.includes(ye)?{changed:!1,relativePath:n}:(d.writeFileSync(o,`${ye}
50
+ ${t}`),{changed:!0,relativePath:n})}function So(e,o={}){let n=l.join(e,"components.json");if(!d.existsSync(n))return{isShadcnProject:!1,changes:[]};let t=q(e),s=po(e),i=[],r=[];if(mo(e,t,o.registryUrl,o.apiUrl)&&i.push(`registered @frontfriend registry for ${t}`),ho(e)&&i.push("added @frontfriend/tailwind dependency"),o.enableRuntime!==!1){if(s==="next"){let a=yo(e);a==="created"&&i.push("created next.config.js with the FrontFriend plugin"),a==="manual"&&r.push('wrap your existing next.config with `require("@frontfriend/tailwind/next")(...)`')}if(s==="vite"){let a=wo(e);a==="created"&&i.push("created vite.config.ts with the FrontFriend plugin"),a==="manual"&&r.push("add `frontfriend()` from `@frontfriend/tailwind/vite` to your existing vite.config plugins array")}let c=Co(e);c.changed&&i.push(`imported the FrontFriend cache theme in ${c.relativePath}`)}return{isShadcnProject:!0,changes:i,manualSteps:r,framework:t,buildTool:s}}function Fo(e){return new Promise(o=>setTimeout(o,e))}function xo(e){let o=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];try{return fo(o,n,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function jo(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}`)),e.manualSteps&&e.manualSteps.length>0&&(console.log(" \u26A0 Manual steps required (existing config left untouched):"),e.manualSteps.forEach(o=>console.log(` \u2022 ${o}`))),console.log(` Next: npx shadcn add @frontfriend/button
51
+ `))}function A(e){return l.basename(e).replace(/\.(tsx|ts|jsx|js|vue)$/,"").replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[_\s]+/g,"-").toLowerCase()}var je=["tsx","ts","jsx","js","vue"],K=/\.(tsx|ts|jsx|js|vue)$/;function ko(e){let o={};for(let n of["tsconfig.json","tsconfig.app.json","jsconfig.json"]){let t=x(l.join(e,n)),s=t&&t.compilerOptions&&t.compilerOptions.paths;s&&Object.assign(o,s)}return o}function $o(e,o){if(!o)return null;let n=ko(e);for(let[t,s]of Object.entries(n))if(!(!Array.isArray(s)||s.length===0)){if(t.endsWith("/*")){let i=t.slice(0,-1);if(o.startsWith(i)){let r=o.slice(i.length),c=s[0].replace(/\*+$/,"");return l.resolve(e,c,r)}}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 ke(e){let o=x(l.join(e,"components.json")),n=o&&o.aliases&&o.aliases.ui,t=[n?$o(e,n):null,l.join(e,"src","components","ui"),l.join(e,"components","ui")].filter(Boolean);return[...new Set(t)].filter(s=>d.existsSync(s))}function $e(e,o){let n=x(l.join(e,"components.json")),t=io(n,o),s=ke(e).flatMap(g=>[l.join(g,"icon","index.tsx"),l.join(g,"icon","Icon.vue")]).find(g=>d.existsSync(g));if(!s)return{changed:!1,iconLibrary:t};let i=d.readFileSync(s,"utf8"),r=co(i,t),c=r!==i;c&&d.writeFileSync(s,r);let a=l.join(l.dirname(s),"adapters");if(d.existsSync(a))for(let g of ao(d.readdirSync(a),t))d.rmSync(l.join(a,g),{force:!0}),c=!0;let f=l.join(e,"package.json"),u=x(f);if(u){u.dependencies=u.dependencies||{};let g=!1;for(let h of ve[t])u.dependencies[h]||(u.dependencies[h]="latest",g=!0);g&&N(f,u)}return{changed:c,iconLibrary:t}}function bo(e,o){for(let t of je){let s=l.join(e,`${o}.${t}`);if(d.existsSync(s))return s}let n=l.join(e,o);if(d.existsSync(n)&&d.statSync(n).isDirectory()){let t=d.readdirSync(n).filter(r=>K.test(r)),s=t.filter(r=>!/^index\./i.test(r)),i=s.find(r=>r.toLowerCase().startsWith(`${o.toLowerCase()}.`))||s[0]||t.find(r=>/^index\./i.test(r));if(i)return l.join(n,i)}return null}function we(e,o,n){for(let i of je){let r=l.join(e,`${o}.${i}`);if(d.existsSync(r))return{inputPath:r,source:d.readFileSync(r,"utf8")}}let t=l.join(e,o);if(!d.existsSync(t)||!d.statSync(t).isDirectory())return null;if(n==="vue"){let i=d.readdirSync(t).filter(f=>K.test(f)).sort(),r=i.filter(f=>/^index\.(tsx?|jsx?)$/i.test(f)),c=i.filter(f=>/\.vue$/i.test(f)),a=[...r,...c];if(a.length>0){let f=a.map(g=>d.readFileSync(l.join(t,g),"utf8")).join(`
52
+ `),u=c.find(g=>g.toLowerCase().startsWith(`${o.toLowerCase()}.`))||c[0]||r[0];return{inputPath:l.join(t,u),source:f}}}let s=bo(e,o);return s?{inputPath:s,source:d.readFileSync(s,"utf8")}:null}function be(e,o,n){let t=ke(e);if(o&&o!=="all"){for(let r of t){let c=we(r,o,n);if(c)return[{component:o,...c}]}return[]}let s=new Set,i=[];for(let r of t)for(let c of d.readdirSync(r,{withFileTypes:!0})){let a=null;if((c.isFile()&&K.test(c.name)&&!/^index\./i.test(c.name)||c.isDirectory())&&(a=A(c.name)),!a)continue;let f=a.toLowerCase();if(s.has(f))continue;let u=we(r,a,n);u&&(s.add(f),i.push({component:a,...u}))}return i}S.name("frontfriend").description("FrontFriend Tailwind CLI - Manage design tokens and cache").version(Ce);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||H).option("--no-open","Do not open the browser automatically").action(async e=>{var o,n;try{let t=e.apiUrl.replace(/\/$/,""),s=await G(`${t}/api/auth/device/start`,{}),i=s.interval||5,r=Date.now()+(s.expires_in||600)*1e3;for(console.log("\u{1F510} FrontFriend Login"),console.log(`====================
53
+ `),console.log(`Go to ${s.verification_uri} and enter the code:`),console.log(`
54
+ ${s.user_code}
55
+ `),e.open!==!1&&xo(s.verification_uri)&&console.log("Opened the browser for you."),console.log(`Waiting for approval...
56
+ `);Date.now()<r;){await Fo(i*1e3);let c;try{c=await G(`${t}/api/auth/device/poll`,{device_code:s.device_code})}catch(a){if(a.statusCode===429||((o=a.body)==null?void 0:o.error)==="slow_down"){i=((n=a.body)==null?void 0:n.interval)||i+5;continue}throw a}if(c.error!=="authorization_pending"){if(c.error==="slow_down"){i=c.interval||i+5;continue}if(c.error)throw new Error(`${c.error}: ${c.error_description||"Authentication failed"}`);if(!c.access_token||!c.refresh_token||!c.device_id)throw new Error("Invalid login response from FrontFriend. Run `frontfriend login` again.");oo({accessToken:c.access_token,refreshToken:c.refresh_token,deviceId:c.device_id,expiresAt:Date.now()+(c.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(c.refresh_expires_in||604800)*1e3,ffApiUrl:t}),console.log("\u2705 Login complete!"),console.log(` Credentials saved to ${eo()}`),process.exit(0)}}throw new Error("expired_token: the code has expired, run `frontfriend login` again.")}catch(t){console.error("\u274C Login failed:",t.message),process.exit(1)}});S.command("logout").description("Remove FrontFriend CLI credentials").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||H).action(async e=>{let o=no(),n=(e.apiUrl||(o==null?void 0:o.ffApiUrl)||H).replace(/\/$/,"");if(o!=null&&o.accessToken&&(o!=null&&o.deviceId))try{await G(`${n}/api/plugin/logout`,{device_id:o.deviceId},o.accessToken)}catch{}let t=to();console.log(t?"\u2705 Logged out. Credentials removed.":"\u2139\uFE0F No stored credentials found."),process.exit(0)});S.command("init").alias("sync").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(`==================
57
+ `);let t=await new T().load(),s=d.existsSync(l.join(t.appRoot,"components.json")),i=l.join(t.appRoot,Fe);s&&!d.existsSync(i)&&!e.force&&(console.log("\u{1F6D1} shadcn project detected (components.json) that has not been migrated yet."),console.log(""),console.log(" Run `npx frontfriend migrate` first: it reads your components' classes and"),console.log(" pushes them to your design system, so FrontFriend components keep your app's look."),console.log(""),console.log(" Or run `npx frontfriend init --force` to skip this and use the design system's styling."),process.exit(1));let r=So(t.appRoot,{registryUrl:e.registryUrl,apiUrl:t["api-url"]||t.apiUrl,enableRuntime:!!t.ffId});if(jo(r),!t.ffId)throw r.isShadcnProject&&(console.log("\u2705 Local FrontFriend wiring complete!"),console.log(' Add frontfriend.config.js with "ff-id" later to fetch cloud design tokens.'),process.exit(0)),new C(`ff-id not found in frontfriend.config.js
58
+ Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let c=e.tag||t.tag,a=e.version||t.version;console.log("\u{1F4CB} Configuration loaded"),console.log(` FF_ID: ${t.ffId}`),console.log(` App Root: ${t.appRoot}`),c&&console.log(` Tag: ${c}`),a&&console.log(` Version: ${a}`),console.log("");let f=new D(t.appRoot),u=!1;if(f.exists())try{Qe(f),u=!0}catch{}!e.force&&u&&f.isValid()&&!f.isLocalOnly()&&(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
59
+ `):f.exists()?u?f.isLocalOnly()?console.log(` Local migrate cache found \u2014 fetching the design system
60
60
  `):console.log(` Cache expired
61
+ `):console.log(` Cache is incomplete \u2014 refreshing it
61
62
  `):console.log(` No cache found
62
- `),console.log("\u{1F310} Fetching configuration...");let u=new G(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 en,p=null;try{p=await u.fetchProcessedTokens({tag:f,version:c,tailwindV4:g.useTailwindV4})}catch(h){console.log(` \u26A0\uFE0F Failed to fetch pre-processed tokens: ${h.message}`)}if(p){if(console.log(" \u2713 Pre-processed tokens fetched from server"),console.log(" \u2713 Skipping local processing"),p.versionMetadata){let h=p.versionMetadata;console.log(" \u2139\uFE0F Version Information:"),h.version&&console.log(` Version: ${h.version}`),h.tag&&console.log(` Tag: ${h.tag}`),h.cached!==void 0&&console.log(` From Cache: ${h.cached?"Yes":"No"}`)}if(console.log(""),(!((n=p.tokens)!=null&&n.fontFamily)||Object.keys(p.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"),p.globalTokens?console.log(` Global tokens are present - font processor may need to be updated
63
+ `),console.log("\u{1F310} Fetching configuration...");let g=new U(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 h=new ro,p=null;try{p=await g.fetchProcessedTokens({tag:c,version:a,tailwindV4:h.useTailwindV4})}catch(y){console.log(` \u26A0\uFE0F Failed to fetch pre-processed tokens: ${y.message}`)}if(p){if(me(p.componentsConfig,he),console.log(" \u2713 Pre-processed tokens fetched from server"),console.log(" \u2713 Skipping local processing"),p.versionMetadata){let y=p.versionMetadata;console.log(" \u2139\uFE0F Version Information:"),y.version&&console.log(` Version: ${y.version}`),y.tag&&console.log(` Tag: ${y.tag}`),y.cached!==void 0&&console.log(` From Cache: ${y.cached?"Yes":"No"}`)}if(console.log(""),(!((o=p.tokens)!=null&&o.fontFamily)||Object.keys(p.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"),p.globalTokens?console.log(` Global tokens are present - font processor may need to be updated
63
64
  `):console.log(` Consider adding font family tokens to your design system
64
- `)),g.useTailwindV4){let h=g.extractClassesFromComponentsConfig(p.componentsConfig),E=[...p.safelist||[],...h||[]];p.safelist=[...new Set(E)].sort(),p.themeCSS||(p.themeCSS=g.generateThemeCSS({variables:p.variables||{},semanticVariables:p.semanticVariables||{},semanticDarkVariables:p.semanticDarkVariables||{},fontFaces:p.fonts||[],keyframes:p.keyframes||{},animations:p.animations||{},custom:p.custom||{}})),p.classesContent||(p.classesContent=g.generateClassesContent(p.safelist))}if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&console.log(` Safelist has ${p.safelist?p.safelist.length:0} items`),l.save(p),console.log(` \u2713 Cache saved successfully
65
+ `)),h.useTailwindV4){let y=h.extractClassesFromComponentsConfig(p.componentsConfig),_=[...p.safelist||[],...y||[]];p.safelist=[...new Set(_)].sort(),p.themeCSS||(p.themeCSS=h.generateThemeCSS({variables:p.variables||{},semanticVariables:p.semanticVariables||{},semanticDarkVariables:p.semanticDarkVariables||{},fontFaces:p.fonts||[],keyframes:p.keyframes||{},animations:p.animations||{},custom:p.custom||{}})),p.classesContent||(p.classesContent=h.generateClassesContent(p.safelist))}if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&console.log(` Safelist has ${p.safelist?p.safelist.length:0} items`),f.save(p),console.log(` \u2713 Cache saved successfully
65
66
  `),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(`
66
- \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:h}=M(),E=t.aliases&&t.aliases.types?a.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;h({projectRoot:t.appRoot,outputPath:E})}catch(h){console.log(" \u26A0\uFE0F Type generation failed:",h.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
67
- `);let[m,y,w,j,k,$]=await Promise.all([u.fetchTokens(),u.fetchComponentsConfig(),u.fetchFonts(),u.fetchIcons(),u.fetchVersion(),u.fetchCustomCss()]),K=y;if(console.log(" \u2713 Tokens fetched"),m.global||m.colors||m.semantic||m.semanticDark){let h=[m.global?"global":null,m.colors?"colors":null,m.semantic?"semantic":null,m.semanticDark?"semanticDark":null].filter(Boolean).join(", ");console.log(` (Found: ${h})`)}console.log(" \u2713 Components config fetched"),console.log(" \u2713 Fonts fetched"),console.log(" \u2713 Icons fetched"),console.log(" \u2713 Version fetched"),console.log(` \u2713 Custom CSS fetched
68
- `),console.log("\u2699\uFE0F Processing tokens..."),console.log(" Processing raw token data...");let S=await g.process({colors:m.colors||m.global,semantic:m.semantic,semanticDark:m.semanticDark,fonts:w,globalTokens:m.global,animations:m.animations,version:k==null?void 0:k.version,ffId:t.ffId,customCss:$});console.log(" \u2713 Colors processed"),console.log(" \u2713 Semantic tokens processed"),S.fontFaces.length>0&&console.log(` \u2713 ${S.fontFaces.length} font faces processed`),Object.keys(S.animations).length>0&&console.log(` \u2713 ${Object.keys(S.animations).length} animations processed`),console.log(`
69
- `);let Ie=g.extractClassesFromComponentsConfig(K),_e=[...S.safelist||[],...Ie||[]],z=[...new Set(_e)].sort(),X,Z;g.useTailwindV4&&(console.log("\u{1F3A8} Generating Tailwind v4 CSS artifacts..."),X=g.generateThemeCSS(S),Z=g.generateClassesContent(z),console.log(" \u2713 theme.css generated"),console.log(` \u2713 classes.css generated for @source scanning
70
- `));let I={tokens:S.utilities,variables:S.variables,semanticVariables:S.semanticVariables,semanticDarkVariables:S.semanticDarkVariables,fonts:S.fontFaces,icons:j,componentsConfig:K,keyframes:S.keyframes,animations:S.animations,safelist:z,version:k,metadata:S.metadata,custom:S.custom,themeCSS:X,classesContent:Z};console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&(console.log(" Cache data summary:"),console.log(` - Tokens: ${Object.keys(I.tokens||{}).length} utilities`),console.log(` - Variables: ${Object.keys(I.variables||{}).length} CSS variables`),console.log(` - Semantic variables: ${Object.keys(I.semanticVariables||{}).length} semantic variables`),console.log(` - Font faces: ${(I.fonts||[]).length} fonts`),console.log(` - Safelist: ${(I.safelist||[]).length} safelist classes`)),l.save(I),console.log(` \u2713 Cache saved successfully
71
- `);let Q=je(t.appRoot,l.getIconLibrary());if(Q.changed&&console.log(` \u2713 Icon library: ${Q.iconLibrary} (adapter + dependency wired)
67
+ \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:y}=B(),_=t.aliases&&t.aliases.types?l.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;y({projectRoot:t.appRoot,outputPath:_})}catch(y){console.log(" \u26A0\uFE0F Type generation failed:",y.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
68
+ `);let[m,w,k,P,F,Le]=await Promise.all([g.fetchTokens(),g.fetchComponentsConfig(),g.fetchFonts(),g.fetchIcons(),g.fetchVersion(),g.fetchCustomCss()]),W=me(w,he);if(console.log(" \u2713 Tokens fetched"),m.global||m.colors||m.semantic||m.semanticDark){let y=[m.global?"global":null,m.colors?"colors":null,m.semantic?"semantic":null,m.semanticDark?"semanticDark":null].filter(Boolean).join(", ");console.log(` (Found: ${y})`)}console.log(" \u2713 Components config fetched"),console.log(" \u2713 Fonts fetched"),console.log(" \u2713 Icons fetched"),console.log(" \u2713 Version fetched"),console.log(` \u2713 Custom CSS fetched
69
+ `),console.log("\u2699\uFE0F Processing tokens..."),console.log(" Processing raw token data...");let v=await h.process({colors:m.colors||m.global,semantic:m.semantic,semanticDark:m.semanticDark,fonts:k,globalTokens:m.global,animations:m.animations,version:F==null?void 0:F.version,ffId:t.ffId,customCss:Le});console.log(" \u2713 Colors processed"),console.log(" \u2713 Semantic tokens processed"),v.fontFaces.length>0&&console.log(` \u2713 ${v.fontFaces.length} font faces processed`),Object.keys(v.animations).length>0&&console.log(` \u2713 ${Object.keys(v.animations).length} animations processed`),console.log(`
70
+ `);let Ee=h.extractClassesFromComponentsConfig(W),Ae=[...v.safelist||[],...Ee||[]],z=[...new Set(Ae)].sort(),X,Z;h.useTailwindV4&&(console.log("\u{1F3A8} Generating Tailwind v4 CSS artifacts..."),X=h.generateThemeCSS(v),Z=h.generateClassesContent(z),console.log(" \u2713 theme.css generated"),console.log(` \u2713 classes.css generated for @source scanning
71
+ `));let I={tokens:v.utilities,variables:v.variables,semanticVariables:v.semanticVariables,semanticDarkVariables:v.semanticDarkVariables,fonts:v.fontFaces,icons:P,componentsConfig:W,keyframes:v.keyframes,animations:v.animations,safelist:z,version:F,metadata:v.metadata,custom:v.custom,themeCSS:X,classesContent:Z};console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&(console.log(" Cache data summary:"),console.log(` - Tokens: ${Object.keys(I.tokens||{}).length} utilities`),console.log(` - Variables: ${Object.keys(I.variables||{}).length} CSS variables`),console.log(` - Semantic variables: ${Object.keys(I.semanticVariables||{}).length} semantic variables`),console.log(` - Font faces: ${(I.fonts||[]).length} fonts`),console.log(` - Safelist: ${(I.safelist||[]).length} safelist classes`)),f.save(I),console.log(` \u2713 Cache saved successfully
72
+ `);let Q=$e(t.appRoot,f.getIconLibrary());if(Q.changed&&console.log(` \u2713 Icon library: ${Q.iconLibrary} (adapter + dependency wired)
72
73
  `),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(`
73
- \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:h}=M(),E=t.aliases&&t.aliases.types?a.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;h({projectRoot:t.appRoot,outputPath:E})}catch(h){console.log(" \u26A0\uFE0F Type generation failed:",h.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}catch(o){o instanceof C?console.error("\u274C Configuration Error:",o.message):o instanceof H?(console.error("\u274C API Error:",o.message),console.error(` Status: ${o.statusCode}`),console.error(` URL: ${o.url}`)):o instanceof B?(console.error("\u274C Cache Error:",o.message),console.error(` Operation: ${o.operation}`)):console.error("\u274C Setup failed:",o.message),process.exit(1)}});v.command("clean").description("Remove cached configuration").action(async()=>{try{console.log(`\u{1F9F9} Cleaning FrontFriend cache...
74
- `);let n=new _().load(),o=new R(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 B?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Clean failed:",e.message),process.exit(1)}});v.command("status").description("Show cache status and configuration").action(async()=>{try{console.log("\u{1F4CA} FrontFriend Status"),console.log(`===================
75
- `),console.log("Package:"),console.log(` Version: ${we}`),console.log("");let n=await new _().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 R(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 C?console.error("\u274C Configuration Error:",e.message):e instanceof B?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Status check failed:",e.message),process.exit(1)}});function $e(e,n,o={}){let{component:t="all",input:s,keepShadcnClasses:r=!1}=o,i=[];if(s){let u=a.resolve(e,s);d.existsSync(u)&&i.push({path:a.relative(e,u),content:d.readFileSync(u,"utf8"),component:P(u)})}else for(let u of ke(e,t,n))i.push({path:a.relative(e,u.inputPath),content:u.source,component:u.component});let f=Ce(e),c=f?d.readFileSync(f,"utf8"):"",l=F(a.join(e,"components.json"))||{};return{framework:n,keepShadcnClasses:r,componentsJson:l,themeCss:c,files:i}}function be(e,n,o){let t=a.join(e,ve);d.mkdirSync(a.dirname(t),{recursive:!0}),U(t,{migratedAt:new Date().toISOString(),ffId:n,snapshotId:o.snapshotId||null,summary:o.summary||null});let s=!1,r=null,i=o.localActions&&o.localActions.themeCss;return i&&typeof i.scaffoldToKeep=="string"&&(r=Ce(e),r&&(d.writeFileSync(`${r}.bak`,d.readFileSync(r)),d.writeFileSync(r,i.scaffoldToKeep?`${i.scaffoldToKeep}
76
- `:""),s=!0)),{themeCssRewritten:s,themeCssPath:r}}v.command("migrate").description("Migrate shadcn components on the FrontFriend platform: upload sources, which are transformed, snapshotted (Restore) and persisted server-side").option("--component <name>",'Component to migrate, or "all" to scan the UI dir',"all").option("--input <path>","Path to the shadcn component source").option("--keep-shadcn-classes","Keep raw shadcn classes instead of rewriting them to FrontFriend tokens (default: rewrite)").action(async e=>{try{let o=await new _().load(),t=o.appRoot,s=Y(t);if(!o.ffId)throw new C("ff-id not found in frontfriend.config.js \u2014 migrate now runs on the FrontFriend platform and needs an ff-id","ff-id");let r=e.input&&e.component==="all"?P(e.input):e.component,i=$e(t,s,{component:r,input:e.input,keepShadcnClasses:!!e.keepShadcnClasses});if(i.files.length===0)throw new C(e.input?`Component source not found: ${e.input}`:"No shadcn components found under components/ui or src/components/ui","component");console.log(`\u{1F680} Migrating ${i.files.length} file(s) on the FrontFriend platform...`);let c=await new G(o.ffId,{baseURL:o["api-url"]||o.apiUrl,authToken:o["auth-token"]||o.authToken}).migrateComponents(i);if(!c||c.ok!==!0)throw new H("Migrate failed on the server",0,"migrate");let l=be(t,o.ffId,c),u=c.summary&&c.summary.migrated||[],g=c.summary&&c.summary.skipped||[];if(console.log("\u2705 Migration complete!"),console.log(` Migrated: ${u.length?u.join(", "):"(none)"}`),g.length>0&&console.log(` Skipped: ${g.map(p=>`${p.component} (${p.reason})`).join(", ")}`),c.snapshotId&&console.log(` Snapshot: ${c.snapshotId} (Restore point)`),c.version&&c.version.versionLabel){let p=c.version.changed===!1?" (no change)":"";console.log(` Design system: version ${c.version.versionLabel}${p}`)}l.themeCssRewritten&&console.log(` Centralised host CSS \u2192 design system (backup: ${a.relative(t,l.themeCssPath)}.bak)`),process.exit(0)}catch(n){n instanceof C?console.error("\u274C Migration Error:",n.message):console.error("\u274C Migration failed:",n.message),process.exit(1)}});function Te(e,n){let o=a.resolve(e),t=[];for(let s of n||[]){if(!s||typeof s.path!="string"||typeof s.content!="string")continue;let r=a.resolve(o,s.path);r!==o&&!r.startsWith(o+a.sep)||(d.mkdirSync(a.dirname(r),{recursive:!0}),d.writeFileSync(r,s.content),t.push(s.path))}return t}function Fn(e){return new Promise((n,o)=>{(e.startsWith("https")?require("https"):require("http")).get(e,s=>{if(s.statusCode>=300){s.resume(),o(new Error(`Download failed: HTTP ${s.statusCode}`));return}let r=[];s.on("data",i=>r.push(i)),s.on("end",()=>n(Buffer.concat(r))),s.on("error",o)}).on("error",o)})}v.command("restore [snapshotId]").description("Restore the original shadcn sources from a migrate snapshot (no id lists the snapshots)").action(async e=>{try{let o=await new _().load();if(!o.ffId)throw new C("ff-id not found in frontfriend.config.js","ff-id");let t=new G(o.ffId,{baseURL:o["api-url"]||o.apiUrl,authToken:o["auth-token"]||o.authToken});if(!e){let{snapshots:c=[]}=await t.listMigrationSnapshots()||{};c.length===0&&(console.log("No migrate snapshots found for this design system."),process.exit(0)),console.log(`\u{1F4F8} Migrate snapshots (newest first):
77
- `);for(let l of c){let u=(l.files||[]).length,g=l.createdAt?new Date(l.createdAt).toISOString().slice(0,19).replace("T"," "):"",p=l.restorable?"":" (no bundle)";console.log(` ${l.id} ${g} ${l.status} ${u} file(s)${p}`)}console.log("\n Run `npx frontfriend restore <id>` to restore one."),process.exit(0)}console.log(`\u23EC Restoring snapshot ${e}...`);let s=await t.getMigrationSnapshot(e);if(!s||!s.url)throw new H("Snapshot has no downloadable bundle",0,"restore");let r=await Fn(s.url),i=JSON.parse(require("zlib").gunzipSync(r).toString("utf8")),f=Te(o.appRoot,i.files||[]);console.log("\u2705 Restore complete!"),console.log(` Restored ${f.length} file(s):`);for(let c of f)console.log(` \u2022 ${c}`);process.exit(0)}catch(n){n instanceof C?console.error("\u274C Restore Error:",n.message):console.error("\u274C Restore failed:",n.message),process.exit(1)}});v.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...
78
- `);let t=await new _().load();if(!t.ffId)throw new C(`ff-id not found in frontfriend.config.js
79
- Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let s=new Qe({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(),c=await s.getCustomComponents();process.env.FF_DEBUG&&console.log(`Debug: Found ${c.length} custom components: ${c.join(", ")}`),f.length===0&&(console.error("\u274C Failed to fetch component list"),process.exit(1));let l=new Set(c),u=f.filter(g=>!l.has(g));r=[...c,...u],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&&c.length>0&&console.log(` Debug: ${c.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(", ")}
80
- `);let i=await s.downloadComponents(r);if(i.successful.length>0){console.log(`
81
- \u2705 Download complete!`),console.log(` Downloaded: ${i.successful.length} components`);let f=new R(t.appRoot).getIconLibrary()||t.iconLibrary,c=je(t.appRoot,f);c.changed&&console.log(` Icon library: ${c.iconLibrary} (adapter + dependency wired)`)}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(`
82
- \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 C?(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)}});require.main===module&&(v.parse(process.argv),process.argv.slice(2).length||(v.outputHelp(),process.exit(0)));module.exports={buildMigratePayload:$e,applyMigrateResult:be,applyRestore:Te,findComponentSources:ke,inferComponentNameFromInput:P,detectProjectFramework:Y};
74
+ \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:y}=B(),_=t.aliases&&t.aliases.types?l.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;y({projectRoot:t.appRoot,outputPath:_})}catch(y){console.log(" \u26A0\uFE0F Type generation failed:",y.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}catch(n){n instanceof C?console.error("\u274C Configuration Error:",n.message):n instanceof O?(console.error("\u274C API Error:",n.message),console.error(` Status: ${n.statusCode}`),console.error(` URL: ${n.url}`)):n instanceof Y?(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...
75
+ `);let o=new T().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 Y?(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(`===================
76
+ `),console.log("Package:"),console.log(` Version: ${Ce}`),console.log("");let o=await new T().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 i=new Date(s.metadata.timestamp);console.log(` Created: ${i.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 C?console.error("\u274C Configuration Error:",e.message):e instanceof Y?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Status check failed:",e.message),process.exit(1)}});function Te(e,o,n={}){let{component:t="all",input:s,keepShadcnClasses:i=!1}=n,r=[];if(s){let u=l.resolve(e,s);d.existsSync(u)&&r.push({path:l.relative(e,u),content:d.readFileSync(u,"utf8"),component:A(u)})}else for(let u of be(e,t,o))r.push({path:l.relative(e,u.inputPath),content:u.source,component:u.component});let c=xe(e),a=c?d.readFileSync(c,"utf8"):"",f=x(l.join(e,"components.json"))||{};return{framework:o,keepShadcnClasses:i,componentsJson:f,themeCss:a,files:r}}function Ie(e,o,n){let t=l.join(e,Fe);d.mkdirSync(l.dirname(t),{recursive:!0}),N(t,{migratedAt:new Date().toISOString(),ffId:o,snapshotId:n.snapshotId||null,summary:n.summary||null});let s=!1,i=null,r=n.localActions&&n.localActions.themeCss;return r&&typeof r.scaffoldToKeep=="string"&&(i=xe(e),i&&(d.writeFileSync(`${i}.bak`,d.readFileSync(i)),d.writeFileSync(i,r.scaffoldToKeep?`${r.scaffoldToKeep}
77
+ `:""),s=!0)),{themeCssRewritten:s,themeCssPath:i}}S.command("migrate").description("Migrate shadcn components on the FrontFriend platform: upload sources, which are transformed, snapshotted (Restore) and persisted server-side").option("--component <name>",'Component to migrate, or "all" to scan the UI dir',"all").option("--input <path>","Path to the shadcn component source").option("--keep-shadcn-classes","Keep raw shadcn classes instead of rewriting them to FrontFriend tokens (default: rewrite)").action(async e=>{try{let n=await new T().load(),t=n.appRoot,s=q(t);if(!n.ffId)throw new C("ff-id not found in frontfriend.config.js \u2014 migrate now runs on the FrontFriend platform and needs an ff-id","ff-id");let i=e.input&&e.component==="all"?A(e.input):e.component,r=Te(t,s,{component:i,input:e.input,keepShadcnClasses:!!e.keepShadcnClasses});if(r.files.length===0)throw new C(e.input?`Component source not found: ${e.input}`:"No shadcn components found under components/ui or src/components/ui","component");console.log(`\u{1F680} Migrating ${r.files.length} file(s) on the FrontFriend platform...`);let a=await new U(n.ffId,{baseURL:n["api-url"]||n.apiUrl,authToken:n["auth-token"]||n.authToken}).migrateComponents(r);if(!a||a.ok!==!0)throw new O("Migrate failed on the server",0,"migrate");let f=Ie(t,n.ffId,a),u=a.summary&&a.summary.migrated||[],g=a.summary&&a.summary.skipped||[];if(console.log("\u2705 Migration complete!"),console.log(` Migrated: ${u.length?u.join(", "):"(none)"}`),g.length>0&&console.log(` Skipped: ${g.map(h=>`${h.component} (${h.reason})`).join(", ")}`),a.snapshotId&&console.log(` Snapshot: ${a.snapshotId} (Restore point)`),a.version&&a.version.versionLabel){let h=a.version.changed===!1?" (no change)":"";console.log(` Design system: version ${a.version.versionLabel}${h}`)}f.themeCssRewritten&&console.log(` Centralised host CSS \u2192 design system (backup: ${l.relative(t,f.themeCssPath)}.bak)`),process.exit(0)}catch(o){o instanceof C?console.error("\u274C Migration Error:",o.message):console.error("\u274C Migration failed:",o.message),process.exit(1)}});S.command("upgrade-config").description("Convert this design system's v3 componentsConfig to the canonical v4 styles/behavior format on the FrontFriend platform").option("--dry-run","Preview the conversion and report without writing a new version").option("--tag <tag>","Tag whose version to convert (default: dev)").option("--version <version>","Specific version id/label to convert").action(async e=>{try{let n=await new T().load(),t=q(n.appRoot);if(!n.ffId)throw new C("ff-id not found in frontfriend.config.js","ff-id");let s=new U(n.ffId,{baseURL:n["api-url"]||n.apiUrl,authToken:n["auth-token"]||n.authToken});console.log(`\u{1F501} Converting componentsConfig v3 \u2192 v4 (${t})${e.dryRun?" [dry run]":""}...`);let i=await s.upgradeConfig({framework:t},{dryRun:!!e.dryRun,tag:e.tag,version:e.version});if(!i||i.ok!==!0)throw new O("Config upgrade failed on the server",0,"upgrade-config");let r=i.report||{};if(console.log(i.report&&i.report.alreadyV4?"\u2705 Already v4 \u2014 nothing to convert.":"\u2705 Conversion complete!"),r.renames&&r.renames.length&&console.log(` Renamed keys: ${r.renames.map(c=>`${c.from}\u2192${c.to}`).join(", ")}`),r.movedToBehavior&&r.movedToBehavior.length&&console.log(` Non-class values moved to behavior: ${r.movedToBehavior.length}`),r.unknownKeys&&r.unknownKeys.length&&console.log(` \u26A0\uFE0F Unknown/custom keys preserved: ${r.unknownKeys.join(", ")}`),r.conflicts&&r.conflicts.length&&console.log(` \u26A0\uFE0F Conflicts: ${r.conflicts.join("; ")}`),r.compatibility&&r.compatibility.length){console.log(" \u26A0\uFE0F Component API changes (v3\u2192v4):");for(let c of r.compatibility){let a=c.replacement?` \u2192 use ${c.replacement}`:"";console.log(` \u2022 ${c.component} [${c.decision}]${a}: ${c.note||""}`)}}if(r.manualFollowUp&&r.manualFollowUp.length){console.log(" Follow-up:");for(let c of r.manualFollowUp)console.log(` \u2022 ${c}`)}if(e.dryRun)console.log(" (dry run \u2014 no version written)");else if(i.version&&i.version.versionLabel){let c=i.version.changed===!1?" (no change)":"";console.log(` Design system: version ${i.version.versionLabel}${c}`)}process.exit(0)}catch(o){o instanceof C?console.error("\u274C Upgrade Error:",o.message):console.error("\u274C Config upgrade failed:",o.message),process.exit(1)}});function _e(e,o){let n=l.resolve(e),t=[];for(let s of o||[]){if(!s||typeof s.path!="string"||typeof s.content!="string")continue;let i=l.resolve(n,s.path);i!==n&&!i.startsWith(n+l.sep)||(d.mkdirSync(l.dirname(i),{recursive:!0}),d.writeFileSync(i,s.content),t.push(s.path))}return t}function To(e){return new Promise((o,n)=>{(e.startsWith("https")?require("https"):require("http")).get(e,s=>{if(s.statusCode>=300){s.resume(),n(new Error(`Download failed: HTTP ${s.statusCode}`));return}let i=[];s.on("data",r=>i.push(r)),s.on("end",()=>o(Buffer.concat(i))),s.on("error",n)}).on("error",n)})}S.command("restore [snapshotId]").description("Restore the original shadcn sources from a migrate snapshot (no id lists the snapshots)").action(async e=>{try{let n=await new T().load();if(!n.ffId)throw new C("ff-id not found in frontfriend.config.js","ff-id");let t=new U(n.ffId,{baseURL:n["api-url"]||n.apiUrl,authToken:n["auth-token"]||n.authToken});if(!e){let{snapshots:a=[]}=await t.listMigrationSnapshots()||{};a.length===0&&(console.log("No migrate snapshots found for this design system."),process.exit(0)),console.log(`\u{1F4F8} Migrate snapshots (newest first):
78
+ `);for(let f of a){let u=(f.files||[]).length,g=f.createdAt?new Date(f.createdAt).toISOString().slice(0,19).replace("T"," "):"",h=f.restorable?"":" (no bundle)";console.log(` ${f.id} ${g} ${f.status} ${u} file(s)${h}`)}console.log("\n Run `npx frontfriend restore <id>` to restore one."),process.exit(0)}console.log(`\u23EC Restoring snapshot ${e}...`);let s=await t.getMigrationSnapshot(e);if(!s||!s.url)throw new O("Snapshot has no downloadable bundle",0,"restore");let i=await To(s.url),r=JSON.parse(require("zlib").gunzipSync(i).toString("utf8")),c=_e(n.appRoot,r.files||[]);console.log("\u2705 Restore complete!"),console.log(` Restored ${c.length} file(s):`);for(let a of c)console.log(` \u2022 ${a}`);process.exit(0)}catch(o){o instanceof C?console.error("\u274C Restore Error:",o.message):console.error("\u274C Restore 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...
79
+ `);let t=await new T().load();if(!t.ffId)throw new C(`ff-id not found in frontfriend.config.js
80
+ Please add "ff-id" to your frontfriend.config.js file`,"ff-id");let s=new so({appRoot:t.appRoot,config:t,framework:o.framework,registryGeneration:o.registry,outputPath:o.output,overwrite:o.overwrite}),i=e;if(e.length===1&&e[0].toLowerCase()==="all"){let c=await s.getAllComponents(),a=await s.getCustomComponents();process.env.FF_DEBUG&&console.log(`Debug: Found ${a.length} custom components: ${a.join(", ")}`),c.length===0&&(console.error("\u274C Failed to fetch component list"),process.exit(1));let f=new Set(a),u=c.filter(g=>!f.has(g));i=[...a,...u],console.log("\u{1F4CB} Configuration"),console.log(` Framework: ${s.framework}`),console.log(` Registry: ${s.registryGeneration}`),console.log(` Output: ${s.outputPath}`),console.log(` Components: All ${i.length} components`),process.env.FF_DEBUG&&a.length>0&&console.log(` Debug: ${a.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(", ")}
81
+ `);let r=await s.downloadComponents(i);if(r.successful.length>0){console.log(`
82
+ \u2705 Download complete!`),console.log(` Downloaded: ${r.successful.length} components`);let c=new D(t.appRoot).getIconLibrary()||t.iconLibrary,a=$e(t.appRoot,c);a.changed&&console.log(` Icon library: ${a.iconLibrary} (adapter + dependency wired)`)}r.failed.length>0&&(console.log(""),r.failed.forEach(c=>{c.error.includes("not found")?console.log(`\u274C ${c.error}`):console.log(`\u274C Failed to download ${c.component}: ${c.error}`)})),r.successful.length>0&&r.dependencies.length>0&&(console.log(`
83
+ \u{1F4E6} Install dependencies:`),console.log(` npm install ${r.dependencies.join(" ")}`)),r.successful.length===0&&r.failed.length>0&&process.exit(1),process.exit(0)}catch(n){n instanceof C?(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)}});require.main===module&&(S.parse(process.argv),process.argv.slice(2).length||(S.outputHelp(),process.exit(0)));module.exports={buildMigratePayload:Te,applyMigrateResult:Ie,applyRestore:_e,findComponentSources:be,inferComponentNameFromInput:A,detectProjectFramework:q};
83
84
  //# sourceMappingURL=cli-temp.js.map
@@ -0,0 +1,14 @@
1
+ export interface ComponentRecipe {
2
+ config: Record<string, any>;
3
+ classes: Record<string, string>;
4
+ }
5
+
6
+ export function createComponentRecipe(
7
+ componentsConfig: Record<string, any>,
8
+ options?: { prefix?: string }
9
+ ): ComponentRecipe;
10
+
11
+ export function emitComponentRecipeCss(
12
+ classes: Record<string, string>,
13
+ options?: { scope?: string }
14
+ ): string;
@@ -1,2 +1,2 @@
1
- var r={anyOf:[{type:"string"},{type:"number"},{type:"boolean"},{type:"null"}]},f={$id:"https://frontfriend.dev/schemas/components-config.schema.json",type:"object",additionalProperties:{anyOf:[{$ref:"#/$defs/classValue"},{$ref:"#/$defs/componentEnvelope"}]},$defs:{classValue:r,slotValue:{anyOf:[{$ref:"#/$defs/classValue"},{type:"object",additionalProperties:{$ref:"#/$defs/slotValue"}}]},reservedBucket:{anyOf:[{$ref:"#/$defs/classValue"},{type:"object",additionalProperties:{$ref:"#/$defs/slotValue"}}]},componentEnvelope:{type:"object",additionalProperties:!1,properties:{root:{$ref:"#/$defs/slotValue"},variants:{type:"object",additionalProperties:{$ref:"#/$defs/reservedBucket"}},variant:{$ref:"#/$defs/reservedBucket"},size:{$ref:"#/$defs/reservedBucket"},sizes:{$ref:"#/$defs/reservedBucket"},iconPosition:{$ref:"#/$defs/reservedBucket"},icons:{$ref:"#/$defs/reservedBucket"},color:{$ref:"#/$defs/reservedBucket"},fullwidth:{$ref:"#/$defs/reservedBucket"},states:{$ref:"#/$defs/reservedBucket"},compoundVariants:{$ref:"#/$defs/reservedBucket"},defaultVariants:{$ref:"#/$defs/reservedBucket"},props:{$ref:"#/$defs/reservedBucket"},slots:{type:"object",additionalProperties:{$ref:"#/$defs/slotValue"}}}}}};function o(e){if(typeof e!="string"||e.trim().length===0||/^[0-9]+(?:\.[0-9]+)?$/.test(e)||e==="true"||e==="false")return!1;let s=/\s/.test(e),t=/[-:\[\]\/]/.test(e);return!0}module.exports={componentsConfigSchema:f,isCSSClassString:o};
1
+ var t={$id:"https://frontfriend.dev/schemas/components-config.v4.schema.json",type:"object",additionalProperties:{$ref:"#/$defs/componentConfig"},$defs:{componentConfig:{anyOf:[{$ref:"#/$defs/componentEnvelope"},{$ref:"#/$defs/legacyEntry"}]},legacyEntry:{type:"object",additionalProperties:!1,required:["legacy"],properties:{legacy:{}}},styleTree:{anyOf:[{type:"string"},{type:"object",additionalProperties:{$ref:"#/$defs/styleTree"}}]},behaviorTree:{anyOf:[{type:["string","number","boolean","null"]},{type:"array",items:{$ref:"#/$defs/behaviorTree"}},{type:"object",additionalProperties:{$ref:"#/$defs/behaviorTree"}}]},componentEnvelope:{type:"object",additionalProperties:!1,required:["styles"],properties:{styles:{type:"object",additionalProperties:{$ref:"#/$defs/styleTree"}},behavior:{type:"object",additionalProperties:{$ref:"#/$defs/behaviorTree"}}}}}};function r(e){return typeof e=="string"&&e.trim().length>0}module.exports={componentsConfigSchema:t,isCSSClassString:r};
2
2
  //# sourceMappingURL=components-config-schema.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../lib/core/components-config-schema.js"],
4
- "sourcesContent": ["/**\n * Shared componentsConfig schema for FrontFriend tools.\n *\n * The schema defines the canonical per-component envelope used by ffdc,\n * validation scripts, migration tooling, and registry completeness checks.\n * Keep this file as the single source of truth; consumers should re-export it\n * instead of maintaining local schema copies.\n */\n\nconst classValueSchema = {\n anyOf: [\n { type: 'string' },\n { type: 'number' },\n { type: 'boolean' },\n { type: 'null' },\n ],\n};\n\nconst componentsConfigSchema = {\n $id: 'https://frontfriend.dev/schemas/components-config.schema.json',\n type: 'object',\n // A component is a bare class string (e.g. spinner: \"animate-spin\") or a\n // strict envelope.\n additionalProperties: {\n anyOf: [{ $ref: '#/$defs/classValue' }, { $ref: '#/$defs/componentEnvelope' }],\n },\n $defs: {\n classValue: classValueSchema,\n\n // Permissive recursive tree used INSIDE `slots` and for `root`: leaves are\n // class values, objects nest freely. Slot internals are NOT namespaced\n // again (slots live at the component top level only), so e.g.\n // `slots.trigger.icon` and `slots.list.line` stay as plain nested keys.\n slotValue: {\n anyOf: [\n { $ref: '#/$defs/classValue' },\n { type: 'object', additionalProperties: { $ref: '#/$defs/slotValue' } },\n ],\n },\n\n // Variant / prop buckets: a class-value leaf or a (possibly nested) map.\n reservedBucket: {\n anyOf: [\n { $ref: '#/$defs/classValue' },\n { type: 'object', additionalProperties: { $ref: '#/$defs/slotValue' } },\n ],\n },\n\n // STRICT canonical v4 envelope: a fixed set of reserved buckets plus a\n // single `slots` namespace holding every named child slot.\n // `additionalProperties: false` is what standardizes the shape \u2014 any stray\n // top-level key (a slot left outside `slots`, a typo) is rejected.\n componentEnvelope: {\n type: 'object',\n additionalProperties: false,\n properties: {\n // Root classes for the component. Usually a class string; some\n // components (e.g. sidebar) nest a sub-tree under root.\n root: { $ref: '#/$defs/slotValue' },\n\n // Canonical variant buckets (variants.variant, variants.size, \u2026) plus\n // the flat compatibility aliases.\n variants: { type: 'object', additionalProperties: { $ref: '#/$defs/reservedBucket' } },\n variant: { $ref: '#/$defs/reservedBucket' },\n size: { $ref: '#/$defs/reservedBucket' },\n sizes: { $ref: '#/$defs/reservedBucket' },\n iconPosition: { $ref: '#/$defs/reservedBucket' },\n icons: { $ref: '#/$defs/reservedBucket' },\n color: { $ref: '#/$defs/reservedBucket' },\n fullwidth: { $ref: '#/$defs/reservedBucket' },\n states: { $ref: '#/$defs/reservedBucket' },\n compoundVariants: { $ref: '#/$defs/reservedBucket' },\n defaultVariants: { $ref: '#/$defs/reservedBucket' },\n props: { $ref: '#/$defs/reservedBucket' },\n\n // All named child slots (item, trigger, content, icon, menu, \u2026) live\n // here. Top-level only \u2014 slot internals stay direct.\n slots: { type: 'object', additionalProperties: { $ref: '#/$defs/slotValue' } },\n },\n },\n },\n};\n\nfunction isCSSClassString(value) {\n if (typeof value !== 'string') return false;\n\n if (value.trim().length === 0) return false;\n\n if (/^[0-9]+(?:\\.[0-9]+)?$/.test(value)) return false;\n\n if (value === 'true' || value === 'false') return false;\n\n const hasSpaces = /\\s/.test(value);\n const hasTailwindSyntax = /[-:\\[\\]\\/]/.test(value);\n\n if (hasSpaces || hasTailwindSyntax) return true;\n\n return true;\n}\n\nmodule.exports = {\n componentsConfigSchema,\n isCSSClassString,\n};\n"],
5
- "mappings": "AASA,IAAMA,EAAmB,CACvB,MAAO,CACL,CAAE,KAAM,QAAS,EACjB,CAAE,KAAM,QAAS,EACjB,CAAE,KAAM,SAAU,EAClB,CAAE,KAAM,MAAO,CACjB,CACF,EAEMC,EAAyB,CAC7B,IAAK,gEACL,KAAM,SAGN,qBAAsB,CACpB,MAAO,CAAC,CAAE,KAAM,oBAAqB,EAAG,CAAE,KAAM,2BAA4B,CAAC,CAC/E,EACA,MAAO,CACL,WAAYD,EAMZ,UAAW,CACT,MAAO,CACL,CAAE,KAAM,oBAAqB,EAC7B,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CACxE,CACF,EAGA,eAAgB,CACd,MAAO,CACL,CAAE,KAAM,oBAAqB,EAC7B,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CACxE,CACF,EAMA,kBAAmB,CACjB,KAAM,SACN,qBAAsB,GACtB,WAAY,CAGV,KAAM,CAAE,KAAM,mBAAoB,EAIlC,SAAU,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,wBAAyB,CAAE,EACrF,QAAS,CAAE,KAAM,wBAAyB,EAC1C,KAAM,CAAE,KAAM,wBAAyB,EACvC,MAAO,CAAE,KAAM,wBAAyB,EACxC,aAAc,CAAE,KAAM,wBAAyB,EAC/C,MAAO,CAAE,KAAM,wBAAyB,EACxC,MAAO,CAAE,KAAM,wBAAyB,EACxC,UAAW,CAAE,KAAM,wBAAyB,EAC5C,OAAQ,CAAE,KAAM,wBAAyB,EACzC,iBAAkB,CAAE,KAAM,wBAAyB,EACnD,gBAAiB,CAAE,KAAM,wBAAyB,EAClD,MAAO,CAAE,KAAM,wBAAyB,EAIxC,MAAO,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CAC/E,CACF,CACF,CACF,EAEA,SAASE,EAAiBC,EAAO,CAO/B,GANI,OAAOA,GAAU,UAEjBA,EAAM,KAAK,EAAE,SAAW,GAExB,wBAAwB,KAAKA,CAAK,GAElCA,IAAU,QAAUA,IAAU,QAAS,MAAO,GAElD,IAAMC,EAAY,KAAK,KAAKD,CAAK,EAC3BE,EAAoB,aAAa,KAAKF,CAAK,EAEjD,MAA2C,EAG7C,CAEA,OAAO,QAAU,CACf,uBAAAF,EACA,iBAAAC,CACF",
6
- "names": ["classValueSchema", "componentsConfigSchema", "isCSSClassString", "value", "hasSpaces", "hasTailwindSyntax"]
4
+ "sourcesContent": ["/**\n * Canonical Frontfriend v4 componentsConfig schema.\n *\n * Styling and runtime behavior are deliberately separate. Every string below\n * `styles` is a Tailwind class string; values below `behavior` are component\n * data and are never interpreted as CSS.\n */\n\nconst componentsConfigSchema = {\n $id: \"https://frontfriend.dev/schemas/components-config.v4.schema.json\",\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/componentConfig\" },\n $defs: {\n // A component config is either a fully-migrated v4 envelope OR an explicit\n // legacy/unresolved custom payload awaiting promotion (#512/#514). The\n // generic converter never guesses how custom fields map to styles/behavior;\n // it preserves the v3 payload verbatim under `legacy` until promotion.\n componentConfig: {\n anyOf: [\n { $ref: \"#/$defs/componentEnvelope\" },\n { $ref: \"#/$defs/legacyEntry\" },\n ],\n },\n legacyEntry: {\n type: \"object\",\n additionalProperties: false,\n required: [\"legacy\"],\n properties: { legacy: {} },\n },\n styleTree: {\n anyOf: [\n { type: \"string\" },\n { type: \"object\", additionalProperties: { $ref: \"#/$defs/styleTree\" } },\n ],\n },\n behaviorTree: {\n anyOf: [\n { type: [\"string\", \"number\", \"boolean\", \"null\"] },\n { type: \"array\", items: { $ref: \"#/$defs/behaviorTree\" } },\n {\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/behaviorTree\" },\n },\n ],\n },\n componentEnvelope: {\n type: \"object\",\n additionalProperties: false,\n required: [\"styles\"],\n properties: {\n styles: {\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/styleTree\" },\n },\n behavior: {\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/behaviorTree\" },\n },\n },\n },\n },\n};\n\nfunction isCSSClassString(value) {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\nmodule.exports = {\n componentsConfigSchema,\n isCSSClassString,\n};\n"],
5
+ "mappings": "AAQA,IAAMA,EAAyB,CAC7B,IAAK,mEACL,KAAM,SACN,qBAAsB,CAAE,KAAM,yBAA0B,EACxD,MAAO,CAKL,gBAAiB,CACf,MAAO,CACL,CAAE,KAAM,2BAA4B,EACpC,CAAE,KAAM,qBAAsB,CAChC,CACF,EACA,YAAa,CACX,KAAM,SACN,qBAAsB,GACtB,SAAU,CAAC,QAAQ,EACnB,WAAY,CAAE,OAAQ,CAAC,CAAE,CAC3B,EACA,UAAW,CACT,MAAO,CACL,CAAE,KAAM,QAAS,EACjB,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CACxE,CACF,EACA,aAAc,CACZ,MAAO,CACL,CAAE,KAAM,CAAC,SAAU,SAAU,UAAW,MAAM,CAAE,EAChD,CAAE,KAAM,QAAS,MAAO,CAAE,KAAM,sBAAuB,CAAE,EACzD,CACE,KAAM,SACN,qBAAsB,CAAE,KAAM,sBAAuB,CACvD,CACF,CACF,EACA,kBAAmB,CACjB,KAAM,SACN,qBAAsB,GACtB,SAAU,CAAC,QAAQ,EACnB,WAAY,CACV,OAAQ,CACN,KAAM,SACN,qBAAsB,CAAE,KAAM,mBAAoB,CACpD,EACA,SAAU,CACR,KAAM,SACN,qBAAsB,CAAE,KAAM,sBAAuB,CACvD,CACF,CACF,CACF,CACF,EAEA,SAASC,EAAiBC,EAAO,CAC/B,OAAO,OAAOA,GAAU,UAAYA,EAAM,KAAK,EAAE,OAAS,CAC5D,CAEA,OAAO,QAAU,CACf,uBAAAF,EACA,iBAAAC,CACF",
6
+ "names": ["componentsConfigSchema", "isCSSClassString", "value"]
7
7
  }
package/dist/ffdc.d.ts CHANGED
@@ -1,8 +1,18 @@
1
+ export type ComponentStyles = string | { [key: string]: ComponentStyles };
2
+ export type ComponentBehavior = string | number | boolean | null | ComponentBehavior[] | { [key: string]: ComponentBehavior };
3
+ export interface ComponentConfigEnvelope {
4
+ styles: Record<string, ComponentStyles>;
5
+ behavior?: Record<string, ComponentBehavior>;
6
+ }
7
+ export type ComponentsConfig = Record<string, ComponentConfigEnvelope>;
8
+
1
9
  /**
2
10
  * FrontFriend Design Config processor
3
11
  * @param config - Design configuration object
4
12
  * @returns Processed configuration
5
13
  */
6
- export function ffdc(config: Record<string, any> | null | undefined): Record<string, any>;
14
+ declare function ffdc(config: ComponentsConfig | Record<string, any> | null | undefined): Record<string, any>;
15
+ export { ffdc };
16
+ export default ffdc;
7
17
  export const componentsConfigSchema: Record<string, any>;
8
18
  export function isCSSClassString(value: string): boolean;
package/dist/ffdc.js CHANGED
@@ -1,2 +1,2 @@
1
- var n=(e,s)=>()=>(s||e((s={exports:{}}).exports,s),s.exports);var o=n((u,r)=>{var a={anyOf:[{type:"string"},{type:"number"},{type:"boolean"},{type:"null"}]},i={$id:"https://frontfriend.dev/schemas/components-config.schema.json",type:"object",additionalProperties:{anyOf:[{$ref:"#/$defs/classValue"},{$ref:"#/$defs/componentEnvelope"}]},$defs:{classValue:a,slotValue:{anyOf:[{$ref:"#/$defs/classValue"},{type:"object",additionalProperties:{$ref:"#/$defs/slotValue"}}]},reservedBucket:{anyOf:[{$ref:"#/$defs/classValue"},{type:"object",additionalProperties:{$ref:"#/$defs/slotValue"}}]},componentEnvelope:{type:"object",additionalProperties:!1,properties:{root:{$ref:"#/$defs/slotValue"},variants:{type:"object",additionalProperties:{$ref:"#/$defs/reservedBucket"}},variant:{$ref:"#/$defs/reservedBucket"},size:{$ref:"#/$defs/reservedBucket"},sizes:{$ref:"#/$defs/reservedBucket"},iconPosition:{$ref:"#/$defs/reservedBucket"},icons:{$ref:"#/$defs/reservedBucket"},color:{$ref:"#/$defs/reservedBucket"},fullwidth:{$ref:"#/$defs/reservedBucket"},states:{$ref:"#/$defs/reservedBucket"},compoundVariants:{$ref:"#/$defs/reservedBucket"},defaultVariants:{$ref:"#/$defs/reservedBucket"},props:{$ref:"#/$defs/reservedBucket"},slots:{type:"object",additionalProperties:{$ref:"#/$defs/slotValue"}}}}}};function d(e){if(typeof e!="string"||e.trim().length===0||/^[0-9]+(?:\.[0-9]+)?$/.test(e)||e==="true"||e==="false")return!1;let s=/\s/.test(e),f=/[-:\[\]\/]/.test(e);return!0}r.exports={componentsConfigSchema:i,isCSSClassString:d}});var{componentsConfigSchema:c,isCSSClassString:$}=o();function t(e){if(!e)return{};if(typeof e!="object")throw new Error("Config must be an object");return e}t.componentsConfigSchema=c;t.isCSSClassString=$;module.exports=t;
1
+ var c=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var d=c((P,p)=>{var m={$id:"https://frontfriend.dev/schemas/components-config.v4.schema.json",type:"object",additionalProperties:{$ref:"#/$defs/componentConfig"},$defs:{componentConfig:{anyOf:[{$ref:"#/$defs/componentEnvelope"},{$ref:"#/$defs/legacyEntry"}]},legacyEntry:{type:"object",additionalProperties:!1,required:["legacy"],properties:{legacy:{}}},styleTree:{anyOf:[{type:"string"},{type:"object",additionalProperties:{$ref:"#/$defs/styleTree"}}]},behaviorTree:{anyOf:[{type:["string","number","boolean","null"]},{type:"array",items:{$ref:"#/$defs/behaviorTree"}},{type:"object",additionalProperties:{$ref:"#/$defs/behaviorTree"}}]},componentEnvelope:{type:"object",additionalProperties:!1,required:["styles"],properties:{styles:{type:"object",additionalProperties:{$ref:"#/$defs/styleTree"}},behavior:{type:"object",additionalProperties:{$ref:"#/$defs/behaviorTree"}}}}}};function C(e){return typeof e=="string"&&e.trim().length>0}p.exports={componentsConfigSchema:m,isCSSClassString:C}});var l=c((T,b)=>{function i(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function s(e,n){if(!i(e)||!i(n))return n===void 0?e:n;let t={...e};for(let[r,o]of Object.entries(n))t[r]=r in t?s(t[r],o):o;return t}function f(e,n,t=[],r=[]){if(e===void 0||n===void 0)return r;if(!i(e)||!i(n))return r.push(t.join(".")),r;for(let o of Object.keys(e))o in n&&f(e[o],n[o],[...t,o],r);return r}function y(e){return i(e)&&("styles"in e||"behavior"in e)}function u(e,n="component"){if(!y(e))return e;let t=f(e.styles,e.behavior,[n]);if(t.length>0)throw new Error(`Component config styles/behavior conflict at ${t.join(", ")}`);return s(e.styles||{},e.behavior||{})}function $(e){if(!i(e))return e;let n=!1,t={};for(let[r,o]of Object.entries(e))t[r]=u(o,r),t[r]!==o&&(n=!0);return n?t:e}b.exports={deepMerge:s,findTreeConflicts:f,isV4Envelope:y,toRuntimeComponentConfig:u,toRuntimeComponentsConfig:$}});var{componentsConfigSchema:j,isCSSClassString:g}=d(),{toRuntimeComponentsConfig:h}=l();function a(e){if(!e)return{};if(typeof e!="object")throw new Error("Config must be an object");return h(e)}a.componentsConfigSchema=j;a.isCSSClassString=g;module.exports=a;
2
2
  //# sourceMappingURL=ffdc.js.map
package/dist/ffdc.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../lib/core/components-config-schema.js", "../ffdc.js"],
4
- "sourcesContent": ["/**\n * Shared componentsConfig schema for FrontFriend tools.\n *\n * The schema defines the canonical per-component envelope used by ffdc,\n * validation scripts, migration tooling, and registry completeness checks.\n * Keep this file as the single source of truth; consumers should re-export it\n * instead of maintaining local schema copies.\n */\n\nconst classValueSchema = {\n anyOf: [\n { type: 'string' },\n { type: 'number' },\n { type: 'boolean' },\n { type: 'null' },\n ],\n};\n\nconst componentsConfigSchema = {\n $id: 'https://frontfriend.dev/schemas/components-config.schema.json',\n type: 'object',\n // A component is a bare class string (e.g. spinner: \"animate-spin\") or a\n // strict envelope.\n additionalProperties: {\n anyOf: [{ $ref: '#/$defs/classValue' }, { $ref: '#/$defs/componentEnvelope' }],\n },\n $defs: {\n classValue: classValueSchema,\n\n // Permissive recursive tree used INSIDE `slots` and for `root`: leaves are\n // class values, objects nest freely. Slot internals are NOT namespaced\n // again (slots live at the component top level only), so e.g.\n // `slots.trigger.icon` and `slots.list.line` stay as plain nested keys.\n slotValue: {\n anyOf: [\n { $ref: '#/$defs/classValue' },\n { type: 'object', additionalProperties: { $ref: '#/$defs/slotValue' } },\n ],\n },\n\n // Variant / prop buckets: a class-value leaf or a (possibly nested) map.\n reservedBucket: {\n anyOf: [\n { $ref: '#/$defs/classValue' },\n { type: 'object', additionalProperties: { $ref: '#/$defs/slotValue' } },\n ],\n },\n\n // STRICT canonical v4 envelope: a fixed set of reserved buckets plus a\n // single `slots` namespace holding every named child slot.\n // `additionalProperties: false` is what standardizes the shape \u2014 any stray\n // top-level key (a slot left outside `slots`, a typo) is rejected.\n componentEnvelope: {\n type: 'object',\n additionalProperties: false,\n properties: {\n // Root classes for the component. Usually a class string; some\n // components (e.g. sidebar) nest a sub-tree under root.\n root: { $ref: '#/$defs/slotValue' },\n\n // Canonical variant buckets (variants.variant, variants.size, \u2026) plus\n // the flat compatibility aliases.\n variants: { type: 'object', additionalProperties: { $ref: '#/$defs/reservedBucket' } },\n variant: { $ref: '#/$defs/reservedBucket' },\n size: { $ref: '#/$defs/reservedBucket' },\n sizes: { $ref: '#/$defs/reservedBucket' },\n iconPosition: { $ref: '#/$defs/reservedBucket' },\n icons: { $ref: '#/$defs/reservedBucket' },\n color: { $ref: '#/$defs/reservedBucket' },\n fullwidth: { $ref: '#/$defs/reservedBucket' },\n states: { $ref: '#/$defs/reservedBucket' },\n compoundVariants: { $ref: '#/$defs/reservedBucket' },\n defaultVariants: { $ref: '#/$defs/reservedBucket' },\n props: { $ref: '#/$defs/reservedBucket' },\n\n // All named child slots (item, trigger, content, icon, menu, \u2026) live\n // here. Top-level only \u2014 slot internals stay direct.\n slots: { type: 'object', additionalProperties: { $ref: '#/$defs/slotValue' } },\n },\n },\n },\n};\n\nfunction isCSSClassString(value) {\n if (typeof value !== 'string') return false;\n\n if (value.trim().length === 0) return false;\n\n if (/^[0-9]+(?:\\.[0-9]+)?$/.test(value)) return false;\n\n if (value === 'true' || value === 'false') return false;\n\n const hasSpaces = /\\s/.test(value);\n const hasTailwindSyntax = /[-:\\[\\]\\/]/.test(value);\n\n if (hasSpaces || hasTailwindSyntax) return true;\n\n return true;\n}\n\nmodule.exports = {\n componentsConfigSchema,\n isCSSClassString,\n};\n", "// ffdc.js - Simple config accessor\n// No base64 decoding, just returns the config object directly\n\nconst {\n componentsConfigSchema,\n isCSSClassString,\n} = require('./lib/core/components-config-schema');\n\nfunction ffdc(config) {\n if (!config) {\n return {};\n }\n\n if (typeof config !== 'object') {\n throw new Error('Config must be an object');\n }\n\n return config;\n}\n\nffdc.componentsConfigSchema = componentsConfigSchema;\nffdc.isCSSClassString = isCSSClassString;\n\nmodule.exports = ffdc;\n"],
5
- "mappings": "8DAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CASA,IAAMC,EAAmB,CACvB,MAAO,CACL,CAAE,KAAM,QAAS,EACjB,CAAE,KAAM,QAAS,EACjB,CAAE,KAAM,SAAU,EAClB,CAAE,KAAM,MAAO,CACjB,CACF,EAEMC,EAAyB,CAC7B,IAAK,gEACL,KAAM,SAGN,qBAAsB,CACpB,MAAO,CAAC,CAAE,KAAM,oBAAqB,EAAG,CAAE,KAAM,2BAA4B,CAAC,CAC/E,EACA,MAAO,CACL,WAAYD,EAMZ,UAAW,CACT,MAAO,CACL,CAAE,KAAM,oBAAqB,EAC7B,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CACxE,CACF,EAGA,eAAgB,CACd,MAAO,CACL,CAAE,KAAM,oBAAqB,EAC7B,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CACxE,CACF,EAMA,kBAAmB,CACjB,KAAM,SACN,qBAAsB,GACtB,WAAY,CAGV,KAAM,CAAE,KAAM,mBAAoB,EAIlC,SAAU,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,wBAAyB,CAAE,EACrF,QAAS,CAAE,KAAM,wBAAyB,EAC1C,KAAM,CAAE,KAAM,wBAAyB,EACvC,MAAO,CAAE,KAAM,wBAAyB,EACxC,aAAc,CAAE,KAAM,wBAAyB,EAC/C,MAAO,CAAE,KAAM,wBAAyB,EACxC,MAAO,CAAE,KAAM,wBAAyB,EACxC,UAAW,CAAE,KAAM,wBAAyB,EAC5C,OAAQ,CAAE,KAAM,wBAAyB,EACzC,iBAAkB,CAAE,KAAM,wBAAyB,EACnD,gBAAiB,CAAE,KAAM,wBAAyB,EAClD,MAAO,CAAE,KAAM,wBAAyB,EAIxC,MAAO,CAAE,KAAM,SAAU,qBAAsB,CAAE,KAAM,mBAAoB,CAAE,CAC/E,CACF,CACF,CACF,EAEA,SAASE,EAAiBC,EAAO,CAO/B,GANI,OAAOA,GAAU,UAEjBA,EAAM,KAAK,EAAE,SAAW,GAExB,wBAAwB,KAAKA,CAAK,GAElCA,IAAU,QAAUA,IAAU,QAAS,MAAO,GAElD,IAAMC,EAAY,KAAK,KAAKD,CAAK,EAC3BE,EAAoB,aAAa,KAAKF,CAAK,EAEjD,MAA2C,EAG7C,CAEAJ,EAAO,QAAU,CACf,uBAAAE,EACA,iBAAAC,CACF,ICpGA,GAAM,CACJ,uBAAAI,EACA,iBAAAC,CACF,EAAI,IAEJ,SAASC,EAAKC,EAAQ,CACpB,GAAI,CAACA,EACH,MAAO,CAAC,EAGV,GAAI,OAAOA,GAAW,SACpB,MAAM,IAAI,MAAM,0BAA0B,EAG5C,OAAOA,CACT,CAEAD,EAAK,uBAAyBF,EAC9BE,EAAK,iBAAmBD,EAExB,OAAO,QAAUC",
6
- "names": ["require_components_config_schema", "__commonJSMin", "exports", "module", "classValueSchema", "componentsConfigSchema", "isCSSClassString", "value", "hasSpaces", "hasTailwindSyntax", "componentsConfigSchema", "isCSSClassString", "ffdc", "config"]
3
+ "sources": ["../lib/core/components-config-schema.js", "../lib/core/components-config-v4.js", "../ffdc.js"],
4
+ "sourcesContent": ["/**\n * Canonical Frontfriend v4 componentsConfig schema.\n *\n * Styling and runtime behavior are deliberately separate. Every string below\n * `styles` is a Tailwind class string; values below `behavior` are component\n * data and are never interpreted as CSS.\n */\n\nconst componentsConfigSchema = {\n $id: \"https://frontfriend.dev/schemas/components-config.v4.schema.json\",\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/componentConfig\" },\n $defs: {\n // A component config is either a fully-migrated v4 envelope OR an explicit\n // legacy/unresolved custom payload awaiting promotion (#512/#514). The\n // generic converter never guesses how custom fields map to styles/behavior;\n // it preserves the v3 payload verbatim under `legacy` until promotion.\n componentConfig: {\n anyOf: [\n { $ref: \"#/$defs/componentEnvelope\" },\n { $ref: \"#/$defs/legacyEntry\" },\n ],\n },\n legacyEntry: {\n type: \"object\",\n additionalProperties: false,\n required: [\"legacy\"],\n properties: { legacy: {} },\n },\n styleTree: {\n anyOf: [\n { type: \"string\" },\n { type: \"object\", additionalProperties: { $ref: \"#/$defs/styleTree\" } },\n ],\n },\n behaviorTree: {\n anyOf: [\n { type: [\"string\", \"number\", \"boolean\", \"null\"] },\n { type: \"array\", items: { $ref: \"#/$defs/behaviorTree\" } },\n {\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/behaviorTree\" },\n },\n ],\n },\n componentEnvelope: {\n type: \"object\",\n additionalProperties: false,\n required: [\"styles\"],\n properties: {\n styles: {\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/styleTree\" },\n },\n behavior: {\n type: \"object\",\n additionalProperties: { $ref: \"#/$defs/behaviorTree\" },\n },\n },\n },\n },\n};\n\nfunction isCSSClassString(value) {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\nmodule.exports = {\n componentsConfigSchema,\n isCSSClassString,\n};\n", "function isPlainObject(value) {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction deepMerge(left, right) {\n if (!isPlainObject(left) || !isPlainObject(right))\n return right === undefined ? left : right;\n\n const result = { ...left };\n for (const [key, value] of Object.entries(right)) {\n result[key] = key in result ? deepMerge(result[key], value) : value;\n }\n return result;\n}\n\nfunction findTreeConflicts(left, right, path = [], conflicts = []) {\n if (left === undefined || right === undefined) return conflicts;\n if (!isPlainObject(left) || !isPlainObject(right)) {\n conflicts.push(path.join('.'));\n return conflicts;\n }\n\n for (const key of Object.keys(left)) {\n if (key in right) {\n findTreeConflicts(left[key], right[key], [...path, key], conflicts);\n }\n }\n return conflicts;\n}\n\nfunction isV4Envelope(value) {\n return isPlainObject(value) && (\"styles\" in value || \"behavior\" in value);\n}\n\nfunction toRuntimeComponentConfig(envelope, component = 'component') {\n if (!isV4Envelope(envelope)) return envelope;\n const conflicts = findTreeConflicts(envelope.styles, envelope.behavior, [component]);\n if (conflicts.length > 0) {\n throw new Error(`Component config styles/behavior conflict at ${conflicts.join(', ')}`);\n }\n return deepMerge(envelope.styles || {}, envelope.behavior || {});\n}\n\nfunction toRuntimeComponentsConfig(config) {\n if (!isPlainObject(config)) return config;\n\n let changed = false;\n const result = {};\n for (const [name, envelope] of Object.entries(config)) {\n result[name] = toRuntimeComponentConfig(envelope, name);\n if (result[name] !== envelope) changed = true;\n }\n return changed ? result : config;\n}\n\nmodule.exports = {\n deepMerge,\n findTreeConflicts,\n isV4Envelope,\n toRuntimeComponentConfig,\n toRuntimeComponentsConfig,\n};\n", "// ffdc.js - Simple config accessor\n// No base64 decoding, just returns the config object directly\n\nconst {\n componentsConfigSchema,\n isCSSClassString,\n} = require('./lib/core/components-config-schema');\nconst { toRuntimeComponentsConfig } = require('./lib/core/components-config-v4');\n\nfunction ffdc(config) {\n if (!config) {\n return {};\n }\n\n if (typeof config !== 'object') {\n throw new Error('Config must be an object');\n }\n\n return toRuntimeComponentsConfig(config);\n}\n\nffdc.componentsConfigSchema = componentsConfigSchema;\nffdc.isCSSClassString = isCSSClassString;\n\nmodule.exports = ffdc;\n"],
5
+ "mappings": "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",
6
+ "names": ["require_components_config_schema", "__commonJSMin", "exports", "module", "componentsConfigSchema", "isCSSClassString", "value", "require_components_config_v4", "__commonJSMin", "exports", "module", "isPlainObject", "value", "deepMerge", "left", "right", "result", "key", "findTreeConflicts", "path", "conflicts", "isV4Envelope", "toRuntimeComponentConfig", "envelope", "component", "toRuntimeComponentsConfig", "config", "changed", "name", "componentsConfigSchema", "isCSSClassString", "toRuntimeComponentsConfig", "ffdc", "config"]
7
7
  }