basuicn 0.1.9 → 0.2.3
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.
- package/dist/ui-cli.cjs +281 -29
- package/package.json +1 -1
- package/registry.json +91 -7
- package/scripts/build-registry.ts +1 -1
- package/scripts/ui-cli.ts +334 -28
package/dist/ui-cli.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var import_fs = __toESM(require("fs"), 1);
|
|
|
27
27
|
var import_path = __toESM(require("path"), 1);
|
|
28
28
|
var import_child_process = require("child_process");
|
|
29
29
|
var import_readline = __toESM(require("readline"), 1);
|
|
30
|
-
var VERSION = "0.
|
|
30
|
+
var VERSION = "0.2.3";
|
|
31
31
|
var REGISTRY_LOCAL = "./registry.json";
|
|
32
32
|
var REGISTRY_REMOTE = "https://raw.githubusercontent.com/Basuicn/basuicn-core/main/registry.json";
|
|
33
33
|
var c = {
|
|
@@ -47,6 +47,27 @@ var ok = (msg) => console.log(`${c.green}\u2714${c.reset} ${msg}`);
|
|
|
47
47
|
var warn = (msg) => console.warn(`${c.yellow}\u26A0${c.reset} ${msg}`);
|
|
48
48
|
var error = (msg) => console.error(`${c.red}\u2716${c.reset} ${msg}`);
|
|
49
49
|
var getTargetProjectDir = () => process.cwd();
|
|
50
|
+
var detectFramework = (cwd) => {
|
|
51
|
+
const hasNextConfig = import_fs.default.existsSync(import_path.default.join(cwd, "next.config.js")) || import_fs.default.existsSync(import_path.default.join(cwd, "next.config.ts")) || import_fs.default.existsSync(import_path.default.join(cwd, "next.config.mjs"));
|
|
52
|
+
const hasNextDep = (() => {
|
|
53
|
+
const pkgPath = import_path.default.join(cwd, "package.json");
|
|
54
|
+
if (!import_fs.default.existsSync(pkgPath)) return false;
|
|
55
|
+
try {
|
|
56
|
+
const pkg = JSON.parse(import_fs.default.readFileSync(pkgPath, "utf-8"));
|
|
57
|
+
const all = { ...pkg.dependencies || {}, ...pkg.devDependencies || {} };
|
|
58
|
+
return !!all["next"];
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
if (hasNextConfig || hasNextDep) {
|
|
64
|
+
const hasAppDir = import_fs.default.existsSync(import_path.default.join(cwd, "src/app")) || import_fs.default.existsSync(import_path.default.join(cwd, "app"));
|
|
65
|
+
const hasPagesDir = import_fs.default.existsSync(import_path.default.join(cwd, "src/pages")) || import_fs.default.existsSync(import_path.default.join(cwd, "pages"));
|
|
66
|
+
if (hasPagesDir && !hasAppDir) return "nextjs-pages";
|
|
67
|
+
return "nextjs-app";
|
|
68
|
+
}
|
|
69
|
+
return "vite";
|
|
70
|
+
};
|
|
50
71
|
var ask = (question) => {
|
|
51
72
|
const rl = import_readline.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
52
73
|
return new Promise((resolve) => {
|
|
@@ -130,6 +151,19 @@ var RUNTIME_PACKAGES = [
|
|
|
130
151
|
"tailwindcss-animate",
|
|
131
152
|
"lucide-react"
|
|
132
153
|
];
|
|
154
|
+
var NEXTJS_DEV_PACKAGES = [
|
|
155
|
+
"tailwindcss",
|
|
156
|
+
"@tailwindcss/postcss",
|
|
157
|
+
"@types/node"
|
|
158
|
+
];
|
|
159
|
+
var POSTCSS_CONFIG_TEMPLATE = `const config = {
|
|
160
|
+
plugins: {
|
|
161
|
+
'@tailwindcss/postcss': {},
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export default config;
|
|
166
|
+
`;
|
|
133
167
|
var VITE_CONFIG_TEMPLATE = `import { defineConfig } from 'vite';
|
|
134
168
|
import tailwindcss from '@tailwindcss/vite';
|
|
135
169
|
import react from '@vitejs/plugin-react';
|
|
@@ -237,6 +271,22 @@ var setupViteConfig = (cwd) => {
|
|
|
237
271
|
import_fs.default.writeFileSync(existingPath, content);
|
|
238
272
|
ok(`Updated ${import_path.default.basename(existingPath)} with Tailwind + path aliases.`);
|
|
239
273
|
};
|
|
274
|
+
var setupNextConfig = (cwd) => {
|
|
275
|
+
installNpmPackages(NEXTJS_DEV_PACKAGES, cwd, true);
|
|
276
|
+
const postcssCandidates = ["postcss.config.mjs", "postcss.config.js", "postcss.config.cjs"];
|
|
277
|
+
const existingPostcss = postcssCandidates.map((f) => import_path.default.join(cwd, f)).find((p) => import_fs.default.existsSync(p));
|
|
278
|
+
if (!existingPostcss) {
|
|
279
|
+
import_fs.default.writeFileSync(import_path.default.join(cwd, "postcss.config.mjs"), POSTCSS_CONFIG_TEMPLATE);
|
|
280
|
+
ok("Created postcss.config.mjs with @tailwindcss/postcss.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const content = import_fs.default.readFileSync(existingPostcss, "utf-8");
|
|
284
|
+
if (!content.includes("@tailwindcss/postcss") && !content.includes("tailwindcss")) {
|
|
285
|
+
warn(`${import_path.default.basename(existingPostcss)} found but missing Tailwind plugin \u2014 add '@tailwindcss/postcss': {} to plugins manually.`);
|
|
286
|
+
} else {
|
|
287
|
+
ok(`${import_path.default.basename(existingPostcss)} already configured \u2014 skipping.`);
|
|
288
|
+
}
|
|
289
|
+
};
|
|
240
290
|
var setupTsConfig = (cwd) => {
|
|
241
291
|
const candidates = ["tsconfig.app.json", "tsconfig.json"];
|
|
242
292
|
for (const candidate of candidates) {
|
|
@@ -288,6 +338,154 @@ var ensureCore = (registry, cwd, options = {}) => {
|
|
|
288
338
|
ok(`${import_fs.default.existsSync(targetPath) ? "Updated" : "Created"} core file: ${file.path}`);
|
|
289
339
|
}
|
|
290
340
|
};
|
|
341
|
+
var NEXT_APP_LAYOUT_CANDIDATES = [
|
|
342
|
+
"src/app/layout.tsx",
|
|
343
|
+
"src/app/layout.jsx",
|
|
344
|
+
"app/layout.tsx",
|
|
345
|
+
"app/layout.jsx"
|
|
346
|
+
];
|
|
347
|
+
var NEXT_PAGES_APP_CANDIDATES = [
|
|
348
|
+
"src/pages/_app.tsx",
|
|
349
|
+
"src/pages/_app.jsx",
|
|
350
|
+
"pages/_app.tsx",
|
|
351
|
+
"pages/_app.jsx"
|
|
352
|
+
];
|
|
353
|
+
var findNextLayoutFile = (cwd) => {
|
|
354
|
+
for (const c2 of NEXT_APP_LAYOUT_CANDIDATES) {
|
|
355
|
+
const p = import_path.default.join(cwd, c2);
|
|
356
|
+
if (import_fs.default.existsSync(p)) return p;
|
|
357
|
+
}
|
|
358
|
+
return null;
|
|
359
|
+
};
|
|
360
|
+
var findNextPagesAppFile = (cwd) => {
|
|
361
|
+
for (const c2 of NEXT_PAGES_APP_CANDIDATES) {
|
|
362
|
+
const p = import_path.default.join(cwd, c2);
|
|
363
|
+
if (import_fs.default.existsSync(p)) return p;
|
|
364
|
+
}
|
|
365
|
+
return null;
|
|
366
|
+
};
|
|
367
|
+
var patchNextLayout = (cwd) => {
|
|
368
|
+
const layoutPath = findNextLayoutFile(cwd);
|
|
369
|
+
if (!layoutPath) {
|
|
370
|
+
warn("Could not find app/layout.tsx \u2014 add ThemeProvider and CSS import manually.");
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
let content = import_fs.default.readFileSync(layoutPath, "utf-8");
|
|
374
|
+
let changed = false;
|
|
375
|
+
const cssImport = "import '@/styles/index.css';";
|
|
376
|
+
if (!content.includes("styles/index.css") && !content.includes("index.css")) {
|
|
377
|
+
const firstImport = content.match(/^import\s/m);
|
|
378
|
+
if (firstImport?.index !== void 0) {
|
|
379
|
+
content = content.slice(0, firstImport.index) + cssImport + "\n" + content.slice(firstImport.index);
|
|
380
|
+
} else {
|
|
381
|
+
content = cssImport + "\n" + content;
|
|
382
|
+
}
|
|
383
|
+
changed = true;
|
|
384
|
+
}
|
|
385
|
+
if (!content.includes("ThemeProvider")) {
|
|
386
|
+
content = insertImport(content, "import { ThemeProvider } from '@/lib/theme/ThemeProvider';");
|
|
387
|
+
const wrapped = content.replace(/\{children\}/, "<ThemeProvider>{children}</ThemeProvider>");
|
|
388
|
+
if (wrapped !== content) {
|
|
389
|
+
content = wrapped;
|
|
390
|
+
} else {
|
|
391
|
+
warn("Could not locate {children} in layout.tsx \u2014 add <ThemeProvider> wrapper manually.");
|
|
392
|
+
}
|
|
393
|
+
changed = true;
|
|
394
|
+
}
|
|
395
|
+
if (changed) {
|
|
396
|
+
import_fs.default.writeFileSync(layoutPath, content);
|
|
397
|
+
ok(`Patched ${import_path.default.relative(cwd, layoutPath)}.`);
|
|
398
|
+
} else {
|
|
399
|
+
ok(`${import_path.default.relative(cwd, layoutPath)} already configured \u2014 skipping.`);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
var patchNextPagesApp = (cwd) => {
|
|
403
|
+
const appPath = findNextPagesAppFile(cwd);
|
|
404
|
+
if (!appPath) {
|
|
405
|
+
warn("Could not find pages/_app.tsx \u2014 add ThemeProvider and CSS import manually.");
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
let content = import_fs.default.readFileSync(appPath, "utf-8");
|
|
409
|
+
let changed = false;
|
|
410
|
+
const cssImport = "import '@/styles/index.css';";
|
|
411
|
+
if (!content.includes("styles/index.css") && !content.includes("index.css")) {
|
|
412
|
+
content = insertImport(content, cssImport);
|
|
413
|
+
changed = true;
|
|
414
|
+
}
|
|
415
|
+
if (!content.includes("ThemeProvider")) {
|
|
416
|
+
content = insertImport(content, "import { ThemeProvider } from '@/lib/theme/ThemeProvider';");
|
|
417
|
+
const wrapped = content.replace(/(<Component\s[^/]*\/\s*>)/, "<ThemeProvider>\n $1\n </ThemeProvider>");
|
|
418
|
+
if (wrapped !== content) {
|
|
419
|
+
content = wrapped;
|
|
420
|
+
} else {
|
|
421
|
+
warn("Could not locate <Component .../> in _app.tsx \u2014 add <ThemeProvider> wrapper manually.");
|
|
422
|
+
}
|
|
423
|
+
changed = true;
|
|
424
|
+
}
|
|
425
|
+
if (changed) {
|
|
426
|
+
import_fs.default.writeFileSync(appPath, content);
|
|
427
|
+
ok(`Patched ${import_path.default.relative(cwd, appPath)}.`);
|
|
428
|
+
} else {
|
|
429
|
+
ok(`${import_path.default.relative(cwd, appPath)} already configured \u2014 skipping.`);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
var patchNextLayoutComponent = (cwd, patch) => {
|
|
433
|
+
const layoutPath = findNextLayoutFile(cwd);
|
|
434
|
+
if (!layoutPath) {
|
|
435
|
+
warn(`Could not find Next.js layout \u2014 add ${patch.jsx} manually.`);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
let content = import_fs.default.readFileSync(layoutPath, "utf-8");
|
|
439
|
+
const tagName = patch.jsx.match(/<(\w+)/)?.[1];
|
|
440
|
+
if (tagName && content.includes(`<${tagName}`)) return;
|
|
441
|
+
content = insertImport(content, patch.import);
|
|
442
|
+
const updated = content.replace(/<\/body>/, ` ${patch.jsx}
|
|
443
|
+
</body>`);
|
|
444
|
+
if (updated !== content) {
|
|
445
|
+
import_fs.default.writeFileSync(layoutPath, updated);
|
|
446
|
+
ok(`Added <${tagName}> to ${import_path.default.relative(cwd, layoutPath)}.`);
|
|
447
|
+
} else {
|
|
448
|
+
warn(`Could not auto-add <${tagName}> to layout.tsx \u2014 add it manually.`);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
var patchNextPagesAppComponent = (cwd, patch) => {
|
|
452
|
+
const appPath = findNextPagesAppFile(cwd);
|
|
453
|
+
if (!appPath) {
|
|
454
|
+
warn(`Could not find pages/_app.tsx \u2014 add ${patch.jsx} manually.`);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
let content = import_fs.default.readFileSync(appPath, "utf-8");
|
|
458
|
+
const tagName = patch.jsx.match(/<(\w+)/)?.[1];
|
|
459
|
+
if (tagName && content.includes(`<${tagName}`)) return;
|
|
460
|
+
content = insertImport(content, patch.import);
|
|
461
|
+
let updated = content.replace(
|
|
462
|
+
/(<Component\s[^/]*\/\s*>)(\s*\n\s*<\/ThemeProvider>)/,
|
|
463
|
+
`$1
|
|
464
|
+
${patch.jsx}$2`
|
|
465
|
+
);
|
|
466
|
+
if (updated === content) {
|
|
467
|
+
updated = content.replace(/(<Component\s[^/]*\/\s*>)/, `$1
|
|
468
|
+
${patch.jsx}`);
|
|
469
|
+
}
|
|
470
|
+
if (updated !== content) {
|
|
471
|
+
import_fs.default.writeFileSync(appPath, updated);
|
|
472
|
+
ok(`Added <${tagName}> to ${import_path.default.relative(cwd, appPath)}.`);
|
|
473
|
+
} else {
|
|
474
|
+
warn(`Could not auto-add <${tagName}> to _app.tsx \u2014 add it manually.`);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
var patchEntryFile = (cwd, framework) => {
|
|
478
|
+
if (framework === "nextjs-app") patchNextLayout(cwd);
|
|
479
|
+
else if (framework === "nextjs-pages") patchNextPagesApp(cwd);
|
|
480
|
+
else patchMainTsx(cwd);
|
|
481
|
+
};
|
|
482
|
+
var patchEntryComponentFile = (cwd, componentName, framework) => {
|
|
483
|
+
const patch = MAIN_PATCH_COMPONENTS[componentName];
|
|
484
|
+
if (!patch) return;
|
|
485
|
+
if (framework === "nextjs-app") patchNextLayoutComponent(cwd, patch);
|
|
486
|
+
else if (framework === "nextjs-pages") patchNextPagesAppComponent(cwd, patch);
|
|
487
|
+
else patchMainTsxComponent(cwd, componentName);
|
|
488
|
+
};
|
|
291
489
|
var MAIN_PATCH_COMPONENTS = {
|
|
292
490
|
toast: {
|
|
293
491
|
import: "import { Toaster } from '@/components/ui/toast/Toaster';",
|
|
@@ -400,7 +598,13 @@ var addComponent = (name, registry, cwd, options, added = /* @__PURE__ */ new Se
|
|
|
400
598
|
warn(`Skipped (exists): ${file.path} \u2014 use ${c.cyan}--force${c.reset} to overwrite`);
|
|
401
599
|
continue;
|
|
402
600
|
}
|
|
403
|
-
|
|
601
|
+
let content = file.content;
|
|
602
|
+
if (options.framework === "nextjs-app" && file.path.endsWith(".tsx")) {
|
|
603
|
+
if (!content.startsWith("'use client'") && !content.startsWith('"use client"')) {
|
|
604
|
+
content = "'use client';\n" + content;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
import_fs.default.writeFileSync(targetPath, content);
|
|
404
608
|
ok(`Created: ${file.path}`);
|
|
405
609
|
}
|
|
406
610
|
};
|
|
@@ -468,13 +672,21 @@ var HELP_COMMANDS = {
|
|
|
468
672
|
${c.bold}basuicn init${c.reset}
|
|
469
673
|
|
|
470
674
|
Initialize your project for basuicn components.
|
|
675
|
+
Auto-detects Vite or Next.js (App Router / Pages Router).
|
|
471
676
|
|
|
472
|
-
${c.bold}What it does:${c.reset}
|
|
677
|
+
${c.bold}What it does (Vite):${c.reset}
|
|
473
678
|
1. Installs runtime dependencies (@base-ui/react, tailwind-variants, etc.)
|
|
474
679
|
2. Sets up vite.config.ts with Tailwind CSS + path aliases
|
|
475
680
|
3. Patches tsconfig.json with path aliases (@/*, @lib/*, etc.)
|
|
476
681
|
4. Copies core files (cn.ts, themes.ts, ThemeProvider.tsx, index.css)
|
|
477
|
-
5. Wraps your <App /> with <ThemeProvider> in
|
|
682
|
+
5. Wraps your <App /> with <ThemeProvider> in src/main.tsx
|
|
683
|
+
|
|
684
|
+
${c.bold}What it does (Next.js):${c.reset}
|
|
685
|
+
1. Installs runtime dependencies (@base-ui/react, tailwind-variants, etc.)
|
|
686
|
+
2. Sets up postcss.config.mjs with @tailwindcss/postcss
|
|
687
|
+
3. Patches tsconfig.json with path aliases (@/*, @lib/*, etc.)
|
|
688
|
+
4. Copies core files (cn.ts, themes.ts, ThemeProvider.tsx, index.css)
|
|
689
|
+
5. Wraps {children} with <ThemeProvider> in app/layout.tsx (or pages/_app.tsx)
|
|
478
690
|
|
|
479
691
|
${c.bold}Usage:${c.reset}
|
|
480
692
|
${c.dim}$${c.reset} npx basuicn init
|
|
@@ -584,11 +796,17 @@ var main = async () => {
|
|
|
584
796
|
switch (command) {
|
|
585
797
|
case "init": {
|
|
586
798
|
log("Initializing project...");
|
|
587
|
-
|
|
799
|
+
const framework = detectFramework(cwd);
|
|
800
|
+
if (framework === "vite") {
|
|
801
|
+
setupViteConfig(cwd);
|
|
802
|
+
} else {
|
|
803
|
+
log(`Detected Next.js (${framework === "nextjs-app" ? "App Router" : "Pages Router"}).`);
|
|
804
|
+
setupNextConfig(cwd);
|
|
805
|
+
}
|
|
588
806
|
setupTsConfig(cwd);
|
|
589
807
|
installNpmPackages(RUNTIME_PACKAGES, cwd);
|
|
590
808
|
ensureCore(registry, cwd, { force: true });
|
|
591
|
-
|
|
809
|
+
patchEntryFile(cwd, framework);
|
|
592
810
|
console.log("");
|
|
593
811
|
ok(`${c.bold}Initialization complete!${c.reset} Run ${c.cyan}npx basuicn add <component>${c.reset} to get started.`);
|
|
594
812
|
break;
|
|
@@ -619,18 +837,24 @@ ${c.bold}Available components (${all.length}):${c.reset}`);
|
|
|
619
837
|
names = answer === "all" ? all : answer.split(/[\s,]+/).filter(Boolean);
|
|
620
838
|
}
|
|
621
839
|
const cnPath = import_path.default.join(cwd, "src/lib/utils/cn.ts");
|
|
840
|
+
const framework = detectFramework(cwd);
|
|
622
841
|
if (!import_fs.default.existsSync(cnPath)) {
|
|
623
842
|
log("Project not initialized \u2014 running init first...");
|
|
624
|
-
|
|
843
|
+
if (framework === "vite") {
|
|
844
|
+
setupViteConfig(cwd);
|
|
845
|
+
} else {
|
|
846
|
+
log(`Detected Next.js (${framework === "nextjs-app" ? "App Router" : "Pages Router"}).`);
|
|
847
|
+
setupNextConfig(cwd);
|
|
848
|
+
}
|
|
625
849
|
setupTsConfig(cwd);
|
|
626
850
|
installNpmPackages(RUNTIME_PACKAGES, cwd);
|
|
627
851
|
ensureCore(registry, cwd, { force: true });
|
|
628
|
-
|
|
852
|
+
patchEntryFile(cwd, framework);
|
|
629
853
|
console.log("");
|
|
630
854
|
}
|
|
631
855
|
for (const name of names) {
|
|
632
|
-
addComponent(name, registry, cwd, { force: isForce });
|
|
633
|
-
|
|
856
|
+
addComponent(name, registry, cwd, { force: isForce, framework });
|
|
857
|
+
patchEntryComponentFile(cwd, name, framework);
|
|
634
858
|
}
|
|
635
859
|
console.log("");
|
|
636
860
|
ok(`${c.bold}Done!${c.reset} Added ${names.length} component(s).`);
|
|
@@ -762,6 +986,11 @@ ${c.bold}Project Health Check${c.reset}
|
|
|
762
986
|
issues++;
|
|
763
987
|
}
|
|
764
988
|
};
|
|
989
|
+
const docFramework = detectFramework(cwd);
|
|
990
|
+
if (docFramework !== "vite") {
|
|
991
|
+
console.log(` ${c.cyan}\u2139${c.reset} Framework: Next.js (${docFramework === "nextjs-app" ? "App Router" : "Pages Router"})
|
|
992
|
+
`);
|
|
993
|
+
}
|
|
765
994
|
check(
|
|
766
995
|
import_fs.default.existsSync(import_path.default.join(cwd, "src/lib/utils/cn.ts")),
|
|
767
996
|
"src/lib/utils/cn.ts",
|
|
@@ -782,31 +1011,49 @@ ${c.bold}Project Health Check${c.reset}
|
|
|
782
1011
|
"src/styles/index.css (theme variables)",
|
|
783
1012
|
"run: npx basuicn init"
|
|
784
1013
|
);
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
"
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
1014
|
+
if (docFramework === "nextjs-app") {
|
|
1015
|
+
const layoutPath = findNextLayoutFile(cwd);
|
|
1016
|
+
if (layoutPath) {
|
|
1017
|
+
const layoutContent = import_fs.default.readFileSync(layoutPath, "utf-8");
|
|
1018
|
+
check(layoutContent.includes("ThemeProvider"), "ThemeProvider in app/layout.tsx", "run: npx basuicn init");
|
|
1019
|
+
check(layoutContent.includes("styles/index.css") || layoutContent.includes("index.css"), "CSS import in app/layout.tsx", "run: npx basuicn init");
|
|
1020
|
+
} else {
|
|
1021
|
+
check(false, "app/layout.tsx", "create src/app/layout.tsx");
|
|
1022
|
+
}
|
|
1023
|
+
} else if (docFramework === "nextjs-pages") {
|
|
1024
|
+
const pagesAppPath = findNextPagesAppFile(cwd);
|
|
1025
|
+
if (pagesAppPath) {
|
|
1026
|
+
const pagesAppContent = import_fs.default.readFileSync(pagesAppPath, "utf-8");
|
|
1027
|
+
check(pagesAppContent.includes("ThemeProvider"), "ThemeProvider in pages/_app.tsx", "run: npx basuicn init");
|
|
1028
|
+
check(pagesAppContent.includes("styles/index.css") || pagesAppContent.includes("index.css"), "CSS import in pages/_app.tsx", "run: npx basuicn init");
|
|
1029
|
+
} else {
|
|
1030
|
+
check(false, "pages/_app.tsx", "create pages/_app.tsx");
|
|
1031
|
+
}
|
|
798
1032
|
} else {
|
|
799
|
-
|
|
1033
|
+
const mainPath = findMainFile(cwd);
|
|
1034
|
+
if (mainPath) {
|
|
1035
|
+
const mainContent = import_fs.default.readFileSync(mainPath, "utf-8");
|
|
1036
|
+
check(mainContent.includes("ThemeProvider"), "ThemeProvider in main entry", "run: npx basuicn init");
|
|
1037
|
+
check(mainContent.includes("styles/index.css") || mainContent.includes("index.css"), "CSS import in main entry", "run: npx basuicn init");
|
|
1038
|
+
} else {
|
|
1039
|
+
check(false, "main entry file (src/main.tsx)", "create src/main.tsx");
|
|
1040
|
+
}
|
|
800
1041
|
}
|
|
801
1042
|
const pkgPath = import_path.default.join(cwd, "package.json");
|
|
802
1043
|
if (import_fs.default.existsSync(pkgPath)) {
|
|
803
1044
|
const pkg = JSON.parse(import_fs.default.readFileSync(pkgPath, "utf-8"));
|
|
804
|
-
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1045
|
+
const allDeps = { ...pkg.dependencies || {}, ...pkg.devDependencies || {} };
|
|
805
1046
|
for (const dep of RUNTIME_PACKAGES) {
|
|
806
1047
|
check(!!allDeps[dep], `package: ${dep}`, `run: npm install ${dep}`);
|
|
807
1048
|
}
|
|
808
|
-
|
|
809
|
-
|
|
1049
|
+
if (docFramework === "vite") {
|
|
1050
|
+
for (const dep of VITE_DEV_PACKAGES) {
|
|
1051
|
+
check(!!allDeps[dep], `package (dev): ${dep}`, `run: npm install -D ${dep}`);
|
|
1052
|
+
}
|
|
1053
|
+
} else {
|
|
1054
|
+
for (const dep of NEXTJS_DEV_PACKAGES) {
|
|
1055
|
+
check(!!allDeps[dep], `package (dev): ${dep}`, `run: npm install -D ${dep}`);
|
|
1056
|
+
}
|
|
810
1057
|
}
|
|
811
1058
|
} else {
|
|
812
1059
|
check(false, "package.json found", "run: npm init -y");
|
|
@@ -829,8 +1076,13 @@ ${c.bold}Project Health Check${c.reset}
|
|
|
829
1076
|
return content.includes('"@/*"') || content.includes("'@/*'");
|
|
830
1077
|
});
|
|
831
1078
|
check(hasAlias, "TypeScript path aliases (@/*)", "run: npx basuicn init");
|
|
832
|
-
|
|
833
|
-
|
|
1079
|
+
if (docFramework === "vite") {
|
|
1080
|
+
const hasViteConfig = import_fs.default.existsSync(import_path.default.join(cwd, "vite.config.ts")) || import_fs.default.existsSync(import_path.default.join(cwd, "vite.config.js"));
|
|
1081
|
+
check(hasViteConfig, "vite.config.ts / vite.config.js", "run: npx basuicn init");
|
|
1082
|
+
} else {
|
|
1083
|
+
const hasPostcss = ["postcss.config.mjs", "postcss.config.js", "postcss.config.cjs"].some((f) => import_fs.default.existsSync(import_path.default.join(cwd, f)));
|
|
1084
|
+
check(hasPostcss, "postcss.config.mjs (Tailwind CSS for Next.js)", "run: npx basuicn init");
|
|
1085
|
+
}
|
|
834
1086
|
console.log("");
|
|
835
1087
|
if (issues === 0) {
|
|
836
1088
|
ok(`${c.bold}All checks passed!${c.reset} Project is healthy.`);
|