@hobui/viui-cli 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +138 -139
  2. package/dist/adapters/adapter-registry.d.ts +12 -0
  3. package/dist/adapters/adapter-registry.d.ts.map +1 -0
  4. package/dist/adapters/adapter-registry.js +49 -0
  5. package/dist/adapters/adapter-types.d.ts +20 -0
  6. package/dist/adapters/adapter-types.d.ts.map +1 -0
  7. package/dist/adapters/adapter-types.js +1 -0
  8. package/dist/adapters/aider-adapter.d.ts +3 -0
  9. package/dist/adapters/aider-adapter.d.ts.map +1 -0
  10. package/dist/adapters/aider-adapter.js +8 -0
  11. package/dist/adapters/claude-adapter.d.ts +3 -0
  12. package/dist/adapters/claude-adapter.d.ts.map +1 -0
  13. package/dist/adapters/claude-adapter.js +15 -0
  14. package/dist/adapters/cline-adapter.d.ts +3 -0
  15. package/dist/adapters/cline-adapter.d.ts.map +1 -0
  16. package/dist/adapters/cline-adapter.js +8 -0
  17. package/dist/adapters/copilot-adapter.d.ts +5 -0
  18. package/dist/adapters/copilot-adapter.d.ts.map +1 -0
  19. package/dist/adapters/copilot-adapter.js +20 -0
  20. package/dist/adapters/cursor-adapter.d.ts +3 -0
  21. package/dist/adapters/cursor-adapter.d.ts.map +1 -0
  22. package/dist/adapters/cursor-adapter.js +18 -0
  23. package/dist/adapters/external/bolt-adapter.d.ts +3 -0
  24. package/dist/adapters/external/bolt-adapter.d.ts.map +1 -0
  25. package/dist/adapters/external/bolt-adapter.js +15 -0
  26. package/dist/adapters/external/chatgpt-adapter.d.ts +3 -0
  27. package/dist/adapters/external/chatgpt-adapter.d.ts.map +1 -0
  28. package/dist/adapters/external/chatgpt-adapter.js +14 -0
  29. package/dist/adapters/external/external-adapter-base.d.ts +15 -0
  30. package/dist/adapters/external/external-adapter-base.d.ts.map +1 -0
  31. package/dist/adapters/external/external-adapter-base.js +92 -0
  32. package/dist/adapters/external/gemini-adapter.d.ts +3 -0
  33. package/dist/adapters/external/gemini-adapter.d.ts.map +1 -0
  34. package/dist/adapters/external/gemini-adapter.js +14 -0
  35. package/dist/adapters/external/lovable-adapter.d.ts +3 -0
  36. package/dist/adapters/external/lovable-adapter.d.ts.map +1 -0
  37. package/dist/adapters/external/lovable-adapter.js +14 -0
  38. package/dist/adapters/external/v0-adapter.d.ts +3 -0
  39. package/dist/adapters/external/v0-adapter.d.ts.map +1 -0
  40. package/dist/adapters/external/v0-adapter.js +15 -0
  41. package/dist/adapters/windsurf-adapter.d.ts +3 -0
  42. package/dist/adapters/windsurf-adapter.d.ts.map +1 -0
  43. package/dist/adapters/windsurf-adapter.js +23 -0
  44. package/dist/assets/plugins/viui-conf/apply-theme-body.ts +23 -4
  45. package/dist/assets/plugins/viui-conf/defaults/README.md +2 -0
  46. package/dist/assets/plugins/viui-conf/defaults/app-bar.ts +1 -1
  47. package/dist/assets/plugins/viui-conf/defaults/buttons.ts +1 -1
  48. package/dist/assets/plugins/viui-conf/defaults/by-theme/minimalist-2.ts +1 -1
  49. package/dist/assets/plugins/viui-conf/defaults/cards.ts +1 -1
  50. package/dist/assets/plugins/viui-conf/defaults/expansion-panels.ts +16 -0
  51. package/dist/assets/plugins/viui-conf/defaults/index.ts +3 -0
  52. package/dist/assets/plugins/viui-conf/defaults/inputs.ts +11 -1
  53. package/dist/assets/plugins/viui-conf/design-tokens.ts +135 -0
  54. package/dist/assets/plugins/viui-conf/theme-base.ts +1 -1
  55. package/dist/assets/plugins/viui-conf/v-dark.ts +3 -5
  56. package/dist/assets/plugins/viui-conf/v-light.ts +3 -5
  57. package/dist/assets/plugins/vuetify.ts +36 -0
  58. package/dist/assets/prompt-data/components.json +106 -0
  59. package/dist/assets/prompt-data/tokens.json +83 -0
  60. package/dist/assets/themes/_bento-grid.scss +8 -0
  61. package/dist/assets/themes/_glassmorphism.scss +8 -0
  62. package/dist/assets/themes/_material.scss +8 -0
  63. package/dist/assets/themes/_minimalist-2.scss +375 -0
  64. package/dist/assets/themes/_minimalist.scss +9 -0
  65. package/dist/assets/themes/_neo-brutalism.scss +199 -0
  66. package/dist/assets/themes/bento-grid.scss +4 -0
  67. package/dist/assets/themes/glassmorphism.scss +4 -0
  68. package/dist/assets/themes/index.scss +11 -0
  69. package/dist/assets/themes/material.scss +4 -0
  70. package/dist/assets/themes/minimalist-2.scss +5 -0
  71. package/dist/assets/themes/minimalist.scss +4 -0
  72. package/dist/assets/themes/neo-brutalism.scss +5 -0
  73. package/dist/assets/viui-themes/_neo-brutalism.scss +70 -152
  74. package/dist/cli-paths.d.ts +7 -0
  75. package/dist/cli-paths.d.ts.map +1 -0
  76. package/dist/cli-paths.js +19 -0
  77. package/dist/cli.js +28 -578
  78. package/dist/cli.legacy.d.ts +3 -0
  79. package/dist/cli.legacy.d.ts.map +1 -0
  80. package/dist/cli.legacy.js +597 -0
  81. package/dist/commands/audit.d.ts +3 -0
  82. package/dist/commands/audit.d.ts.map +1 -0
  83. package/dist/commands/audit.js +152 -0
  84. package/dist/commands/config/config-export.d.ts +6 -0
  85. package/dist/commands/config/config-export.d.ts.map +1 -0
  86. package/dist/commands/config/config-export.js +23 -0
  87. package/dist/commands/config/config-health.d.ts +6 -0
  88. package/dist/commands/config/config-health.d.ts.map +1 -0
  89. package/dist/commands/config/config-health.js +42 -0
  90. package/dist/commands/config/config-import.d.ts +6 -0
  91. package/dist/commands/config/config-import.d.ts.map +1 -0
  92. package/dist/commands/config/config-import.js +63 -0
  93. package/dist/commands/config/config-rollback.d.ts +6 -0
  94. package/dist/commands/config/config-rollback.d.ts.map +1 -0
  95. package/dist/commands/config/config-rollback.js +47 -0
  96. package/dist/commands/config/config-setup.d.ts +6 -0
  97. package/dist/commands/config/config-setup.d.ts.map +1 -0
  98. package/dist/commands/config/config-setup.js +103 -0
  99. package/dist/commands/config/config-status.d.ts +6 -0
  100. package/dist/commands/config/config-status.d.ts.map +1 -0
  101. package/dist/commands/config/config-status.js +42 -0
  102. package/dist/commands/config/config-uninstall.d.ts +6 -0
  103. package/dist/commands/config/config-uninstall.d.ts.map +1 -0
  104. package/dist/commands/config/config-uninstall.js +74 -0
  105. package/dist/commands/config.d.ts +6 -0
  106. package/dist/commands/config.d.ts.map +1 -0
  107. package/dist/commands/config.js +19 -0
  108. package/dist/commands/docs.d.ts +3 -0
  109. package/dist/commands/docs.d.ts.map +1 -0
  110. package/dist/commands/docs.js +17 -0
  111. package/dist/commands/doctor.d.ts +3 -0
  112. package/dist/commands/doctor.d.ts.map +1 -0
  113. package/dist/commands/doctor.js +93 -0
  114. package/dist/commands/init.d.ts +3 -0
  115. package/dist/commands/init.d.ts.map +1 -0
  116. package/dist/commands/init.js +183 -0
  117. package/dist/commands/sync.d.ts +3 -0
  118. package/dist/commands/sync.d.ts.map +1 -0
  119. package/dist/commands/sync.js +73 -0
  120. package/dist/commands/theme.d.ts +3 -0
  121. package/dist/commands/theme.d.ts.map +1 -0
  122. package/dist/commands/theme.js +86 -0
  123. package/dist/commands/update.d.ts +3 -0
  124. package/dist/commands/update.d.ts.map +1 -0
  125. package/dist/commands/update.js +97 -0
  126. package/dist/prompts/prompt-builder.d.ts +4 -0
  127. package/dist/prompts/prompt-builder.d.ts.map +1 -0
  128. package/dist/prompts/prompt-builder.js +18 -0
  129. package/dist/prompts/prompt-data-loader.d.ts +11 -0
  130. package/dist/prompts/prompt-data-loader.d.ts.map +1 -0
  131. package/dist/prompts/prompt-data-loader.js +15 -0
  132. package/dist/prompts/prompt-sections/section-code-examples.d.ts +2 -0
  133. package/dist/prompts/prompt-sections/section-code-examples.d.ts.map +1 -0
  134. package/dist/prompts/prompt-sections/section-code-examples.js +36 -0
  135. package/dist/prompts/prompt-sections/section-color-tokens.d.ts +2 -0
  136. package/dist/prompts/prompt-sections/section-color-tokens.d.ts.map +1 -0
  137. package/dist/prompts/prompt-sections/section-color-tokens.js +19 -0
  138. package/dist/prompts/prompt-sections/section-component-map.d.ts +3 -0
  139. package/dist/prompts/prompt-sections/section-component-map.d.ts.map +1 -0
  140. package/dist/prompts/prompt-sections/section-component-map.js +12 -0
  141. package/dist/prompts/prompt-sections/section-typography-spacing.d.ts +2 -0
  142. package/dist/prompts/prompt-sections/section-typography-spacing.d.ts.map +1 -0
  143. package/dist/prompts/prompt-sections/section-typography-spacing.js +29 -0
  144. package/dist/services/backup-service.d.ts +7 -0
  145. package/dist/services/backup-service.d.ts.map +1 -0
  146. package/dist/services/backup-service.js +54 -0
  147. package/dist/services/config-service.d.ts +17 -0
  148. package/dist/services/config-service.d.ts.map +1 -0
  149. package/dist/services/config-service.js +64 -0
  150. package/dist/services/diff-engine.d.ts +13 -0
  151. package/dist/services/diff-engine.d.ts.map +1 -0
  152. package/dist/services/diff-engine.js +59 -0
  153. package/dist/services/ide-detector.d.ts +9 -0
  154. package/dist/services/ide-detector.d.ts.map +1 -0
  155. package/dist/services/ide-detector.js +113 -0
  156. package/dist/services/ide-detector.spec.d.ts +2 -0
  157. package/dist/services/ide-detector.spec.d.ts.map +1 -0
  158. package/dist/services/ide-detector.spec.js +108 -0
  159. package/dist/services/lock-file-service.d.ts +15 -0
  160. package/dist/services/lock-file-service.d.ts.map +1 -0
  161. package/dist/services/lock-file-service.js +74 -0
  162. package/dist/services/mcp-config-reader.d.ts +11 -0
  163. package/dist/services/mcp-config-reader.d.ts.map +1 -0
  164. package/dist/services/mcp-config-reader.js +40 -0
  165. package/dist/services/mcp-config-reader.spec.d.ts +2 -0
  166. package/dist/services/mcp-config-reader.spec.d.ts.map +1 -0
  167. package/dist/services/mcp-config-reader.spec.js +125 -0
  168. package/dist/services/mcp-config-writer.d.ts +11 -0
  169. package/dist/services/mcp-config-writer.d.ts.map +1 -0
  170. package/dist/services/mcp-config-writer.js +98 -0
  171. package/dist/services/mcp-config-writer.spec.d.ts +2 -0
  172. package/dist/services/mcp-config-writer.spec.d.ts.map +1 -0
  173. package/dist/services/mcp-config-writer.spec.js +162 -0
  174. package/dist/services/merge-engine.d.ts +12 -0
  175. package/dist/services/merge-engine.d.ts.map +1 -0
  176. package/dist/services/merge-engine.js +54 -0
  177. package/dist/services/vuetify-scaffold-service.d.ts +5 -0
  178. package/dist/services/vuetify-scaffold-service.d.ts.map +1 -0
  179. package/dist/services/vuetify-scaffold-service.js +67 -0
  180. package/dist/templates/vuetify-plugin.d.ts +90 -0
  181. package/dist/templates/vuetify-plugin.d.ts.map +1 -0
  182. package/dist/templates/vuetify-plugin.js +33 -0
  183. package/dist/types/command-types.d.ts +15 -0
  184. package/dist/types/command-types.d.ts.map +1 -0
  185. package/dist/types/command-types.js +2 -0
  186. package/dist/types/config-types.d.ts +29 -0
  187. package/dist/types/config-types.d.ts.map +1 -0
  188. package/dist/types/config-types.js +10 -0
  189. package/dist/types/ide-types.d.ts +29 -0
  190. package/dist/types/ide-types.d.ts.map +1 -0
  191. package/dist/types/ide-types.js +4 -0
  192. package/dist/types/lock-file-types.d.ts +27 -0
  193. package/dist/types/lock-file-types.d.ts.map +1 -0
  194. package/dist/types/lock-file-types.js +2 -0
  195. package/dist/utils/diff-display.d.ts +18 -0
  196. package/dist/utils/diff-display.d.ts.map +1 -0
  197. package/dist/utils/diff-display.js +61 -0
  198. package/dist/utils/fs-safe.d.ts +9 -0
  199. package/dist/utils/fs-safe.d.ts.map +1 -0
  200. package/dist/utils/fs-safe.js +44 -0
  201. package/dist/utils/logger.d.ts +14 -0
  202. package/dist/utils/logger.d.ts.map +1 -0
  203. package/dist/utils/logger.js +28 -0
  204. package/dist/utils/open-browser.d.ts +3 -0
  205. package/dist/utils/open-browser.d.ts.map +1 -0
  206. package/dist/utils/open-browser.js +13 -0
  207. package/package.json +11 -6
  208. package/dist/assets/cursor/.design-system-version +0 -1
  209. package/dist/assets/cursor/commands/audit-accessibility.md +0 -25
  210. package/dist/assets/cursor/commands/audit-ui.md +0 -35
  211. package/dist/assets/cursor/commands/component.md +0 -18
  212. package/dist/assets/cursor/commands/fix-storybook.md +0 -24
  213. package/dist/assets/cursor/commands/generate-component-from-figma.md +0 -26
  214. package/dist/assets/cursor/commands/generate-page-from-figma.md +0 -26
  215. package/dist/assets/cursor/plans/DESIGN_SYSTEM_PLAN.md +0 -177
  216. package/dist/assets/cursor/plans/PLANS_INDEX.md +0 -35
  217. package/dist/assets/cursor/rules/accessibility-contrast.mdc +0 -38
  218. package/dist/assets/cursor/rules/bem-class-style.mdc +0 -107
  219. package/dist/assets/cursor/rules/component-naming.mdc +0 -57
  220. package/dist/assets/cursor/rules/design-system-component-library.mdc +0 -59
  221. package/dist/assets/cursor/rules/design-system-workflow.mdc +0 -48
  222. package/dist/assets/cursor/rules/figma-mapping.mdc +0 -37
  223. package/dist/assets/cursor/rules/icons.mdc +0 -42
  224. package/dist/assets/cursor/rules/project-structure.mdc +0 -137
  225. package/dist/assets/cursor/rules/storybook-component-template.mdc +0 -103
  226. package/dist/assets/cursor/rules/storybook.mdc +0 -68
  227. package/dist/assets/cursor/rules/tokens.mdc +0 -32
  228. package/dist/assets/cursor/rules/viui-themes.mdc +0 -53
  229. package/dist/assets/cursor/rules/vuetify-layout.mdc +0 -52
  230. package/dist/assets/cursor/skills/accessibility.md +0 -75
  231. package/dist/assets/cursor/skills/design-system-thinking.md +0 -40
  232. package/dist/assets/cursor/skills/figma-interpretation.md +0 -38
  233. package/dist/assets/cursor/skills/vue-vuetify-design-system-architect.md +0 -60
  234. package/dist/assets/cursor/sync-manifest.json +0 -6
  235. package/dist/assets/viui-themes/bento-grid-global.scss +0 -5
  236. package/dist/assets/viui-themes/glassmorphism-global.scss +0 -5
  237. package/dist/assets/viui-themes/material-global.scss +0 -5
  238. package/dist/assets/viui-themes/minimalist-2-global.scss +0 -5
  239. package/dist/assets/viui-themes/minimalist-global.scss +0 -5
  240. package/dist/assets/viui-themes/neo-brutalism-global.scss +0 -5
@@ -0,0 +1,597 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @viui/cli — Sync .cursor (rules, skills, commands) from i-design-system into consumer repo.
4
+ * Commands: init, sync, setup, version.
5
+ * After `pnpm add @viui/cli`, postinstall runs `setup --postinstall` for step-by-step UX.
6
+ */
7
+ import { parseArgs } from 'node:util';
8
+ import { createRequire } from 'node:module';
9
+ import path from 'node:path';
10
+ import fs from 'node:fs';
11
+ import { fileURLToPath } from 'node:url';
12
+ import readline from 'node:readline/promises';
13
+ const require = createRequire(import.meta.url);
14
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
+ const pkg = require(path.join(__dirname, '..', 'package.json'));
16
+ function getAssetsCursorDir() {
17
+ return path.join(__dirname, 'assets', 'cursor');
18
+ }
19
+ /** viui-conf bundle path (synced to consumer src/plugins/viui-conf). */
20
+ function getAssetsPluginsDir() {
21
+ return path.join(__dirname, 'assets', 'plugins');
22
+ }
23
+ /** viui-themes SCSS bundle path (synced to consumer src/assets/styles/viui-themes). */
24
+ function getAssetsViuiThemesDir() {
25
+ return path.join(__dirname, 'assets', 'viui-themes');
26
+ }
27
+ function loadManifest(assetsDir) {
28
+ const p = path.join(assetsDir, 'sync-manifest.json');
29
+ if (!fs.existsSync(p))
30
+ return {};
31
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
32
+ }
33
+ function getDesignSystemVersion(assetsDir) {
34
+ const p = path.join(assetsDir, '.design-system-version');
35
+ if (!fs.existsSync(p))
36
+ return '0.0.0';
37
+ return fs.readFileSync(p, 'utf8').trim();
38
+ }
39
+ function copyRecursive(src, dest, opts) {
40
+ if (!fs.existsSync(src))
41
+ return;
42
+ if (!opts.dryRun)
43
+ fs.mkdirSync(dest, { recursive: true });
44
+ const entries = fs.readdirSync(src, { withFileTypes: true });
45
+ for (const e of entries) {
46
+ const srcPath = path.join(src, e.name);
47
+ const destPath = path.join(dest, e.name);
48
+ if (e.isDirectory()) {
49
+ copyRecursive(srcPath, destPath, opts);
50
+ }
51
+ else {
52
+ if (opts.dryRun) {
53
+ console.log(`Would copy: ${path.relative(process.cwd(), destPath) || destPath}`);
54
+ }
55
+ else {
56
+ if (opts.backup && fs.existsSync(destPath)) {
57
+ const backupPath = destPath + '.backup.' + Date.now();
58
+ fs.copyFileSync(destPath, backupPath);
59
+ }
60
+ fs.copyFileSync(srcPath, destPath);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * List all relative paths under dir (files and dirs), with forward slashes.
67
+ */
68
+ function listRelativePaths(dir, prefix = '') {
69
+ if (!fs.existsSync(dir))
70
+ return [];
71
+ const out = [];
72
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
73
+ for (const e of entries) {
74
+ const rel = prefix ? `${prefix}/${e.name}` : e.name;
75
+ out.push(rel);
76
+ if (e.isDirectory()) {
77
+ out.push(...listRelativePaths(path.join(dir, e.name), rel));
78
+ }
79
+ }
80
+ return out;
81
+ }
82
+ /**
83
+ * Remove from destDir any path that does not exist in sourceSet (mirror bundle).
84
+ * Deletes deeper paths first so dirs can be removed after their contents.
85
+ */
86
+ function removePathsNotInSource(destDir, sourceSet, opts) {
87
+ if (!fs.existsSync(destDir))
88
+ return;
89
+ const destPaths = listRelativePaths(destDir);
90
+ const sorted = destPaths.sort((a, b) => b.split('/').length - a.split('/').length);
91
+ for (const rel of sorted) {
92
+ const relNorm = rel.replace(/\\/g, '/');
93
+ if (sourceSet.has(relNorm))
94
+ continue;
95
+ const destPath = path.join(destDir, relNorm);
96
+ if (!fs.existsSync(destPath))
97
+ continue;
98
+ if (opts.dryRun) {
99
+ console.log(`Would remove: ${path.relative(process.cwd(), destPath) || destPath}`);
100
+ }
101
+ else {
102
+ fs.rmSync(destPath, { recursive: true });
103
+ console.log('Removed:', path.relative(process.cwd(), destPath) || destPath);
104
+ }
105
+ }
106
+ }
107
+ function runInit(cwd, assetsDir, opts) {
108
+ const manifest = loadManifest(assetsDir);
109
+ const version = getDesignSystemVersion(assetsDir);
110
+ const cursorDir = path.join(cwd, '.cursor');
111
+ const dirs = ['rules', 'skills', 'commands'];
112
+ if (!opts.noPlans)
113
+ dirs.push('plans');
114
+ if (opts.dryRun) {
115
+ console.log('Dry run: would create .cursor and copy:');
116
+ for (const key of Object.keys(manifest)) {
117
+ if (key === 'plans' && opts.noPlans)
118
+ continue;
119
+ const src = path.join(assetsDir, manifest[key].dir);
120
+ if (fs.existsSync(src)) {
121
+ const entries = fs.readdirSync(src, { withFileTypes: true });
122
+ entries.forEach(e => console.log(` .cursor/${manifest[key].dir}/${e.name}`));
123
+ }
124
+ }
125
+ console.log(` .cursor/.design-system-version (${version})`);
126
+ return;
127
+ }
128
+ if (!fs.existsSync(cursorDir))
129
+ fs.mkdirSync(cursorDir, { recursive: true });
130
+ for (const d of dirs) {
131
+ const sub = path.join(cursorDir, d);
132
+ if (!fs.existsSync(sub))
133
+ fs.mkdirSync(sub, { recursive: true });
134
+ }
135
+ for (const key of Object.keys(manifest)) {
136
+ if (key === 'plans' && opts.noPlans)
137
+ continue;
138
+ const src = path.join(assetsDir, manifest[key].dir);
139
+ const dest = path.join(cursorDir, manifest[key].dir);
140
+ if (fs.existsSync(src))
141
+ copyRecursive(src, dest, { dryRun: false });
142
+ }
143
+ fs.writeFileSync(path.join(cursorDir, '.design-system-version'), version, 'utf8');
144
+ console.log('Initialized .cursor with design system version', version);
145
+ // Sync viui-conf (theme + defaults) — trừ vuetify.ts
146
+ const viuiConfSrc = path.join(getAssetsPluginsDir(), 'viui-conf');
147
+ const viuiConfDest = path.join(cwd, 'src', 'plugins', 'viui-conf');
148
+ if (fs.existsSync(viuiConfSrc)) {
149
+ if (opts.dryRun) {
150
+ console.log('Would sync viui-conf to src/plugins/viui-conf');
151
+ }
152
+ else {
153
+ if (!fs.existsSync(path.join(cwd, 'src', 'plugins')))
154
+ fs.mkdirSync(path.join(cwd, 'src', 'plugins'), { recursive: true });
155
+ copyRecursive(viuiConfSrc, viuiConfDest, { dryRun: false });
156
+ }
157
+ if (!opts.dryRun)
158
+ console.log('Synced viui-conf to src/plugins/viui-conf');
159
+ }
160
+ syncViuiThemesAndEntry(cwd, opts.dryRun ?? false);
161
+ }
162
+ /**
163
+ * Sync viui-themes SCSS to consumer and ensure theme SCSS is loaded.
164
+ * - Copies dist/assets/viui-themes → src/assets/styles/viui-themes
165
+ * - Writes viui-themes-entry.scss that @use's viui-themes/index.scss
166
+ * - Injects import into main.scss if present and not already there
167
+ */
168
+ function syncViuiThemesAndEntry(cwd, dryRun) {
169
+ const themesSrc = getAssetsViuiThemesDir();
170
+ const stylesDir = path.join(cwd, 'src', 'assets', 'styles');
171
+ const themesDest = path.join(stylesDir, 'viui-themes');
172
+ const entryPath = path.join(stylesDir, 'viui-themes-entry.scss');
173
+ const mainScssPath = path.join(stylesDir, 'main.scss');
174
+ const entryImport = "@use './viui-themes-entry' as *;";
175
+ if (!fs.existsSync(themesSrc))
176
+ return;
177
+ if (dryRun) {
178
+ console.log('Would sync viui-themes to src/assets/styles/viui-themes');
179
+ console.log('Would write src/assets/styles/viui-themes-entry.scss');
180
+ console.log('Would ensure main.scss imports viui-themes-entry');
181
+ return;
182
+ }
183
+ if (!fs.existsSync(path.join(cwd, 'src', 'assets')))
184
+ fs.mkdirSync(path.join(cwd, 'src', 'assets'), { recursive: true });
185
+ if (!fs.existsSync(stylesDir))
186
+ fs.mkdirSync(stylesDir, { recursive: true });
187
+ copyRecursive(themesSrc, themesDest, { dryRun: false });
188
+ console.log('Synced viui-themes to src/assets/styles/viui-themes');
189
+ const entryContent = `/**
190
+ * ViUi design style themes — auto-loaded when using viui-conf (VITE_VIUI_THEME).
191
+ * Do not edit: generated by viui-cli sync. Styles apply when body has .design-style-<id> or wrapper has .design-style-<id>.
192
+ */
193
+ @use './viui-themes/index.scss' as *;
194
+ `;
195
+ fs.writeFileSync(entryPath, entryContent, 'utf8');
196
+ console.log('Wrote viui-themes-entry.scss');
197
+ if (fs.existsSync(mainScssPath)) {
198
+ const mainContent = fs.readFileSync(mainScssPath, 'utf8');
199
+ const hasEntry = /viui-themes-entry/.test(mainContent);
200
+ if (!hasEntry) {
201
+ const appended = mainContent.trimEnd() + '\n' + entryImport + '\n';
202
+ fs.writeFileSync(mainScssPath, appended, 'utf8');
203
+ console.log('Added viui-themes-entry import to main.scss');
204
+ }
205
+ }
206
+ else {
207
+ console.log('Note: src/assets/styles/main.scss not found. To load theme styles: create it with "' +
208
+ entryImport +
209
+ '" and import main.scss in your app entry (e.g. main.ts).');
210
+ }
211
+ }
212
+ function runSync(cwd, assetsDir, opts) {
213
+ const manifest = loadManifest(assetsDir);
214
+ const version = getDesignSystemVersion(assetsDir);
215
+ const cursorDir = path.join(cwd, '.cursor');
216
+ console.log('Syncing .cursor at:', path.resolve(cursorDir));
217
+ let keys = Object.keys(manifest);
218
+ if (opts.rulesOnly)
219
+ keys = keys.filter(k => k === 'rules');
220
+ if (opts.skillsOnly)
221
+ keys = keys.filter(k => k === 'skills');
222
+ if (opts.commandsOnly)
223
+ keys = keys.filter(k => k === 'commands');
224
+ if (opts.dryRun) {
225
+ console.log('Dry run: would overwrite:');
226
+ for (const key of keys) {
227
+ const src = path.join(assetsDir, manifest[key].dir);
228
+ if (fs.existsSync(src)) {
229
+ const entries = fs.readdirSync(src, { withFileTypes: true });
230
+ entries.forEach(e => console.log(` .cursor/${manifest[key].dir}/${e.name}`));
231
+ }
232
+ }
233
+ console.log(` .cursor/.design-system-version (${version})`);
234
+ return;
235
+ }
236
+ if (!fs.existsSync(cursorDir))
237
+ fs.mkdirSync(cursorDir, { recursive: true });
238
+ for (const key of keys) {
239
+ const src = path.join(assetsDir, manifest[key].dir);
240
+ const dest = path.join(cursorDir, manifest[key].dir);
241
+ if (fs.existsSync(src)) {
242
+ if (!fs.existsSync(dest))
243
+ fs.mkdirSync(dest, { recursive: true });
244
+ copyRecursive(src, dest, { dryRun: opts.dryRun, backup: opts.backup });
245
+ const sourceRelPaths = listRelativePaths(src).map(p => p.replace(/\\/g, '/'));
246
+ const sourceSet = new Set(sourceRelPaths);
247
+ removePathsNotInSource(dest, sourceSet, { dryRun: opts.dryRun });
248
+ }
249
+ }
250
+ fs.writeFileSync(path.join(cursorDir, '.design-system-version'), version, 'utf8');
251
+ console.log('Synced .cursor with design system version', version);
252
+ // Sync viui-conf (theme + defaults) — trừ vuetify.ts
253
+ const viuiConfSrc = path.join(getAssetsPluginsDir(), 'viui-conf');
254
+ const viuiConfDest = path.join(cwd, 'src', 'plugins', 'viui-conf');
255
+ if (fs.existsSync(viuiConfSrc)) {
256
+ if (opts.dryRun) {
257
+ console.log('Would sync viui-conf to src/plugins/viui-conf');
258
+ }
259
+ else {
260
+ if (!fs.existsSync(path.join(cwd, 'src', 'plugins')))
261
+ fs.mkdirSync(path.join(cwd, 'src', 'plugins'), { recursive: true });
262
+ copyRecursive(viuiConfSrc, viuiConfDest, { dryRun: false, backup: opts.backup });
263
+ console.log('Synced viui-conf to src/plugins/viui-conf');
264
+ }
265
+ }
266
+ syncViuiThemesAndEntry(cwd, opts.dryRun ?? false);
267
+ }
268
+ function detectPackageManager(cwd) {
269
+ if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml')))
270
+ return 'pnpm';
271
+ if (fs.existsSync(path.join(cwd, 'yarn.lock')))
272
+ return 'yarn';
273
+ return 'npm';
274
+ }
275
+ function addPostinstallScript(cwd, pm) {
276
+ const pkgPath = path.join(cwd, 'package.json');
277
+ if (!fs.existsSync(pkgPath))
278
+ return false;
279
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
280
+ const scripts = pkg.scripts ?? {};
281
+ const cmd = pm === 'pnpm' ? 'pnpm exec viui-cli sync' : pm === 'yarn' ? 'yarn viui-cli sync' : 'npx viui-cli sync';
282
+ if (scripts.postinstall?.includes('viui-cli'))
283
+ return false;
284
+ scripts.postinstall = scripts.postinstall ? `${scripts.postinstall} && ${cmd}` : cmd;
285
+ pkg.scripts = scripts;
286
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
287
+ return true;
288
+ }
289
+ const VIUI_THEME_IDS = ['minimalist-2', 'neo-brutalism', 'material'];
290
+ function setEnvTheme(cwd, themeId) {
291
+ const envPath = path.join(cwd, '.env');
292
+ const examplePath = path.join(cwd, '.env.example');
293
+ const line = `VITE_VIUI_THEME=${themeId}`;
294
+ const targets = [envPath, examplePath].filter((p) => fs.existsSync(p));
295
+ if (targets.length === 0) {
296
+ fs.writeFileSync(envPath, line + '\n', 'utf8');
297
+ console.log('Created .env with', line);
298
+ return;
299
+ }
300
+ for (const p of targets) {
301
+ let content = fs.readFileSync(p, 'utf8');
302
+ const re = /^\s*VITE_VIUI_THEME=.*/m;
303
+ if (re.test(content)) {
304
+ content = content.replace(re, line);
305
+ }
306
+ else {
307
+ content = content.trimEnd() + '\n' + line + '\n';
308
+ }
309
+ fs.writeFileSync(p, content, 'utf8');
310
+ console.log('Set', line, 'in', path.basename(p));
311
+ }
312
+ }
313
+ function ensureApplyThemeBodyInVuetify(cwd) {
314
+ const vuetifyPath = path.join(cwd, 'src', 'plugins', 'vuetify.ts');
315
+ if (!fs.existsSync(vuetifyPath))
316
+ return false;
317
+ const content = fs.readFileSync(vuetifyPath, 'utf8');
318
+ if (/apply-theme-body|applyThemeBody/.test(content))
319
+ return false;
320
+ const importLine = "import './viui-conf/apply-theme-body'";
321
+ const defaultsImportMatch = content.match(/import\s+.+\s+from\s+['"]\.\/viui-conf\/defaults[^'"]*['"]/);
322
+ const insert = defaultsImportMatch
323
+ ? content.replace(defaultsImportMatch[0], defaultsImportMatch[0] + '\n' + importLine)
324
+ : content.trimStart().replace(/^(\s*)/, `$1${importLine}\n$1`);
325
+ fs.writeFileSync(vuetifyPath, insert, 'utf8');
326
+ console.log('Added apply-theme-body import to src/plugins/vuetify.ts');
327
+ return true;
328
+ }
329
+ function showHelpDocs(cwd) {
330
+ console.log('\n--- Design system setup ---');
331
+ console.log('Design themes (viui-themes) are in: src/assets/styles/viui-themes/');
332
+ console.log('Available theme ids: minimalist-2 (default), neo-brutalism, material');
333
+ console.log('To use a theme: set VITE_VIUI_THEME in .env and add in vuetify.ts:');
334
+ console.log(" import './viui-conf/apply-theme-body'");
335
+ console.log('Details: src/plugins/viui-conf/defaults/README.md');
336
+ console.log('CLI docs: pnpm exec viui-cli --help');
337
+ console.log('---\n');
338
+ }
339
+ async function runConfigureTheme(cwd, rl, opts) {
340
+ console.log('\n Design theme (viui-themes)');
341
+ console.log(' Available: minimalist-2 (default), neo-brutalism, material\n');
342
+ console.log(' a) Use minimalist-2 (default) — thin borders, flat');
343
+ console.log(' b) Use neo-brutalism — thick borders, hard shadow');
344
+ console.log(' c) Use material — elevated, standard Material');
345
+ console.log(' d) Skip / configure manually — set .env yourself\n');
346
+ const a = await rl.question(' Choose (a-d, or Enter for a): ');
347
+ const choice = (a.trim().toLowerCase() || 'a')[0];
348
+ const map = {
349
+ a: 'minimalist-2',
350
+ b: 'neo-brutalism',
351
+ c: 'material',
352
+ d: 'skip',
353
+ };
354
+ const themeId = map[choice] ?? map.a;
355
+ if (themeId === 'skip') {
356
+ console.log(' Skipped. Set VITE_VIUI_THEME in .env and add import in vuetify.ts. See src/plugins/viui-conf/defaults/README.md');
357
+ return;
358
+ }
359
+ setEnvTheme(cwd, themeId);
360
+ const vuetifyPath = path.join(cwd, 'src', 'plugins', 'vuetify.ts');
361
+ const hasImport = fs.existsSync(vuetifyPath) && /apply-theme-body|applyThemeBody/.test(fs.readFileSync(vuetifyPath, 'utf8'));
362
+ if (!hasImport && fs.existsSync(vuetifyPath)) {
363
+ const ans = await rl.question(' Add apply-theme-body import to vuetify.ts? (Y/n): ');
364
+ const add = opts.yes || (ans.trim().toLowerCase() === '' || ans.trim().toLowerCase() === 'y' || ans.trim().toLowerCase() === 'yes');
365
+ if (add)
366
+ ensureApplyThemeBodyInVuetify(cwd);
367
+ }
368
+ console.log(' Theme configured:', themeId);
369
+ }
370
+ async function runSetup(cwd, assetsDir, opts) {
371
+ const isPostinstall = opts.postinstall === true;
372
+ if (isPostinstall && !process.stdin.isTTY) {
373
+ return;
374
+ }
375
+ if (!fs.existsSync(assetsDir)) {
376
+ if (isPostinstall)
377
+ return;
378
+ console.error('Assets not found. Run "pnpm build" in packages/cli first.');
379
+ throw new Error('Assets not found');
380
+ }
381
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
382
+ const ask = async (q, defaultYes) => {
383
+ const a = await rl.question(`${q} (${defaultYes ? 'Y/n' : 'y/N'}): `);
384
+ const s = a.trim().toLowerCase();
385
+ if (s === '')
386
+ return defaultYes;
387
+ return s === 'y' || s === 'yes';
388
+ };
389
+ console.log(`\n${pkg.name ?? '@viui/cli'} — Setup i-design-system in this repo\n`);
390
+ console.log(' This will: sync .cursor, viui-conf, viui-themes; optional @viui/web, theme config, postinstall.\n');
391
+ const runNow = opts.yes || (await ask('Run setup now?', true));
392
+ if (!runNow) {
393
+ console.log('Skipped. Run later: pnpm exec viui-cli setup');
394
+ rl.close();
395
+ return;
396
+ }
397
+ const pm = detectPackageManager(cwd);
398
+ const cursorDir = path.join(cwd, '.cursor');
399
+ for (;;) {
400
+ console.log('\n What do you want to do?\n');
401
+ console.log(' 1) Full setup (recommended) — init/sync .cursor + viui-conf + viui-themes, install @viui/web, configure theme, add postinstall');
402
+ console.log(' 2) Sync only — update .cursor, viui-conf, viui-themes (no npm install)');
403
+ console.log(' 3) Install @viui/web only — add Vi* components dependency');
404
+ console.log(' 4) Configure design theme — set VITE_VIUI_THEME in .env and ensure body class is applied');
405
+ console.log(' 5) Add postinstall script — auto-sync on every pnpm install');
406
+ console.log(' 6) Show help / docs — print links and next steps\n');
407
+ const choiceInput = await rl.question(' Choose (1-6, or Enter for 1): ');
408
+ const choice = (choiceInput.trim() || '1').replace(/[^1-6]/, '1');
409
+ const n = parseInt(choice, 10);
410
+ if (n < 1 || n > 6)
411
+ continue;
412
+ if (n === 1) {
413
+ if (!fs.existsSync(cursorDir)) {
414
+ console.log('\nStep: Initializing .cursor, viui-conf, viui-themes...');
415
+ runInit(cwd, assetsDir, { yes: true, dryRun: false, noPlans: false });
416
+ }
417
+ else {
418
+ console.log('\nStep: Syncing .cursor, viui-conf, viui-themes...');
419
+ runSync(cwd, assetsDir, { dryRun: false, backup: false });
420
+ }
421
+ console.log('\nStep: Installing @viui/web...');
422
+ const { execSync } = await import('node:child_process');
423
+ const addCmd = pm === 'pnpm' ? 'pnpm add @viui/web' : pm === 'yarn' ? 'yarn add @viui/web' : 'npm install @viui/web';
424
+ try {
425
+ execSync(addCmd, { cwd, stdio: 'inherit' });
426
+ }
427
+ catch {
428
+ console.warn('\nCould not install @viui/web (e.g. not published or no permission). Add it manually: pnpm add @viui/web or use a file: link. Continuing with theme config and postinstall.');
429
+ }
430
+ await runConfigureTheme(cwd, rl, { yes: opts.yes });
431
+ if (!isPostinstall && (opts.yes || (await ask('\nAdd postinstall to auto-sync on install?', false)))) {
432
+ if (addPostinstallScript(cwd, pm))
433
+ console.log('Added postinstall script to package.json.');
434
+ }
435
+ console.log('\nDone. Use: import { ViButton, ViInput, ... } from \'@viui/web\'');
436
+ console.log('Design themes: src/assets/styles/viui-themes/ — set VITE_VIUI_THEME in .env; see src/plugins/viui-conf/defaults/README.md');
437
+ break;
438
+ }
439
+ if (n === 2) {
440
+ if (!fs.existsSync(cursorDir)) {
441
+ console.log('\nInitializing .cursor, viui-conf, viui-themes...');
442
+ runInit(cwd, assetsDir, { yes: true, dryRun: false, noPlans: false });
443
+ }
444
+ else {
445
+ console.log('\nSyncing .cursor, viui-conf, viui-themes...');
446
+ runSync(cwd, assetsDir, { dryRun: false, backup: false });
447
+ }
448
+ console.log('Sync done.');
449
+ break;
450
+ }
451
+ if (n === 3) {
452
+ const { execSync } = await import('node:child_process');
453
+ const addCmd = pm === 'pnpm' ? 'pnpm add @viui/web' : pm === 'yarn' ? 'yarn add @viui/web' : 'npm install @viui/web';
454
+ console.log('\nRunning:', addCmd);
455
+ try {
456
+ execSync(addCmd, { cwd, stdio: 'inherit' });
457
+ }
458
+ catch {
459
+ console.warn('\nCould not install @viui/web (e.g. not published or no permission). Add manually: pnpm add @viui/web or use file: link.');
460
+ break;
461
+ }
462
+ console.log('Done. Use: import { ViButton, ViInput, ... } from \'@viui/web\'');
463
+ break;
464
+ }
465
+ if (n === 4) {
466
+ await runConfigureTheme(cwd, rl, { yes: opts.yes });
467
+ break;
468
+ }
469
+ if (n === 5) {
470
+ if (addPostinstallScript(cwd, pm)) {
471
+ console.log('\nAdded postinstall script to package.json.');
472
+ }
473
+ else {
474
+ console.log('\npostinstall already contains viui-cli or package.json not found.');
475
+ }
476
+ break;
477
+ }
478
+ if (n === 6) {
479
+ showHelpDocs(cwd);
480
+ const again = opts.yes || (await ask('Show menu again?', true));
481
+ if (!again)
482
+ break;
483
+ }
484
+ }
485
+ rl.close();
486
+ }
487
+ const result = parseArgs({
488
+ options: {
489
+ help: { type: 'boolean', short: 'h', default: false },
490
+ version: { type: 'boolean', short: 'v', default: false },
491
+ yes: { type: 'boolean', short: 'y', default: false },
492
+ postinstall: { type: 'boolean', default: false },
493
+ 'dry-run': { type: 'boolean', default: false },
494
+ 'no-plans': { type: 'boolean', default: false },
495
+ backup: { type: 'boolean', default: false },
496
+ 'rules-only': { type: 'boolean', default: false },
497
+ 'skills-only': { type: 'boolean', default: false },
498
+ 'commands-only': { type: 'boolean', default: false },
499
+ },
500
+ allowPositionals: true,
501
+ });
502
+ const { values } = result;
503
+ const positionals = result.positionals ?? [];
504
+ const [command] = positionals;
505
+ if (values.version && !command) {
506
+ console.log(`${pkg.name ?? '@viui/cli'} ${pkg.version}`);
507
+ const cwd = process.cwd();
508
+ const versionFile = path.join(cwd, '.cursor', '.design-system-version');
509
+ if (fs.existsSync(versionFile)) {
510
+ console.log('Design system (synced):', fs.readFileSync(versionFile, 'utf8').trim());
511
+ }
512
+ process.exit(0);
513
+ }
514
+ if (values.help || !command || command === 'help') {
515
+ console.log(`
516
+ ${pkg.name ?? '@viui/cli'} — Sync design system .cursor into your repo
517
+
518
+ Usage: viui-cli <command> [options]
519
+
520
+ Commands:
521
+ init Create .cursor and copy rules, skills, commands (run once at repo root)
522
+ sync Update .cursor from design system (overwrite)
523
+ setup Interactive setup: init/sync .cursor, install @viui/web, optional postinstall (runs after pnpm add ${pkg.name ?? '@viui/cli'})
524
+ version Print CLI and design system version
525
+
526
+ Setup options:
527
+ -y, --yes Non-interactive: run all steps (init/sync, add @viui/web, skip postinstall prompt)
528
+ --postinstall Used by postinstall hook; skips wizard when not TTY (e.g. CI)
529
+
530
+ Init options:
531
+ -y, --yes Skip confirmation
532
+ --dry-run Print what would be copied
533
+ --no-plans Do not sync plans
534
+
535
+ Sync options:
536
+ --dry-run Print what would be overwritten
537
+ --backup Backup existing files before overwrite
538
+ --rules-only Sync only rules
539
+ --skills-only Sync only skills
540
+ --commands-only Sync only commands
541
+
542
+ Global:
543
+ -h, --help Show this help
544
+ -v, --version Print version
545
+
546
+ One-command UX: pnpm add ${pkg.name ?? '@viui/cli'} — then follow the setup steps. Or run: viui-cli setup
547
+ `);
548
+ process.exit(0);
549
+ }
550
+ if (command === 'version') {
551
+ console.log(`${pkg.name ?? '@viui/cli'} ${pkg.version}`);
552
+ const cwd = process.cwd();
553
+ const versionFile = path.join(cwd, '.cursor', '.design-system-version');
554
+ if (fs.existsSync(versionFile)) {
555
+ console.log('Design system (synced):', fs.readFileSync(versionFile, 'utf8').trim());
556
+ }
557
+ process.exit(0);
558
+ }
559
+ const assetsDir = getAssetsCursorDir();
560
+ const cwd = process.cwd();
561
+ if (!fs.existsSync(assetsDir) && command !== 'setup') {
562
+ console.error('Assets not found. Run "pnpm build" in packages/cli first.');
563
+ process.exit(1);
564
+ }
565
+ if (command === 'init') {
566
+ runInit(cwd, assetsDir, {
567
+ yes: values.yes,
568
+ dryRun: values['dry-run'],
569
+ noPlans: values['no-plans'],
570
+ });
571
+ process.exit(0);
572
+ }
573
+ if (command === 'sync') {
574
+ runSync(cwd, assetsDir, {
575
+ dryRun: values['dry-run'],
576
+ backup: values.backup,
577
+ rulesOnly: values['rules-only'],
578
+ skillsOnly: values['skills-only'],
579
+ commandsOnly: values['commands-only'],
580
+ });
581
+ process.exit(0);
582
+ }
583
+ if (command === 'setup') {
584
+ runSetup(cwd, assetsDir, {
585
+ postinstall: values.postinstall,
586
+ yes: values.yes,
587
+ })
588
+ .then(() => process.exit(0))
589
+ .catch((err) => {
590
+ console.error(err);
591
+ process.exit(1);
592
+ });
593
+ }
594
+ else {
595
+ console.error(`Unknown command: ${command}. Use --help for usage.`);
596
+ process.exit(1);
597
+ }
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerAuditCommand(program: Command): void;
3
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/commands/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAoHxC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4C3D"}