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.
- package/dist/actions.d.ts +16 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +133 -0
- package/dist/actions.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +15 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +56 -0
- package/dist/prompts.js.map +1 -0
- package/dist/templates/base/gitignore +31 -0
- package/dist/templates/base/package.template.json +28 -0
- package/dist/templates/base/src/index.ts +28 -0
- package/dist/templates/tsconfig/moderate.json +19 -0
- package/dist/templates/tsconfig/relaxed.json +19 -0
- package/dist/templates/tsconfig/strict.json +25 -0
- package/package.json +44 -0
|
@@ -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"}
|
package/dist/actions.js
ADDED
|
@@ -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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/prompts.js
ADDED
|
@@ -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
|
+
}
|