cus-base-ui 0.2.5 → 0.2.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 (2) hide show
  1. package/package.json +1 -1
  2. package/scripts/ui-cli.ts +78 -24
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cus-base-ui",
3
3
  "private": false,
4
- "version": "0.2.5",
4
+ "version": "0.2.7",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "cus-base-ui": "./dist/ui-cli.cjs"
package/scripts/ui-cli.ts CHANGED
@@ -126,6 +126,7 @@ const setupViteConfig = (cwd: string) => {
126
126
  const configTs = path.join(cwd, 'vite.config.ts');
127
127
  const configJs = path.join(cwd, 'vite.config.js');
128
128
 
129
+ // No config exists — create from template
129
130
  if (!fs.existsSync(configTs) && !fs.existsSync(configJs)) {
130
131
  fs.writeFileSync(configTs, VITE_CONFIG_TEMPLATE);
131
132
  log('Created vite.config.ts with Tailwind + React Compiler setup.');
@@ -133,49 +134,87 @@ const setupViteConfig = (cwd: string) => {
133
134
  }
134
135
 
135
136
  const existingPath = fs.existsSync(configTs) ? configTs : configJs;
136
- const content = fs.readFileSync(existingPath, 'utf-8');
137
+ let content = fs.readFileSync(existingPath, 'utf-8');
137
138
 
138
139
  const missingImports: string[] = [];
139
140
  if (!content.includes('@tailwindcss/vite')) missingImports.push("import tailwindcss from '@tailwindcss/vite';");
140
141
  if (!content.includes('@vitejs/plugin-react')) missingImports.push("import react from '@vitejs/plugin-react';");
141
142
  if (!content.includes('vite-plugin-babel')) missingImports.push("import babel from 'vite-plugin-babel';");
142
143
  if (!content.includes('babel-plugin-react-compiler')) missingImports.push("import { reactCompilerPreset } from 'babel-plugin-react-compiler';");
144
+ if (!content.includes("from 'path'") && !content.includes('from "path"')) missingImports.push("import path from 'path';");
143
145
 
144
146
  const missingPlugins: string[] = [];
145
147
  if (!content.includes('tailwindcss()')) missingPlugins.push('tailwindcss()');
146
148
  if (!content.includes('react()') && !content.includes('react({')) missingPlugins.push('react()');
147
- if (!content.includes('reactCompilerPreset')) missingPlugins.push('babel({ presets: [reactCompilerPreset()] })');
149
+ if (!content.includes('reactCompilerPreset')) missingPlugins.push("babel({ presets: [reactCompilerPreset()] })");
148
150
 
149
- const hasAlias = content.includes('alias:') || content.includes("'@'") || content.includes('"@"');
151
+ const hasAlias = content.includes('alias:') || content.includes('alias(') || content.includes("'@'") || content.includes('"@"');
150
152
 
151
153
  if (missingImports.length === 0 && missingPlugins.length === 0 && hasAlias) {
152
154
  log('vite.config already configured — skipping.');
153
155
  return;
154
156
  }
155
157
 
156
- warn(`${path.basename(existingPath)} exists but is missing required setup. Add the following manually:`);
158
+ // --- Auto-patch the file ---
159
+
160
+ // 1. Insert missing imports after the last import statement
157
161
  if (missingImports.length > 0) {
158
- console.log('\n // Imports to add:');
159
- for (const imp of missingImports) console.log(` ${imp}`);
162
+ const importBlock = missingImports.join('\n');
163
+ const allImports = [...content.matchAll(/^import\s.+$/gm)];
164
+ if (allImports.length > 0) {
165
+ const last = allImports[allImports.length - 1];
166
+ const pos = last.index! + last[0].length;
167
+ content = content.slice(0, pos) + '\n' + importBlock + content.slice(pos);
168
+ } else {
169
+ content = importBlock + '\n' + content;
170
+ }
160
171
  }
172
+
173
+ // 2. Insert missing plugins into plugins: [...]
161
174
  if (missingPlugins.length > 0) {
162
- console.log('\n // Plugins to add inside defineConfig({ plugins: [...] }):');
163
- for (const plugin of missingPlugins) console.log(` ${plugin},`);
175
+ const match = content.match(/plugins:\s*\[/);
176
+ if (match && match.index !== undefined) {
177
+ const pos = match.index + match[0].length;
178
+ const pluginLines = missingPlugins.map((p) => `\n ${p},`).join('');
179
+ content = content.slice(0, pos) + pluginLines + content.slice(pos);
180
+ }
164
181
  }
182
+
183
+ // 3. Insert resolve.alias block if missing
165
184
  if (!hasAlias) {
166
- console.log('\n // resolve.alias to add inside defineConfig({}):');
167
- console.log(" resolve: {");
168
- console.log(" alias: {");
169
- console.log(" '@': path.resolve(__dirname, './src'),");
170
- console.log(" '@lib': path.resolve(__dirname, './src/lib'),");
171
- console.log(" '@components': path.resolve(__dirname, './src/components'),");
172
- console.log(" '@assets': path.resolve(__dirname, './src/assets'),");
173
- console.log(" '@pages': path.resolve(__dirname, './src/pages'),");
174
- console.log(" '@styles': path.resolve(__dirname, './src/styles'),");
175
- console.log(" },");
176
- console.log(" },");
185
+ const aliasBlock = [
186
+ ' resolve: {',
187
+ ' alias: {',
188
+ " '@': path.resolve(__dirname, './src'),",
189
+ " '@lib': path.resolve(__dirname, './src/lib'),",
190
+ " '@components': path.resolve(__dirname, './src/components'),",
191
+ " '@assets': path.resolve(__dirname, './src/assets'),",
192
+ " '@pages': path.resolve(__dirname, './src/pages'),",
193
+ " '@styles': path.resolve(__dirname, './src/styles'),",
194
+ ' },',
195
+ ' },',
196
+ ].join('\n');
197
+
198
+ // Find end of plugins array, then insert after that line
199
+ const pluginsStart = content.search(/plugins:\s*\[/);
200
+ if (pluginsStart !== -1) {
201
+ let depth = 0;
202
+ let foundStart = false;
203
+ for (let i = pluginsStart; i < content.length; i++) {
204
+ if (content[i] === '[') { depth++; foundStart = true; }
205
+ if (content[i] === ']') depth--;
206
+ if (foundStart && depth === 0) {
207
+ let lineEnd = content.indexOf('\n', i);
208
+ if (lineEnd === -1) lineEnd = content.length;
209
+ content = content.slice(0, lineEnd + 1) + aliasBlock + '\n' + content.slice(lineEnd + 1);
210
+ break;
211
+ }
212
+ }
213
+ }
177
214
  }
178
- console.log('');
215
+
216
+ fs.writeFileSync(existingPath, content);
217
+ log(`Updated ${path.basename(existingPath)} with Tailwind + React Compiler + path aliases.`);
179
218
  };
180
219
 
181
220
  const ensureTailwindCss = (cwd: string) => {
@@ -215,16 +254,20 @@ const setupTsConfig = (cwd: string) => {
215
254
  }
216
255
 
217
256
  try {
218
- // Strip single-line and block comments before parsing
219
- const stripped = raw.replace(/\/\/[^\n]*/g, '').replace(/\/\*[\s\S]*?\*\//g, '');
257
+ // Strip comments safely: block comments first, then single-line comments
258
+ // only when they appear outside of string values (preceded by whitespace or line start)
259
+ const stripped = raw
260
+ .replace(/\/\*[\s\S]*?\*\//g, '')
261
+ .replace(/(^|[\s,{[\]])\/\/[^\n]*/g, '$1');
220
262
  const parsed = JSON.parse(stripped) as { compilerOptions?: Record<string, unknown> };
221
263
  if (!parsed.compilerOptions) parsed.compilerOptions = {};
222
264
  parsed.compilerOptions.baseUrl = '.';
223
265
  parsed.compilerOptions.paths = TSCONFIG_PATHS;
224
266
  fs.writeFileSync(configPath, JSON.stringify(parsed, null, 2));
225
267
  log(`Added path aliases to ${candidate}.`);
226
- } catch {
227
- warn(`Could not auto-patch ${candidate}. Add these to compilerOptions manually:`);
268
+ } catch (err) {
269
+ warn(`Could not auto-patch ${candidate}: ${err instanceof Error ? err.message : err}`);
270
+ warn('Add these to compilerOptions manually:');
228
271
  console.log('\n "baseUrl": ".",');
229
272
  console.log(' "paths": {');
230
273
  for (const [alias, targets] of Object.entries(TSCONFIG_PATHS)) {
@@ -359,6 +402,17 @@ const main = async () => {
359
402
  error('Usage: npx cus-base-ui add <component-name> [--force]');
360
403
  return;
361
404
  }
405
+
406
+ // Auto-init if not yet initialized
407
+ const cnPath = path.join(cwd, 'src/lib/utils/cn.ts');
408
+ if (!fs.existsSync(cnPath)) {
409
+ log('Project not initialized — running init first...');
410
+ setupViteConfig(cwd);
411
+ setupTsConfig(cwd);
412
+ ensureTailwindCss(cwd);
413
+ installNpmPackages(RUNTIME_PACKAGES, cwd);
414
+ }
415
+
362
416
  for (const name of componentNames) {
363
417
  addComponent(name, registry, cwd, { force: isForce });
364
418
  }