@lema-ufpb/ds-sync 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +23 -10
  2. package/dist/cli.js +5 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -154,6 +154,19 @@ Triggers on **push to `main`**. The release-please bot:
154
154
  2. Opens/updates a `chore(release): vX.Y.Z` PR containing updates to `package.json`, `.release-please-manifest.json` and `CHANGELOG.md`
155
155
  3. When the PR is merged → creates the `vX.Y.Z` tag + GitHub Release automatically
156
156
 
157
+ ### Post-release sync (`.github/workflows/post-release-sync.yml`)
158
+
159
+ After each release, `develop` must be updated with the new manifest, version, and changelog from `main`. This workflow triggers on **`release: published`** and copies only `.release-please-manifest.json`, `package.json`, and `CHANGELOG.md` from `main` to `develop` — without merging branches.
160
+
161
+ **Why this is necessary:** release-please only updates these three files on `main` (via its release PR). Since the project uses GitFlow (`develop → main`, never `main → develop`), `develop` would otherwise keep stale version info. On the next `develop → main` PR, the stale files would overwrite the correct values on `main`, causing release-please to miscalculate the next version or open duplicate release PRs.
162
+
163
+ If the workflow fails, run manually:
164
+ ```bash
165
+ git checkout develop && git fetch origin main && \
166
+ git checkout origin/main -- .release-please-manifest.json package.json CHANGELOG.md && \
167
+ git commit -m "chore(release): sync develop after vX.Y.Z" && git push origin develop
168
+ ```
169
+
157
170
  ### CD (`.github/workflows/cd.yml`)
158
171
 
159
172
  Triggers on **`release: published`**.
@@ -175,16 +188,16 @@ For complex scenarios (tag created but publish failed, package published with cr
175
188
 
176
189
  For release-please to correctly calculate the next version and generate `CHANGELOG.md`, **all commits must follow the [Conventional Commits](https://www.conventionalcommits.org) standard**:
177
190
 
178
- | Prefix | Bump (pre-1.0) | Appears in CHANGELOG |
179
- | :--------------------------------------- | :------------------------------ | :------------------- |
180
- | `feat:` | minor (`0.X.0`) | Features |
181
- | `fix:` | patch (`0.0.X`) | Bug Fixes |
182
- | `perf:` | patch | Performance |
183
- | `refactor:` | patch | Refactor |
184
- | `docs:` | patch | Documentation |
185
- | `revert:` | patch | Reverts |
186
- | `feat!:` / `BREAKING CHANGE:` | minor (pre-1.0 doesn't jump to 1.0) | Breaking |
187
- | `chore:` `style:` `test:` `build:` `ci:` | — (no bump) | hidden |
191
+ | Prefix | Bump (semver) | Appears in CHANGELOG |
192
+ | :--------------------------------------- | :------------------------------- | :------------------- |
193
+ | `feat:` | minor (`X.1.0`) | Features |
194
+ | `fix:` | patch (`X.X.1`) | Bug Fixes |
195
+ | `perf:` | patch | Performance |
196
+ | `refactor:` | patch | Refactor |
197
+ | `docs:` | patch | Documentation |
198
+ | `revert:` | patch | Reverts |
199
+ | `feat!:` / `BREAKING CHANGE:` | major (`2.0.0`) | Breaking |
200
+ | `chore:` `style:` `test:` `build:` `ci:` | — (no bump) | hidden |
188
201
 
189
202
  ### Pull Request
190
203
 
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- var oe=Object.defineProperty;var xt=(t,n)=>()=>(t&&(n=t(t=0)),n);var Lt=(t,n)=>{for(var e in n)oe(t,e,{get:n[e],enumerable:!0})};var h,tt,A,B,yt,pt,u,$=xt(()=>{"use strict";h=class extends Error{constructor(e,o,i){super(o);this.code=e;this.hint=i;this.name="LemaError"}code;hint},tt=class extends h{constructor(n,e,o){super(n,e,o),this.name="AuthError"}},A=class extends h{constructor(n,e,o){super(n,e,o),this.name="ConfigError"}},B=class extends h{constructor(n,e,o){super(n,e,o),this.name="RegistryError"}},yt=class extends h{constructor(n,e,o){super(n,e,o),this.name="WriteError"}},pt=class extends h{constructor(n,e,o){super(n,e,o),this.name="ResolveError"}},u={SUCCESS:0,ERROR:1,AUTH:2,CONFIG:3,DRIFT:4,REGISTRY:5}});var Pt={};Lt(Pt,{loadConfig:()=>j,loadEnv:()=>I,parseEnvLine:()=>Ft,resolveTargetPath:()=>ft});import{readFileSync as se,existsSync as ie}from"fs";import{readFile as re}from"fs/promises";import{resolve as wt}from"path";function Ft(t){let n=t.trim();if(!n||n.startsWith("#"))return null;let e=n.indexOf("=");if(e===-1)return null;let o=n.slice(0,e).trim(),i=n.slice(e+1).trim();return(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))&&(i=i.slice(1,-1)),!o||!i?null:[o,i]}function I(t){let n=process.env.LEMA_DS_TOKEN??"",e=process.env.LEMA_DS_REGISTRY??ae,o=[".env.local",".env"].map(i=>wt(t,i));for(let i of o){if(!ie(i))continue;let s=se(i,"utf-8");for(let a of s.split(`
3
- `)){let r=Ft(a);if(!r)continue;let[l,p]=r;l==="LEMA_DS_TOKEN"&&!n&&(n=p),l==="LEMA_DS_REGISTRY"&&!e&&(e=p)}}return{token:n,registry:e}}function kt(t,n){return t?t.replace(/^\.\//,"").replace(/^@\//,""):n}async function j(t){let n=wt(t,"components.json"),e;try{let s=await re(n,"utf-8");e=JSON.parse(s)}catch{throw new A("E_CONFIG_NO_COMPONENTS_JSON",`components.json not found or invalid at ${n}`,"Run npx shadcn@latest init to generate components.json in your project.")}let o={ui:kt(e.aliases?.ui,"components/ui"),components:kt(e.aliases?.components,"components"),lib:kt(e.aliases?.lib,"lib"),hooks:kt(e.aliases?.hooks,"hooks")},i=e.tailwind?.css?wt(t,e.tailwind.css):null;return{componentsJson:e,aliases:o,tailwindCssPath:i,cwd:t}}function ft(t,n,e){if(e.startsWith("/"))throw new A("E_CONFIG_INVALID_TARGET",`Absolute target path not allowed: ${e}`,"Use relative paths starting with components/, lib/ or hooks/.");let o;if(e.startsWith("components/ui/")){let i=e.slice(14);o=`${t.ui}/${i}`}else if(e.startsWith("components/")){let i=e.slice(11);o=`${t.components}/${i}`}else if(e.startsWith("lib/")){let i=e.slice(4);o=`${t.lib}/${i}`}else if(e.startsWith("hooks/")){let i=e.slice(6);o=`${t.hooks}/${i}`}else o=e;return wt(n,o)}var ae,U=xt(()=>{"use strict";$();ae="https://ds.lema.ufpb.br"});var Vt={};Lt(Vt,{detectPackageManager:()=>Wt,getInstallArgs:()=>Gt,installPackages:()=>X});import{existsSync as gt}from"fs";import{resolve as dt}from"path";import{execSync as Ce}from"child_process";function Wt(t){if(gt(dt(t,"pnpm-lock.yaml")))return"pnpm";if(gt(dt(t,"yarn.lock")))return"yarn";if(gt(dt(t,"bun.lockb"))||gt(dt(t,"bun.lock")))return"bun";if(gt(dt(t,"package-lock.json")))return"npm";let n=process.env.npm_config_user_agent??"";return n.includes("pnpm")?"pnpm":n.includes("yarn")?"yarn":n.includes("bun")?"bun":"npm"}function Gt(t,n){switch(t){case"npm":return["install",...n,"--save-dev"];case"pnpm":return["add",...n,"--save-dev"];case"yarn":return["add",...n,"--dev"];case"bun":return["add",...n,"--dev"]}}async function X(t,n,e){let o=e??Wt(t),i=Gt(o,n);try{Ce(`${o} ${i.join(" ")}`,{cwd:t,stdio:"ignore",timeout:12e4})}catch{throw new h("E_PM_INSTALL",`Failed to install packages with ${o}`,`Run manually: ${o} ${i.join(" ")}`)}}var ut=xt(()=>{"use strict";$()});import{Command as ze}from"commander";import Ot from"picocolors";import*as Y from"@clack/prompts";var it="info",It=!1;function _t(t){it=t}function Nt(t){It=t}function C(){return It}function N(){return it==="silent"}function S(t){It&&console.log(JSON.stringify(t,null,2))}function c(t){it!=="silent"&&console.log(t)}function T(t){it!=="silent"&&console.error(Ot.yellow(`\u26A0 ${t}`))}function R(t){it!=="silent"&&console.error(Ot.red(`\u2716 ${t}`))}function O(t){it!=="silent"&&console.log(Ot.green(`\u2714 ${t}`))}function E(t,n){let e=Y.spinner();return e.start(t),n().finally(()=>e.stop(""))}function z(t){return Y.confirm({message:t})}function Dt(t,n){return Y.select({message:t,options:n})}function D(t){it!=="silent"&&Y.outro(t)}U();import{existsSync as Tt}from"fs";import{resolve as ce}from"path";import{execSync as le}from"child_process";$();async function et(t,n){let e=ce(t,"components.json");if(Tt(e))return;if(n){if(At(t),!Tt(e))throw new A("E_CONFIG_NO_COMPONENTS_JSON","components.json still not found after npx shadcn@latest init","Run npx shadcn@latest init manually in your project.");return}if(C()||N())throw new A("E_CONFIG_NO_COMPONENTS_JSON","components.json not found","Run npx shadcn@latest init first, then try again.");if(!await z("components.json not found. Run npx shadcn@latest init to create it?"))throw new A("E_CONFIG_NO_COMPONENTS_JSON","components.json is required to run this command","Run npx shadcn@latest init first, then try again.");At(t)}function At(t){le("npx shadcn@latest init --defaults",{cwd:t,stdio:"inherit",timeout:12e4})}var me={ui:"components/ui",components:"components",lib:"lib",hooks:"hooks"};function q(t,n){let e=[];for(let[i,s]of Object.entries(me)){let a=n[i];a!==s&&e.push({from:`@/${s}/`,to:`@/${a}/`})}if(e.length===0)return t;e.sort((i,s)=>s.from.length-i.from.length);let o=t;for(let{from:i,to:s}of e)o=o.replaceAll(i,s);return o}function Q(t,n){let e=new Map;for(let i of n)for(let s of i.files??[]){if(!s.path||!s.target||!s.path.startsWith("components/ds/"))continue;let a=`@/${s.path.replace(/\.tsx$/,"")}`,r=`@/${s.target.replace(/\.tsx$/,"")}`;a!==r&&e.set(a,r)}let o=t;for(let[i,s]of e)o=o.replaceAll(i,s);return o=o.replaceAll("@/components/custom/","@/components/ds/"),o}$();var jt=3,Ut=250,pe=3e4;async function St(t,n,e=1){let o=new AbortController,i=setTimeout(()=>o.abort(),pe);try{let s={"User-Agent":"@lema-ufpb/ds-sync/0.3.0"};n&&(s.Authorization=`Bearer ${n}`);let a=await fetch(t,{headers:s,signal:o.signal});if(a.status===401)throw new tt("E_AUTH_401",`Token rejected by registry at ${t}`,"Check LEMA_DS_TOKEN in your .env.local file. Test with: ds whoami");if(a.status===404)throw new B("E_REGISTRY_NOT_FOUND",`Resource not found: ${t}`,"Use ds list to see available components.");if(a.status>=500&&e<jt){let r=Ut*Math.pow(2,e-1);return await new Promise(l=>setTimeout(l,r)),St(t,n,e+1)}if(!a.ok)throw new B("E_REGISTRY_NETWORK",`Registry returned ${a.status} for ${t}`,"Check connectivity and proxy settings.");return a}catch(s){if(s instanceof tt||s instanceof B)throw s;if(e<jt){let a=Ut*Math.pow(2,e-1);return await new Promise(r=>setTimeout(r,a)),St(t,n,e+1)}throw new B("E_REGISTRY_NETWORK",`Network error accessing ${t}: ${s instanceof Error?s.message:String(s)}`,"Check connectivity, proxy, and registry availability.")}finally{clearTimeout(i)}}async function J(t,n){let e=`${t}/r/registry.json`,i=await(await St(e,n)).json();if(!i||typeof i!="object"||!("name"in i)||!("items"in i))throw new B("E_REGISTRY_INVALID",`Malformed registry manifest at ${e}`,"Report to the registry maintainer.");let s=i;return{name:String(s.name),version:String(s.version??"0.0.0"),homepage:s.homepage?String(s.homepage):void 0,items:s.items??[]}}async function F(t,n,e){let o=`${t}/r/${e}.json`,s=await(await St(o,n)).json();if(!s||typeof s!="object"||!("name"in s))throw new B("E_REGISTRY_INVALID",`Malformed registry item for "${e}" at ${o}`,"Report to the registry maintainer.");return s}$();async function Ct(t,n){let e=new Set,o=new Set,i=[],s=new Set;async function a(r,l){if(e.has(r))return;if(o.has(r)){let g=[...l,r].join(" \u2192 ");throw new pt("E_RESOLVE_CYCLE",`Cycle detected in registryDependencies: ${g}`,"Report to the registry maintainer.")}o.add(r);let p=[...l,r],f;try{f=await n(r)}catch(g){throw o.delete(r),g instanceof h?g:new pt("E_RESOLVE_UNKNOWN",`Item "${r}" not found in registry`,g instanceof Error?g.message:String(g))}if(f.dependencies)for(let g of f.dependencies)s.add(g);if(f.registryDependencies)for(let g of f.registryDependencies)await a(g,p);o.delete(r),e.add(r),i.push(f)}for(let r of t)await a(r,[]);return{items:i,allNpmDeps:s}}$();U();import{writeFile as fe,rename as ge,unlink as de}from"fs/promises";import{existsSync as yn}from"fs";import{dirname as ue}from"path";import{randomUUID as he}from"crypto";async function nt(t,n){let e=[],o=[];try{for(let i of n){let s=ft(t.aliases,t.cwd,i.target),a=ue(s),{mkdir:r}=await import("fs/promises");await r(a,{recursive:!0});let l=`${s}.lema-tmp-${he().slice(0,8)}`;await fe(l,i.content,"utf-8"),e.push({tmp:l,real:s}),o.push({target:i.target,resolvedPath:s})}for(let{tmp:i,real:s}of e)await ge(i,s);return o}catch(i){for(let{tmp:s}of e)try{await de(s)}catch{}throw new yt("E_WRITE_FILE",`Error writing files: ${i instanceof Error?i.message:String(i)}`,"Check write permissions in the project directory.")}}$();import{readFile as ye,writeFile as ke}from"fs/promises";import{existsSync as we}from"fs";import{resolve as Rt}from"path";function Jt(t){return{$schema:"https://ds.lema.ufpb.br/schemas/lock-v1.json",lockfileVersion:1,registry:{url:t,name:"",version:"0.0.0",fetchedAt:new Date().toISOString()},components:{},tokens:null}}async function _(t,n){let e=n?Rt(t,n):Rt(t,"ds.lock");if(!we(e))return null;try{let o=await ye(e,"utf-8"),i=JSON.parse(o);return i.lockfileVersion?i:null}catch{throw new A("E_LOCK_INVALID",`Corrupted lockfile at ${e}`,"Backup the file and run ds add --all to recreate it.")}}async function ot(t,n,e){let o=e?Rt(t,e):Rt(t,"ds.lock");await ke(o,JSON.stringify(n,null,2)+`
2
+ var oe=Object.defineProperty;var xt=(t,n)=>()=>(t&&(n=t(t=0)),n);var Lt=(t,n)=>{for(var e in n)oe(t,e,{get:n[e],enumerable:!0})};var h,tt,A,B,yt,mt,u,$=xt(()=>{"use strict";h=class extends Error{constructor(e,o,i){super(o);this.code=e;this.hint=i;this.name="LemaError"}code;hint},tt=class extends h{constructor(n,e,o){super(n,e,o),this.name="AuthError"}},A=class extends h{constructor(n,e,o){super(n,e,o),this.name="ConfigError"}},B=class extends h{constructor(n,e,o){super(n,e,o),this.name="RegistryError"}},yt=class extends h{constructor(n,e,o){super(n,e,o),this.name="WriteError"}},mt=class extends h{constructor(n,e,o){super(n,e,o),this.name="ResolveError"}},u={SUCCESS:0,ERROR:1,AUTH:2,CONFIG:3,DRIFT:4,REGISTRY:5}});var Pt={};Lt(Pt,{loadConfig:()=>U,loadEnv:()=>I,parseEnvLine:()=>Ft,resolveTargetPath:()=>ft});import{readFileSync as se,existsSync as ie}from"fs";import{readFile as re}from"fs/promises";import{resolve as wt}from"path";function Ft(t){let n=t.trim();if(!n||n.startsWith("#"))return null;let e=n.indexOf("=");if(e===-1)return null;let o=n.slice(0,e).trim(),i=n.slice(e+1).trim();return(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))&&(i=i.slice(1,-1)),!o||!i?null:[o,i]}function I(t){let n=process.env.LEMA_DS_TOKEN??"",e=process.env.LEMA_DS_REGISTRY??ae,o=[".env.local",".env"].map(i=>wt(t,i));for(let i of o){if(!ie(i))continue;let s=se(i,"utf-8");for(let a of s.split(`
3
+ `)){let r=Ft(a);if(!r)continue;let[l,m]=r;l==="LEMA_DS_TOKEN"&&!n&&(n=m),l==="LEMA_DS_REGISTRY"&&!e&&(e=m)}}return{token:n,registry:e}}function kt(t,n){return t?t.replace(/^\.\//,"").replace(/^@\//,""):n}async function U(t){let n=wt(t,"components.json"),e;try{let s=await re(n,"utf-8");e=JSON.parse(s)}catch{throw new A("E_CONFIG_NO_COMPONENTS_JSON",`components.json not found or invalid at ${n}`,"Run npx shadcn@latest init to generate components.json in your project.")}let o={ui:kt(e.aliases?.ui,"components/ui"),components:kt(e.aliases?.components,"components"),lib:kt(e.aliases?.lib,"lib"),hooks:kt(e.aliases?.hooks,"hooks")},i=e.tailwind?.css?wt(t,e.tailwind.css):null;return{componentsJson:e,aliases:o,tailwindCssPath:i,cwd:t}}function ft(t,n,e){if(e.startsWith("/"))throw new A("E_CONFIG_INVALID_TARGET",`Absolute target path not allowed: ${e}`,"Use relative paths starting with components/, lib/ or hooks/.");let o;if(e.startsWith("components/ui/")){let i=e.slice(14);o=`${t.ui}/${i}`}else if(e.startsWith("components/")){let i=e.slice(11);o=`${t.components}/${i}`}else if(e.startsWith("lib/")){let i=e.slice(4);o=`${t.lib}/${i}`}else if(e.startsWith("hooks/")){let i=e.slice(6);o=`${t.hooks}/${i}`}else o=e;return wt(n,o)}var ae,j=xt(()=>{"use strict";$();ae="https://ds.lema.ufpb.br"});var Vt={};Lt(Vt,{detectPackageManager:()=>Wt,getInstallArgs:()=>Gt,installPackages:()=>X});import{existsSync as gt}from"fs";import{resolve as dt}from"path";import{execSync as ve}from"child_process";function Wt(t){if(gt(dt(t,"pnpm-lock.yaml")))return"pnpm";if(gt(dt(t,"yarn.lock")))return"yarn";if(gt(dt(t,"bun.lockb"))||gt(dt(t,"bun.lock")))return"bun";if(gt(dt(t,"package-lock.json")))return"npm";let n=process.env.npm_config_user_agent??"";return n.includes("pnpm")?"pnpm":n.includes("yarn")?"yarn":n.includes("bun")?"bun":"npm"}function Gt(t,n){switch(t){case"npm":return["install",...n,"--save-dev"];case"pnpm":return["add",...n,"--save-dev"];case"yarn":return["add",...n,"--dev"];case"bun":return["add",...n,"--dev"]}}async function X(t,n,e){let o=e??Wt(t),i=Gt(o,n);try{ve(`${o} ${i.join(" ")}`,{cwd:t,stdio:"ignore",timeout:12e4})}catch{throw new h("E_PM_INSTALL",`Failed to install packages with ${o}`,`Run manually: ${o} ${i.join(" ")}`)}}var ut=xt(()=>{"use strict";$()});import{Command as ze}from"commander";import Ot from"picocolors";import*as Y from"@clack/prompts";var it="info",It=!1;function _t(t){it=t}function Nt(t){It=t}function v(){return It}function N(){return it==="silent"}function S(t){It&&console.log(JSON.stringify(t,null,2))}function c(t){it!=="silent"&&console.log(t)}function T(t){it!=="silent"&&console.error(Ot.yellow(`\u26A0 ${t}`))}function C(t){it!=="silent"&&console.error(Ot.red(`\u2716 ${t}`))}function O(t){it!=="silent"&&console.log(Ot.green(`\u2714 ${t}`))}function R(t,n){let e=Y.spinner();return e.start(t),n().finally(()=>e.stop(""))}function z(t){return Y.confirm({message:t})}function Dt(t,n){return Y.select({message:t,options:n})}function D(t){it!=="silent"&&Y.outro(t)}j();import{existsSync as Tt}from"fs";import{resolve as ce}from"path";import{execSync as le}from"child_process";$();async function et(t,n){let e=ce(t,"components.json");if(Tt(e))return;if(n){if(At(t),!Tt(e))throw new A("E_CONFIG_NO_COMPONENTS_JSON","components.json still not found after npx shadcn@latest init","Run npx shadcn@latest init manually in your project.");return}if(v()||N())throw new A("E_CONFIG_NO_COMPONENTS_JSON","components.json not found","Run npx shadcn@latest init first, then try again.");if(!await z("components.json not found. Run npx shadcn@latest init to create it?"))throw new A("E_CONFIG_NO_COMPONENTS_JSON","components.json is required to run this command","Run npx shadcn@latest init first, then try again.");At(t)}function At(t){le("npx shadcn@latest init --defaults",{cwd:t,stdio:"inherit",timeout:12e4})}var pe={ui:"components/ui",components:"components",lib:"lib",hooks:"hooks"};function q(t,n){let e=[];for(let[i,s]of Object.entries(pe)){let a=n[i];a!==s&&e.push({from:`@/${s}/`,to:`@/${a}/`})}if(e.length===0)return t;e.sort((i,s)=>s.from.length-i.from.length);let o=t;for(let{from:i,to:s}of e)o=o.replaceAll(i,s);return o}function Q(t,n){let e=new Map;for(let i of n)for(let s of i.files??[]){if(!s.path||!s.target||!s.path.startsWith("components/ds/"))continue;let a=`@/${s.path.replace(/\.tsx$/,"")}`,r=`@/${s.target.replace(/\.tsx$/,"")}`;a!==r&&e.set(a,r)}let o=t;for(let[i,s]of e)o=o.replaceAll(i,s);return o=o.replaceAll("@/components/custom/","@/components/ds/"),o}$();var Ut=3,jt=250,me=3e4;async function St(t,n,e=1){let o=new AbortController,i=setTimeout(()=>o.abort(),me);try{let s={"User-Agent":"@lema-ufpb/ds-sync/0.3.0"};n&&(s.Authorization=`Bearer ${n}`);let a=await fetch(t,{headers:s,signal:o.signal});if(a.status===401)throw new tt("E_AUTH_401",`Token rejected by registry at ${t}`,"Check LEMA_DS_TOKEN in your .env.local file. Test with: ds whoami");if(a.status===404)throw new B("E_REGISTRY_NOT_FOUND",`Resource not found: ${t}`,"Use ds list to see available components.");if(a.status>=500&&e<Ut){let r=jt*Math.pow(2,e-1);return await new Promise(l=>setTimeout(l,r)),St(t,n,e+1)}if(!a.ok)throw new B("E_REGISTRY_NETWORK",`Registry returned ${a.status} for ${t}`,"Check connectivity and proxy settings.");return a}catch(s){if(s instanceof tt||s instanceof B)throw s;if(e<Ut){let a=jt*Math.pow(2,e-1);return await new Promise(r=>setTimeout(r,a)),St(t,n,e+1)}throw new B("E_REGISTRY_NETWORK",`Network error accessing ${t}: ${s instanceof Error?s.message:String(s)}`,"Check connectivity, proxy, and registry availability.")}finally{clearTimeout(i)}}async function J(t,n){let e=`${t}/r/registry.json`,i=await(await St(e,n)).json();if(!i||typeof i!="object"||!("name"in i)||!("items"in i))throw new B("E_REGISTRY_INVALID",`Malformed registry manifest at ${e}`,"Report to the registry maintainer.");let s=i;return{name:String(s.name),version:String(s.version??"0.0.0"),homepage:s.homepage?String(s.homepage):void 0,items:s.items??[]}}async function F(t,n,e){let o=`${t}/r/${e}.json`,s=await(await St(o,n)).json();if(!s||typeof s!="object"||!("name"in s))throw new B("E_REGISTRY_INVALID",`Malformed registry item for "${e}" at ${o}`,"Report to the registry maintainer.");return s}$();async function vt(t,n){let e=new Set,o=new Set,i=[],s=new Set;async function a(r,l){if(e.has(r))return;if(o.has(r)){let g=[...l,r].join(" \u2192 ");throw new mt("E_RESOLVE_CYCLE",`Cycle detected in registryDependencies: ${g}`,"Report to the registry maintainer.")}o.add(r);let m=[...l,r],f;try{f=await n(r)}catch(g){throw o.delete(r),g instanceof h?g:new mt("E_RESOLVE_UNKNOWN",`Item "${r}" not found in registry`,g instanceof Error?g.message:String(g))}if(f.dependencies)for(let g of f.dependencies)s.add(g);if(f.registryDependencies)for(let g of f.registryDependencies)await a(g,m);o.delete(r),e.add(r),i.push(f)}for(let r of t)await a(r,[]);return{items:i,allNpmDeps:s}}$();j();import{writeFile as fe,rename as ge,unlink as de}from"fs/promises";import{existsSync as yn}from"fs";import{dirname as ue}from"path";import{randomUUID as he}from"crypto";async function nt(t,n){let e=[],o=[];try{for(let i of n){let s=ft(t.aliases,t.cwd,i.target),a=ue(s),{mkdir:r}=await import("fs/promises");await r(a,{recursive:!0});let l=`${s}.lema-tmp-${he().slice(0,8)}`;await fe(l,i.content,"utf-8"),e.push({tmp:l,real:s}),o.push({target:i.target,resolvedPath:s})}for(let{tmp:i,real:s}of e)await ge(i,s);return o}catch(i){for(let{tmp:s}of e)try{await de(s)}catch{}throw new yt("E_WRITE_FILE",`Error writing files: ${i instanceof Error?i.message:String(i)}`,"Check write permissions in the project directory.")}}$();import{readFile as ye,writeFile as ke}from"fs/promises";import{existsSync as we}from"fs";import{resolve as Ct}from"path";function Jt(t){return{$schema:"https://ds.lema.ufpb.br/schemas/lock-v1.json",lockfileVersion:1,registry:{url:t,name:"",version:"0.0.0",fetchedAt:new Date().toISOString()},components:{},tokens:null}}async function _(t,n){let e=n?Ct(t,n):Ct(t,"ds.lock");if(!we(e))return null;try{let o=await ye(e,"utf-8"),i=JSON.parse(o);return i.lockfileVersion?i:null}catch{throw new A("E_LOCK_INVALID",`Corrupted lockfile at ${e}`,"Backup the file and run ds add --all to recreate it.")}}async function ot(t,n,e){let o=e?Ct(t,e):Ct(t,"ds.lock");await ke(o,JSON.stringify(n,null,2)+`
4
4
  `,"utf-8")}function ct(t,n,e,o,i,s){t.components[e]={registryVersion:n,installedAt:new Date().toISOString(),files:o,dependencies:i,registryDependencies:s}}function lt(t,n,e,o){t.registry.url=n,t.registry.name=e,t.registry.version=o,t.registry.fetchedAt=new Date().toISOString()}import{createHash as Se}from"crypto";function W(t){let n=t.replace(/\r\n/g,`
5
- `);return Se("sha256").update(n,"utf-8").digest("hex")}async function Et(t){let e=await(await import("fs/promises")).readFile(t,"utf-8");return W(e)}ut();$();import{readFile as Re,writeFile as Ee}from"fs/promises";var Mt=/\/\*\s*lema-ds:tokens:start[^*]*\*\/[\s\S]*?\/\*\s*lema-ds:tokens:end\s*\*\//;function ve(t,n,e){let o=`/* lema-ds:tokens:start v${e} */
5
+ `);return Se("sha256").update(n,"utf-8").digest("hex")}async function Rt(t){let e=await(await import("fs/promises")).readFile(t,"utf-8");return W(e)}ut();$();import{readFile as Ce,writeFile as Re}from"fs/promises";var Mt=/\/\*\s*lema-ds:tokens:start[^*]*\*\/[\s\S]*?\/\*\s*lema-ds:tokens:end\s*\*\//;function Ee(t,n,e){let o=`/* lema-ds:tokens:start v${e} */
6
6
  /* AUTO-GENERATED by @lema-ufpb/ds-sync. Do not edit manually. */
7
7
  ${n.trim()}
8
8
  /* lema-ds:tokens:end */`;return Mt.test(t)?t.replace(Mt,o):t.trimEnd()+`
9
9
 
10
10
  `+o+`
11
- `}async function M(t,n,e){let o;try{o=await Re(t,"utf-8")}catch{throw new A("E_CONFIG_NO_TAILWIND_CSS",`CSS file declared in tailwind.css not found: ${t}`,"Verify the path in components.json \u2192 tailwind.css is correct.")}let i=ve(o,n,e);await Ee(t,i,"utf-8")}$();function Ht(t){t.command("add").description("Install one or more components from the LEMA Design System").argument("[components...]","Component name(s) to install").option("--all","Install all registry components").option("-y, --yes","Skip confirmation prompts").option("--no-install","Skip npm dependency installation").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--pm <name>","Package manager").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await be(n,e),process.exit(u.SUCCESS)}catch(o){if(C()&&S({command:"add",success:!1,error:o instanceof h?{code:o.code,message:o.message,hint:o.hint}:String(o)}),o instanceof h){R(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`);let i={E_AUTH_MISSING:u.AUTH,E_AUTH_401:u.AUTH,E_CONFIG_NO_COMPONENTS_JSON:u.CONFIG,E_CONFIG_NO_ALIAS:u.CONFIG,E_CONFIG_NO_TAILWIND_CSS:u.CONFIG};process.exit(i[o.code]??u.ERROR)}R(String(o)),process.exit(u.ERROR)}})}async function be(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.registry??o.registry,a=n.lock,r=C();!N()&&!r&&console.log(),await et(e,n.yes);let l=await j(e),p=await(r?J(s,i):E("Fetching registry...",()=>J(s,i))),f=p.items.map(m=>m.name),g;if(n.all){let m=await _(e,a),w=new Set(Object.keys(m?.components??{}));if(g=f.filter(k=>!w.has(k)),g.length===0){if(r){S({command:"add",success:!0,components:[],files:[],npmDependencies:[],registryVersion:p.version,tokensUpdated:!1,message:"all_already_installed"});return}O("All components already installed.");return}}else{if(t.length===0)throw new h("E_USAGE","Specify one or more component names or use --all","Example: ds add dashbox bar-chart");{let m=t.filter(w=>!f.includes(w));if(m.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not found: ${m.join(", ")}`,"Use ds list to see available components.");g=t}}r||c(`Resolving dependencies for ${g.length} component(s)...`);let d=await Ct(g,async m=>F(s,i,m)),y=[...d.allNpmDeps];if(!n.yes&&!r){c(`
11
+ `}async function M(t,n,e){let o;try{o=await Ce(t,"utf-8")}catch{throw new A("E_CONFIG_NO_TAILWIND_CSS",`CSS file declared in tailwind.css not found: ${t}`,"Verify the path in components.json \u2192 tailwind.css is correct.")}let i=Ee(o,n,e);await Re(t,i,"utf-8")}$();function Ht(t){t.command("add").description("Install one or more components from the LEMA Design System").argument("[components...]","Component name(s) to install").option("--all","Install all registry components").option("-y, --yes","Skip confirmation prompts").option("--no-install","Skip npm dependency installation").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--pm <name>","Package manager").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await be(n,e),process.exit(u.SUCCESS)}catch(o){if(v()&&S({command:"add",success:!1,error:o instanceof h?{code:o.code,message:o.message,hint:o.hint}:String(o)}),o instanceof h){C(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`);let i={E_AUTH_MISSING:u.AUTH,E_AUTH_401:u.AUTH,E_CONFIG_NO_COMPONENTS_JSON:u.CONFIG,E_CONFIG_NO_ALIAS:u.CONFIG,E_CONFIG_NO_TAILWIND_CSS:u.CONFIG};process.exit(i[o.code]??u.ERROR)}C(String(o)),process.exit(u.ERROR)}})}async function be(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.dev?"http://localhost:6006":n.registry??o.registry,a=n.lock,r=v();!N()&&!r&&console.log(),await et(e,n.yes);let l=await U(e),m=await(r?J(s,i):R("Fetching registry...",()=>J(s,i))),f=m.items.map(p=>p.name),g;if(n.all){let p=await _(e,a),w=new Set(Object.keys(p?.components??{}));if(g=f.filter(k=>!w.has(k)),g.length===0){if(r){S({command:"add",success:!0,components:[],files:[],npmDependencies:[],registryVersion:m.version,tokensUpdated:!1,message:"all_already_installed"});return}O("All components already installed.");return}}else{if(t.length===0)throw new h("E_USAGE","Specify one or more component names or use --all","Example: ds add dashbox bar-chart");{let p=t.filter(w=>!f.includes(w));if(p.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not found: ${p.join(", ")}`,"Use ds list to see available components.");g=t}}r||c(`Resolving dependencies for ${g.length} component(s)...`);let d=await vt(g,async p=>F(s,i,p)),y=[...d.allNpmDeps];if(!n.yes&&!r){c(`
12
12
  Components to install:`);for(let w of d.items)c(` \u2022 ${w.name}${w.title?` (${w.title})`:""}`);if(y.length>0&&c(`
13
- npm dependencies: ${y.join(", ")}`),!await z("Proceed?")){c("Operation cancelled.");return}}let v=d.items.flatMap(m=>(m.files??[]).filter(w=>!!w.content).map(w=>{let k=q(w.content,l.aliases);return k=Q(k,d.items),{target:w.target??w.path,content:k}})),L=await(r?nt(l,v):E("Writing files...",()=>nt(l,v)));if(!r)for(let m of L)O(`Written: ${m.resolvedPath}`);let Z=await _(e,a)??Jt(s);lt(Z,s,p.name,p.version);for(let m of d.items){let w=(m.files??[]).map(k=>{let b=k.content??"",x=q(b,l.aliases);return x=Q(x,d.items),{target:k.target??k.path,sha256:W(x)}});ct(Z,p.version,m.name,w,m.dependencies,m.registryDependencies)}await ot(e,Z,a),!n.noInstall&&y.length>0&&(r?await X(e,y):await E(`Installing dependencies (${y.length} packages)...`,async()=>{let{detectPackageManager:m}=await Promise.resolve().then(()=>(ut(),Vt)),w=n.pm??m(e);await X(e,y,w)}));let K=!1;if(!d.items.some(m=>m.type==="registry:style")){let m=await F(s,i,"tokens").catch(()=>null),w=l.tailwindCssPath,k=m?.files?.[0]?.content;w&&k&&(r?await M(w,k,p.version):(await E("Patching CSS tokens...",()=>M(w,k,p.version)),O("CSS tokens updated.")),K=!0)}if(r){S({command:"add",success:!0,components:d.items.map(m=>m.name),files:L.map(m=>({target:m.target,path:m.resolvedPath})),npmDependencies:y,registryVersion:p.version,tokensUpdated:K});return}D(`Added ${d.items.length} component(s).`)}U();$();function Kt(t){t.command("list").description("List available components in the registry").option("--installed","Show only installed components").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{await $e(n),process.exit(u.SUCCESS)}catch(e){C()&&S({command:"list",success:!1,error:e instanceof h?{code:e.code,message:e.message,hint:e.hint}:String(e)}),e instanceof h&&(T(`[${e.code}] ${e.message}`),process.exit(u.REGISTRY)),T(String(e)),process.exit(u.ERROR)}})}async function $e(t){let n=t.cwd??process.cwd(),e=I(n),o=t.token??e.token,i=t.registry??e.registry,s=t.lock;N()||console.log();let a=await E("Fetching registry...",()=>J(i,o));if(C()){if(t.installed){let l=await _(n,s);S({command:"list",mode:"installed",components:l?.components??{}})}else S({command:"list",mode:"available",...a});return}let r=a.version&&a.version!=="0.0.0"?` ${a.version}`:"";if(c(`ds v1.2.0 \u2014 Registry: ${a.name}${r}`),a.homepage&&c(`Homepage: ${a.homepage}`),c(""),t.installed){let l=await _(n,s);if(!l||Object.keys(l.components).length===0){T("No components installed.");return}c("Installed components:");for(let[p,f]of Object.entries(l.components)){let g=f.files.map(d=>d.target).join(", ");c(` \u2022 ${p}`),c(` Version: ${f.registryVersion}`),c(` Files: ${g}`)}}else{c(`Available components (${a.items.length}):`);for(let l of a.items)c(` \u2022 ${l.name}`)}D(`${t.installed?"Installed":"Available"}: ${t.installed?Object.keys((await _(n,s))?.components??{}).length:a.items.length}`)}U();ut();$();function Yt(t){t.command("update").description("Update installed components").argument("[components...]","Component name(s)").option("--all","Update all components").option("--force","Force update even if same version").option("-y, --yes","Skip confirmation prompts").option("--no-install","Skip npm dependency installation").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--pm <name>","Package manager").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await xe(n,e),process.exit(u.SUCCESS)}catch(o){C()&&S({command:"update",success:!1,error:o instanceof h?{code:o.code,message:o.message,hint:o.hint}:String(o)}),o instanceof h&&(R(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.ERROR)),R(String(o)),process.exit(u.ERROR)}})}async function xe(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.registry??o.registry,a=n.lock,r=C();!N()&&!r&&console.log(),await et(e,n.yes);let l=await _(e,a);if(!l||Object.keys(l.components).length===0){if(r){S({command:"update",success:!1,error:"no_components_installed"});return}T("No components installed. Run ds add first.");return}let p=await j(e),f=await(r?J(s,i):E("Fetching registry...",()=>J(s,i)));if(f.version===l.registry.version&&!n.force){if(r){S({command:"update",success:!0,components:[],files:[],npmDependencies:[],registryVersion:f.version,tokensUpdated:!1,message:"already_up_to_date"});return}O("Registry is already up to date (no changes).");return}let g;if(n.all)g=Object.keys(l.components);else if(t.length>0){let m=t.filter(w=>!l.components[w]);if(m.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not installed: ${m.join(", ")}`,"Use ds list --installed to see installed components.");g=t}else g=Object.keys(l.components);let d=await Ct(g,async m=>F(s,i,m));if(!n.yes&&!r&&!await z(`Update ${d.items.length} component(s) to version ${f.version}?`)){c("Operation cancelled.");return}let y=d.items.flatMap(m=>(m.files??[]).filter(w=>!!w.content).map(w=>{let k=q(w.content,p.aliases);return k=Q(k,d.items),{target:w.target??w.path,content:k}})),v=await(r?nt(p,y):E("Updating files...",()=>nt(p,y)));lt(l,s,f.name,f.version);for(let m of d.items){let w=(m.files??[]).map(k=>{let b=k.content??"",x=q(b,p.aliases);return x=Q(x,d.items),{target:k.target??k.path,sha256:W(x)}});ct(l,f.version,m.name,w,m.dependencies,m.registryDependencies)}await ot(e,l,a),r||O(`Updated ${v.length} file(s).`);let L=[...d.allNpmDeps];!n.noInstall&&L.length>0&&(r?await X(e,L):await E("Installing dependencies...",()=>X(e,L)));let rt=!1,Z=await F(s,i,"tokens").catch(()=>null),K=p.tailwindCssPath,at=Z?.files?.[0]?.content;if(K&&at&&(r?await M(K,at,f.version):await E("Patching CSS tokens...",()=>M(K,at,f.version)),rt=!0),r){S({command:"update",success:!0,components:d.items.map(m=>m.name),files:v.map(m=>({target:m.target,path:m.resolvedPath})),npmDependencies:L,registryVersion:f.version,tokensUpdated:rt});return}D(`Updated ${d.items.length} component(s).`)}U();$();import Oe from"picocolors";function zt(t){t.command("verify").description("Verify installed component integrity (local vs lock drift check)").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{let e=await Ie(n);process.exit(e?u.SUCCESS:u.DRIFT)}catch(e){e instanceof h&&(R(`[${e.code}] ${e.message}`),process.exit(u.ERROR)),R(String(e)),process.exit(u.ERROR)}})}async function Ie(t){let n=t.cwd??process.cwd(),e=t.lock;N()||console.log();let o=await _(n,e);if(!o)return T("No lockfile found. Run ds add first."),!0;let i=await j(n),s=[];for(let[a,r]of Object.entries(o.components))for(let l of r.files){let p=(await Promise.resolve().then(()=>(U(),Pt))).resolveTargetPath(i.aliases,n,l.target),f=await Et(p).catch(()=>null);f?f!==l.sha256&&s.push({name:a,target:l.target,expected:l.sha256,actual:f}):s.push({name:a,target:l.target,expected:l.sha256,actual:"FILE_MISSING"})}if(C())return S({command:"verify",ok:s.length===0,drifted:s}),s.length===0;if(s.length===0)return O("All components are intact. No drift detected."),!0;R(`Drift detected in ${s.length} file(s):`);for(let a of s)c(` ${Oe.red("!")} ${a.name}: ${a.target}`),c(` Expected: ${a.expected.slice(0,12)}...`),c(` Actual: ${a.actual==="FILE_MISSING"?"FILE MISSING":`${a.actual.slice(0,12)}...`}`);return c(""),T("Run ds diff to see detailed changes."),!1}U();$();import mt from"picocolors";function Bt(t){t.command("info").description("Show detailed information about a component").argument("<component>","Component name").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await _e(n,e),process.exit(u.SUCCESS)}catch(o){C()&&S({command:"info",success:!1,error:o instanceof h?{code:o.code,message:o.message,hint:o.hint}:String(o)}),o instanceof h&&(R(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.REGISTRY)),R(String(o)),process.exit(u.ERROR)}})}async function _e(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.registry??o.registry,a=await E(`Fetching ${t}...`,()=>F(s,i,t));if(C()){S({command:"info",...a});return}if(c(""),c(`${mt.bold(a.name)}${a.title?` \u2014 ${a.title}`:""}`),a.description&&c(` ${mt.dim(a.description)}`),c(""),c(`${mt.dim("Type:")} ${a.type}`),c(""),a.dependencies&&a.dependencies.length>0){c(`${mt.dim("npm dependencies:")}`);for(let r of a.dependencies)c(` \u2022 ${r}`);c("")}if(a.registryDependencies&&a.registryDependencies.length>0){c(`${mt.dim("Registry dependencies:")}`);for(let r of a.registryDependencies)c(` \u2022 ${r}`);c("")}c(`${mt.dim("Files:")}`);for(let r of a.files??[])c(` \u2022 ${r.path} (${r.type})`);D(`info: ${a.name}`)}U();$();import qt from"picocolors";function Qt(t){t.command("whoami").description("Validate auth token against the registry").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{await Le(n),process.exit(u.SUCCESS)}catch(e){C()&&S({command:"whoami",authenticated:!1,error:e instanceof h?{code:e.code,message:e.message,hint:e.hint}:String(e)}),e instanceof tt&&(R(`[${e.code}] ${e.message}`),e.hint&&c(` \u2192 ${e.hint}`),process.exit(u.AUTH)),e instanceof h&&(R(`[${e.code}] ${e.message}`),process.exit(u.ERROR)),R(String(e)),process.exit(u.ERROR)}})}async function Le(t){let n=t.cwd??process.cwd(),e=I(n),o=t.token??e.token,i=t.registry??e.registry;if(!o)throw new tt("E_AUTH_MISSING","Auth token not found","Set LEMA_DS_TOKEN in your .env.local file.");let s=await E("Validating token...",()=>J(i,o));if(C()){S({command:"whoami",authenticated:!0,registry:s.name,version:s.version});return}c(""),c(`${qt.green("\u2714")} Token is valid!`),c(` Registry: ${s.name} ${s.version}`),c(` URL: ${i}`);let a=o.length>8?`${o.slice(0,4)}${"\u2022".repeat(o.length-8)}${o.slice(-4)}`:"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";c(` Token: ${qt.dim(a)}`),D("Authenticated")}U();import V from"picocolors";import{execSync as Ne}from"child_process";import{existsSync as De,writeFileSync as Fe,unlinkSync as Pe}from"fs";import{readFile as Te}from"fs/promises";import{tmpdir as Ae}from"os";import{randomUUID as je}from"crypto";import{resolve as Ue}from"path";U();async function vt(t,n,e,o){let i=[];for(let s of e.files){let a=ft(t.aliases,t.cwd,s.target),r=De(a)?await Et(a).catch(()=>null):null,l=o?.files?.find(v=>(v.target??v.path)===s.target||v.path===s.target),p=l?.content??null,f=p?W(p):null,g=l&&(l.target??l.path)!==s.target?l.target??l.path:void 0,d;r?f===null?d=r===s.sha256?"up-to-date":"drift-only":r===s.sha256&&f===s.sha256?d="up-to-date":r===s.sha256&&f!==s.sha256?d="clean-update":r!==s.sha256&&f===s.sha256?d="drift-only":d="conflict":d="missing";let y=null;if(d==="conflict"||d==="drift-only")try{y=await Te(a,"utf-8")}catch{y=null}i.push({target:s.target,resolvedPath:a,status:d,localHash:r,lockHash:s.sha256,remoteHash:f,localContent:y,remoteContent:p,remoteTarget:g})}return{name:e.registryVersion,files:i}}function bt(t){let n={components:t,upToDate:0,cleanUpdates:0,drifts:0,conflicts:0,missing:0};for(let e of t)for(let o of e.files)o.status==="up-to-date"?n.upToDate++:o.status==="clean-update"?n.cleanUpdates++:o.status==="drift-only"?n.drifts++:o.status==="conflict"?n.conflicts++:o.status==="missing"&&n.missing++;return n}function Xt(t,n,e){let o=Ue(Ae(),`ds-${e}-${je().slice(0,8)}`);Fe(o,n,"utf-8");try{return Ne(`git diff --no-index -- "${t}" "${o}"`,{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:15e3})}catch(i){return i.stdout?i.stdout:i.stderr?i.stderr:`[diff failed: ${i.message}]`}finally{try{Pe(o)}catch{}}}function ht(t,n){return Xt(t,n,"remote")}function Zt(t,n,e){return Xt(t,n,e)}$();function te(t){t.command("diff").description("Show differences between local files and the registry").argument("[components...]","Component name(s)").option("--all","Show diff for all installed components").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await Je(n,e),process.exit(u.SUCCESS)}catch(o){o instanceof h&&(R(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.ERROR)),R(String(o)),process.exit(u.ERROR)}})}async function Je(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.registry??o.registry,a=n.lock;N()||console.log();let r=await _(e,a);if(!r||Object.keys(r.components).length===0){T("No components installed. Run ds add first.");return}let l=await j(e),p;if(n.all)p=Object.keys(r.components);else if(t.length>0){let d=t.filter(y=>!r.components[y]);if(d.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not installed: ${d.join(", ")}`,"Use ds list --installed to see installed components.");p=t}else p=Object.keys(r.components);let f=[];for(let d of p){let y=r.components[d],v=await F(s,i,d).catch(()=>null),L=await vt(l,r,y,v);f.push({...L,name:d})}let g=bt(f);if(C()){S({summary:g,components:f});return}if(g.upToDate===g.upToDate+g.cleanUpdates+g.drifts+g.conflicts+g.missing){O("All components are up to date. No differences found.");return}for(let d of f)for(let y of d.files)y.status!=="up-to-date"&&(c(""),c(V.bold(`\u{1F4C4} ${y.target}`)),c(` Status: ${We(y.status)}`),y.status==="drift-only"&&y.localContent&&(c(" Local changes (not reflected in lock):"),c(Zt(y.resolvedPath,y.localContent,"local"))),y.status==="conflict"&&y.remoteContent&&(c(" Conflict between local and remote versions:"),c(ht(y.resolvedPath,y.remoteContent))),y.status==="clean-update"&&y.remoteContent&&(c(" Remote version available (safe to apply):"),c(ht(y.resolvedPath,y.remoteContent))),y.status==="missing"&&c(` Expected file not found at: ${y.resolvedPath}`));c(""),c(Ge(g)),D("diff complete")}function We(t){return{"up-to-date":V.green("\u2713 up to date"),"clean-update":V.blue("\u21BB safe update"),"drift-only":V.yellow("\u26A1 locally edited"),conflict:V.red("\u2717 conflict"),missing:V.red("\u2717 file missing")}[t]??t}function Ge(t){let n=[];return t.upToDate>0&&n.push(V.green(`${t.upToDate} up to date`)),t.cleanUpdates>0&&n.push(V.blue(`${t.cleanUpdates} safe update(s)`)),t.drifts>0&&n.push(V.yellow(`${t.drifts} drift(s)`)),t.conflicts>0&&n.push(V.red(`${t.conflicts} conflict(s)`)),t.missing>0&&n.push(V.red(`${t.missing} missing`)),n.join(" | ")}U();import H from"picocolors";ut();$();function ee(t){t.command("sync").description("Synchronize installed components with the registry (interactive)").argument("[components...]","Component name(s)").option("--all","Synchronize all components").option("-y, --yes","Auto-apply safe changes (no prompts)").option("--no-install","Skip npm dependency installation").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--pm <name>","Package manager").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await Ve(n,e),process.exit(u.SUCCESS)}catch(o){o instanceof h&&(R(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.ERROR)),R(String(o)),process.exit(u.ERROR)}})}async function Ve(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.registry??o.registry,a=n.lock,r=C();!N()&&!r&&console.log(),await et(e,n.yes);let l=await _(e,a);if(!l||Object.keys(l.components).length===0){if(r){S({command:"sync",success:!1,message:"no_components_installed"});return}T("No components installed. Run ds add first.");return}let p=await j(e),f=await(r?J(s,i):E("Fetching registry...",()=>J(s,i)));f.version===l.registry.version&&!r&&O("Registry is up to date. Checking for local drift...");let g;if(n.all)g=Object.keys(l.components);else if(t.length>0){let k=t.filter(b=>!l.components[b]);if(k.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not installed: ${k.join(", ")}`,"Use ds list --installed to see installed components.");g=t}else g=Object.keys(l.components);let{diffs:d,remoteItems:y}=await Me(g,p,l,s,i),v=bt(d);if(r){S({command:"sync",summary:v,components:d});return}if(v.upToDate===v.upToDate+v.cleanUpdates+v.drifts+v.conflicts+v.missing&&v.cleanUpdates+v.drifts+v.conflicts===0){O("Everything is in sync. No changes detected.");return}c(""),c(H.bold("Change summary:")),c(Ke(v)),c("");let L=[],rt=[],Z=new Set;for(let k of d)for(let b of k.files){if(b.status==="up-to-date")continue;let x;if(n.yes?x=b.status==="conflict"?"skip":"take":x=await He(k.name,b),x==="abort"){c("Operation aborted by user.");return}if(x==="skip"){c(` ${H.dim("\u2192 skipping")} ${b.target}`);continue}if(x==="keep"){c(` ${H.dim("\u2192 keeping local")} ${b.target}`);continue}if(x==="take"&&b.remoteContent){let P=b.remoteTarget??b.target,st=q(b.remoteContent,p.aliases);st=Q(st,y),L.push({target:P,content:st}),O(`${H.green("\u2192")} ${P}`)}}if(L.length===0){c("No changes to apply.");return}if(!n.yes&&!await z(`Apply ${L.length} change(s)?`)){c("Operation cancelled.");return}await E("Applying changes...",()=>nt(p,L));for(let k of d){let b=y.find(P=>P.name===k.name);if(!b)continue;let x=(b.files??[]).filter(P=>L.some(st=>st.target===(P.target??P.path))).map(P=>{let st=P.content??"",$t=q(st,p.aliases);return $t=Q($t,y),{target:P.target??P.path,sha256:W($t)}});if(x.length>0&&(rt.push({name:k.name,files:x,dependencies:b.dependencies,registryDependencies:b.registryDependencies}),b.dependencies))for(let P of b.dependencies)Z.add(P)}lt(l,s,f.name,f.version);for(let k of rt)ct(l,f.version,k.name,k.files,k.dependencies,k.registryDependencies);await ot(e,l,a);let K=[...Z];!n.noInstall&&K.length>0&&await E("Installing dependencies...",()=>X(e,K));let at=await F(s,i,"tokens").catch(()=>null),m=p.tailwindCssPath,w=at?.files?.[0]?.content;m&&w&&await E("Patching CSS tokens...",()=>M(m,w,f.version)),D(`${L.length} file(s) synchronized.`)}async function Me(t,n,e,o,i){let s=[],a=[];for(let r of t){let l=e.components[r],p=await F(o,i,r).catch(()=>null);p&&a.push(p);let f=await vt(n,e,l,p);s.push({...f,name:r})}return{diffs:s,remoteItems:a}}async function He(t,n){c(""),c(H.bold(`Conflict in ${t} \u2014 ${n.target}`));let e=[{label:"Keep local",value:"keep"},{label:"Overwrite with remote",value:"take"},{label:"Skip this file",value:"skip"},{label:"Abort everything",value:"abort"}];n.remoteContent&&await z("View diff before deciding?")&&(c(""),c(ht(n.resolvedPath,n.remoteContent)));let o=await Dt(`What to do with ${n.target}?`,e);return typeof o!="string"?"skip":o}function Ke(t){let n=[];return t.upToDate>0&&n.push(H.green(`${t.upToDate} up to date`)),t.cleanUpdates>0&&n.push(H.blue(`${t.cleanUpdates} safe update(s)`)),t.drifts>0&&n.push(H.yellow(`${t.drifts} drift(s)`)),t.conflicts>0&&n.push(H.red(`${t.conflicts} conflict(s)`)),t.missing>0&&n.push(H.red(`${t.missing} missing`)),n.join(" | ")}U();$();function ne(t){t.command("sync-tokens").description("Force refetch and patch CSS tokens").option("--registry <url>","Registry URL").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{await Ye(n),process.exit(u.SUCCESS)}catch(e){C()&&S({command:"sync-tokens",success:!1,error:e instanceof h?{code:e.code,message:e.message,hint:e.hint}:String(e)}),e instanceof h&&(R(`[${e.code}] ${e.message}`),e.hint&&c(` \u2192 ${e.hint}`),process.exit(u.ERROR)),R(String(e)),process.exit(u.ERROR)}})}async function Ye(t){let n=t.cwd??process.cwd(),e=I(n),o=t.token??e.token,i=t.registry??e.registry,s=t.lock,a=C();!N()&&!a&&console.log(),await et(n);let r=await j(n);if(!r.tailwindCssPath)throw new h("E_CONFIG_NO_TAILWIND_CSS","tailwind.css not declared in components.json","Add tailwind.css to your components.json.");let p=(await E("Fetching tokens from registry...",()=>F(i,o,"tokens"))).files?.[0]?.content;if(!p)throw new h("E_REGISTRY_INVALID","Tokens item does not contain CSS content","Report to the registry maintainer.");let f=r.tailwindCssPath;await E("Patching globals.css...",()=>M(f,p,"0.0.0"));let g=await _(n,s);if(g&&(g.tokens={registryVersion:g.registry.version,installedAt:new Date().toISOString(),sha256:W(p)},await ot(n,g,s)),a){S({command:"sync-tokens",success:!0,sha256:W(p),path:r.tailwindCssPath});return}O(`CSS tokens updated at ${r.tailwindCssPath}`),D("sync-tokens complete")}var G=new ze;G.name("ds").description("CLI to manage LEMA Design System components").version("1.2.0").hook("preAction",t=>{let n=t.optsWithGlobals();n.silent?_t("silent"):n.verbose&&_t("verbose"),n.json&&Nt(!0)});G.option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output");Ht(G);Kt(G);Yt(G);zt(G);Bt(G);Qt(G);te(G);ee(G);ne(G);G.parse(process.argv);
13
+ npm dependencies: ${y.join(", ")}`),!await z("Proceed?")){c("Operation cancelled.");return}}let E=d.items.flatMap(p=>(p.files??[]).filter(w=>!!w.content).map(w=>{let k=q(w.content,l.aliases);return k=Q(k,d.items),{target:w.target??w.path,content:k}})),L=await(r?nt(l,E):R("Writing files...",()=>nt(l,E)));if(!r)for(let p of L)O(`Written: ${p.resolvedPath}`);let Z=await _(e,a)??Jt(s);lt(Z,s,m.name,m.version);for(let p of d.items){let w=(p.files??[]).map(k=>{let b=k.content??"",x=q(b,l.aliases);return x=Q(x,d.items),{target:k.target??k.path,sha256:W(x)}});ct(Z,m.version,p.name,w,p.dependencies,p.registryDependencies)}await ot(e,Z,a),!n.noInstall&&y.length>0&&(r?await X(e,y):await R(`Installing dependencies (${y.length} packages)...`,async()=>{let{detectPackageManager:p}=await Promise.resolve().then(()=>(ut(),Vt)),w=n.pm??p(e);await X(e,y,w)}));let K=!1;if(!d.items.some(p=>p.type==="registry:style")){let p=await F(s,i,"tokens").catch(()=>null),w=l.tailwindCssPath,k=p?.files?.[0]?.content;w&&k&&(r?await M(w,k,m.version):(await R("Patching CSS tokens...",()=>M(w,k,m.version)),O("CSS tokens updated.")),K=!0)}if(r){S({command:"add",success:!0,components:d.items.map(p=>p.name),files:L.map(p=>({target:p.target,path:p.resolvedPath})),npmDependencies:y,registryVersion:m.version,tokensUpdated:K});return}D(`Added ${d.items.length} component(s).`)}j();$();function Kt(t){t.command("list").description("List available components in the registry").option("--installed","Show only installed components").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{await $e(n),process.exit(u.SUCCESS)}catch(e){v()&&S({command:"list",success:!1,error:e instanceof h?{code:e.code,message:e.message,hint:e.hint}:String(e)}),e instanceof h&&(T(`[${e.code}] ${e.message}`),process.exit(u.REGISTRY)),T(String(e)),process.exit(u.ERROR)}})}async function $e(t){let n=t.cwd??process.cwd(),e=I(n),o=t.token??e.token,i=t.dev?"http://localhost:6006":t.registry??e.registry,s=t.lock;N()||console.log();let a=await R("Fetching registry...",()=>J(i,o));if(v()){if(t.installed){let l=await _(n,s);S({command:"list",mode:"installed",components:l?.components??{}})}else S({command:"list",mode:"available",...a});return}let r=a.version&&a.version!=="0.0.0"?` ${a.version}`:"";if(c(`ds v1.3.0 \u2014 Registry: ${a.name}${r}`),a.homepage&&c(`Homepage: ${a.homepage}`),c(""),t.installed){let l=await _(n,s);if(!l||Object.keys(l.components).length===0){T("No components installed.");return}c("Installed components:");for(let[m,f]of Object.entries(l.components)){let g=f.files.map(d=>d.target).join(", ");c(` \u2022 ${m}`),c(` Version: ${f.registryVersion}`),c(` Files: ${g}`)}}else{c(`Available components (${a.items.length}):`);for(let l of a.items)c(` \u2022 ${l.name}`)}D(`${t.installed?"Installed":"Available"}: ${t.installed?Object.keys((await _(n,s))?.components??{}).length:a.items.length}`)}j();ut();$();function Yt(t){t.command("update").description("Update installed components").argument("[components...]","Component name(s)").option("--all","Update all components").option("--force","Force update even if same version").option("-y, --yes","Skip confirmation prompts").option("--no-install","Skip npm dependency installation").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--pm <name>","Package manager").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await xe(n,e),process.exit(u.SUCCESS)}catch(o){v()&&S({command:"update",success:!1,error:o instanceof h?{code:o.code,message:o.message,hint:o.hint}:String(o)}),o instanceof h&&(C(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.ERROR)),C(String(o)),process.exit(u.ERROR)}})}async function xe(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.dev?"http://localhost:6006":n.registry??o.registry,a=n.lock,r=v();!N()&&!r&&console.log(),await et(e,n.yes);let l=await _(e,a);if(!l||Object.keys(l.components).length===0){if(r){S({command:"update",success:!1,error:"no_components_installed"});return}T("No components installed. Run ds add first.");return}let m=await U(e),f=await(r?J(s,i):R("Fetching registry...",()=>J(s,i)));if(f.version===l.registry.version&&!n.force){if(r){S({command:"update",success:!0,components:[],files:[],npmDependencies:[],registryVersion:f.version,tokensUpdated:!1,message:"already_up_to_date"});return}O("Registry is already up to date (no changes).");return}let g;if(n.all)g=Object.keys(l.components);else if(t.length>0){let p=t.filter(w=>!l.components[w]);if(p.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not installed: ${p.join(", ")}`,"Use ds list --installed to see installed components.");g=t}else g=Object.keys(l.components);let d=await vt(g,async p=>F(s,i,p));if(!n.yes&&!r&&!await z(`Update ${d.items.length} component(s) to version ${f.version}?`)){c("Operation cancelled.");return}let y=d.items.flatMap(p=>(p.files??[]).filter(w=>!!w.content).map(w=>{let k=q(w.content,m.aliases);return k=Q(k,d.items),{target:w.target??w.path,content:k}})),E=await(r?nt(m,y):R("Updating files...",()=>nt(m,y)));lt(l,s,f.name,f.version);for(let p of d.items){let w=(p.files??[]).map(k=>{let b=k.content??"",x=q(b,m.aliases);return x=Q(x,d.items),{target:k.target??k.path,sha256:W(x)}});ct(l,f.version,p.name,w,p.dependencies,p.registryDependencies)}await ot(e,l,a),r||O(`Updated ${E.length} file(s).`);let L=[...d.allNpmDeps];!n.noInstall&&L.length>0&&(r?await X(e,L):await R("Installing dependencies...",()=>X(e,L)));let rt=!1,Z=await F(s,i,"tokens").catch(()=>null),K=m.tailwindCssPath,at=Z?.files?.[0]?.content;if(K&&at&&(r?await M(K,at,f.version):await R("Patching CSS tokens...",()=>M(K,at,f.version)),rt=!0),r){S({command:"update",success:!0,components:d.items.map(p=>p.name),files:E.map(p=>({target:p.target,path:p.resolvedPath})),npmDependencies:L,registryVersion:f.version,tokensUpdated:rt});return}D(`Updated ${d.items.length} component(s).`)}j();$();import Oe from"picocolors";function zt(t){t.command("verify").description("Verify installed component integrity (local vs lock drift check)").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{let e=await Ie(n);process.exit(e?u.SUCCESS:u.DRIFT)}catch(e){e instanceof h&&(C(`[${e.code}] ${e.message}`),process.exit(u.ERROR)),C(String(e)),process.exit(u.ERROR)}})}async function Ie(t){let n=t.cwd??process.cwd(),e=t.lock;N()||console.log();let o=await _(n,e);if(!o)return T("No lockfile found. Run ds add first."),!0;let i=await U(n),s=[];for(let[a,r]of Object.entries(o.components))for(let l of r.files){let m=(await Promise.resolve().then(()=>(j(),Pt))).resolveTargetPath(i.aliases,n,l.target),f=await Rt(m).catch(()=>null);f?f!==l.sha256&&s.push({name:a,target:l.target,expected:l.sha256,actual:f}):s.push({name:a,target:l.target,expected:l.sha256,actual:"FILE_MISSING"})}if(v())return S({command:"verify",ok:s.length===0,drifted:s}),s.length===0;if(s.length===0)return O("All components are intact. No drift detected."),!0;C(`Drift detected in ${s.length} file(s):`);for(let a of s)c(` ${Oe.red("!")} ${a.name}: ${a.target}`),c(` Expected: ${a.expected.slice(0,12)}...`),c(` Actual: ${a.actual==="FILE_MISSING"?"FILE MISSING":`${a.actual.slice(0,12)}...`}`);return c(""),T("Run ds diff to see detailed changes."),!1}j();$();import pt from"picocolors";function Bt(t){t.command("info").description("Show detailed information about a component").argument("<component>","Component name").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await _e(n,e),process.exit(u.SUCCESS)}catch(o){v()&&S({command:"info",success:!1,error:o instanceof h?{code:o.code,message:o.message,hint:o.hint}:String(o)}),o instanceof h&&(C(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.REGISTRY)),C(String(o)),process.exit(u.ERROR)}})}async function _e(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.dev?"http://localhost:6006":n.registry??o.registry,a=await R(`Fetching ${t}...`,()=>F(s,i,t));if(v()){S({command:"info",...a});return}if(c(""),c(`${pt.bold(a.name)}${a.title?` \u2014 ${a.title}`:""}`),a.description&&c(` ${pt.dim(a.description)}`),c(""),c(`${pt.dim("Type:")} ${a.type}`),c(""),a.dependencies&&a.dependencies.length>0){c(`${pt.dim("npm dependencies:")}`);for(let r of a.dependencies)c(` \u2022 ${r}`);c("")}if(a.registryDependencies&&a.registryDependencies.length>0){c(`${pt.dim("Registry dependencies:")}`);for(let r of a.registryDependencies)c(` \u2022 ${r}`);c("")}c(`${pt.dim("Files:")}`);for(let r of a.files??[])c(` \u2022 ${r.path} (${r.type})`);D(`info: ${a.name}`)}j();$();import qt from"picocolors";function Qt(t){t.command("whoami").description("Validate auth token against the registry").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{await Le(n),process.exit(u.SUCCESS)}catch(e){v()&&S({command:"whoami",authenticated:!1,error:e instanceof h?{code:e.code,message:e.message,hint:e.hint}:String(e)}),e instanceof tt&&(C(`[${e.code}] ${e.message}`),e.hint&&c(` \u2192 ${e.hint}`),process.exit(u.AUTH)),e instanceof h&&(C(`[${e.code}] ${e.message}`),process.exit(u.ERROR)),C(String(e)),process.exit(u.ERROR)}})}async function Le(t){let n=t.cwd??process.cwd(),e=I(n),o=t.token??e.token,i=t.dev?"http://localhost:6006":t.registry??e.registry;if(!o)throw new tt("E_AUTH_MISSING","Auth token not found","Set LEMA_DS_TOKEN in your .env.local file.");let s=await R("Validating token...",()=>J(i,o));if(v()){S({command:"whoami",authenticated:!0,registry:s.name,version:s.version});return}c(""),c(`${qt.green("\u2714")} Token is valid!`),c(` Registry: ${s.name} ${s.version}`),c(` URL: ${i}`);let a=o.length>8?`${o.slice(0,4)}${"\u2022".repeat(o.length-8)}${o.slice(-4)}`:"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";c(` Token: ${qt.dim(a)}`),D("Authenticated")}j();import V from"picocolors";import{execSync as Ne}from"child_process";import{existsSync as De,writeFileSync as Fe,unlinkSync as Pe}from"fs";import{readFile as Te}from"fs/promises";import{tmpdir as Ae}from"os";import{randomUUID as Ue}from"crypto";import{resolve as je}from"path";j();async function Et(t,n,e,o){let i=[];for(let s of e.files){let a=ft(t.aliases,t.cwd,s.target),r=De(a)?await Rt(a).catch(()=>null):null,l=o?.files?.find(E=>(E.target??E.path)===s.target||E.path===s.target),m=l?.content??null,f=m?W(m):null,g=l&&(l.target??l.path)!==s.target?l.target??l.path:void 0,d;r?f===null?d=r===s.sha256?"up-to-date":"drift-only":r===s.sha256&&f===s.sha256?d="up-to-date":r===s.sha256&&f!==s.sha256?d="clean-update":r!==s.sha256&&f===s.sha256?d="drift-only":d="conflict":d="missing";let y=null;if(d==="conflict"||d==="drift-only")try{y=await Te(a,"utf-8")}catch{y=null}i.push({target:s.target,resolvedPath:a,status:d,localHash:r,lockHash:s.sha256,remoteHash:f,localContent:y,remoteContent:m,remoteTarget:g})}return{name:e.registryVersion,files:i}}function bt(t){let n={components:t,upToDate:0,cleanUpdates:0,drifts:0,conflicts:0,missing:0};for(let e of t)for(let o of e.files)o.status==="up-to-date"?n.upToDate++:o.status==="clean-update"?n.cleanUpdates++:o.status==="drift-only"?n.drifts++:o.status==="conflict"?n.conflicts++:o.status==="missing"&&n.missing++;return n}function Xt(t,n,e){let o=je(Ae(),`ds-${e}-${Ue().slice(0,8)}`);Fe(o,n,"utf-8");try{return Ne(`git diff --no-index -- "${t}" "${o}"`,{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:15e3})}catch(i){return i.stdout?i.stdout:i.stderr?i.stderr:`[diff failed: ${i.message}]`}finally{try{Pe(o)}catch{}}}function ht(t,n){return Xt(t,n,"remote")}function Zt(t,n,e){return Xt(t,n,e)}$();function te(t){t.command("diff").description("Show differences between local files and the registry").argument("[components...]","Component name(s)").option("--all","Show diff for all installed components").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await Je(n,e),process.exit(u.SUCCESS)}catch(o){o instanceof h&&(C(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.ERROR)),C(String(o)),process.exit(u.ERROR)}})}async function Je(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.dev?"http://localhost:6006":n.registry??o.registry,a=n.lock;N()||console.log();let r=await _(e,a);if(!r||Object.keys(r.components).length===0){T("No components installed. Run ds add first.");return}let l=await U(e),m;if(n.all)m=Object.keys(r.components);else if(t.length>0){let d=t.filter(y=>!r.components[y]);if(d.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not installed: ${d.join(", ")}`,"Use ds list --installed to see installed components.");m=t}else m=Object.keys(r.components);let f=[];for(let d of m){let y=r.components[d],E=await F(s,i,d).catch(()=>null),L=await Et(l,r,y,E);f.push({...L,name:d})}let g=bt(f);if(v()){S({summary:g,components:f});return}if(g.upToDate===g.upToDate+g.cleanUpdates+g.drifts+g.conflicts+g.missing){O("All components are up to date. No differences found.");return}for(let d of f)for(let y of d.files)y.status!=="up-to-date"&&(c(""),c(V.bold(`\u{1F4C4} ${y.target}`)),c(` Status: ${We(y.status)}`),y.status==="drift-only"&&y.localContent&&(c(" Local changes (not reflected in lock):"),c(Zt(y.resolvedPath,y.localContent,"local"))),y.status==="conflict"&&y.remoteContent&&(c(" Conflict between local and remote versions:"),c(ht(y.resolvedPath,y.remoteContent))),y.status==="clean-update"&&y.remoteContent&&(c(" Remote version available (safe to apply):"),c(ht(y.resolvedPath,y.remoteContent))),y.status==="missing"&&c(` Expected file not found at: ${y.resolvedPath}`));c(""),c(Ge(g)),D("diff complete")}function We(t){return{"up-to-date":V.green("\u2713 up to date"),"clean-update":V.blue("\u21BB safe update"),"drift-only":V.yellow("\u26A1 locally edited"),conflict:V.red("\u2717 conflict"),missing:V.red("\u2717 file missing")}[t]??t}function Ge(t){let n=[];return t.upToDate>0&&n.push(V.green(`${t.upToDate} up to date`)),t.cleanUpdates>0&&n.push(V.blue(`${t.cleanUpdates} safe update(s)`)),t.drifts>0&&n.push(V.yellow(`${t.drifts} drift(s)`)),t.conflicts>0&&n.push(V.red(`${t.conflicts} conflict(s)`)),t.missing>0&&n.push(V.red(`${t.missing} missing`)),n.join(" | ")}j();import H from"picocolors";ut();$();function ee(t){t.command("sync").description("Synchronize installed components with the registry (interactive)").argument("[components...]","Component name(s)").option("--all","Synchronize all components").option("-y, --yes","Auto-apply safe changes (no prompts)").option("--no-install","Skip npm dependency installation").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--pm <name>","Package manager").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async(n,e)=>{try{await Ve(n,e),process.exit(u.SUCCESS)}catch(o){o instanceof h&&(C(`[${o.code}] ${o.message}`),o.hint&&c(` \u2192 ${o.hint}`),process.exit(u.ERROR)),C(String(o)),process.exit(u.ERROR)}})}async function Ve(t,n){let e=n.cwd??process.cwd(),o=I(e),i=n.token??o.token,s=n.dev?"http://localhost:6006":n.registry??o.registry,a=n.lock,r=v();!N()&&!r&&console.log(),await et(e,n.yes);let l=await _(e,a);if(!l||Object.keys(l.components).length===0){if(r){S({command:"sync",success:!1,message:"no_components_installed"});return}T("No components installed. Run ds add first.");return}let m=await U(e),f=await(r?J(s,i):R("Fetching registry...",()=>J(s,i)));f.version===l.registry.version&&!r&&O("Registry is up to date. Checking for local drift...");let g;if(n.all)g=Object.keys(l.components);else if(t.length>0){let k=t.filter(b=>!l.components[b]);if(k.length>0)throw new h("E_RESOLVE_UNKNOWN",`Component(s) not installed: ${k.join(", ")}`,"Use ds list --installed to see installed components.");g=t}else g=Object.keys(l.components);let{diffs:d,remoteItems:y}=await Me(g,m,l,s,i),E=bt(d);if(r){S({command:"sync",summary:E,components:d});return}if(E.upToDate===E.upToDate+E.cleanUpdates+E.drifts+E.conflicts+E.missing&&E.cleanUpdates+E.drifts+E.conflicts===0){O("Everything is in sync. No changes detected.");return}c(""),c(H.bold("Change summary:")),c(Ke(E)),c("");let L=[],rt=[],Z=new Set;for(let k of d)for(let b of k.files){if(b.status==="up-to-date")continue;let x;if(n.yes?x=b.status==="conflict"?"skip":"take":x=await He(k.name,b),x==="abort"){c("Operation aborted by user.");return}if(x==="skip"){c(` ${H.dim("\u2192 skipping")} ${b.target}`);continue}if(x==="keep"){c(` ${H.dim("\u2192 keeping local")} ${b.target}`);continue}if(x==="take"&&b.remoteContent){let P=b.remoteTarget??b.target,st=q(b.remoteContent,m.aliases);st=Q(st,y),L.push({target:P,content:st}),O(`${H.green("\u2192")} ${P}`)}}if(L.length===0){c("No changes to apply.");return}if(!n.yes&&!await z(`Apply ${L.length} change(s)?`)){c("Operation cancelled.");return}await R("Applying changes...",()=>nt(m,L));for(let k of d){let b=y.find(P=>P.name===k.name);if(!b)continue;let x=(b.files??[]).filter(P=>L.some(st=>st.target===(P.target??P.path))).map(P=>{let st=P.content??"",$t=q(st,m.aliases);return $t=Q($t,y),{target:P.target??P.path,sha256:W($t)}});if(x.length>0&&(rt.push({name:k.name,files:x,dependencies:b.dependencies,registryDependencies:b.registryDependencies}),b.dependencies))for(let P of b.dependencies)Z.add(P)}lt(l,s,f.name,f.version);for(let k of rt)ct(l,f.version,k.name,k.files,k.dependencies,k.registryDependencies);await ot(e,l,a);let K=[...Z];!n.noInstall&&K.length>0&&await R("Installing dependencies...",()=>X(e,K));let at=await F(s,i,"tokens").catch(()=>null),p=m.tailwindCssPath,w=at?.files?.[0]?.content;p&&w&&await R("Patching CSS tokens...",()=>M(p,w,f.version)),D(`${L.length} file(s) synchronized.`)}async function Me(t,n,e,o,i){let s=[],a=[];for(let r of t){let l=e.components[r],m=await F(o,i,r).catch(()=>null);m&&a.push(m);let f=await Et(n,e,l,m);s.push({...f,name:r})}return{diffs:s,remoteItems:a}}async function He(t,n){c(""),c(H.bold(`Conflict in ${t} \u2014 ${n.target}`));let e=[{label:"Keep local",value:"keep"},{label:"Overwrite with remote",value:"take"},{label:"Skip this file",value:"skip"},{label:"Abort everything",value:"abort"}];n.remoteContent&&await z("View diff before deciding?")&&(c(""),c(ht(n.resolvedPath,n.remoteContent)));let o=await Dt(`What to do with ${n.target}?`,e);return typeof o!="string"?"skip":o}function Ke(t){let n=[];return t.upToDate>0&&n.push(H.green(`${t.upToDate} up to date`)),t.cleanUpdates>0&&n.push(H.blue(`${t.cleanUpdates} safe update(s)`)),t.drifts>0&&n.push(H.yellow(`${t.drifts} drift(s)`)),t.conflicts>0&&n.push(H.red(`${t.conflicts} conflict(s)`)),t.missing>0&&n.push(H.red(`${t.missing} missing`)),n.join(" | ")}j();$();function ne(t){t.command("sync-tokens").description("Force refetch and patch CSS tokens").option("--registry <url>","Registry URL").option("--dev","Use local registry (http://localhost:6006) for testing").option("--token <token>","Auth token").option("--cwd <path>","Project directory").option("--lock <path>","Lockfile path").option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output").action(async n=>{try{await Ye(n),process.exit(u.SUCCESS)}catch(e){v()&&S({command:"sync-tokens",success:!1,error:e instanceof h?{code:e.code,message:e.message,hint:e.hint}:String(e)}),e instanceof h&&(C(`[${e.code}] ${e.message}`),e.hint&&c(` \u2192 ${e.hint}`),process.exit(u.ERROR)),C(String(e)),process.exit(u.ERROR)}})}async function Ye(t){let n=t.cwd??process.cwd(),e=I(n),o=t.token??e.token,i=t.dev?"http://localhost:6006":t.registry??e.registry,s=t.lock,a=v();!N()&&!a&&console.log(),await et(n);let r=await U(n);if(!r.tailwindCssPath)throw new h("E_CONFIG_NO_TAILWIND_CSS","tailwind.css not declared in components.json","Add tailwind.css to your components.json.");let m=(await R("Fetching tokens from registry...",()=>F(i,o,"tokens"))).files?.[0]?.content;if(!m)throw new h("E_REGISTRY_INVALID","Tokens item does not contain CSS content","Report to the registry maintainer.");let f=r.tailwindCssPath;await R("Patching globals.css...",()=>M(f,m,"0.0.0"));let g=await _(n,s);if(g&&(g.tokens={registryVersion:g.registry.version,installedAt:new Date().toISOString(),sha256:W(m)},await ot(n,g,s)),a){S({command:"sync-tokens",success:!0,sha256:W(m),path:r.tailwindCssPath});return}O(`CSS tokens updated at ${r.tailwindCssPath}`),D("sync-tokens complete")}var G=new ze;G.name("ds").description("CLI to manage LEMA Design System components").version("1.3.0").hook("preAction",t=>{let n=t.optsWithGlobals();n.silent?_t("silent"):n.verbose&&_t("verbose"),n.json&&Nt(!0)});G.option("--verbose","Verbose output").option("--silent","Errors only").option("--json","JSON output");Ht(G);Kt(G);Yt(G);zt(G);Bt(G);Qt(G);te(G);ee(G);ne(G);G.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lema-ufpb/ds-sync",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI to manage LEMA Design System components in consuming projects",
5
5
  "type": "module",
6
6
  "bin": {