create-enterprise-next 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OFinit, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # create-enterprise-next (`cen`)
2
+
3
+ > CLI tool to scaffold enterprise-grade Next.js projects.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g create-enterprise-next
9
+ # or use via npx
10
+ npx create-enterprise-next@latest my-app
11
+ # short alias
12
+ npx cen my-app
13
+ ```
14
+
15
+ ## Command Grammar
16
+
17
+ ### Interactive Mode
18
+
19
+ Prompts for any unsupplied configuration options:
20
+
21
+ ```bash
22
+ npx cen my-app
23
+ ```
24
+
25
+ ### Fully Flag-Driven Mode
26
+
27
+ Non-interactive execution using `--yes` / `-y`. Useful for CI, automation scripts, and Web interfaces:
28
+
29
+ ```bash
30
+ npx cen my-app \
31
+ --ts \
32
+ --styling=tailwind \
33
+ --auth=clerk \
34
+ --orm=prisma \
35
+ --db=postgres \
36
+ --testing=vitest,playwright \
37
+ --ci=github-actions \
38
+ --docker \
39
+ --no-monorepo \
40
+ --package-manager=pnpm \
41
+ --yes
42
+ ```
43
+
44
+ ### Configuration File Mode
45
+
46
+ Loads base configuration from a JSON file:
47
+
48
+ ```bash
49
+ npx cen my-app --config=./cen.config.json
50
+ ```
51
+
52
+ ### Preview / Dry-Run Mode
53
+
54
+ Resolves configuration (flags -> prompts -> defaults) and outputs formatted JSON without writing files:
55
+
56
+ ```bash
57
+ npx cen my-app --dry-run --yes
58
+ ```
59
+
60
+ ## CLI Flags Reference
61
+
62
+ | Flag | Type / Choices | Default | Description |
63
+ | ----------------------------- | ----------------------------------------------------------- | ---------------- | ------------------------------- |
64
+ | `[project-name]` | Positional string | `my-app` | Target directory / project name |
65
+ | `--ts`, `--no-ts` | Boolean | `true` | Enable or disable TypeScript |
66
+ | `--styling <styling>` | `tailwind`, `css-modules`, `styled-components` | `tailwind` | Styling framework |
67
+ | `--auth <auth>` | `none`, `clerk`, `next-auth`, `auth0` | `none` | Auth provider |
68
+ | `--orm <orm>` | `none`, `prisma`, `drizzle` | `none` | ORM / DB abstraction |
69
+ | `--db, --database <db>` | `postgres`, `mysql`, `sqlite`, `mongo` | `undefined` | Database solution |
70
+ | `--testing <frameworks>` | Comma-separated (`vitest`, `jest`, `playwright`, `cypress`) | `vitest` | Testing frameworks |
71
+ | `--ci <ci>` | `none`, `github-actions`, `gitlab-ci` | `github-actions` | CI workflow setup |
72
+ | `--docker`, `--no-docker` | Boolean | `true` | Include Docker setup |
73
+ | `--monorepo`, `--no-monorepo` | Boolean | `false` | Set up project as a monorepo |
74
+ | `--state-management <state>` | `none`, `zustand`, `redux`, `jotai` | `none` | State management solution |
75
+ | `--package-manager <pm>` | `npm`, `pnpm`, `yarn`, `bun` | `pnpm` | Package manager |
76
+ | `-y, --yes` | Flag | `false` | Skip prompts and use defaults |
77
+ | `--dry-run` | Flag | `false` | Output configuration JSON only |
78
+ | `-c, --config <path>` | Path string | `undefined` | JSON config file path |
79
+
80
+ ## Precedence Rules
81
+
82
+ 1. CLI Flags (highest priority)
83
+ 2. `--config` JSON File
84
+ 3. Interactive `@clack/prompts` (if interactive terminal & `--yes` is not set)
85
+ 4. Default Configuration (lowest priority)
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,495 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command as Command2 } from "commander";
5
+ import fs3 from "fs";
6
+ import path3 from "path";
7
+ import { fileURLToPath } from "url";
8
+
9
+ // src/cli/flags.ts
10
+ import { InvalidArgumentError, Option } from "commander";
11
+
12
+ // src/config/schema.ts
13
+ import { z } from "zod";
14
+ var StylingEnum = z.enum(["tailwind", "css-modules", "styled-components"]);
15
+ var AuthEnum = z.enum(["none", "clerk", "next-auth", "auth0"]);
16
+ var OrmEnum = z.enum(["none", "prisma", "drizzle"]);
17
+ var DatabaseEnum = z.enum(["postgres", "mysql", "sqlite", "mongo"]);
18
+ var TestingEnum = z.enum(["vitest", "jest", "playwright", "cypress"]);
19
+ var CiEnum = z.enum(["none", "github-actions", "gitlab-ci"]);
20
+ var StateManagementEnum = z.enum(["none", "zustand", "redux", "jotai"]);
21
+ var PackageManagerEnum = z.enum(["npm", "pnpm", "yarn", "bun"]);
22
+ var projectConfigSchema = z.object({
23
+ projectName: z.string().min(1, "Project name is required"),
24
+ typescript: z.boolean(),
25
+ styling: StylingEnum,
26
+ auth: AuthEnum,
27
+ orm: OrmEnum,
28
+ database: DatabaseEnum.optional(),
29
+ testing: z.array(TestingEnum),
30
+ ci: CiEnum,
31
+ docker: z.boolean(),
32
+ monorepo: z.boolean(),
33
+ stateManagement: StateManagementEnum,
34
+ packageManager: PackageManagerEnum
35
+ }).superRefine((data, ctx) => {
36
+ if (data.orm === "none" && data.database !== void 0) {
37
+ ctx.addIssue({
38
+ code: z.ZodIssueCode.custom,
39
+ message: 'Database must not be specified when ORM is "none".',
40
+ path: ["database"]
41
+ });
42
+ }
43
+ if (data.orm !== "none" && !data.database) {
44
+ ctx.addIssue({
45
+ code: z.ZodIssueCode.custom,
46
+ message: "Database must be specified when an ORM is selected.",
47
+ path: ["database"]
48
+ });
49
+ }
50
+ });
51
+
52
+ // src/cli/flags.ts
53
+ function parseBoolean(val) {
54
+ if (typeof val === "boolean") return val;
55
+ if (val === "true" || val === "1") return true;
56
+ if (val === "false" || val === "0") return false;
57
+ throw new InvalidArgumentError(`Invalid boolean value '${val}'. Expected true or false.`);
58
+ }
59
+ function parseTesting(val) {
60
+ const allowed = TestingEnum.options;
61
+ const items = val.split(",").map((item) => item.trim()).filter(Boolean);
62
+ if (items.length === 0) {
63
+ throw new InvalidArgumentError("Testing option cannot be empty.");
64
+ }
65
+ for (const item of items) {
66
+ if (!allowed.includes(item)) {
67
+ throw new InvalidArgumentError(
68
+ `Invalid testing framework '${item}'. Allowed choices are: ${allowed.join(", ")}.`
69
+ );
70
+ }
71
+ }
72
+ return items;
73
+ }
74
+ function setupCliFlags(program) {
75
+ return program.argument("[project-name]", "Target project directory / name").addOption(
76
+ new Option("--ts, --typescript [boolean]", "Use TypeScript").argParser(parseBoolean)
77
+ ).addOption(new Option("--no-ts", "Do not use TypeScript")).addOption(
78
+ new Option("--styling <styling>", "Styling framework").choices(StylingEnum.options)
79
+ ).addOption(new Option("--auth <auth>", "Authentication provider").choices(AuthEnum.options)).addOption(new Option("--orm <orm>", "ORM selection").choices(OrmEnum.options)).addOption(
80
+ new Option("--db, --database <database>", "Database solution").choices(DatabaseEnum.options)
81
+ ).addOption(
82
+ new Option(
83
+ "--testing <frameworks>",
84
+ "Comma-separated testing frameworks (e.g. vitest,playwright)"
85
+ ).argParser(parseTesting)
86
+ ).addOption(new Option("--ci <ci>", "CI workflow setup").choices(CiEnum.options)).addOption(new Option("--docker [boolean]", "Include Docker setup").argParser(parseBoolean)).addOption(new Option("--no-docker", "Disable Docker setup")).addOption(
87
+ new Option("--monorepo [boolean]", "Set up project as a monorepo").argParser(parseBoolean)
88
+ ).addOption(new Option("--no-monorepo", "Do not set up as monorepo")).addOption(
89
+ new Option("--state-management <state>", "State management solution").choices(
90
+ StateManagementEnum.options
91
+ )
92
+ ).addOption(
93
+ new Option("--package-manager <packageManager>", "Package manager").choices(
94
+ PackageManagerEnum.options
95
+ )
96
+ ).addOption(new Option("-y, --yes", "Skip interactive prompts and use default values")).addOption(new Option("--dry-run", "Output resolved configuration JSON without scaffolding")).addOption(new Option("-c, --config <path>", "Path to JSON configuration file"));
97
+ }
98
+
99
+ // src/config/resolve.ts
100
+ import fs from "fs";
101
+ import path from "path";
102
+
103
+ // src/config/defaults.ts
104
+ var defaultConfig = {
105
+ projectName: "my-app",
106
+ typescript: true,
107
+ styling: "tailwind",
108
+ auth: "none",
109
+ orm: "none",
110
+ database: void 0,
111
+ testing: ["vitest"],
112
+ ci: "github-actions",
113
+ docker: true,
114
+ monorepo: false,
115
+ stateManagement: "none",
116
+ packageManager: "pnpm"
117
+ };
118
+
119
+ // src/config/resolve.ts
120
+ async function resolveConfig(input, prompter) {
121
+ const cwd = input.cwd ?? process.cwd();
122
+ const flags = input.cliOptions;
123
+ let fileConfig = {};
124
+ if (flags.config) {
125
+ const configPath = path.resolve(cwd, flags.config);
126
+ if (!fs.existsSync(configPath)) {
127
+ throw new Error(`Config file not found at path: ${flags.config}`);
128
+ }
129
+ try {
130
+ const fileContent = fs.readFileSync(configPath, "utf-8");
131
+ fileConfig = JSON.parse(fileContent);
132
+ } catch (err) {
133
+ if (err instanceof SyntaxError) {
134
+ throw new Error(`Failed to parse "${flags.config}". The file does not contain valid JSON.`);
135
+ }
136
+ throw new Error(`Failed to read config file at "${flags.config}": ${err instanceof Error ? err.message : String(err)}`);
137
+ }
138
+ }
139
+ const cliConfig = {};
140
+ if (flags.typescript !== void 0) cliConfig.typescript = flags.typescript;
141
+ if (flags.styling !== void 0) cliConfig.styling = flags.styling;
142
+ if (flags.auth !== void 0) cliConfig.auth = flags.auth;
143
+ if (flags.orm !== void 0) cliConfig.orm = flags.orm;
144
+ const dbFlag = flags.db ?? flags.database;
145
+ if (dbFlag !== void 0) cliConfig.database = dbFlag;
146
+ if (flags.testing !== void 0) cliConfig.testing = flags.testing;
147
+ if (flags.ci !== void 0) cliConfig.ci = flags.ci;
148
+ if (flags.docker !== void 0) cliConfig.docker = flags.docker;
149
+ if (flags.monorepo !== void 0) cliConfig.monorepo = flags.monorepo;
150
+ if (flags.stateManagement !== void 0)
151
+ cliConfig.stateManagement = flags.stateManagement;
152
+ if (flags.packageManager !== void 0)
153
+ cliConfig.packageManager = flags.packageManager;
154
+ let resolvedPartial = {
155
+ ...fileConfig,
156
+ ...cliConfig
157
+ };
158
+ if (input.projectName) {
159
+ resolvedPartial.projectName = input.projectName;
160
+ }
161
+ const shouldPrompt = input.interactive ?? (!flags.yes && Boolean(process.stdout.isTTY));
162
+ if (shouldPrompt && prompter) {
163
+ resolvedPartial = await prompter(resolvedPartial);
164
+ }
165
+ const finalProjectName = resolvedPartial.projectName || defaultConfig.projectName;
166
+ const finalOrm = resolvedPartial.orm ?? defaultConfig.orm;
167
+ let finalDatabase = resolvedPartial.database;
168
+ if (finalOrm !== "none" && !finalDatabase) {
169
+ finalDatabase = "postgres";
170
+ }
171
+ const finalMerged = {
172
+ projectName: finalProjectName,
173
+ typescript: resolvedPartial.typescript ?? defaultConfig.typescript,
174
+ styling: resolvedPartial.styling ?? defaultConfig.styling,
175
+ auth: resolvedPartial.auth ?? defaultConfig.auth,
176
+ orm: finalOrm,
177
+ database: finalDatabase,
178
+ testing: resolvedPartial.testing ?? defaultConfig.testing,
179
+ ci: resolvedPartial.ci ?? defaultConfig.ci,
180
+ docker: resolvedPartial.docker ?? defaultConfig.docker,
181
+ monorepo: resolvedPartial.monorepo ?? defaultConfig.monorepo,
182
+ stateManagement: resolvedPartial.stateManagement ?? defaultConfig.stateManagement,
183
+ packageManager: resolvedPartial.packageManager ?? defaultConfig.packageManager
184
+ };
185
+ const validationResult = projectConfigSchema.safeParse(finalMerged);
186
+ if (!validationResult.success) {
187
+ const issueMessages = validationResult.error.issues.map((issue) => ` - [${issue.path.join(".")}]: ${issue.message}`).join("\n");
188
+ throw new Error(`Invalid configuration:
189
+ ${issueMessages}`);
190
+ }
191
+ return validationResult.data;
192
+ }
193
+
194
+ // src/prompts/interactive.ts
195
+ import * as clack from "@clack/prompts";
196
+ import pc from "picocolors";
197
+
198
+ // src/utils/validate-project-name.ts
199
+ import fs2 from "fs";
200
+ import path2 from "path";
201
+ import validateNpmName from "validate-npm-package-name";
202
+ function validateProjectName(name, cwd = process.cwd()) {
203
+ if (!name || name.trim().length === 0) {
204
+ return "Project name cannot be empty.";
205
+ }
206
+ const trimmed = name.trim();
207
+ if (trimmed.includes(" ")) {
208
+ return "Project name cannot contain spaces.";
209
+ }
210
+ const targetPath = path2.resolve(cwd, trimmed);
211
+ const relativePath = path2.relative(cwd, targetPath);
212
+ if (relativePath.startsWith("..") || path2.isAbsolute(trimmed) && !targetPath.startsWith(cwd)) {
213
+ return "Project name cannot resolve outside the current working directory.";
214
+ }
215
+ const basename = path2.basename(trimmed);
216
+ const npmValidation = validateNpmName(basename);
217
+ if (!npmValidation.validForNewPackages) {
218
+ const errors = [...npmValidation.errors || [], ...npmValidation.warnings || []];
219
+ return `Invalid npm package name: ${errors.join(", ")}`;
220
+ }
221
+ return void 0;
222
+ }
223
+ function validateTargetDirectory(targetPath, cwd = process.cwd()) {
224
+ const absolutePath = path2.resolve(cwd, targetPath);
225
+ if (!fs2.existsSync(absolutePath)) {
226
+ return void 0;
227
+ }
228
+ const stats = fs2.statSync(absolutePath);
229
+ if (!stats.isDirectory()) {
230
+ return `Target path "${targetPath}" exists and is a file, not a directory.`;
231
+ }
232
+ const files = fs2.readdirSync(absolutePath);
233
+ const nonHiddenFiles = files.filter((file) => !file.startsWith("."));
234
+ if (nonHiddenFiles.length > 0) {
235
+ return `Target directory "${targetPath}" is not empty. Please choose another name or empty the directory.`;
236
+ }
237
+ return void 0;
238
+ }
239
+
240
+ // src/prompts/interactive.ts
241
+ function handleCancel(value) {
242
+ if (clack.isCancel(value)) {
243
+ clack.cancel("Operation cancelled.");
244
+ process.exit(1);
245
+ }
246
+ return value;
247
+ }
248
+ async function promptForProjectName(initial) {
249
+ if (initial) return initial;
250
+ const name = await clack.text({
251
+ message: "What is your project name?",
252
+ placeholder: "my-app",
253
+ defaultValue: "my-app",
254
+ validate(val) {
255
+ const nameErr = validateProjectName(val);
256
+ if (nameErr) return nameErr;
257
+ const dirErr = validateTargetDirectory(val);
258
+ if (dirErr) return dirErr;
259
+ }
260
+ });
261
+ return handleCancel(name).trim();
262
+ }
263
+ async function promptForTypeScript(initial) {
264
+ if (initial !== void 0) return initial;
265
+ const ts = await clack.confirm({
266
+ message: "Would you like to use TypeScript?",
267
+ initialValue: true
268
+ });
269
+ return handleCancel(ts);
270
+ }
271
+ async function promptForStyling(initial) {
272
+ if (initial) return initial;
273
+ const styling = await clack.select({
274
+ message: "Which styling solution would you like to use?",
275
+ options: [
276
+ { value: "tailwind", label: "Tailwind CSS", hint: "Recommended" },
277
+ { value: "css-modules", label: "CSS Modules" },
278
+ { value: "styled-components", label: "Styled Components" }
279
+ ],
280
+ initialValue: "tailwind"
281
+ });
282
+ return handleCancel(styling);
283
+ }
284
+ async function promptForAuth(initial) {
285
+ if (initial) return initial;
286
+ const auth = await clack.select({
287
+ message: "Which authentication provider would you like to use?",
288
+ options: [
289
+ { value: "none", label: "None" },
290
+ { value: "clerk", label: "Clerk", hint: "User management platform" },
291
+ { value: "next-auth", label: "NextAuth.js / Auth.js", hint: "Open source auth" },
292
+ { value: "auth0", label: "Auth0", hint: "Enterprise Identity Platform" }
293
+ ],
294
+ initialValue: "none"
295
+ });
296
+ return handleCancel(auth);
297
+ }
298
+ async function promptForOrm(initial) {
299
+ if (initial) return initial;
300
+ const orm = await clack.select({
301
+ message: "Which ORM / Database abstraction would you like to use?",
302
+ options: [
303
+ { value: "none", label: "None" },
304
+ { value: "prisma", label: "Prisma", hint: "Next-gen ORM" },
305
+ { value: "drizzle", label: "Drizzle ORM", hint: "Lightweight & fast" }
306
+ ],
307
+ initialValue: "none"
308
+ });
309
+ return handleCancel(orm);
310
+ }
311
+ async function promptForDatabase(orm, initial) {
312
+ if (orm === "none") return void 0;
313
+ if (initial) return initial;
314
+ const db = await clack.select({
315
+ message: "Which database would you like to connect to?",
316
+ options: [
317
+ { value: "postgres", label: "PostgreSQL" },
318
+ { value: "mysql", label: "MySQL" },
319
+ { value: "sqlite", label: "SQLite" },
320
+ { value: "mongo", label: "MongoDB" }
321
+ ],
322
+ initialValue: "postgres"
323
+ });
324
+ return handleCancel(db);
325
+ }
326
+ async function promptForTesting(initial) {
327
+ if (initial && initial.length > 0) return initial;
328
+ const testing = await clack.multiselect({
329
+ message: "Select testing frameworks to include:",
330
+ options: [
331
+ { value: "vitest", label: "Vitest", hint: "Fast unit/integration test runner" },
332
+ { value: "jest", label: "Jest", hint: "Delightful JS testing" },
333
+ { value: "playwright", label: "Playwright", hint: "End-to-end browser testing" },
334
+ { value: "cypress", label: "Cypress", hint: "E2E & component testing" }
335
+ ],
336
+ required: false,
337
+ initialValues: ["vitest"]
338
+ });
339
+ return handleCancel(testing);
340
+ }
341
+ async function promptForCi(initial) {
342
+ if (initial) return initial;
343
+ const ci = await clack.select({
344
+ message: "Which Continuous Integration (CI) setup would you like?",
345
+ options: [
346
+ { value: "github-actions", label: "GitHub Actions", hint: "Recommended" },
347
+ { value: "gitlab-ci", label: "GitLab CI" },
348
+ { value: "none", label: "None" }
349
+ ],
350
+ initialValue: "github-actions"
351
+ });
352
+ return handleCancel(ci);
353
+ }
354
+ async function promptForDocker(initial) {
355
+ if (initial !== void 0) return initial;
356
+ const docker = await clack.confirm({
357
+ message: "Would you like to include a Docker container setup?",
358
+ initialValue: true
359
+ });
360
+ return handleCancel(docker);
361
+ }
362
+ async function promptForMonorepo(initial) {
363
+ if (initial !== void 0) return initial;
364
+ const monorepo = await clack.confirm({
365
+ message: "Would you like to configure this project as a monorepo?",
366
+ initialValue: false
367
+ });
368
+ return handleCancel(monorepo);
369
+ }
370
+ async function promptForStateManagement(initial) {
371
+ if (initial) return initial;
372
+ const stateManagement = await clack.select({
373
+ message: "Which state management solution would you like?",
374
+ options: [
375
+ { value: "none", label: "None" },
376
+ { value: "zustand", label: "Zustand", hint: "Small, fast, scaleable" },
377
+ { value: "redux", label: "Redux Toolkit", hint: "Opinionated toolset for Redux" },
378
+ { value: "jotai", label: "Jotai", hint: "Primitive and flexible state management" }
379
+ ],
380
+ initialValue: "none"
381
+ });
382
+ return handleCancel(stateManagement);
383
+ }
384
+ async function promptForPackageManager(initial) {
385
+ if (initial) return initial;
386
+ const packageManager = await clack.select({
387
+ message: "Which package manager would you like to use?",
388
+ options: [
389
+ { value: "pnpm", label: "pnpm", hint: "Recommended" },
390
+ { value: "npm", label: "npm" },
391
+ { value: "yarn", label: "yarn" },
392
+ { value: "bun", label: "bun" }
393
+ ],
394
+ initialValue: "pnpm"
395
+ });
396
+ return handleCancel(packageManager);
397
+ }
398
+ async function runInteractivePrompts(partial) {
399
+ clack.intro(pc.bgCyan(pc.black(" create-enterprise-next ")));
400
+ const projectName = await promptForProjectName(partial.projectName);
401
+ const typescript = await promptForTypeScript(partial.typescript);
402
+ const styling = await promptForStyling(partial.styling);
403
+ const auth = await promptForAuth(partial.auth);
404
+ const orm = await promptForOrm(partial.orm);
405
+ const database = await promptForDatabase(orm, partial.database);
406
+ const testing = await promptForTesting(partial.testing);
407
+ const ci = await promptForCi(partial.ci);
408
+ const docker = await promptForDocker(partial.docker);
409
+ const monorepo = await promptForMonorepo(partial.monorepo);
410
+ const stateManagement = await promptForStateManagement(partial.stateManagement);
411
+ const packageManager = await promptForPackageManager(partial.packageManager);
412
+ clack.outro(pc.green("Configuration completed!"));
413
+ return {
414
+ projectName,
415
+ typescript,
416
+ styling,
417
+ auth,
418
+ orm,
419
+ database,
420
+ testing,
421
+ ci,
422
+ docker,
423
+ monorepo,
424
+ stateManagement,
425
+ packageManager
426
+ };
427
+ }
428
+
429
+ // src/utils/logger.ts
430
+ import pc2 from "picocolors";
431
+ var logger = {
432
+ info: (msg) => console.log(pc2.blue("\u2139 ") + msg),
433
+ success: (msg) => console.log(pc2.green("\u2714 ") + msg),
434
+ warn: (msg) => console.warn(pc2.yellow("\u26A0 ") + msg),
435
+ error: (msg) => console.error(pc2.red("\u2716 ") + msg),
436
+ log: (msg) => console.log(msg)
437
+ };
438
+
439
+ // src/index.ts
440
+ function getPackageVersion() {
441
+ try {
442
+ const __filename = fileURLToPath(import.meta.url);
443
+ const __dirname = path3.dirname(__filename);
444
+ const pkgPath = path3.resolve(__dirname, "../package.json");
445
+ if (fs3.existsSync(pkgPath)) {
446
+ const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
447
+ if (pkg.version) return pkg.version;
448
+ }
449
+ } catch {
450
+ }
451
+ return "0.1.0";
452
+ }
453
+ async function main() {
454
+ const program = new Command2();
455
+ program.name("cen").description("Scaffold enterprise-grade Next.js applications").version(getPackageVersion());
456
+ setupCliFlags(program);
457
+ program.action(async (positionalProjectName, flags) => {
458
+ try {
459
+ if (positionalProjectName) {
460
+ const nameErr = validateProjectName(positionalProjectName);
461
+ if (nameErr) {
462
+ logger.error(nameErr);
463
+ process.exit(1);
464
+ }
465
+ const dirErr = validateTargetDirectory(positionalProjectName);
466
+ if (dirErr) {
467
+ logger.error(dirErr);
468
+ process.exit(1);
469
+ }
470
+ }
471
+ const config = await resolveConfig(
472
+ {
473
+ projectName: positionalProjectName,
474
+ cliOptions: flags
475
+ },
476
+ runInteractivePrompts
477
+ );
478
+ if (flags.dryRun) {
479
+ console.log(JSON.stringify(config, null, 2));
480
+ process.exit(0);
481
+ }
482
+ console.log(JSON.stringify(config, null, 2));
483
+ logger.success("Config resolved \u2014 scaffolding logic not yet implemented");
484
+ } catch (err) {
485
+ logger.error(err instanceof Error ? err.message : String(err));
486
+ process.exit(1);
487
+ }
488
+ });
489
+ await program.parseAsync(process.argv);
490
+ }
491
+ main().catch((err) => {
492
+ logger.error(err instanceof Error ? err.message : String(err));
493
+ process.exit(1);
494
+ });
495
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/cli/flags.ts","../src/config/schema.ts","../src/config/resolve.ts","../src/config/defaults.ts","../src/prompts/interactive.ts","../src/utils/validate-project-name.ts","../src/utils/logger.ts"],"sourcesContent":["import { Command } from 'commander';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { setupCliFlags, type CliOptions } from './cli/flags.js';\nimport { resolveConfig } from './config/resolve.js';\nimport { runInteractivePrompts } from './prompts/interactive.js';\nimport { logger } from './utils/logger.js';\nimport { validateProjectName, validateTargetDirectory } from './utils/validate-project-name.js';\n\nfunction getPackageVersion(): string {\n try {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n const pkgPath = path.resolve(__dirname, '../package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n if (pkg.version) return pkg.version as string;\n }\n } catch {\n // fallback if package.json cannot be read\n }\n return '0.1.0';\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name('cen')\n .description('Scaffold enterprise-grade Next.js applications')\n .version(getPackageVersion());\n\n setupCliFlags(program);\n\n program.action(async (positionalProjectName: string | undefined, flags: CliOptions) => {\n try {\n if (positionalProjectName) {\n const nameErr = validateProjectName(positionalProjectName);\n if (nameErr) {\n logger.error(nameErr);\n process.exit(1);\n }\n const dirErr = validateTargetDirectory(positionalProjectName);\n if (dirErr) {\n logger.error(dirErr);\n process.exit(1);\n }\n }\n\n const config = await resolveConfig(\n {\n projectName: positionalProjectName,\n cliOptions: flags,\n },\n runInteractivePrompts,\n );\n\n if (flags.dryRun) {\n console.log(JSON.stringify(config, null, 2));\n process.exit(0);\n }\n\n console.log(JSON.stringify(config, null, 2));\n logger.success('Config resolved — scaffolding logic not yet implemented');\n } catch (err) {\n logger.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\nmain().catch((err) => {\n logger.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n","import { Command, InvalidArgumentError, Option } from 'commander';\nimport {\n AuthEnum,\n CiEnum,\n DatabaseEnum,\n OrmEnum,\n PackageManagerEnum,\n StateManagementEnum,\n StylingEnum,\n TestingEnum,\n type TestingOption,\n} from '../config/schema.js';\n\nexport interface CliOptions {\n typescript?: boolean;\n styling?: string;\n auth?: string;\n orm?: string;\n database?: string;\n db?: string;\n testing?: TestingOption[];\n ci?: string;\n docker?: boolean;\n monorepo?: boolean;\n stateManagement?: string;\n packageManager?: string;\n yes?: boolean;\n dryRun?: boolean;\n config?: string;\n}\n\nfunction parseBoolean(val: string | boolean): boolean {\n if (typeof val === 'boolean') return val;\n if (val === 'true' || val === '1') return true;\n if (val === 'false' || val === '0') return false;\n throw new InvalidArgumentError(`Invalid boolean value '${val}'. Expected true or false.`);\n}\n\nfunction parseTesting(val: string): TestingOption[] {\n const allowed = TestingEnum.options;\n const items = val.split(',').map((item) => item.trim()).filter(Boolean);\n if (items.length === 0) {\n throw new InvalidArgumentError('Testing option cannot be empty.');\n }\n for (const item of items) {\n if (!allowed.includes(item as TestingOption)) {\n throw new InvalidArgumentError(\n `Invalid testing framework '${item}'. Allowed choices are: ${allowed.join(', ')}.`,\n );\n }\n }\n return items as TestingOption[];\n}\n\nexport function setupCliFlags(program: Command): Command {\n return program\n .argument('[project-name]', 'Target project directory / name')\n .addOption(\n new Option('--ts, --typescript [boolean]', 'Use TypeScript').argParser(parseBoolean),\n )\n .addOption(new Option('--no-ts', 'Do not use TypeScript'))\n .addOption(\n new Option('--styling <styling>', 'Styling framework').choices(StylingEnum.options),\n )\n .addOption(new Option('--auth <auth>', 'Authentication provider').choices(AuthEnum.options))\n .addOption(new Option('--orm <orm>', 'ORM selection').choices(OrmEnum.options))\n .addOption(\n new Option('--db, --database <database>', 'Database solution').choices(DatabaseEnum.options),\n )\n .addOption(\n new Option(\n '--testing <frameworks>',\n 'Comma-separated testing frameworks (e.g. vitest,playwright)',\n ).argParser(parseTesting),\n )\n .addOption(new Option('--ci <ci>', 'CI workflow setup').choices(CiEnum.options))\n .addOption(new Option('--docker [boolean]', 'Include Docker setup').argParser(parseBoolean))\n .addOption(new Option('--no-docker', 'Disable Docker setup'))\n .addOption(\n new Option('--monorepo [boolean]', 'Set up project as a monorepo').argParser(parseBoolean),\n )\n .addOption(new Option('--no-monorepo', 'Do not set up as monorepo'))\n .addOption(\n new Option('--state-management <state>', 'State management solution').choices(\n StateManagementEnum.options,\n ),\n )\n .addOption(\n new Option('--package-manager <packageManager>', 'Package manager').choices(\n PackageManagerEnum.options,\n ),\n )\n .addOption(new Option('-y, --yes', 'Skip interactive prompts and use default values'))\n .addOption(new Option('--dry-run', 'Output resolved configuration JSON without scaffolding'))\n .addOption(new Option('-c, --config <path>', 'Path to JSON configuration file'));\n}\n","import { z } from 'zod';\n\nexport const StylingEnum = z.enum(['tailwind', 'css-modules', 'styled-components']);\nexport const AuthEnum = z.enum(['none', 'clerk', 'next-auth', 'auth0']);\nexport const OrmEnum = z.enum(['none', 'prisma', 'drizzle']);\nexport const DatabaseEnum = z.enum(['postgres', 'mysql', 'sqlite', 'mongo']);\nexport const TestingEnum = z.enum(['vitest', 'jest', 'playwright', 'cypress']);\nexport const CiEnum = z.enum(['none', 'github-actions', 'gitlab-ci']);\nexport const StateManagementEnum = z.enum(['none', 'zustand', 'redux', 'jotai']);\nexport const PackageManagerEnum = z.enum(['npm', 'pnpm', 'yarn', 'bun']);\n\nexport const projectConfigSchema = z\n .object({\n projectName: z.string().min(1, 'Project name is required'),\n typescript: z.boolean(),\n styling: StylingEnum,\n auth: AuthEnum,\n orm: OrmEnum,\n database: DatabaseEnum.optional(),\n testing: z.array(TestingEnum),\n ci: CiEnum,\n docker: z.boolean(),\n monorepo: z.boolean(),\n stateManagement: StateManagementEnum,\n packageManager: PackageManagerEnum,\n })\n .superRefine((data, ctx) => {\n if (data.orm === 'none' && data.database !== undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Database must not be specified when ORM is \"none\".',\n path: ['database'],\n });\n }\n if (data.orm !== 'none' && !data.database) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Database must be specified when an ORM is selected.',\n path: ['database'],\n });\n }\n });\n\n// Single source of truth inferred TypeScript type\nexport type ProjectConfig = z.infer<typeof projectConfigSchema>;\n\nexport type StylingOption = z.infer<typeof StylingEnum>;\nexport type AuthOption = z.infer<typeof AuthEnum>;\nexport type OrmOption = z.infer<typeof OrmEnum>;\nexport type DatabaseOption = z.infer<typeof DatabaseEnum>;\nexport type TestingOption = z.infer<typeof TestingEnum>;\nexport type CiOption = z.infer<typeof CiEnum>;\nexport type StateManagementOption = z.infer<typeof StateManagementEnum>;\nexport type PackageManagerOption = z.infer<typeof PackageManagerEnum>;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { CliOptions } from '../cli/flags.js';\nimport { defaultConfig } from './defaults.js';\nimport {\n projectConfigSchema,\n type ProjectConfig,\n} from './schema.js';\n\nexport interface ResolveConfigInput {\n projectName?: string;\n cliOptions: CliOptions;\n cwd?: string;\n interactive?: boolean;\n}\n\n/**\n * Merges configuration sources according to strict precedence rules:\n * 1. Authoritative positional project name\n * 2. Explicit CLI configuration flags\n * 3. Config file options\n * 4. Interactive prompt answers (if TTY & `--yes` is not set)\n * 5. Enterprise default values (fallback)\n */\nexport async function resolveConfig(\n input: ResolveConfigInput,\n prompter?: (partial: Partial<ProjectConfig>) => Promise<Partial<ProjectConfig>>,\n): Promise<ProjectConfig> {\n const cwd = input.cwd ?? process.cwd();\n const flags = input.cliOptions;\n let fileConfig: Partial<ProjectConfig> = {};\n\n // 1. If `--config` is provided, read and parse the JSON file\n if (flags.config) {\n const configPath = path.resolve(cwd, flags.config);\n if (!fs.existsSync(configPath)) {\n throw new Error(`Config file not found at path: ${flags.config}`);\n }\n\n try {\n const fileContent = fs.readFileSync(configPath, 'utf-8');\n fileConfig = JSON.parse(fileContent) as Partial<ProjectConfig>;\n } catch (err) {\n if (err instanceof SyntaxError) {\n throw new Error(`Failed to parse \"${flags.config}\". The file does not contain valid JSON.`);\n }\n throw new Error(`Failed to read config file at \"${flags.config}\": ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // 2. Extract CLI options explicitly supplied by the user\n const cliConfig: Partial<ProjectConfig> = {};\n\n if (flags.typescript !== undefined) cliConfig.typescript = flags.typescript;\n if (flags.styling !== undefined) cliConfig.styling = flags.styling as ProjectConfig['styling'];\n if (flags.auth !== undefined) cliConfig.auth = flags.auth as ProjectConfig['auth'];\n if (flags.orm !== undefined) cliConfig.orm = flags.orm as ProjectConfig['orm'];\n\n const dbFlag = flags.db ?? flags.database;\n if (dbFlag !== undefined) cliConfig.database = dbFlag as ProjectConfig['database'];\n\n if (flags.testing !== undefined) cliConfig.testing = flags.testing;\n if (flags.ci !== undefined) cliConfig.ci = flags.ci as ProjectConfig['ci'];\n if (flags.docker !== undefined) cliConfig.docker = flags.docker;\n if (flags.monorepo !== undefined) cliConfig.monorepo = flags.monorepo;\n if (flags.stateManagement !== undefined)\n cliConfig.stateManagement = flags.stateManagement as ProjectConfig['stateManagement'];\n if (flags.packageManager !== undefined)\n cliConfig.packageManager = flags.packageManager as ProjectConfig['packageManager'];\n\n // CLI flags override config file values\n let resolvedPartial: Partial<ProjectConfig> = {\n ...fileConfig,\n ...cliConfig,\n };\n\n // Authoritative positional project name overrides config file / flags if provided\n if (input.projectName) {\n resolvedPartial.projectName = input.projectName;\n }\n\n // 3. Interactivity step\n const shouldPrompt =\n input.interactive ?? (!flags.yes && Boolean(process.stdout.isTTY));\n\n if (shouldPrompt && prompter) {\n resolvedPartial = await prompter(resolvedPartial);\n }\n\n // 4. Fall back to defaults for remaining unresolved fields\n const finalProjectName = resolvedPartial.projectName || defaultConfig.projectName;\n const finalOrm = resolvedPartial.orm ?? defaultConfig.orm;\n\n let finalDatabase = resolvedPartial.database;\n if (finalOrm !== 'none' && !finalDatabase) {\n finalDatabase = 'postgres';\n }\n\n const finalMerged: ProjectConfig = {\n projectName: finalProjectName,\n typescript: resolvedPartial.typescript ?? defaultConfig.typescript,\n styling: resolvedPartial.styling ?? defaultConfig.styling,\n auth: resolvedPartial.auth ?? defaultConfig.auth,\n orm: finalOrm,\n database: finalDatabase,\n testing: resolvedPartial.testing ?? defaultConfig.testing,\n ci: resolvedPartial.ci ?? defaultConfig.ci,\n docker: resolvedPartial.docker ?? defaultConfig.docker,\n monorepo: resolvedPartial.monorepo ?? defaultConfig.monorepo,\n stateManagement: resolvedPartial.stateManagement ?? defaultConfig.stateManagement,\n packageManager: resolvedPartial.packageManager ?? defaultConfig.packageManager,\n };\n\n // 5. Final validation against Zod schema\n const validationResult = projectConfigSchema.safeParse(finalMerged);\n\n if (!validationResult.success) {\n const issueMessages = validationResult.error.issues\n .map((issue) => ` - [${issue.path.join('.')}]: ${issue.message}`)\n .join('\\n');\n throw new Error(`Invalid configuration:\\n${issueMessages}`);\n }\n\n return validationResult.data;\n}\n","import type { ProjectConfig } from './schema.js';\n\nexport const defaultConfig: ProjectConfig = {\n projectName: 'my-app',\n typescript: true,\n styling: 'tailwind',\n auth: 'none',\n orm: 'none',\n database: undefined,\n testing: ['vitest'],\n ci: 'github-actions',\n docker: true,\n monorepo: false,\n stateManagement: 'none',\n packageManager: 'pnpm',\n};\n","import * as clack from '@clack/prompts';\nimport pc from 'picocolors';\nimport type {\n AuthOption,\n CiOption,\n DatabaseOption,\n OrmOption,\n PackageManagerOption,\n ProjectConfig,\n StateManagementOption,\n StylingOption,\n TestingOption,\n} from '../config/schema.js';\nimport { validateProjectName, validateTargetDirectory } from '../utils/validate-project-name.js';\n\nfunction handleCancel<T>(value: T | symbol): T {\n if (clack.isCancel(value)) {\n clack.cancel('Operation cancelled.');\n process.exit(1);\n }\n return value as T;\n}\n\nexport async function promptForProjectName(initial?: string): Promise<string> {\n if (initial) return initial;\n const name = await clack.text({\n message: 'What is your project name?',\n placeholder: 'my-app',\n defaultValue: 'my-app',\n validate(val) {\n const nameErr = validateProjectName(val);\n if (nameErr) return nameErr;\n const dirErr = validateTargetDirectory(val);\n if (dirErr) return dirErr;\n },\n });\n return handleCancel(name).trim();\n}\n\nexport async function promptForTypeScript(initial?: boolean): Promise<boolean> {\n if (initial !== undefined) return initial;\n const ts = await clack.confirm({\n message: 'Would you like to use TypeScript?',\n initialValue: true,\n });\n return handleCancel(ts);\n}\n\nexport async function promptForStyling(initial?: StylingOption): Promise<StylingOption> {\n if (initial) return initial;\n const styling = await clack.select<StylingOption>({\n message: 'Which styling solution would you like to use?',\n options: [\n { value: 'tailwind', label: 'Tailwind CSS', hint: 'Recommended' },\n { value: 'css-modules', label: 'CSS Modules' },\n { value: 'styled-components', label: 'Styled Components' },\n ],\n initialValue: 'tailwind',\n });\n return handleCancel(styling);\n}\n\nexport async function promptForAuth(initial?: AuthOption): Promise<AuthOption> {\n if (initial) return initial;\n const auth = await clack.select<AuthOption>({\n message: 'Which authentication provider would you like to use?',\n options: [\n { value: 'none', label: 'None' },\n { value: 'clerk', label: 'Clerk', hint: 'User management platform' },\n { value: 'next-auth', label: 'NextAuth.js / Auth.js', hint: 'Open source auth' },\n { value: 'auth0', label: 'Auth0', hint: 'Enterprise Identity Platform' },\n ],\n initialValue: 'none',\n });\n return handleCancel(auth);\n}\n\nexport async function promptForOrm(initial?: OrmOption): Promise<OrmOption> {\n if (initial) return initial;\n const orm = await clack.select<OrmOption>({\n message: 'Which ORM / Database abstraction would you like to use?',\n options: [\n { value: 'none', label: 'None' },\n { value: 'prisma', label: 'Prisma', hint: 'Next-gen ORM' },\n { value: 'drizzle', label: 'Drizzle ORM', hint: 'Lightweight & fast' },\n ],\n initialValue: 'none',\n });\n return handleCancel(orm);\n}\n\nexport async function promptForDatabase(\n orm: OrmOption,\n initial?: DatabaseOption,\n): Promise<DatabaseOption | undefined> {\n if (orm === 'none') return undefined;\n if (initial) return initial;\n const db = await clack.select<DatabaseOption>({\n message: 'Which database would you like to connect to?',\n options: [\n { value: 'postgres', label: 'PostgreSQL' },\n { value: 'mysql', label: 'MySQL' },\n { value: 'sqlite', label: 'SQLite' },\n { value: 'mongo', label: 'MongoDB' },\n ],\n initialValue: 'postgres',\n });\n return handleCancel(db);\n}\n\nexport async function promptForTesting(initial?: TestingOption[]): Promise<TestingOption[]> {\n if (initial && initial.length > 0) return initial;\n const testing = await clack.multiselect<TestingOption>({\n message: 'Select testing frameworks to include:',\n options: [\n { value: 'vitest', label: 'Vitest', hint: 'Fast unit/integration test runner' },\n { value: 'jest', label: 'Jest', hint: 'Delightful JS testing' },\n { value: 'playwright', label: 'Playwright', hint: 'End-to-end browser testing' },\n { value: 'cypress', label: 'Cypress', hint: 'E2E & component testing' },\n ],\n required: false,\n initialValues: ['vitest'],\n });\n return handleCancel(testing);\n}\n\nexport async function promptForCi(initial?: CiOption): Promise<CiOption> {\n if (initial) return initial;\n const ci = await clack.select<CiOption>({\n message: 'Which Continuous Integration (CI) setup would you like?',\n options: [\n { value: 'github-actions', label: 'GitHub Actions', hint: 'Recommended' },\n { value: 'gitlab-ci', label: 'GitLab CI' },\n { value: 'none', label: 'None' },\n ],\n initialValue: 'github-actions',\n });\n return handleCancel(ci);\n}\n\nexport async function promptForDocker(initial?: boolean): Promise<boolean> {\n if (initial !== undefined) return initial;\n const docker = await clack.confirm({\n message: 'Would you like to include a Docker container setup?',\n initialValue: true,\n });\n return handleCancel(docker);\n}\n\nexport async function promptForMonorepo(initial?: boolean): Promise<boolean> {\n if (initial !== undefined) return initial;\n const monorepo = await clack.confirm({\n message: 'Would you like to configure this project as a monorepo?',\n initialValue: false,\n });\n return handleCancel(monorepo);\n}\n\nexport async function promptForStateManagement(\n initial?: StateManagementOption,\n): Promise<StateManagementOption> {\n if (initial) return initial;\n const stateManagement = await clack.select<StateManagementOption>({\n message: 'Which state management solution would you like?',\n options: [\n { value: 'none', label: 'None' },\n { value: 'zustand', label: 'Zustand', hint: 'Small, fast, scaleable' },\n { value: 'redux', label: 'Redux Toolkit', hint: 'Opinionated toolset for Redux' },\n { value: 'jotai', label: 'Jotai', hint: 'Primitive and flexible state management' },\n ],\n initialValue: 'none',\n });\n return handleCancel(stateManagement);\n}\n\nexport async function promptForPackageManager(\n initial?: PackageManagerOption,\n): Promise<PackageManagerOption> {\n if (initial) return initial;\n const packageManager = await clack.select<PackageManagerOption>({\n message: 'Which package manager would you like to use?',\n options: [\n { value: 'pnpm', label: 'pnpm', hint: 'Recommended' },\n { value: 'npm', label: 'npm' },\n { value: 'yarn', label: 'yarn' },\n { value: 'bun', label: 'bun' },\n ],\n initialValue: 'pnpm',\n });\n return handleCancel(packageManager);\n}\n\nexport async function runInteractivePrompts(\n partial: Partial<ProjectConfig>,\n): Promise<Partial<ProjectConfig>> {\n clack.intro(pc.bgCyan(pc.black(' create-enterprise-next ')));\n\n const projectName = await promptForProjectName(partial.projectName);\n const typescript = await promptForTypeScript(partial.typescript);\n const styling = await promptForStyling(partial.styling);\n const auth = await promptForAuth(partial.auth);\n const orm = await promptForOrm(partial.orm);\n const database = await promptForDatabase(orm, partial.database);\n const testing = await promptForTesting(partial.testing);\n const ci = await promptForCi(partial.ci);\n const docker = await promptForDocker(partial.docker);\n const monorepo = await promptForMonorepo(partial.monorepo);\n const stateManagement = await promptForStateManagement(partial.stateManagement);\n const packageManager = await promptForPackageManager(partial.packageManager);\n\n clack.outro(pc.green('Configuration completed!'));\n\n return {\n projectName,\n typescript,\n styling,\n auth,\n orm,\n database,\n testing,\n ci,\n docker,\n monorepo,\n stateManagement,\n packageManager,\n };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport validateNpmName from 'validate-npm-package-name';\n\n/**\n * Validates project name for filesystem safety and npm package name compliance.\n */\nexport function validateProjectName(name: string, cwd: string = process.cwd()): string | undefined {\n if (!name || name.trim().length === 0) {\n return 'Project name cannot be empty.';\n }\n\n const trimmed = name.trim();\n\n if (trimmed.includes(' ')) {\n return 'Project name cannot contain spaces.';\n }\n\n // Path traversal check\n const targetPath = path.resolve(cwd, trimmed);\n const relativePath = path.relative(cwd, targetPath);\n if (relativePath.startsWith('..') || path.isAbsolute(trimmed) && !targetPath.startsWith(cwd)) {\n return 'Project name cannot resolve outside the current working directory.';\n }\n\n const basename = path.basename(trimmed);\n const npmValidation = validateNpmName(basename);\n if (!npmValidation.validForNewPackages) {\n const errors = [...(npmValidation.errors || []), ...(npmValidation.warnings || [])];\n return `Invalid npm package name: ${errors.join(', ')}`;\n }\n\n return undefined;\n}\n\n/**\n * Validates that target directory path does not exist or is an empty directory.\n */\nexport function validateTargetDirectory(targetPath: string, cwd: string = process.cwd()): string | undefined {\n const absolutePath = path.resolve(cwd, targetPath);\n\n if (!fs.existsSync(absolutePath)) {\n return undefined;\n }\n\n const stats = fs.statSync(absolutePath);\n if (!stats.isDirectory()) {\n return `Target path \"${targetPath}\" exists and is a file, not a directory.`;\n }\n\n const files = fs.readdirSync(absolutePath);\n const nonHiddenFiles = files.filter((file) => !file.startsWith('.'));\n if (nonHiddenFiles.length > 0) {\n return `Target directory \"${targetPath}\" is not empty. Please choose another name or empty the directory.`;\n }\n\n return undefined;\n}\n","import pc from 'picocolors';\n\nexport const logger = {\n info: (msg: string) => console.log(pc.blue('ℹ ') + msg),\n success: (msg: string) => console.log(pc.green('✔ ') + msg),\n warn: (msg: string) => console.warn(pc.yellow('⚠ ') + msg),\n error: (msg: string) => console.error(pc.red('✖ ') + msg),\n log: (msg: string) => console.log(msg),\n};\n"],"mappings":"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","names":["Command","fs","path","fs","path","pc","path","fs","Command"]}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "create-enterprise-next",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool to scaffold enterprise-grade Next.js projects",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-enterprise-next": "./dist/index.js",
8
+ "cen": "./dist/index.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "keywords": [
20
+ "nextjs",
21
+ "cli",
22
+ "scaffold",
23
+ "enterprise",
24
+ "create-enterprise-next",
25
+ "cen"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "engines": {
30
+ "node": ">=18.0.0"
31
+ },
32
+ "dependencies": {
33
+ "@clack/prompts": "^0.8.2",
34
+ "commander": "^12.1.0",
35
+ "picocolors": "^1.1.1",
36
+ "validate-npm-package-name": "^5.0.1",
37
+ "zod": "^3.23.8"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.14.9",
41
+ "@types/validate-npm-package-name": "^4.0.2",
42
+ "@typescript-eslint/eslint-plugin": "^7.14.0",
43
+ "@typescript-eslint/parser": "^7.14.0",
44
+ "eslint": "^8.57.0",
45
+ "prettier": "^3.3.2",
46
+ "tsup": "^8.1.0",
47
+ "typescript": "^5.5.2"
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "dev": "tsup --watch",
52
+ "typecheck": "tsc --noEmit",
53
+ "lint": "eslint src --ext .ts",
54
+ "format": "prettier --write \"src/**/*.ts\""
55
+ }
56
+ }