express-ts-wizard 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.
@@ -0,0 +1,16 @@
1
+ import type { TsStrictness, UserChoices } from "./prompts.js";
2
+ /**
3
+ * Creates a new Express + TypeScript project based on user choices.
4
+ * Handles directory creation, file copying, dependency installation, and Git initialization.
5
+ * @param {UserChoices} choices - User selections from the wizard
6
+ * @returns {Promise<void>} Resolves when the project is fully created
7
+ * @throws {Error} If the target directory already exists or file operations fail
8
+ */
9
+ export declare function createProject(choices: UserChoices): Promise<void>;
10
+ /**
11
+ * Returns a human-readable description of the TypeScript strictness level.
12
+ * @param {TsStrictness} level - The strictness level
13
+ * @returns {string} A formatted description of the strictness level
14
+ */
15
+ export declare function getTsStrictnessDescription(level: TsStrictness): string;
16
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA0F9D;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCvE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAOtE"}
@@ -0,0 +1,133 @@
1
+ import * as p from "@clack/prompts";
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+ import { execa } from "execa";
5
+ import { fileURLToPath } from "url";
6
+ const currentFilePath = fileURLToPath(import.meta.url);
7
+ const currentDirectory = path.dirname(currentFilePath);
8
+ /**
9
+ * Resolves the templates directory path.
10
+ * Works in both development (src/templates) and production (dist/templates) environments.
11
+ * @returns {string} The absolute path to the templates directory
12
+ */
13
+ function getTemplatesDirectory() {
14
+ const productionPath = path.join(currentDirectory, "templates");
15
+ const developmentPath = path.join(currentDirectory, "..", "src", "templates");
16
+ if (fs.existsSync(productionPath)) {
17
+ return productionPath;
18
+ }
19
+ return developmentPath;
20
+ }
21
+ /**
22
+ * Copies template files to the target project directory.
23
+ * @param {string} templatesDirectory - Path to the templates directory
24
+ * @param {string} projectPath - Path to the new project directory
25
+ * @param {string} projectName - Name of the project for package.json
26
+ * @param {TsStrictness} tsStrictness - TypeScript strictness level to use
27
+ * @returns {Promise<void>} Resolves when all files are copied
28
+ * @throws {Error} If file operations fail
29
+ */
30
+ async function copyProjectFiles(templatesDirectory, projectPath, projectName, tsStrictness) {
31
+ await fs.ensureDir(path.join(projectPath, "src"));
32
+ const sourceIndexPath = path.join(templatesDirectory, "base", "src", "index.ts");
33
+ await fs.copy(sourceIndexPath, path.join(projectPath, "src", "index.ts"));
34
+ const gitignoreSourcePath = path.join(templatesDirectory, "base", "gitignore");
35
+ await fs.copy(gitignoreSourcePath, path.join(projectPath, ".gitignore"));
36
+ const packageTemplateContent = await fs.readFile(path.join(templatesDirectory, "base", "package.template.json"), "utf-8");
37
+ const packageJsonContent = packageTemplateContent.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
38
+ await fs.writeFile(path.join(projectPath, "package.json"), packageJsonContent);
39
+ const tsconfigSourcePath = path.join(templatesDirectory, "tsconfig", `${tsStrictness}.json`);
40
+ await fs.copy(tsconfigSourcePath, path.join(projectPath, "tsconfig.json"));
41
+ }
42
+ /**
43
+ * Installs npm dependencies in the project directory.
44
+ * @param {string} projectPath - Path to the project directory
45
+ * @returns {Promise<void>} Resolves when dependencies are installed
46
+ * @throws {Error} If npm install fails
47
+ */
48
+ async function installDependencies(projectPath) {
49
+ await execa("npm", ["install"], {
50
+ cwd: projectPath,
51
+ stdio: "pipe",
52
+ });
53
+ }
54
+ /**
55
+ * Initializes a Git repository with an initial commit.
56
+ * @param {string} projectPath - Path to the project directory
57
+ * @returns {Promise<void>} Resolves when Git is initialized and first commit is made
58
+ * @throws {Error} If git commands fail
59
+ */
60
+ async function initializeGitRepository(projectPath) {
61
+ await execa("git", ["init"], {
62
+ cwd: projectPath,
63
+ stdio: "pipe",
64
+ });
65
+ await execa("git", ["add", "."], {
66
+ cwd: projectPath,
67
+ stdio: "pipe",
68
+ });
69
+ await execa("git", ["commit", "-m", "Initial commit from express-ts-wizard"], {
70
+ cwd: projectPath,
71
+ stdio: "pipe",
72
+ });
73
+ }
74
+ /**
75
+ * Creates a new Express + TypeScript project based on user choices.
76
+ * Handles directory creation, file copying, dependency installation, and Git initialization.
77
+ * @param {UserChoices} choices - User selections from the wizard
78
+ * @returns {Promise<void>} Resolves when the project is fully created
79
+ * @throws {Error} If the target directory already exists or file operations fail
80
+ */
81
+ export async function createProject(choices) {
82
+ const { projectName, tsStrictness, initGit } = choices;
83
+ const projectPath = path.resolve(process.cwd(), projectName);
84
+ const templatesDirectory = getTemplatesDirectory();
85
+ if (fs.existsSync(projectPath)) {
86
+ p.cancel(`Directory "${projectName}" already exists.`);
87
+ process.exit(1);
88
+ }
89
+ const spinner = p.spinner();
90
+ spinner.start("Creating project structure...");
91
+ try {
92
+ await copyProjectFiles(templatesDirectory, projectPath, projectName, tsStrictness);
93
+ spinner.stop("Project structure created ✓");
94
+ }
95
+ catch (error) {
96
+ spinner.stop("Error creating structure");
97
+ throw error;
98
+ }
99
+ spinner.start("Installing dependencies...");
100
+ try {
101
+ await installDependencies(projectPath);
102
+ spinner.stop("Dependencies installed ✓");
103
+ }
104
+ catch (error) {
105
+ spinner.stop("Error installing dependencies");
106
+ throw error;
107
+ }
108
+ if (initGit) {
109
+ spinner.start("Initializing Git...");
110
+ try {
111
+ await initializeGitRepository(projectPath);
112
+ spinner.stop("Git initialized ✓");
113
+ }
114
+ catch {
115
+ spinner.stop("Error initializing Git (may not be installed)");
116
+ // Git initialization is optional, so we don't throw
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * Returns a human-readable description of the TypeScript strictness level.
122
+ * @param {TsStrictness} level - The strictness level
123
+ * @returns {string} A formatted description of the strictness level
124
+ */
125
+ export function getTsStrictnessDescription(level) {
126
+ const descriptions = {
127
+ relaxed: "Relaxed (strict: false)",
128
+ moderate: "Moderate (strict: true)",
129
+ strict: "Strict (maximum options)",
130
+ };
131
+ return descriptions[level];
132
+ }
133
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ import * as p from "@clack/prompts";
3
+ import kleur from "kleur";
4
+ import { runPrompts } from "./prompts.js";
5
+ import { createProject, getTsStrictnessDescription } from "./actions.js";
6
+ /**
7
+ * Displays the final success message with next steps for the user.
8
+ * @param {string} projectName - Name of the created project
9
+ * @param {string} strictnessDescription - Human-readable TypeScript strictness level
10
+ * @returns {void}
11
+ */
12
+ function displaySuccessMessage(projectName, strictnessDescription) {
13
+ const nextSteps = [
14
+ `cd ${projectName}`,
15
+ "npm run dev → Start server with hot-reload",
16
+ "npm run build → Compile to JavaScript",
17
+ "npm run start → Run the compiled version",
18
+ "npm run type-check → Check types without compiling",
19
+ ];
20
+ p.note(nextSteps.join("\n"), "Next steps");
21
+ p.outro(kleur.green("✔") +
22
+ ` Project ${kleur.cyan(projectName)} created with TypeScript ${kleur.yellow(strictnessDescription)}`);
23
+ }
24
+ /**
25
+ * Main entry point for the CLI wizard.
26
+ * Orchestrates the prompt collection, project creation, and success messaging.
27
+ * @returns {Promise<void>} Resolves when the CLI completes or exits on error
28
+ */
29
+ async function main() {
30
+ console.clear();
31
+ const choices = await runPrompts();
32
+ if (!choices) {
33
+ process.exit(0);
34
+ }
35
+ console.log();
36
+ try {
37
+ await createProject(choices);
38
+ const strictnessDescription = getTsStrictnessDescription(choices.tsStrictness);
39
+ displaySuccessMessage(choices.projectName, strictnessDescription);
40
+ }
41
+ catch (error) {
42
+ p.cancel("Error creating project");
43
+ console.error(error);
44
+ process.exit(1);
45
+ }
46
+ }
47
+ main();
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAEzE;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,WAAmB,EAAE,qBAA6B;IAC/E,MAAM,SAAS,GAAG;QAChB,MAAM,WAAW,EAAE;QACnB,gDAAgD;QAChD,yCAAyC;QACzC,4CAA4C;QAC5C,oDAAoD;KACrD,CAAC;IAEF,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IAE3C,CAAC,CAAC,KAAK,CACL,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;QACd,YAAY,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,4BAA4B,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,CACvG,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,qBAAqB,GAAG,0BAA0B,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC/E,qBAAqB,CAAC,OAAO,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** Available TypeScript strictness levels for project configuration */
2
+ export type TsStrictness = "relaxed" | "moderate" | "strict";
3
+ /** User selections from the interactive wizard */
4
+ export interface UserChoices {
5
+ readonly projectName: string;
6
+ readonly tsStrictness: TsStrictness;
7
+ readonly initGit: boolean;
8
+ }
9
+ /**
10
+ * Runs the interactive CLI wizard to collect user preferences.
11
+ * Displays prompts for project name, TypeScript strictness, and Git initialization.
12
+ * @returns {Promise<UserChoices | null>} The user's choices, or null if cancelled
13
+ */
14
+ export declare function runPrompts(): Promise<UserChoices | null>;
15
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAGA,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE7D,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAwD9D"}
@@ -0,0 +1,56 @@
1
+ import * as p from "@clack/prompts";
2
+ import kleur from "kleur";
3
+ /**
4
+ * Runs the interactive CLI wizard to collect user preferences.
5
+ * Displays prompts for project name, TypeScript strictness, and Git initialization.
6
+ * @returns {Promise<UserChoices | null>} The user's choices, or null if cancelled
7
+ */
8
+ export async function runPrompts() {
9
+ p.intro(kleur.bgCyan().black(" express-ts-wizard "));
10
+ const project = await p.group({
11
+ projectName: () => p.text({
12
+ message: "What is your project name?",
13
+ placeholder: "my-express-app",
14
+ defaultValue: "my-express-app",
15
+ validate: (value) => {
16
+ if (!value)
17
+ return "Project name is required";
18
+ if (!/^[a-z0-9-_]+$/i.test(value)) {
19
+ return "Only letters, numbers, hyphens and underscores allowed";
20
+ }
21
+ },
22
+ }),
23
+ tsStrictness: () => p.select({
24
+ message: "Which TypeScript strictness level do you prefer?",
25
+ options: [
26
+ {
27
+ value: "relaxed",
28
+ label: "Relaxed",
29
+ hint: "strict: false - Minimal configuration",
30
+ },
31
+ {
32
+ value: "moderate",
33
+ label: "Moderate",
34
+ hint: "strict: true - Recommended",
35
+ },
36
+ {
37
+ value: "strict",
38
+ label: "Strict",
39
+ hint: "strict + additional options - Maximum type safety",
40
+ },
41
+ ],
42
+ initialValue: "moderate",
43
+ }),
44
+ initGit: () => p.confirm({
45
+ message: "Initialize Git repository?",
46
+ initialValue: true,
47
+ }),
48
+ }, {
49
+ onCancel: () => {
50
+ p.cancel("Operation cancelled.");
51
+ process.exit(0);
52
+ },
53
+ });
54
+ return project;
55
+ }
56
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAErD,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,KAAK,CAC3B;QACE,WAAW,EAAE,GAAG,EAAE,CAChB,CAAC,CAAC,IAAI,CAAC;YACL,OAAO,EAAE,4BAA4B;YACrC,WAAW,EAAE,gBAAgB;YAC7B,YAAY,EAAE,gBAAgB;YAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,IAAI,CAAC,KAAK;oBAAE,OAAO,0BAA0B,CAAC;gBAC9C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClC,OAAO,wDAAwD,CAAC;gBAClE,CAAC;YACH,CAAC;SACF,CAAC;QAEJ,YAAY,EAAE,GAAG,EAAE,CACjB,CAAC,CAAC,MAAM,CAAC;YACP,OAAO,EAAE,kDAAkD;YAC3D,OAAO,EAAE;gBACP;oBACE,KAAK,EAAE,SAAS;oBAChB,KAAK,EAAE,SAAS;oBAChB,IAAI,EAAE,uCAAuC;iBAC9C;gBACD;oBACE,KAAK,EAAE,UAAU;oBACjB,KAAK,EAAE,UAAU;oBACjB,IAAI,EAAE,4BAA4B;iBACnC;gBACD;oBACE,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,QAAQ;oBACf,IAAI,EAAE,mDAAmD;iBAC1D;aACF;YACD,YAAY,EAAE,UAA0B;SACzC,CAAC;QAEJ,OAAO,EAAE,GAAG,EAAE,CACZ,CAAC,CAAC,OAAO,CAAC;YACR,OAAO,EAAE,4BAA4B;YACrC,YAAY,EAAE,IAAI;SACnB,CAAC;KACL,EACD;QACE,QAAQ,EAAE,GAAG,EAAE;YACb,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;KACF,CACF,CAAC;IAEF,OAAO,OAAsB,CAAC;AAChC,CAAC"}
@@ -0,0 +1,31 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build output
5
+ dist/
6
+
7
+ # Environment variables
8
+ .env
9
+ .env.local
10
+ .env.*.local
11
+
12
+ # IDE
13
+ .vscode/
14
+ .idea/
15
+ *.swp
16
+ *.swo
17
+
18
+ # OS
19
+ .DS_Store
20
+ Thumbs.db
21
+
22
+ # Logs
23
+ logs/
24
+ *.log
25
+ npm-debug.log*
26
+
27
+ # Testing
28
+ coverage/
29
+
30
+ # Misc
31
+ *.tsbuildinfo
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "1.0.0",
4
+ "description": "Express.js API with TypeScript",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "dev": "tsx watch src/index.ts",
9
+ "build": "tsc",
10
+ "type-check": "tsc --noEmit",
11
+ "start": "node dist/index.js"
12
+ },
13
+ "keywords": ["express", "typescript", "api"],
14
+ "author": "",
15
+ "license": "MIT",
16
+ "dependencies": {
17
+ "express": "^5.0.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/express": "^5.0.0",
21
+ "@types/node": "^22.10.5",
22
+ "typescript": "^5.7.3",
23
+ "tsx": "^4.19.2"
24
+ },
25
+ "engines": {
26
+ "node": ">=18.0.0"
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ import express, { Request, Response } from "express";
2
+
3
+ const app = express();
4
+ const PORT = process.env.PORT || 3000;
5
+
6
+ app.use(express.json());
7
+
8
+ /**
9
+ * Health check endpoint for monitoring and load balancer probes.
10
+ * @param {Request} _request - Express request object (unused)
11
+ * @param {Response} response - Express response object
12
+ */
13
+ app.get("/health", (_request: Request, response: Response) => {
14
+ response.json({ status: "ok", timestamp: new Date().toISOString() });
15
+ });
16
+
17
+ /**
18
+ * Root endpoint returning a welcome message.
19
+ * @param {Request} _request - Express request object (unused)
20
+ * @param {Response} response - Express response object
21
+ */
22
+ app.get("/", (_request: Request, response: Response) => {
23
+ response.json({ message: "Welcome to your Express + TypeScript API!" });
24
+ });
25
+
26
+ app.listen(PORT, () => {
27
+ console.log(`🚀 Server running at http://localhost:${PORT}`);
28
+ });
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": false,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "noUncheckedIndexedAccess": true,
11
+ "exactOptionalPropertyTypes": true,
12
+ "noPropertyAccessFromIndexSignature": true,
13
+ "noImplicitReturns": true,
14
+ "noFallthroughCasesInSwitch": true,
15
+ "noImplicitOverride": true,
16
+ "esModuleInterop": true,
17
+ "skipLibCheck": true,
18
+ "forceConsistentCasingInFileNames": true,
19
+ "resolveJsonModule": true,
20
+ "declaration": true,
21
+ "sourceMap": true
22
+ },
23
+ "include": ["src/**/*"],
24
+ "exclude": ["node_modules", "dist"]
25
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "express-ts-wizard",
3
+ "version": "0.1.0",
4
+ "description": "CLI wizard to create Express.js projects with TypeScript",
5
+ "type": "module",
6
+ "bin": {
7
+ "express-ts-wizard": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "dev": "tsx src/index.ts",
14
+ "build": "tsc && npm run copy-templates",
15
+ "copy-templates": "cp -r src/templates dist/",
16
+ "type-check": "tsc --noEmit",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "express",
21
+ "typescript",
22
+ "cli",
23
+ "generator",
24
+ "scaffold",
25
+ "create"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@clack/prompts": "^0.8.2",
31
+ "execa": "^9.5.2",
32
+ "fs-extra": "^11.2.0",
33
+ "kleur": "^4.1.5"
34
+ },
35
+ "devDependencies": {
36
+ "@types/fs-extra": "^11.0.4",
37
+ "@types/node": "^22.10.5",
38
+ "typescript": "^5.7.3",
39
+ "tsx": "^4.19.2"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ }
44
+ }