shadcn-nextjs-page-generator 1.0.5 → 1.0.6
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/README.md +38 -6
- package/dist/index.cjs +162 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +162 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
✨ **Interactive CLI** - User-friendly prompts guide you through the generation process
|
|
13
13
|
🏗️ **Flexible Architecture** - Choose between DDD (Domain-Driven Design) or Simplified structure
|
|
14
14
|
🎨 **shadcn/ui Components** - Beautiful, accessible components built with Radix UI
|
|
15
|
+
� **Auto-Install** - Automatically detects and installs missing shadcn components
|
|
15
16
|
💨 **Tailwind CSS v4** - Latest Tailwind with modern CSS-first syntax
|
|
16
17
|
🎭 **Framer Motion** - Smooth animations with configurable intensity
|
|
17
18
|
📊 **Complete CRUD** - Tables with search, filter, sort, pagination out of the box
|
|
18
19
|
🔄 **Multiple Data Fetching** - Support for Mock data, TanStack Query, or standard fetch
|
|
19
20
|
⚡ **TypeScript First** - Full type safety and IntelliSense support
|
|
21
|
+
♻️ **Smart Overwrite** - Regenerate files safely with automatic overwrite detection
|
|
20
22
|
|
|
21
23
|
## Quick Start
|
|
22
24
|
|
|
@@ -98,6 +100,20 @@ npx shadcn-nextjs-page-generator
|
|
|
98
100
|
|
|
99
101
|
### 3. Install Dependencies (if needed)
|
|
100
102
|
|
|
103
|
+
The CLI automatically checks and installs missing shadcn/ui components! You'll see:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
🔍 Checking shadcn components...
|
|
107
|
+
✓ button already installed
|
|
108
|
+
✓ table already installed
|
|
109
|
+
- card missing, installing...
|
|
110
|
+
- pagination missing, installing...
|
|
111
|
+
|
|
112
|
+
✓ Installed 2 component(s): card, pagination
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If you prefer to install manually or need additional dependencies:
|
|
116
|
+
|
|
101
117
|
```bash
|
|
102
118
|
# If you selected TanStack Query
|
|
103
119
|
npm install @tanstack/react-query
|
|
@@ -106,6 +122,8 @@ npm install @tanstack/react-query
|
|
|
106
122
|
npm install framer-motion
|
|
107
123
|
```
|
|
108
124
|
|
|
125
|
+
> **Note:** Auto-install requires shadcn/ui to be initialized in your project (`npx shadcn@latest init`)
|
|
126
|
+
|
|
109
127
|
### 4. Navigate to Your Page
|
|
110
128
|
|
|
111
129
|
```bash
|
|
@@ -301,8 +319,9 @@ const containerVariants = {
|
|
|
301
319
|
|
|
302
320
|
## shadcn/ui Components Used
|
|
303
321
|
|
|
304
|
-
The
|
|
322
|
+
The generator automatically detects and installs the required shadcn/ui components based on your configuration:
|
|
305
323
|
|
|
324
|
+
**Always installed:**
|
|
306
325
|
- `button`
|
|
307
326
|
- `table`
|
|
308
327
|
- `card`
|
|
@@ -311,14 +330,27 @@ The generated code uses these shadcn/ui components:
|
|
|
311
330
|
- `badge`
|
|
312
331
|
- `pagination`
|
|
313
332
|
- `dropdown-menu`
|
|
314
|
-
- `popover`
|
|
315
|
-
- `calendar` (if date filters)
|
|
316
|
-
- `checkbox` (if row selection)
|
|
317
333
|
|
|
318
|
-
|
|
334
|
+
**Conditionally installed:**
|
|
335
|
+
- `popover` + `calendar` (if date filters enabled)
|
|
336
|
+
- `checkbox` (if row selection enabled)
|
|
337
|
+
|
|
338
|
+
### Auto-Install Feature
|
|
339
|
+
|
|
340
|
+
The CLI automatically checks for missing components and installs them using:
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
npx shadcn@latest add <component> --yes --overwrite
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
This happens before generating your files, ensuring all required components are available.
|
|
347
|
+
|
|
348
|
+
### Manual Installation
|
|
349
|
+
|
|
350
|
+
If you prefer to install components manually:
|
|
319
351
|
|
|
320
352
|
```bash
|
|
321
|
-
npx shadcn
|
|
353
|
+
npx shadcn@latest add button table card input select badge pagination dropdown-menu popover calendar checkbox
|
|
322
354
|
```
|
|
323
355
|
|
|
324
356
|
## FAQ
|
package/dist/index.cjs
CHANGED
|
@@ -377,7 +377,7 @@ ${message}
|
|
|
377
377
|
};
|
|
378
378
|
|
|
379
379
|
// src/generators/ddd-generator.ts
|
|
380
|
-
var
|
|
380
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
381
381
|
|
|
382
382
|
// src/utils/file-system.ts
|
|
383
383
|
var import_fs_extra = __toESM(require("fs-extra"), 1);
|
|
@@ -425,6 +425,95 @@ async function checkExistingFiles(filePaths) {
|
|
|
425
425
|
return existingFiles;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
+
// src/utils/shadcn-installer.ts
|
|
429
|
+
var import_child_process = require("child_process");
|
|
430
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
431
|
+
var import_path2 = __toESM(require("path"), 1);
|
|
432
|
+
var COMPONENT_MAP = {
|
|
433
|
+
button: "button",
|
|
434
|
+
table: "table",
|
|
435
|
+
select: "select",
|
|
436
|
+
input: "input",
|
|
437
|
+
badge: "badge",
|
|
438
|
+
card: "card",
|
|
439
|
+
checkbox: "checkbox",
|
|
440
|
+
calendar: "calendar",
|
|
441
|
+
popover: "popover",
|
|
442
|
+
pagination: "pagination",
|
|
443
|
+
dropdown: "dropdown-menu"
|
|
444
|
+
};
|
|
445
|
+
function isComponentInstalled(componentName, cwd) {
|
|
446
|
+
const componentPath = import_path2.default.join(cwd, "components", "ui", `${componentName}.tsx`);
|
|
447
|
+
return import_fs.default.existsSync(componentPath);
|
|
448
|
+
}
|
|
449
|
+
function installComponent(componentName, cwd) {
|
|
450
|
+
try {
|
|
451
|
+
logger.info(`Installing ${componentName} component...`);
|
|
452
|
+
(0, import_child_process.execSync)(`npx shadcn@latest add ${componentName} --yes --overwrite`, {
|
|
453
|
+
cwd,
|
|
454
|
+
stdio: "inherit"
|
|
455
|
+
});
|
|
456
|
+
return true;
|
|
457
|
+
} catch (error) {
|
|
458
|
+
logger.error(`Failed to install ${componentName}: ${error}`);
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
function detectRequiredComponents(config) {
|
|
463
|
+
const required = /* @__PURE__ */ new Set();
|
|
464
|
+
required.add(COMPONENT_MAP.button);
|
|
465
|
+
required.add(COMPONENT_MAP.table);
|
|
466
|
+
required.add(COMPONENT_MAP.select);
|
|
467
|
+
required.add(COMPONENT_MAP.input);
|
|
468
|
+
required.add(COMPONENT_MAP.badge);
|
|
469
|
+
required.add(COMPONENT_MAP.card);
|
|
470
|
+
required.add(COMPONENT_MAP.pagination);
|
|
471
|
+
required.add(COMPONENT_MAP.dropdown);
|
|
472
|
+
if (config.includeRowSelection) {
|
|
473
|
+
required.add(COMPONENT_MAP.checkbox);
|
|
474
|
+
}
|
|
475
|
+
if (config.filters.some((f) => f.type === "date")) {
|
|
476
|
+
required.add(COMPONENT_MAP.calendar);
|
|
477
|
+
required.add(COMPONENT_MAP.popover);
|
|
478
|
+
}
|
|
479
|
+
return Array.from(required);
|
|
480
|
+
}
|
|
481
|
+
async function autoInstallComponents(config, cwd = process.cwd()) {
|
|
482
|
+
const result = {
|
|
483
|
+
installed: [],
|
|
484
|
+
skipped: [],
|
|
485
|
+
failed: []
|
|
486
|
+
};
|
|
487
|
+
const required = detectRequiredComponents(config);
|
|
488
|
+
logger.info(`Checking ${required.length} shadcn components...`);
|
|
489
|
+
for (const component of required) {
|
|
490
|
+
if (isComponentInstalled(component, cwd)) {
|
|
491
|
+
result.skipped.push(component);
|
|
492
|
+
logger.dim(` \u2713 ${component} already installed`);
|
|
493
|
+
} else {
|
|
494
|
+
logger.dim(` - ${component} missing, installing...`);
|
|
495
|
+
const success = installComponent(component, cwd);
|
|
496
|
+
if (success) {
|
|
497
|
+
result.installed.push(component);
|
|
498
|
+
} else {
|
|
499
|
+
result.failed.push(component);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return result;
|
|
504
|
+
}
|
|
505
|
+
function checkShadcnCli() {
|
|
506
|
+
try {
|
|
507
|
+
(0, import_child_process.execSync)("npx shadcn@latest --version", { stdio: "ignore" });
|
|
508
|
+
return true;
|
|
509
|
+
} catch {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function isShadcnInitialized(cwd = process.cwd()) {
|
|
514
|
+
return import_fs.default.existsSync(import_path2.default.join(cwd, "components.json"));
|
|
515
|
+
}
|
|
516
|
+
|
|
428
517
|
// src/templates/ddd/entity.ts
|
|
429
518
|
function generateEntity(config) {
|
|
430
519
|
const { entityName, moduleName, columns } = config;
|
|
@@ -656,7 +745,7 @@ import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover
|
|
|
656
745
|
import { Calendar as CalendarIcon } from 'lucide-react';
|
|
657
746
|
import { format } from 'date-fns';` : ""}
|
|
658
747
|
import { Badge } from '@/components/ui/badge';
|
|
659
|
-
|
|
748
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
660
749
|
import {
|
|
661
750
|
Search,
|
|
662
751
|
Plus,
|
|
@@ -1188,44 +1277,45 @@ var DDDGenerator = class {
|
|
|
1188
1277
|
const files = [];
|
|
1189
1278
|
const cwd = process.cwd();
|
|
1190
1279
|
const { moduleName, routePath } = this.config;
|
|
1191
|
-
|
|
1192
|
-
const
|
|
1280
|
+
await this.checkAndInstallComponents(cwd);
|
|
1281
|
+
const moduleDir = import_path3.default.join(cwd, "modules", moduleName);
|
|
1282
|
+
const appDir = import_path3.default.join(cwd, "app", "(dashboard)", routePath);
|
|
1193
1283
|
const dirs = [
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1284
|
+
import_path3.default.join(moduleDir, "domain", "entities"),
|
|
1285
|
+
import_path3.default.join(moduleDir, "domain", "repositories"),
|
|
1286
|
+
import_path3.default.join(moduleDir, "application", "use-cases"),
|
|
1287
|
+
import_path3.default.join(moduleDir, "infrastructure", "repositories"),
|
|
1288
|
+
import_path3.default.join(moduleDir, "presentation", "components"),
|
|
1199
1289
|
appDir
|
|
1200
1290
|
];
|
|
1201
1291
|
await createDirectories(dirs);
|
|
1202
1292
|
files.push({
|
|
1203
|
-
path:
|
|
1293
|
+
path: import_path3.default.join(moduleDir, "domain", "entities", `${moduleName}.entity.ts`),
|
|
1204
1294
|
content: generateEntity(this.config)
|
|
1205
1295
|
});
|
|
1206
1296
|
files.push({
|
|
1207
|
-
path:
|
|
1297
|
+
path: import_path3.default.join(moduleDir, "domain", "repositories", `${moduleName}.repository.interface.ts`),
|
|
1208
1298
|
content: generateRepositoryInterface(this.config)
|
|
1209
1299
|
});
|
|
1210
1300
|
files.push({
|
|
1211
|
-
path:
|
|
1301
|
+
path: import_path3.default.join(moduleDir, "infrastructure", "repositories", `${moduleName}.repository.ts`),
|
|
1212
1302
|
content: generateRepositoryImpl(this.config)
|
|
1213
1303
|
});
|
|
1214
1304
|
files.push({
|
|
1215
|
-
path:
|
|
1305
|
+
path: import_path3.default.join(moduleDir, "application", "use-cases", `get-${moduleName}s.use-case.ts`),
|
|
1216
1306
|
content: generateUseCase(this.config)
|
|
1217
1307
|
});
|
|
1218
1308
|
files.push({
|
|
1219
|
-
path:
|
|
1309
|
+
path: import_path3.default.join(moduleDir, "presentation", "components", `${moduleName}-list.tsx`),
|
|
1220
1310
|
content: generateComponent(this.config)
|
|
1221
1311
|
});
|
|
1222
1312
|
files.push({
|
|
1223
|
-
path:
|
|
1313
|
+
path: import_path3.default.join(appDir, "page.tsx"),
|
|
1224
1314
|
content: generatePage(this.config)
|
|
1225
1315
|
});
|
|
1226
1316
|
if (this.config.animations.pageTransitions) {
|
|
1227
1317
|
files.push({
|
|
1228
|
-
path:
|
|
1318
|
+
path: import_path3.default.join(appDir, "template.tsx"),
|
|
1229
1319
|
content: generateTemplate(this.config)
|
|
1230
1320
|
});
|
|
1231
1321
|
}
|
|
@@ -1235,7 +1325,7 @@ var DDDGenerator = class {
|
|
|
1235
1325
|
console.log("");
|
|
1236
1326
|
logger.warning(`Found ${existingFiles.length} existing file(s):`);
|
|
1237
1327
|
existingFiles.forEach((file) => {
|
|
1238
|
-
const relativePath =
|
|
1328
|
+
const relativePath = import_path3.default.relative(cwd, file);
|
|
1239
1329
|
logger.dim(` - ${relativePath}`);
|
|
1240
1330
|
});
|
|
1241
1331
|
console.log("");
|
|
@@ -1265,10 +1355,33 @@ var DDDGenerator = class {
|
|
|
1265
1355
|
}
|
|
1266
1356
|
return instructions;
|
|
1267
1357
|
}
|
|
1358
|
+
async checkAndInstallComponents(cwd) {
|
|
1359
|
+
if (!isShadcnInitialized(cwd)) {
|
|
1360
|
+
logger.warning("shadcn/ui is not initialized in this project.");
|
|
1361
|
+
logger.info("Please run: npx shadcn@latest init");
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
if (!checkShadcnCli()) {
|
|
1365
|
+
logger.warning("shadcn CLI not available. Skipping component auto-install.");
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
console.log("");
|
|
1369
|
+
logger.info("\u{1F50D} Checking shadcn components...");
|
|
1370
|
+
const result = await autoInstallComponents(this.config, cwd);
|
|
1371
|
+
if (result.installed.length > 0) {
|
|
1372
|
+
console.log("");
|
|
1373
|
+
logger.success(`\u2713 Installed ${result.installed.length} component(s): ${result.installed.join(", ")}`);
|
|
1374
|
+
}
|
|
1375
|
+
if (result.failed.length > 0) {
|
|
1376
|
+
console.log("");
|
|
1377
|
+
logger.error(`\u2717 Failed to install ${result.failed.length} component(s): ${result.failed.join(", ")}`);
|
|
1378
|
+
}
|
|
1379
|
+
console.log("");
|
|
1380
|
+
}
|
|
1268
1381
|
};
|
|
1269
1382
|
|
|
1270
1383
|
// src/generators/simplified-generator.ts
|
|
1271
|
-
var
|
|
1384
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
1272
1385
|
|
|
1273
1386
|
// src/templates/simplified/component.ts
|
|
1274
1387
|
function generateSimplifiedComponent(config) {
|
|
@@ -1395,7 +1508,7 @@ import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover
|
|
|
1395
1508
|
import { Calendar as CalendarIcon } from 'lucide-react';
|
|
1396
1509
|
import { format } from 'date-fns';` : ""}
|
|
1397
1510
|
import { Badge } from '@/components/ui/badge';
|
|
1398
|
-
|
|
1511
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
1399
1512
|
import {
|
|
1400
1513
|
Search,
|
|
1401
1514
|
Plus,
|
|
@@ -1829,20 +1942,21 @@ var SimplifiedGenerator = class {
|
|
|
1829
1942
|
const files = [];
|
|
1830
1943
|
const cwd = process.cwd();
|
|
1831
1944
|
const { moduleName, routePath } = this.config;
|
|
1832
|
-
|
|
1833
|
-
const
|
|
1945
|
+
await this.checkAndInstallComponents(cwd);
|
|
1946
|
+
const componentDir = import_path4.default.join(cwd, "components", moduleName);
|
|
1947
|
+
const appDir = import_path4.default.join(cwd, "app", "(dashboard)", routePath);
|
|
1834
1948
|
await createDirectories([componentDir, appDir]);
|
|
1835
1949
|
files.push({
|
|
1836
|
-
path:
|
|
1950
|
+
path: import_path4.default.join(componentDir, `${moduleName}-list.tsx`),
|
|
1837
1951
|
content: generateSimplifiedComponent(this.config)
|
|
1838
1952
|
});
|
|
1839
1953
|
files.push({
|
|
1840
|
-
path:
|
|
1954
|
+
path: import_path4.default.join(appDir, "page.tsx"),
|
|
1841
1955
|
content: generateSimplifiedPage(this.config)
|
|
1842
1956
|
});
|
|
1843
1957
|
if (this.config.animations.pageTransitions) {
|
|
1844
1958
|
files.push({
|
|
1845
|
-
path:
|
|
1959
|
+
path: import_path4.default.join(appDir, "template.tsx"),
|
|
1846
1960
|
content: generateTemplate(this.config)
|
|
1847
1961
|
});
|
|
1848
1962
|
}
|
|
@@ -1852,7 +1966,7 @@ var SimplifiedGenerator = class {
|
|
|
1852
1966
|
console.log("");
|
|
1853
1967
|
logger.warning(`Found ${existingFiles.length} existing file(s):`);
|
|
1854
1968
|
existingFiles.forEach((file) => {
|
|
1855
|
-
const relativePath =
|
|
1969
|
+
const relativePath = import_path4.default.relative(cwd, file);
|
|
1856
1970
|
logger.dim(` - ${relativePath}`);
|
|
1857
1971
|
});
|
|
1858
1972
|
console.log("");
|
|
@@ -1882,6 +1996,29 @@ var SimplifiedGenerator = class {
|
|
|
1882
1996
|
}
|
|
1883
1997
|
return instructions;
|
|
1884
1998
|
}
|
|
1999
|
+
async checkAndInstallComponents(cwd) {
|
|
2000
|
+
if (!isShadcnInitialized(cwd)) {
|
|
2001
|
+
logger.warning("shadcn/ui is not initialized in this project.");
|
|
2002
|
+
logger.info("Please run: npx shadcn@latest init");
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
if (!checkShadcnCli()) {
|
|
2006
|
+
logger.warning("shadcn CLI not available. Skipping component auto-install.");
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
console.log("");
|
|
2010
|
+
logger.info("\u{1F50D} Checking shadcn components...");
|
|
2011
|
+
const result = await autoInstallComponents(this.config, cwd);
|
|
2012
|
+
if (result.installed.length > 0) {
|
|
2013
|
+
console.log("");
|
|
2014
|
+
logger.success(`\u2713 Installed ${result.installed.length} component(s): ${result.installed.join(", ")}`);
|
|
2015
|
+
}
|
|
2016
|
+
if (result.failed.length > 0) {
|
|
2017
|
+
console.log("");
|
|
2018
|
+
logger.error(`\u2717 Failed to install ${result.failed.length} component(s): ${result.failed.join(", ")}`);
|
|
2019
|
+
}
|
|
2020
|
+
console.log("");
|
|
2021
|
+
}
|
|
1885
2022
|
};
|
|
1886
2023
|
|
|
1887
2024
|
// src/generators/index.ts
|