@blotch/dolan 0.0.0-stage → 22.2.1

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 (273) hide show
  1. package/dist/commands/add.d.ts +22 -0
  2. package/dist/commands/add.js +132 -0
  3. package/dist/commands/add.js.map +1 -0
  4. package/dist/commands/add.test.d.ts +1 -0
  5. package/dist/commands/add.test.js +209 -0
  6. package/dist/commands/add.test.js.map +1 -0
  7. package/dist/commands/diff.d.ts +13 -0
  8. package/dist/commands/diff.js +155 -0
  9. package/dist/commands/diff.js.map +1 -0
  10. package/dist/commands/diff.test.d.ts +1 -0
  11. package/dist/commands/diff.test.js +327 -0
  12. package/dist/commands/diff.test.js.map +1 -0
  13. package/dist/commands/doctor.d.ts +15 -0
  14. package/dist/commands/doctor.js +248 -0
  15. package/dist/commands/doctor.js.map +1 -0
  16. package/dist/commands/doctor.test.d.ts +1 -0
  17. package/dist/commands/doctor.test.js +301 -0
  18. package/dist/commands/doctor.test.js.map +1 -0
  19. package/dist/commands/eject.d.ts +11 -0
  20. package/dist/commands/eject.js +55 -0
  21. package/dist/commands/eject.js.map +1 -0
  22. package/dist/commands/eject.test.d.ts +1 -0
  23. package/dist/commands/eject.test.js +151 -0
  24. package/dist/commands/eject.test.js.map +1 -0
  25. package/dist/commands/info.d.ts +1 -0
  26. package/dist/commands/info.js +73 -0
  27. package/dist/commands/info.js.map +1 -0
  28. package/dist/commands/info.test.d.ts +1 -0
  29. package/dist/commands/info.test.js +143 -0
  30. package/dist/commands/info.test.js.map +1 -0
  31. package/dist/commands/init.d.ts +1 -0
  32. package/dist/commands/init.js +98 -0
  33. package/dist/commands/init.js.map +1 -0
  34. package/dist/commands/init.test.d.ts +1 -0
  35. package/dist/commands/init.test.js +154 -0
  36. package/dist/commands/init.test.js.map +1 -0
  37. package/dist/commands/list.d.ts +16 -0
  38. package/dist/commands/list.js +124 -0
  39. package/dist/commands/list.js.map +1 -0
  40. package/dist/commands/list.test.d.ts +1 -0
  41. package/dist/commands/list.test.js +285 -0
  42. package/dist/commands/list.test.js.map +1 -0
  43. package/dist/commands/outdated.d.ts +13 -0
  44. package/dist/commands/outdated.js +116 -0
  45. package/dist/commands/outdated.js.map +1 -0
  46. package/dist/commands/outdated.test.d.ts +1 -0
  47. package/dist/commands/outdated.test.js +208 -0
  48. package/dist/commands/outdated.test.js.map +1 -0
  49. package/dist/commands/remove.d.ts +18 -0
  50. package/dist/commands/remove.js +161 -0
  51. package/dist/commands/remove.js.map +1 -0
  52. package/dist/commands/remove.test.d.ts +1 -0
  53. package/dist/commands/remove.test.js +361 -0
  54. package/dist/commands/remove.test.js.map +1 -0
  55. package/dist/commands/theme.d.ts +1 -0
  56. package/dist/commands/theme.js +66 -0
  57. package/dist/commands/theme.js.map +1 -0
  58. package/dist/commands/theme.test.d.ts +1 -0
  59. package/dist/commands/theme.test.js +133 -0
  60. package/dist/commands/theme.test.js.map +1 -0
  61. package/dist/commands/update.d.ts +31 -0
  62. package/dist/commands/update.js +601 -0
  63. package/dist/commands/update.js.map +1 -0
  64. package/dist/commands/update.test.d.ts +1 -0
  65. package/dist/commands/update.test.js +1233 -0
  66. package/dist/commands/update.test.js.map +1 -0
  67. package/dist/config.d.ts +11 -0
  68. package/dist/config.js +19 -0
  69. package/dist/config.js.map +1 -0
  70. package/dist/config.test.d.ts +1 -0
  71. package/dist/config.test.js +48 -0
  72. package/dist/config.test.js.map +1 -0
  73. package/dist/index.d.ts +2 -0
  74. package/dist/index.js +89 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/lockfile.d.ts +21 -0
  77. package/dist/lockfile.js +39 -0
  78. package/dist/lockfile.js.map +1 -0
  79. package/dist/registry.d.ts +14 -0
  80. package/dist/registry.js +85 -0
  81. package/dist/registry.js.map +1 -0
  82. package/dist/registry.test.d.ts +1 -0
  83. package/dist/registry.test.js +95 -0
  84. package/dist/registry.test.js.map +1 -0
  85. package/dist/test-utils.d.ts +16 -0
  86. package/dist/test-utils.js +65 -0
  87. package/dist/test-utils.js.map +1 -0
  88. package/dist/ui/components/accordion/accordion.test.ts +194 -0
  89. package/dist/ui/components/accordion/accordion.ts +173 -0
  90. package/dist/ui/components/accordion/index.ts +6 -0
  91. package/dist/ui/components/action-sheet/action-sheet.test.ts +211 -0
  92. package/dist/ui/components/action-sheet/action-sheet.ts +353 -0
  93. package/dist/ui/components/action-sheet/index.ts +6 -0
  94. package/dist/ui/components/alert/alert.test.ts +48 -0
  95. package/dist/ui/components/alert/alert.ts +104 -0
  96. package/dist/ui/components/alert/index.ts +1 -0
  97. package/dist/ui/components/alert-dialog/alert-dialog.test.ts +141 -0
  98. package/dist/ui/components/alert-dialog/alert-dialog.ts +243 -0
  99. package/dist/ui/components/alert-dialog/index.ts +7 -0
  100. package/dist/ui/components/area-chart/area-chart-render.test.ts +121 -0
  101. package/dist/ui/components/area-chart/area-chart.test.ts +158 -0
  102. package/dist/ui/components/area-chart/area-chart.ts +349 -0
  103. package/dist/ui/components/area-chart/index.ts +6 -0
  104. package/dist/ui/components/aspect-ratio/aspect-ratio.test.ts +10 -0
  105. package/dist/ui/components/aspect-ratio/aspect-ratio.ts +28 -0
  106. package/dist/ui/components/aspect-ratio/index.ts +1 -0
  107. package/dist/ui/components/avatar/avatar.test.ts +69 -0
  108. package/dist/ui/components/avatar/avatar.ts +131 -0
  109. package/dist/ui/components/avatar/index.ts +1 -0
  110. package/dist/ui/components/badge/badge.test.ts +49 -0
  111. package/dist/ui/components/badge/badge.ts +97 -0
  112. package/dist/ui/components/badge/index.ts +1 -0
  113. package/dist/ui/components/bar-chart/bar-chart-render.test.ts +174 -0
  114. package/dist/ui/components/bar-chart/bar-chart.test.ts +73 -0
  115. package/dist/ui/components/bar-chart/bar-chart.ts +327 -0
  116. package/dist/ui/components/bar-chart/index.ts +6 -0
  117. package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +163 -0
  118. package/dist/ui/components/bottom-sheet/bottom-sheet.ts +339 -0
  119. package/dist/ui/components/bottom-sheet/index.ts +1 -0
  120. package/dist/ui/components/button/button-render.test.ts +113 -0
  121. package/dist/ui/components/button/button.test.ts +70 -0
  122. package/dist/ui/components/button/button.ts +170 -0
  123. package/dist/ui/components/button/index.ts +6 -0
  124. package/dist/ui/components/button-group/button-group-render.test.ts +146 -0
  125. package/dist/ui/components/button-group/button-group.test.ts +54 -0
  126. package/dist/ui/components/button-group/button-group.ts +209 -0
  127. package/dist/ui/components/button-group/index.ts +8 -0
  128. package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +174 -0
  129. package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +96 -0
  130. package/dist/ui/components/candlestick-chart/candlestick-chart.ts +355 -0
  131. package/dist/ui/components/candlestick-chart/index.ts +7 -0
  132. package/dist/ui/components/card/card.test.ts +110 -0
  133. package/dist/ui/components/card/card.ts +162 -0
  134. package/dist/ui/components/card/index.ts +8 -0
  135. package/dist/ui/components/cartesian-chart/cartesian-chart-render.test.ts +188 -0
  136. package/dist/ui/components/cartesian-chart/cartesian-chart.test.ts +549 -0
  137. package/dist/ui/components/cartesian-chart/cartesian-chart.ts +1140 -0
  138. package/dist/ui/components/cartesian-chart/index.ts +18 -0
  139. package/dist/ui/components/checkbox/checkbox.test.ts +59 -0
  140. package/dist/ui/components/checkbox/checkbox.ts +96 -0
  141. package/dist/ui/components/checkbox/index.ts +1 -0
  142. package/dist/ui/components/collapsible/collapsible.test.ts +112 -0
  143. package/dist/ui/components/collapsible/collapsible.ts +122 -0
  144. package/dist/ui/components/collapsible/index.ts +5 -0
  145. package/dist/ui/components/dialog/dialog.test.ts +157 -0
  146. package/dist/ui/components/dialog/dialog.ts +248 -0
  147. package/dist/ui/components/dialog/index.ts +7 -0
  148. package/dist/ui/components/empty-state/empty-state.test.ts +60 -0
  149. package/dist/ui/components/empty-state/empty-state.ts +46 -0
  150. package/dist/ui/components/empty-state/index.ts +1 -0
  151. package/dist/ui/components/icon/icon.test.ts +52 -0
  152. package/dist/ui/components/icon/icon.ts +54 -0
  153. package/dist/ui/components/icon/icons.ts +569 -0
  154. package/dist/ui/components/icon/index.ts +2 -0
  155. package/dist/ui/components/input/index.ts +1 -0
  156. package/dist/ui/components/input/input.test.ts +134 -0
  157. package/dist/ui/components/input/input.ts +189 -0
  158. package/dist/ui/components/label/index.ts +1 -0
  159. package/dist/ui/components/label/label.test.ts +38 -0
  160. package/dist/ui/components/label/label.ts +24 -0
  161. package/dist/ui/components/line-chart/index.ts +6 -0
  162. package/dist/ui/components/line-chart/line-chart-render.test.ts +121 -0
  163. package/dist/ui/components/line-chart/line-chart.test.ts +81 -0
  164. package/dist/ui/components/line-chart/line-chart.ts +273 -0
  165. package/dist/ui/components/list/index.ts +1 -0
  166. package/dist/ui/components/list/list.test.ts +35 -0
  167. package/dist/ui/components/list/list.ts +71 -0
  168. package/dist/ui/components/nav-drawer/index.ts +8 -0
  169. package/dist/ui/components/nav-drawer/nav-drawer.test.ts +267 -0
  170. package/dist/ui/components/nav-drawer/nav-drawer.ts +504 -0
  171. package/dist/ui/components/pagination/index.ts +1 -0
  172. package/dist/ui/components/pagination/pagination.test.ts +96 -0
  173. package/dist/ui/components/pagination/pagination.ts +147 -0
  174. package/dist/ui/components/progress/index.ts +1 -0
  175. package/dist/ui/components/progress/progress.test.ts +71 -0
  176. package/dist/ui/components/progress/progress.ts +118 -0
  177. package/dist/ui/components/radio-group/index.ts +1 -0
  178. package/dist/ui/components/radio-group/radio-group.test.ts +115 -0
  179. package/dist/ui/components/radio-group/radio-group.ts +129 -0
  180. package/dist/ui/components/scatter-chart/index.ts +6 -0
  181. package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +157 -0
  182. package/dist/ui/components/scatter-chart/scatter-chart.test.ts +57 -0
  183. package/dist/ui/components/scatter-chart/scatter-chart.ts +277 -0
  184. package/dist/ui/components/scroll-area/index.ts +1 -0
  185. package/dist/ui/components/scroll-area/scroll-area.test.ts +40 -0
  186. package/dist/ui/components/scroll-area/scroll-area.ts +73 -0
  187. package/dist/ui/components/select/index.ts +1 -0
  188. package/dist/ui/components/select/select.test.ts +107 -0
  189. package/dist/ui/components/select/select.ts +146 -0
  190. package/dist/ui/components/separator/index.ts +1 -0
  191. package/dist/ui/components/separator/separator.test.ts +26 -0
  192. package/dist/ui/components/separator/separator.ts +45 -0
  193. package/dist/ui/components/sheet/index.ts +7 -0
  194. package/dist/ui/components/sheet/sheet.test.ts +44 -0
  195. package/dist/ui/components/sheet/sheet.ts +114 -0
  196. package/dist/ui/components/skeleton/index.ts +1 -0
  197. package/dist/ui/components/skeleton/skeleton.test.ts +13 -0
  198. package/dist/ui/components/skeleton/skeleton.ts +45 -0
  199. package/dist/ui/components/spinner/index.ts +1 -0
  200. package/dist/ui/components/spinner/spinner.test.ts +39 -0
  201. package/dist/ui/components/spinner/spinner.ts +83 -0
  202. package/dist/ui/components/switch/index.ts +1 -0
  203. package/dist/ui/components/switch/switch.test.ts +63 -0
  204. package/dist/ui/components/switch/switch.ts +98 -0
  205. package/dist/ui/components/tabs/index.ts +1 -0
  206. package/dist/ui/components/tabs/tabs.test.ts +199 -0
  207. package/dist/ui/components/tabs/tabs.ts +317 -0
  208. package/dist/ui/components/textarea/index.ts +1 -0
  209. package/dist/ui/components/textarea/textarea.test.ts +138 -0
  210. package/dist/ui/components/textarea/textarea.ts +221 -0
  211. package/dist/ui/components/toast/index.ts +9 -0
  212. package/dist/ui/components/toast/toast-state.test.ts +54 -0
  213. package/dist/ui/components/toast/toast-state.ts +46 -0
  214. package/dist/ui/components/toast/toast.test.ts +342 -0
  215. package/dist/ui/components/toast/toast.ts +527 -0
  216. package/dist/ui/components/toggle/index.ts +7 -0
  217. package/dist/ui/components/toggle/toggle.test.ts +186 -0
  218. package/dist/ui/components/toggle/toggle.ts +218 -0
  219. package/dist/ui/components/typography/index.ts +5 -0
  220. package/dist/ui/components/typography/typography.test.ts +55 -0
  221. package/dist/ui/components/typography/typography.ts +44 -0
  222. package/dist/ui/theme/dark.css +41 -0
  223. package/dist/ui/theme/default.css +56 -0
  224. package/dist/ui/theme/tailwind-plugin.test.ts +124 -0
  225. package/dist/ui/theme/tailwind-plugin.ts +151 -0
  226. package/dist/ui/utils/animate.test.ts +324 -0
  227. package/dist/ui/utils/animate.ts +544 -0
  228. package/dist/ui/utils/cn.test.ts +27 -0
  229. package/dist/ui/utils/cn.ts +6 -0
  230. package/dist/utils/analyze.d.ts +32 -0
  231. package/dist/utils/analyze.js +109 -0
  232. package/dist/utils/analyze.js.map +1 -0
  233. package/dist/utils/analyze.test.d.ts +1 -0
  234. package/dist/utils/analyze.test.js +146 -0
  235. package/dist/utils/analyze.test.js.map +1 -0
  236. package/dist/utils/animate.d.ts +210 -0
  237. package/dist/utils/animate.js +423 -0
  238. package/dist/utils/animate.js.map +1 -0
  239. package/dist/utils/animate.test.d.ts +1 -0
  240. package/dist/utils/animate.test.js +365 -0
  241. package/dist/utils/animate.test.js.map +1 -0
  242. package/dist/utils/banner.d.ts +1 -0
  243. package/dist/utils/banner.js +15 -0
  244. package/dist/utils/banner.js.map +1 -0
  245. package/dist/utils/banner.test.d.ts +1 -0
  246. package/dist/utils/banner.test.js +29 -0
  247. package/dist/utils/banner.test.js.map +1 -0
  248. package/dist/utils/cn.d.ts +2 -0
  249. package/dist/utils/cn.js +6 -0
  250. package/dist/utils/cn.js.map +1 -0
  251. package/dist/utils/cn.test.d.ts +1 -0
  252. package/dist/utils/cn.test.js +21 -0
  253. package/dist/utils/cn.test.js.map +1 -0
  254. package/dist/utils/format.d.ts +31 -0
  255. package/dist/utils/format.js +95 -0
  256. package/dist/utils/format.js.map +1 -0
  257. package/dist/utils/format.test.d.ts +1 -0
  258. package/dist/utils/format.test.js +71 -0
  259. package/dist/utils/format.test.js.map +1 -0
  260. package/dist/utils/logger.d.ts +6 -0
  261. package/dist/utils/logger.js +16 -0
  262. package/dist/utils/logger.js.map +1 -0
  263. package/dist/utils/logger.test.d.ts +1 -0
  264. package/dist/utils/logger.test.js +36 -0
  265. package/dist/utils/logger.test.js.map +1 -0
  266. package/dist/utils/resolve-paths.d.ts +12 -0
  267. package/dist/utils/resolve-paths.js +29 -0
  268. package/dist/utils/resolve-paths.js.map +1 -0
  269. package/dist/utils/resolve-paths.test.d.ts +1 -0
  270. package/dist/utils/resolve-paths.test.js +52 -0
  271. package/dist/utils/resolve-paths.test.js.map +1 -0
  272. package/package.json +56 -4
  273. package/README.md +0 -3
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copies one or more UI components from the dolan registry into the user's
3
+ * project (`src/components/ui/<name>` by default) and records each file's
4
+ * content hash in `dolan.lock.json`.
5
+ *
6
+ * The shadcn-style philosophy: components are *copied*, not installed as a
7
+ * runtime dependency. Users own and edit the code in their repo. The lockfile
8
+ * lets later commands (update, diff, doctor) detect local modifications by
9
+ * comparing on-disk hashes against the recorded ones, so we know whether an
10
+ * update would clobber user edits.
11
+ *
12
+ * Flow:
13
+ * 1. Resolve the requested components plus transitive dependencies via
14
+ * `resolveDependencies` (topological order, see registry.ts).
15
+ * 2. Detect any already-installed components and prompt for overwrite —
16
+ * "skip the conflicts" is the default so a stray re-run doesn't blow
17
+ * away local changes.
18
+ * 3. For each component: copy every file, rewrite cross-component imports
19
+ * to use the user's alias config, hash the rewritten content, and record
20
+ * it in the lockfile.
21
+ */
22
+ export declare const addCommand: (components: string[]) => Promise<void>;
@@ -0,0 +1,132 @@
1
+ import * as p from '@clack/prompts';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { resolve, join } from 'node:path';
4
+ import pc from 'picocolors';
5
+ import { configExists, readConfig } from '../config.js';
6
+ import { getComponentNames, getEntry, resolveDependencies, } from '../registry.js';
7
+ import { getComponentFiles, getComponentSourceDir, rewriteImports, } from '../utils/resolve-paths.js';
8
+ import { formatContent } from '../utils/format.js';
9
+ import { getOrCreateLockfile, hashContent, writeLockfile, } from '../lockfile.js';
10
+ /**
11
+ * Copies one or more UI components from the dolan registry into the user's
12
+ * project (`src/components/ui/<name>` by default) and records each file's
13
+ * content hash in `dolan.lock.json`.
14
+ *
15
+ * The shadcn-style philosophy: components are *copied*, not installed as a
16
+ * runtime dependency. Users own and edit the code in their repo. The lockfile
17
+ * lets later commands (update, diff, doctor) detect local modifications by
18
+ * comparing on-disk hashes against the recorded ones, so we know whether an
19
+ * update would clobber user edits.
20
+ *
21
+ * Flow:
22
+ * 1. Resolve the requested components plus transitive dependencies via
23
+ * `resolveDependencies` (topological order, see registry.ts).
24
+ * 2. Detect any already-installed components and prompt for overwrite —
25
+ * "skip the conflicts" is the default so a stray re-run doesn't blow
26
+ * away local changes.
27
+ * 3. For each component: copy every file, rewrite cross-component imports
28
+ * to use the user's alias config, hash the rewritten content, and record
29
+ * it in the lockfile.
30
+ */
31
+ export const addCommand = async (components) => {
32
+ const cwd = process.cwd();
33
+ p.intro(pc.bold('dolan add'));
34
+ if (!configExists(cwd)) {
35
+ p.log.error(`No ${pc.cyan('dolan.config.json')} found. Run ${pc.bold('dolan init')} first.`);
36
+ process.exit(1);
37
+ }
38
+ const config = readConfig(cwd);
39
+ const allComponents = getComponentNames();
40
+ let selected;
41
+ if (components.length === 0) {
42
+ const result = await p.multiselect({
43
+ message: 'Which components would you like to add?',
44
+ options: allComponents.map((name) => ({ value: name, label: name })),
45
+ required: true,
46
+ });
47
+ if (p.isCancel(result)) {
48
+ p.cancel('Canceled.');
49
+ process.exit(0);
50
+ }
51
+ selected = result;
52
+ }
53
+ else {
54
+ const invalid = components.filter((c) => !getEntry(c));
55
+ if (invalid.length > 0) {
56
+ p.log.error(`Unknown component(s): ${invalid.map((c) => pc.red(c)).join(', ')}`);
57
+ p.log.info(`Available: ${allComponents.map((c) => pc.cyan(c)).join(', ')}`);
58
+ process.exit(1);
59
+ }
60
+ selected = components;
61
+ }
62
+ const resolved = resolveDependencies(selected);
63
+ const added = resolved.filter((name) => !selected.includes(name));
64
+ if (added.length > 0) {
65
+ // Components in `resolved` that weren't in `selected` are transitive
66
+ // dependencies pulled in by the registry — surface them so the user
67
+ // knows we're installing more than they explicitly asked for.
68
+ p.log.info(`Adding dependencies: ${added.map((c) => pc.cyan(c)).join(', ')}`);
69
+ }
70
+ const existing = resolved.filter((name) => {
71
+ const destDir = resolve(cwd, config.aliases.components, name);
72
+ return existsSync(destDir);
73
+ });
74
+ if (existing.length > 0) {
75
+ // Default to "no" (initialValue: false) — destructive operations on
76
+ // user-owned code should require an explicit affirmative. The user can
77
+ // re-run with --force later if we add that flag.
78
+ const overwrite = await p.confirm({
79
+ message: `${existing.map((c) => pc.yellow(c)).join(', ')} already exist. Overwrite?`,
80
+ initialValue: false,
81
+ });
82
+ if (p.isCancel(overwrite) || !overwrite) {
83
+ // Filter the existing components out of `resolved` in-place via splice
84
+ // so later code (the copy loop, the success message) operates on the
85
+ // narrowed set. We can't just `resolved = filtered` because the array
86
+ // reference is captured by the destructuring below.
87
+ const filtered = resolved.filter((name) => !existing.includes(name));
88
+ if (filtered.length === 0) {
89
+ p.cancel('Nothing to add.');
90
+ process.exit(0);
91
+ }
92
+ resolved.splice(0, resolved.length, ...filtered);
93
+ }
94
+ }
95
+ const s = p.spinner();
96
+ s.start('Adding components...');
97
+ const componentsDir = resolve(cwd, config.aliases.components);
98
+ const lockfile = getOrCreateLockfile(cwd);
99
+ for (const name of resolved) {
100
+ const srcDir = getComponentSourceDir(name);
101
+ const destDir = resolve(componentsDir, name);
102
+ mkdirSync(destDir, { recursive: true });
103
+ if (!lockfile.components[name]) {
104
+ lockfile.components[name] = {};
105
+ }
106
+ const files = getComponentFiles(name);
107
+ for (const file of files) {
108
+ // Read from the registry source, then rewrite cross-component imports.
109
+ // The registry uses workspace-relative imports like
110
+ // `@blotch/ui/components/button` which won't resolve in the user's
111
+ // project — rewriteImports rewrites them to the user's alias
112
+ // (e.g. `@/components/ui/button`) per dolan.config.json.
113
+ const destPath = join(destDir, file);
114
+ const content = readFileSync(join(srcDir, file), 'utf-8');
115
+ // Normalize to the consumer's oxfmt config so what we write already
116
+ // satisfies their formatter (the import rewrite can push lines past
117
+ // printWidth). The hash below must be of this normalized content — see
118
+ // formatContent's doc comment on the lockfile-base invariant.
119
+ const rewritten = formatContent(rewriteImports(content), destPath);
120
+ writeFileSync(destPath, rewritten);
121
+ // Hash the *rewritten* content (not the source) so subsequent
122
+ // dolan-diff/dolan-update compare apples to apples — they re-rewrite
123
+ // the registry source and hash the result the same way.
124
+ lockfile.components[name][file] = { hash: hashContent(rewritten) };
125
+ }
126
+ }
127
+ writeLockfile(cwd, lockfile);
128
+ s.stop('Done!');
129
+ p.log.success(`Added ${resolved.length} component(s): ${resolved.map((c) => pc.green(c)).join(', ')}`);
130
+ p.outro('Components are ready to use.');
131
+ };
132
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,209 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { createFixture, DEFAULT_CONFIG } from '../test-utils';
5
+ const spinnerMock = { start: vi.fn(), stop: vi.fn() };
6
+ vi.mock('@clack/prompts', () => ({
7
+ intro: vi.fn(),
8
+ outro: vi.fn(),
9
+ log: {
10
+ message: vi.fn(),
11
+ error: vi.fn(),
12
+ warn: vi.fn(),
13
+ success: vi.fn(),
14
+ info: vi.fn(),
15
+ },
16
+ spinner: vi.fn(() => spinnerMock),
17
+ multiselect: vi.fn(),
18
+ confirm: vi.fn(),
19
+ cancel: vi.fn(),
20
+ isCancel: vi.fn().mockReturnValue(false),
21
+ }));
22
+ let fixture;
23
+ // `add` reads component source through resolve-paths — stub it to read from
24
+ // the fixture's __ui_source tree instead of the real dist/ui, same pattern
25
+ // used by diff.test.ts / update.test.ts.
26
+ vi.mock('../utils/resolve-paths.js', () => ({
27
+ getComponentSourceDir: (name) => join(fixture.uiDir, 'components', name),
28
+ getComponentFiles: (name) => readdirSync(join(fixture.uiDir, 'components', name)).filter((f) => f.endsWith('.ts')),
29
+ rewriteImports: (content) => content,
30
+ }));
31
+ beforeEach(() => {
32
+ // The @clack/prompts mock above is a module-level vi.fn() object shared by
33
+ // every test in this file (vi.restoreAllMocks() in afterEach only restores
34
+ // vi.spyOn spies, not plain vi.fn() mocks) — clear call history explicitly
35
+ // so assertions like `not.toHaveBeenCalledWith` aren't polluted by earlier tests.
36
+ vi.clearAllMocks();
37
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
38
+ throw new Error(`process.exit(${code})`);
39
+ });
40
+ });
41
+ afterEach(() => {
42
+ fixture?.cleanup();
43
+ vi.restoreAllMocks();
44
+ });
45
+ const readInstalledFile = (dir, component, file) => readFileSync(join(dir, DEFAULT_CONFIG.aliases.components, component, file), 'utf-8');
46
+ describe('addCommand', () => {
47
+ it('exits with error when no config exists', async () => {
48
+ fixture = createFixture({});
49
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
50
+ const { addCommand } = await import('./add');
51
+ await expect(addCommand(['card'])).rejects.toThrow('process.exit(1)');
52
+ });
53
+ it('copies explicitly-named components and records lockfile hashes', async () => {
54
+ const content = 'export const Card = {};';
55
+ fixture = createFixture({
56
+ config: DEFAULT_CONFIG,
57
+ uiSource: { card: { 'card.ts': content } },
58
+ });
59
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
60
+ const { addCommand } = await import('./add');
61
+ await addCommand(['card']);
62
+ expect(readInstalledFile(fixture.dir, 'card', 'card.ts')).toBe(content);
63
+ const lockfile = JSON.parse(readFileSync(join(fixture.dir, 'dolan.lock.json'), 'utf-8'));
64
+ expect(lockfile.components.card['card.ts'].hash).toBeDefined();
65
+ const p = await import('@clack/prompts');
66
+ expect(p.log.success).toHaveBeenCalledWith(expect.stringContaining('Added 1 component(s)'));
67
+ });
68
+ it('exits with error for unknown explicit component names', async () => {
69
+ fixture = createFixture({
70
+ config: DEFAULT_CONFIG,
71
+ uiSource: { card: { 'card.ts': '' } },
72
+ });
73
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
74
+ const { addCommand } = await import('./add');
75
+ await expect(addCommand(['nonexistent'])).rejects.toThrow('process.exit(1)');
76
+ const p = await import('@clack/prompts');
77
+ expect(p.log.info).toHaveBeenCalledWith(expect.stringContaining('Available:'));
78
+ });
79
+ it('surfaces auto-added transitive dependencies', async () => {
80
+ // button depends on spinner (registry.ts) — requesting only "button"
81
+ // should pull spinner in automatically and announce it.
82
+ fixture = createFixture({
83
+ config: DEFAULT_CONFIG,
84
+ uiSource: {
85
+ button: { 'button.ts': 'export const Button = {};' },
86
+ spinner: { 'spinner.ts': 'export const Spinner = {};' },
87
+ },
88
+ });
89
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
90
+ const { addCommand } = await import('./add');
91
+ await addCommand(['button']);
92
+ const p = await import('@clack/prompts');
93
+ // "spinner" is wrapped in its own pc.cyan(...) span, so when colors are
94
+ // enabled (e.g. an interactive TTY) ANSI codes sit between "dependencies:"
95
+ // and "spinner" — a plain stringContaining would fail outside CI. Match
96
+ // loosely with a regex instead of relying on literal adjacency.
97
+ expect(p.log.info).toHaveBeenCalledWith(expect.stringMatching(/Adding dependencies:.*spinner/));
98
+ expect(readInstalledFile(fixture.dir, 'spinner', 'spinner.ts')).toBeDefined();
99
+ });
100
+ it('does not announce dependencies when they were already explicitly requested', async () => {
101
+ fixture = createFixture({
102
+ config: DEFAULT_CONFIG,
103
+ uiSource: {
104
+ button: { 'button.ts': 'export const Button = {};' },
105
+ spinner: { 'spinner.ts': 'export const Spinner = {};' },
106
+ },
107
+ });
108
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
109
+ const { addCommand } = await import('./add');
110
+ await addCommand(['button', 'spinner']);
111
+ const p = await import('@clack/prompts');
112
+ expect(p.log.info).not.toHaveBeenCalledWith(expect.stringContaining('Adding dependencies'));
113
+ });
114
+ it('prompts with multiselect when no components are given, and installs the selection', async () => {
115
+ fixture = createFixture({
116
+ config: DEFAULT_CONFIG,
117
+ uiSource: { card: { 'card.ts': 'export const Card = {};' } },
118
+ });
119
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
120
+ const p = await import('@clack/prompts');
121
+ p.multiselect.mockResolvedValue(['card']);
122
+ const { addCommand } = await import('./add');
123
+ await addCommand([]);
124
+ expect(p.multiselect).toHaveBeenCalled();
125
+ expect(existsSync(join(fixture.dir, DEFAULT_CONFIG.aliases.components, 'card'))).toBe(true);
126
+ });
127
+ it('cancels when the multiselect prompt is canceled', async () => {
128
+ fixture = createFixture({ config: DEFAULT_CONFIG, uiSource: {} });
129
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
130
+ const p = await import('@clack/prompts');
131
+ p.multiselect.mockResolvedValue(Symbol('cancel'));
132
+ p.isCancel.mockReturnValueOnce(true);
133
+ const { addCommand } = await import('./add');
134
+ await expect(addCommand([])).rejects.toThrow('process.exit(0)');
135
+ expect(p.cancel).toHaveBeenCalled();
136
+ });
137
+ it('prompts to overwrite when a component already exists, and proceeds when confirmed', async () => {
138
+ // Also pre-seeds a lockfile entry for the component being re-added — this
139
+ // exercises the "lockfile already tracks this component" branch (as
140
+ // opposed to a brand-new `lockfile.components[name] = {}` initialization).
141
+ const upstream = 'export const Card = { v: 2 };';
142
+ const original = 'export const Card = { v: 1 };';
143
+ fixture = createFixture({
144
+ config: DEFAULT_CONFIG,
145
+ lockfile: {
146
+ version: 1,
147
+ components: { card: { 'card.ts': { hash: 'stale' } } },
148
+ utils: {},
149
+ theme: {},
150
+ },
151
+ components: { card: { 'card.ts': original } },
152
+ uiSource: { card: { 'card.ts': upstream } },
153
+ });
154
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
155
+ const p = await import('@clack/prompts');
156
+ p.confirm.mockResolvedValue(true);
157
+ const { addCommand } = await import('./add');
158
+ await addCommand(['card']);
159
+ expect(p.confirm).toHaveBeenCalled();
160
+ expect(readInstalledFile(fixture.dir, 'card', 'card.ts')).toBe(upstream);
161
+ });
162
+ it('skips overwrite-declined components but still installs the rest', async () => {
163
+ const cardOriginal = 'export const Card = { v: 1 };';
164
+ fixture = createFixture({
165
+ config: DEFAULT_CONFIG,
166
+ components: { card: { 'card.ts': cardOriginal } },
167
+ uiSource: {
168
+ card: { 'card.ts': 'export const Card = { v: 2 };' },
169
+ spinner: { 'spinner.ts': 'export const Spinner = {};' },
170
+ },
171
+ });
172
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
173
+ const p = await import('@clack/prompts');
174
+ p.confirm.mockResolvedValue(false);
175
+ const { addCommand } = await import('./add');
176
+ await addCommand(['card', 'spinner']);
177
+ // card declined — left untouched
178
+ expect(readInstalledFile(fixture.dir, 'card', 'card.ts')).toBe(cardOriginal);
179
+ // spinner wasn't already installed, so it's unaffected by the decline
180
+ expect(readInstalledFile(fixture.dir, 'spinner', 'spinner.ts')).toBeDefined();
181
+ });
182
+ it('cancels entirely when overwrite is declined and nothing else is left to add', async () => {
183
+ fixture = createFixture({
184
+ config: DEFAULT_CONFIG,
185
+ components: { card: { 'card.ts': 'export const Card = { v: 1 };' } },
186
+ uiSource: { card: { 'card.ts': 'export const Card = { v: 2 };' } },
187
+ });
188
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
189
+ const p = await import('@clack/prompts');
190
+ p.confirm.mockResolvedValue(false);
191
+ const { addCommand } = await import('./add');
192
+ await expect(addCommand(['card'])).rejects.toThrow('process.exit(0)');
193
+ expect(p.cancel).toHaveBeenCalledWith('Nothing to add.');
194
+ });
195
+ it('cancels when the overwrite confirm prompt itself is canceled', async () => {
196
+ fixture = createFixture({
197
+ config: DEFAULT_CONFIG,
198
+ components: { card: { 'card.ts': 'export const Card = { v: 1 };' } },
199
+ uiSource: { card: { 'card.ts': 'export const Card = { v: 2 };' } },
200
+ });
201
+ vi.spyOn(process, 'cwd').mockReturnValue(fixture.dir);
202
+ const p = await import('@clack/prompts');
203
+ p.confirm.mockResolvedValue(Symbol('cancel'));
204
+ p.isCancel.mockReturnValueOnce(true);
205
+ const { addCommand } = await import('./add');
206
+ await expect(addCommand(['card'])).rejects.toThrow('process.exit(0)');
207
+ });
208
+ });
209
+ //# sourceMappingURL=add.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.test.js","sourceRoot":"","sources":["../../src/commands/add.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shows the diff between installed components and their current upstream
3
+ * source. Two modes:
4
+ *
5
+ * - With a component name: print the per-file diff immediately. Useful for
6
+ * CI-style "what would change?" inspection.
7
+ * - Without arguments: summarize all components that have any divergence
8
+ * from upstream and prompt to pick which one's diff to display.
9
+ *
10
+ * Uses the same analyzeFile + summarizeComponent pipeline as `list`/`update`
11
+ * so what you see here matches what those commands will report.
12
+ */
13
+ export declare const diffCommand: (component?: string) => Promise<void>;
@@ -0,0 +1,155 @@
1
+ import * as p from '@clack/prompts';
2
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { resolve, join } from 'node:path';
4
+ import pc from 'picocolors';
5
+ import { configExists, readConfig } from '../config.js';
6
+ import { getComponentNames, getEntry } from '../registry.js';
7
+ import { getComponentFiles, getComponentSourceDir, rewriteImports, } from '../utils/resolve-paths.js';
8
+ import { formatContent } from '../utils/format.js';
9
+ import { getOrCreateLockfile, hashContent } from '../lockfile.js';
10
+ import { analyzeFile, formatDiff, summarizeComponent, STATUS_ICONS, } from '../utils/analyze.js';
11
+ const STATUS_SHORT_LABELS = {
12
+ 'up-to-date': pc.dim('up to date'),
13
+ 'auto-update': pc.blue('outdated'),
14
+ 'user-modified': pc.yellow('modified'),
15
+ conflict: pc.red('conflict'),
16
+ 'new-upstream': pc.blue('new upstream'),
17
+ };
18
+ /**
19
+ * Shows the diff between installed components and their current upstream
20
+ * source. Two modes:
21
+ *
22
+ * - With a component name: print the per-file diff immediately. Useful for
23
+ * CI-style "what would change?" inspection.
24
+ * - Without arguments: summarize all components that have any divergence
25
+ * from upstream and prompt to pick which one's diff to display.
26
+ *
27
+ * Uses the same analyzeFile + summarizeComponent pipeline as `list`/`update`
28
+ * so what you see here matches what those commands will report.
29
+ */
30
+ export const diffCommand = async (component) => {
31
+ const cwd = process.cwd();
32
+ p.intro(pc.bold('dolan diff'));
33
+ if (!configExists(cwd)) {
34
+ p.log.error(`No ${pc.cyan('dolan.config.json')} found. Run ${pc.bold('dolan init')} first.`);
35
+ process.exit(1);
36
+ }
37
+ const config = readConfig(cwd);
38
+ const componentsDir = resolve(cwd, config.aliases.components);
39
+ if (!existsSync(componentsDir)) {
40
+ p.log.warn('No components installed.');
41
+ p.outro('Done.');
42
+ return;
43
+ }
44
+ const allKnown = new Set(getComponentNames());
45
+ const installed = readdirSync(componentsDir, { withFileTypes: true })
46
+ .filter((entry) => entry.isDirectory() && allKnown.has(entry.name))
47
+ .map((entry) => entry.name)
48
+ .sort();
49
+ if (installed.length === 0) {
50
+ p.log.warn('No components installed.');
51
+ p.outro('Done.');
52
+ return;
53
+ }
54
+ const lockfile = getOrCreateLockfile(cwd);
55
+ if (component) {
56
+ // Show diff for a specific component
57
+ if (!getEntry(component)) {
58
+ p.log.error(`Unknown component ${pc.bold(component)}. Available: ${getComponentNames().join(', ')}`);
59
+ process.exit(1);
60
+ }
61
+ if (!installed.includes(component)) {
62
+ p.log.error(`${pc.bold(component)} is not installed.`);
63
+ process.exit(1);
64
+ }
65
+ showComponentDiff(component, componentsDir, lockfile);
66
+ p.outro('');
67
+ return;
68
+ }
69
+ // Summary mode — show all components with changes
70
+ const changed = [];
71
+ for (const name of installed) {
72
+ const analyses = analyzeComponent(name, componentsDir, lockfile);
73
+ const overall = summarizeComponent({ name, files: analyses });
74
+ if (overall !== 'up-to-date') {
75
+ changed.push({ name, status: overall });
76
+ }
77
+ }
78
+ if (changed.length === 0) {
79
+ p.log.success('All components are up to date with upstream.');
80
+ p.outro('');
81
+ return;
82
+ }
83
+ p.log.message(pc.bold(`${changed.length} component(s) with changes:\n`));
84
+ for (const { name, status } of changed) {
85
+ p.log.message(` ${STATUS_ICONS[status]} ${pc.bold(name)} ${STATUS_SHORT_LABELS[status]}`);
86
+ }
87
+ p.log.message('');
88
+ const choice = await p.select({
89
+ message: 'Show diff for which component?',
90
+ options: [
91
+ ...changed.map((c) => ({ value: c.name, label: c.name })),
92
+ { value: '__all__', label: 'All changed components' },
93
+ { value: '__none__', label: 'Exit' },
94
+ ],
95
+ });
96
+ if (p.isCancel(choice) || choice === '__none__') {
97
+ p.outro('');
98
+ return;
99
+ }
100
+ const toShow = choice === '__all__' ? changed.map((c) => c.name) : [choice];
101
+ for (const name of toShow) {
102
+ showComponentDiff(name, componentsDir, lockfile);
103
+ }
104
+ p.outro('');
105
+ };
106
+ const analyzeComponent = (name, componentsDir, lockfile) => {
107
+ const srcDir = getComponentSourceDir(name);
108
+ const files = getComponentFiles(name);
109
+ const lockedComponent = lockfile.components[name] ?? {};
110
+ const destDir = resolve(componentsDir, name);
111
+ const analyses = [];
112
+ for (const file of files) {
113
+ const srcContent = readFileSync(join(srcDir, file), 'utf-8');
114
+ const destPath = join(destDir, file);
115
+ // Match how add/update canonicalize upstream content, or every file would
116
+ // read as drifted against the formatted hash recorded in the lockfile.
117
+ const newContent = formatContent(rewriteImports(srcContent), destPath);
118
+ const currentContent = existsSync(destPath)
119
+ ? readFileSync(destPath, 'utf-8')
120
+ : null;
121
+ const storedHash = lockedComponent[file]?.hash ?? null;
122
+ const status = analyzeFile(currentContent, newContent, storedHash, hashContent);
123
+ analyses.push({
124
+ file,
125
+ status,
126
+ currentContent: currentContent ?? '',
127
+ newContent,
128
+ });
129
+ }
130
+ return analyses;
131
+ };
132
+ const showComponentDiff = (name, componentsDir, lockfile) => {
133
+ const analyses = analyzeComponent(name, componentsDir, lockfile);
134
+ p.log.message(`\n${pc.bold(name)}`);
135
+ for (const analysis of analyses) {
136
+ if (analysis.status === 'up-to-date')
137
+ continue;
138
+ const header = `── ${name}/${analysis.file} (${STATUS_SHORT_LABELS[analysis.status]}) ──`;
139
+ p.log.message(`\n${pc.dim(header)}`);
140
+ if (analysis.status === 'new-upstream') {
141
+ // No current content to diff against — render the full upstream file
142
+ // in green so it visually reads as "new content" rather than as a diff.
143
+ p.log.message(pc.green(analysis.newContent));
144
+ }
145
+ else {
146
+ const diff = formatDiff(analysis.currentContent, analysis.newContent);
147
+ p.log.message(diff);
148
+ }
149
+ }
150
+ const allUpToDate = analyses.every((a) => a.status === 'up-to-date');
151
+ if (allUpToDate) {
152
+ p.log.message(pc.dim(' All files up to date.'));
153
+ }
154
+ };
155
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};