scaffy-tool 0.2.0 → 1.0.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/README.md +20 -25
- package/cli.js +14 -35
- package/core/detector.js +5 -31
- package/core/executor.js +5 -27
- package/core/interviewer.js +4 -11
- package/core/plugin-validator.js +1 -1
- package/core/registry.js +37 -25
- package/core/utils.js +2 -19
- package/package.json +11 -11
- package/registry/go/gin/plugin.json +23 -0
- package/registry/go/gin/v1/questions.js +19 -0
- package/registry/go/gin/v1/scaffold.js +196 -0
- package/registry/index.json +2 -2
- package/registry/javascript/expressjs/plugin.json +44 -0
- package/registry/javascript/expressjs/v4/questions.js +43 -0
- package/registry/javascript/expressjs/v4/scaffold.js +236 -0
- package/registry/javascript/nestjs/plugin.json +2 -2
- package/registry/javascript/nestjs/v10/questions.js +4 -2
- package/registry/javascript/nestjs/v10/scaffold.js +1 -1
- package/registry/javascript/nestjs/v11/questions.js +61 -0
- package/registry/javascript/nestjs/v11/scaffold.js +94 -0
- package/registry/javascript/nextjs/plugin.json +44 -0
- package/registry/javascript/nextjs/v14/questions.js +44 -0
- package/registry/javascript/nextjs/v14/scaffold.js +57 -0
- package/registry/javascript/vuejs/v3/questions.js +4 -2
- package/registry/javascript/vuejs/v3/scaffold.js +3 -10
- package/registry/php/laravel/plugin.json +2 -2
- package/registry/php/laravel/v11/questions.js +1 -1
- package/registry/php/laravel/v11/scaffold.js +1 -1
- package/registry/php/laravel/v12/questions.js +45 -0
- package/registry/php/laravel/v12/scaffold.js +46 -0
- package/registry/php/laravel/v13/questions.js +28 -0
- package/registry/php/laravel/v13/scaffold.js +46 -0
- package/registry/php/laravel/v13/test/.gitkeep +0 -0
- package/registry/php/laravel/v13/test/questions.test.js +48 -0
- package/registry/php/laravel/v13/test/scaffold.test.js +105 -0
- package/registry/php/symfony/plugin.json +35 -0
- package/registry/php/symfony/v7/questions.js +32 -0
- package/registry/php/symfony/v7/scaffold.js +86 -0
- package/registry/python/django/plugin.json +35 -0
- package/registry/python/django/v5/questions.js +24 -0
- package/registry/python/django/v5/scaffold.js +107 -0
- package/registry/python/fastapi/plugin.json +35 -0
- package/registry/python/fastapi/v1/questions.js +25 -0
- package/registry/python/fastapi/v1/scaffold.js +180 -0
package/core/utils.js
CHANGED
|
@@ -1,40 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
2
2
|
|
|
3
3
|
const log = message => {
|
|
4
4
|
console.log(chalk.white(` ${message}`));
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// ─── Success Message ───────────────────────────────────
|
|
8
7
|
const success = message => {
|
|
9
8
|
console.log(chalk.green(`\n ${message}\n`));
|
|
10
9
|
};
|
|
11
10
|
|
|
12
|
-
// ─── Warning Message ───────────────────────────────────
|
|
13
11
|
const warn = message => {
|
|
14
12
|
console.log(chalk.yellow(` ⚠️ ${message}`));
|
|
15
13
|
};
|
|
16
14
|
|
|
17
|
-
// ─── Error Message ─────────────────────────────────────
|
|
18
15
|
const error = message => {
|
|
19
16
|
console.log(chalk.red(` ❌ ${message}`));
|
|
20
17
|
};
|
|
21
18
|
|
|
22
|
-
// ─── Section Title ─────────────────────────────────────
|
|
23
19
|
const title = message => {
|
|
24
20
|
console.log(chalk.cyan.bold(`\n ── ${message} ──\n`));
|
|
25
21
|
};
|
|
26
22
|
|
|
27
|
-
// ─── Divider Line ──────────────────────────────────────
|
|
28
23
|
const divider = () => {
|
|
29
24
|
console.log(chalk.gray(' ──────────────────────────────────────────'));
|
|
30
25
|
};
|
|
31
26
|
|
|
32
|
-
// ─── Step Indicator ────────────────────────────────────
|
|
33
27
|
const step = (number, message) => {
|
|
34
28
|
console.log(chalk.cyan(` [${number}]`) + chalk.white(` ${message}`));
|
|
35
29
|
};
|
|
36
30
|
|
|
37
|
-
// ─── Build Utils Object For Plugins ───────────────────
|
|
38
31
|
const buildPluginUtils = executor => ({
|
|
39
32
|
run: executor.run,
|
|
40
33
|
runInProject: executor.runInProject,
|
|
@@ -50,14 +43,4 @@ const buildPluginUtils = executor => ({
|
|
|
50
43
|
divider,
|
|
51
44
|
});
|
|
52
45
|
|
|
53
|
-
|
|
54
|
-
module.exports = {
|
|
55
|
-
log,
|
|
56
|
-
success,
|
|
57
|
-
warn,
|
|
58
|
-
error,
|
|
59
|
-
title,
|
|
60
|
-
divider,
|
|
61
|
-
step,
|
|
62
|
-
buildPluginUtils,
|
|
63
|
-
};
|
|
46
|
+
export { log, success, warn, error, title, divider, step, buildPluginUtils };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scaffy-tool",
|
|
3
|
-
"type": "
|
|
4
|
-
"version": "0.
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"description": "One command. Any framework. Ready to code.",
|
|
6
6
|
"author": "Md Tanvir Hossen <tanvirhossen112@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"scaffy": "cli.js"
|
|
11
11
|
},
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
13
|
+
"node": ">=20.0.0"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"scaffolding",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"start": "node cli.js",
|
|
44
|
-
"test": "jest",
|
|
45
|
-
"test:
|
|
46
|
-
"test:
|
|
47
|
-
"test:ci": "jest --coverage --ci --runInBand",
|
|
44
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
45
|
+
"test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage",
|
|
46
|
+
"test:watch": "node --experimental-vm-modules node_modules/.bin/jest --watch",
|
|
47
|
+
"test:ci": "node --experimental-vm-modules node_modules/.bin/jest --coverage --ci --runInBand",
|
|
48
48
|
"lint": "eslint .",
|
|
49
49
|
"lint:fix": "eslint . --fix",
|
|
50
50
|
"format": "prettier --write .",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"prepare": "husky install"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"chalk": "^
|
|
55
|
+
"chalk": "^5.6.2",
|
|
56
56
|
"commander": "^11.1.0",
|
|
57
57
|
"figlet": "^1.10.0",
|
|
58
|
-
"inquirer": "^
|
|
59
|
-
"ora": "^
|
|
58
|
+
"inquirer": "^13.3.2",
|
|
59
|
+
"ora": "^9.3.0",
|
|
60
60
|
"semver": "^7.7.4"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"!(jest.config).js": [
|
|
74
74
|
"eslint --fix",
|
|
75
75
|
"prettier --write",
|
|
76
|
-
"jest --bail --findRelatedTests"
|
|
76
|
+
"node --experimental-vm-modules node_modules/.bin/jest --bail --findRelatedTests"
|
|
77
77
|
],
|
|
78
78
|
"*.json": [
|
|
79
79
|
"prettier --write"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Gin",
|
|
3
|
+
"alias": ["gin"],
|
|
4
|
+
"language": "go",
|
|
5
|
+
"latest": "v1",
|
|
6
|
+
"versions": ["v1"],
|
|
7
|
+
"description": "Fast and lightweight Go web framework",
|
|
8
|
+
"requires": [
|
|
9
|
+
{
|
|
10
|
+
"tool": "go",
|
|
11
|
+
"checkCommand": "go version",
|
|
12
|
+
"parseVersion": "go version go([0-9]+\\.[0-9]+\\.[0-9]+)",
|
|
13
|
+
"minVersion": "1.21.0",
|
|
14
|
+
"installGuide": {
|
|
15
|
+
"mac": "brew install go",
|
|
16
|
+
"linux": "sudo apt install golang-go",
|
|
17
|
+
"windows": "https://go.dev/dl",
|
|
18
|
+
"docs": "https://go.dev"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"maintainer": "community"
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
type: 'list',
|
|
4
|
+
name: 'database',
|
|
5
|
+
message: 'Database?',
|
|
6
|
+
choices: [
|
|
7
|
+
{ name: 'None', value: 'none' },
|
|
8
|
+
{ name: 'PostgreSQL — GORM + postgres driver', value: 'postgresql' },
|
|
9
|
+
{ name: 'MySQL — GORM + mysql driver', value: 'mysql' },
|
|
10
|
+
{ name: 'SQLite — GORM + sqlite driver', value: 'sqlite' },
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
type: 'confirm',
|
|
15
|
+
name: 'docker',
|
|
16
|
+
message: 'Include Docker config?',
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const { projectName, database, docker } = answers;
|
|
3
|
+
|
|
4
|
+
utils.title('Creating Gin v1 Project');
|
|
5
|
+
|
|
6
|
+
// ─── Step 1: Create project folder ────────────────────
|
|
7
|
+
utils.step(1, 'Creating project structure');
|
|
8
|
+
await utils.run(`mkdir ${projectName}`);
|
|
9
|
+
|
|
10
|
+
// ─── Step 2: Initialize Go module ─────────────────────
|
|
11
|
+
utils.step(2, 'Initializing Go module');
|
|
12
|
+
await utils.runInProject(projectName, `go mod init ${projectName}`);
|
|
13
|
+
|
|
14
|
+
// ─── Step 3: Install Gin ───────────────────────────────
|
|
15
|
+
utils.step(3, 'Installing Gin');
|
|
16
|
+
await utils.runInProject(projectName, 'go get github.com/gin-gonic/gin');
|
|
17
|
+
|
|
18
|
+
// ─── Step 4: Database ─────────────────────────────────
|
|
19
|
+
if (database !== 'none') {
|
|
20
|
+
utils.step(4, 'Installing database dependencies');
|
|
21
|
+
await utils.runInProject(projectName, 'go get gorm.io/gorm');
|
|
22
|
+
|
|
23
|
+
if (database === 'postgresql') {
|
|
24
|
+
await utils.runInProject(projectName, 'go get gorm.io/driver/postgres');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (database === 'mysql') {
|
|
28
|
+
await utils.runInProject(projectName, 'go get gorm.io/driver/mysql');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (database === 'sqlite') {
|
|
32
|
+
await utils.runInProject(projectName, 'go get gorm.io/driver/sqlite');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ─── Step 5: Generate main.go ─────────────────────────
|
|
37
|
+
utils.step(5, 'Generating application files');
|
|
38
|
+
|
|
39
|
+
const mainGo = `package main
|
|
40
|
+
|
|
41
|
+
import (
|
|
42
|
+
"net/http"
|
|
43
|
+
|
|
44
|
+
"github.com/gin-gonic/gin"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
func main() {
|
|
48
|
+
r := gin.Default()
|
|
49
|
+
|
|
50
|
+
r.GET("/", func(c *gin.Context) {
|
|
51
|
+
c.JSON(http.StatusOK, gin.H{
|
|
52
|
+
"message": "Hello from ${projectName}",
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
r.GET("/health", func(c *gin.Context) {
|
|
57
|
+
c.JSON(http.StatusOK, gin.H{
|
|
58
|
+
"status": "ok",
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
r.Run(":8080")
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
await utils.createFile(`${projectName}/main.go`, mainGo);
|
|
67
|
+
|
|
68
|
+
// ─── Step 6: Generate database.go if needed ───────────
|
|
69
|
+
if (database !== 'none') {
|
|
70
|
+
const dsnMap = {
|
|
71
|
+
postgresql: `host=localhost user=postgres password=password dbname=${projectName} port=5432 sslmode=disable`,
|
|
72
|
+
mysql: `user:password@tcp(localhost:3306)/${projectName}?charset=utf8mb4&parseTime=True&loc=Local`,
|
|
73
|
+
sqlite: `${projectName}.db`,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const driverMap = {
|
|
77
|
+
postgresql: 'postgres',
|
|
78
|
+
mysql: 'mysql',
|
|
79
|
+
sqlite: 'sqlite',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const databaseGo = `package main
|
|
83
|
+
|
|
84
|
+
import (
|
|
85
|
+
"log"
|
|
86
|
+
|
|
87
|
+
"gorm.io/driver/${driverMap[database]}"
|
|
88
|
+
"gorm.io/gorm"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
var DB *gorm.DB
|
|
92
|
+
|
|
93
|
+
func initDB() {
|
|
94
|
+
dsn := "${dsnMap[database]}"
|
|
95
|
+
db, err := gorm.Open(${driverMap[database]}.Open(dsn), &gorm.Config{})
|
|
96
|
+
if err != nil {
|
|
97
|
+
log.Fatal("Failed to connect to database:", err)
|
|
98
|
+
}
|
|
99
|
+
DB = db
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
await utils.createFile(`${projectName}/database.go`, databaseGo);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ─── Step 7: Generate .gitignore ──────────────────────
|
|
106
|
+
const gitignore = `# Binaries
|
|
107
|
+
${projectName}
|
|
108
|
+
*.exe
|
|
109
|
+
*.exe~
|
|
110
|
+
*.dll
|
|
111
|
+
*.so
|
|
112
|
+
*.dylib
|
|
113
|
+
|
|
114
|
+
# Test binary
|
|
115
|
+
*.test
|
|
116
|
+
|
|
117
|
+
# Output of go coverage tool
|
|
118
|
+
*.out
|
|
119
|
+
|
|
120
|
+
# Environment
|
|
121
|
+
.env
|
|
122
|
+
|
|
123
|
+
# IDE
|
|
124
|
+
.vscode/
|
|
125
|
+
.idea/
|
|
126
|
+
`;
|
|
127
|
+
await utils.createFile(`${projectName}/.gitignore`, gitignore);
|
|
128
|
+
|
|
129
|
+
// ─── Step 8: Docker ───────────────────────────────────
|
|
130
|
+
if (docker) {
|
|
131
|
+
utils.step(6, 'Creating Docker config');
|
|
132
|
+
|
|
133
|
+
const dockerfile = `FROM golang:1.21-alpine AS builder
|
|
134
|
+
|
|
135
|
+
WORKDIR /app
|
|
136
|
+
|
|
137
|
+
COPY go.mod go.sum ./
|
|
138
|
+
RUN go mod download
|
|
139
|
+
|
|
140
|
+
COPY . .
|
|
141
|
+
RUN go build -o main .
|
|
142
|
+
|
|
143
|
+
FROM alpine:latest
|
|
144
|
+
|
|
145
|
+
WORKDIR /app
|
|
146
|
+
COPY --from=builder /app/main .
|
|
147
|
+
|
|
148
|
+
EXPOSE 8080
|
|
149
|
+
CMD ["./main"]
|
|
150
|
+
`;
|
|
151
|
+
|
|
152
|
+
const dockerCompose = `version: '3.8'
|
|
153
|
+
services:
|
|
154
|
+
web:
|
|
155
|
+
build: .
|
|
156
|
+
ports:
|
|
157
|
+
- "8080:8080"
|
|
158
|
+
depends_on:
|
|
159
|
+
- db
|
|
160
|
+
${
|
|
161
|
+
database === 'postgresql'
|
|
162
|
+
? ` db:
|
|
163
|
+
image: postgres:15
|
|
164
|
+
environment:
|
|
165
|
+
POSTGRES_PASSWORD: password
|
|
166
|
+
POSTGRES_DB: ${projectName}
|
|
167
|
+
ports:
|
|
168
|
+
- "5432:5432"`
|
|
169
|
+
: ''
|
|
170
|
+
}
|
|
171
|
+
${
|
|
172
|
+
database === 'mysql'
|
|
173
|
+
? ` db:
|
|
174
|
+
image: mysql:8.0
|
|
175
|
+
environment:
|
|
176
|
+
MYSQL_ROOT_PASSWORD: password
|
|
177
|
+
MYSQL_DATABASE: ${projectName}
|
|
178
|
+
ports:
|
|
179
|
+
- "3306:3306"`
|
|
180
|
+
: ''
|
|
181
|
+
}
|
|
182
|
+
`;
|
|
183
|
+
|
|
184
|
+
await utils.createFile(`${projectName}/Dockerfile`, dockerfile);
|
|
185
|
+
await utils.createFile(`${projectName}/docker-compose.yml`, dockerCompose);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ─── Step 9: go mod tidy ──────────────────────────────
|
|
189
|
+
utils.step(7, 'Tidying Go modules');
|
|
190
|
+
await utils.runInProject(projectName, 'go mod tidy');
|
|
191
|
+
|
|
192
|
+
utils.success(`Gin v1 project "${projectName}" created successfully!`);
|
|
193
|
+
utils.log(` cd ${projectName}`);
|
|
194
|
+
utils.log(` go run main.go`);
|
|
195
|
+
utils.log(` Server running at http://localhost:8080`);
|
|
196
|
+
};
|
package/registry/index.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ExpressJS",
|
|
3
|
+
"alias": ["express", "expressjs"],
|
|
4
|
+
"language": "javascript",
|
|
5
|
+
"latest": "v4",
|
|
6
|
+
"versions": ["v4"],
|
|
7
|
+
"description": "Fast, minimalist web framework for Node.js",
|
|
8
|
+
"requires": [
|
|
9
|
+
{
|
|
10
|
+
"tool": "node",
|
|
11
|
+
"checkCommand": "node --version",
|
|
12
|
+
"parseVersion": "v([0-9]+\\.[0-9]+\\.[0-9]+)",
|
|
13
|
+
"minVersion": "18.0.0",
|
|
14
|
+
"installGuide": {
|
|
15
|
+
"mac": "brew install node",
|
|
16
|
+
"linux": "sudo apt install nodejs",
|
|
17
|
+
"windows": "https://nodejs.org",
|
|
18
|
+
"docs": "https://nodejs.org"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"tool": "npm",
|
|
23
|
+
"checkCommand": "npm --version",
|
|
24
|
+
"parseVersion": "([0-9]+\\.[0-9]+\\.[0-9]+)",
|
|
25
|
+
"minVersion": "8.0.0",
|
|
26
|
+
"installGuide": {
|
|
27
|
+
"mac": "brew install node",
|
|
28
|
+
"linux": "sudo apt install npm",
|
|
29
|
+
"windows": "https://nodejs.org",
|
|
30
|
+
"docs": "https://docs.npmjs.com"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"packageManagerQuestion": {
|
|
35
|
+
"tool": "packageManager",
|
|
36
|
+
"message": "Package manager:",
|
|
37
|
+
"choices": [
|
|
38
|
+
{ "name": "npm", "value": "npm", "checkCommand": "npm --version" },
|
|
39
|
+
{ "name": "yarn", "value": "yarn", "checkCommand": "yarn --version" },
|
|
40
|
+
{ "name": "pnpm", "value": "pnpm", "checkCommand": "pnpm --version" }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"maintainer": "community"
|
|
44
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { detectAvailableChoices } from '../../../../core/detector.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const pluginMeta = require('../plugin.json');
|
|
6
|
+
|
|
7
|
+
export default async () => {
|
|
8
|
+
const availableManagers = await detectAvailableChoices(
|
|
9
|
+
pluginMeta.packageManagerQuestion.choices
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
type: 'list',
|
|
15
|
+
name: 'packageManager',
|
|
16
|
+
message: pluginMeta.packageManagerQuestion.message,
|
|
17
|
+
choices: availableManagers,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'confirm',
|
|
21
|
+
name: 'typescript',
|
|
22
|
+
message: 'Use TypeScript?',
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'list',
|
|
27
|
+
name: 'database',
|
|
28
|
+
message: 'Database?',
|
|
29
|
+
choices: [
|
|
30
|
+
{ name: 'None', value: 'none' },
|
|
31
|
+
{ name: 'MongoDB — Mongoose ODM', value: 'mongodb' },
|
|
32
|
+
{ name: 'PostgreSQL — pg driver', value: 'postgresql' },
|
|
33
|
+
{ name: 'MySQL — mysql2 driver', value: 'mysql' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'confirm',
|
|
38
|
+
name: 'docker',
|
|
39
|
+
message: 'Include Docker config?',
|
|
40
|
+
default: false,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const { projectName, packageManager, typescript, database, docker } = answers;
|
|
3
|
+
|
|
4
|
+
utils.title('Creating ExpressJS v4 Project');
|
|
5
|
+
|
|
6
|
+
// ─── Step 1: Create project folder ────────────────────
|
|
7
|
+
utils.step(1, 'Creating project structure');
|
|
8
|
+
await utils.run(`mkdir ${projectName}`);
|
|
9
|
+
|
|
10
|
+
// ─── Step 2: Init package.json ────────────────────────
|
|
11
|
+
utils.step(2, 'Initializing package.json');
|
|
12
|
+
await utils.runInProject(projectName, `${packageManager} init -y`);
|
|
13
|
+
|
|
14
|
+
// ─── Step 3: Install Express ──────────────────────────
|
|
15
|
+
utils.step(3, 'Installing Express');
|
|
16
|
+
await utils.runInProject(
|
|
17
|
+
projectName,
|
|
18
|
+
`${packageManager} ${packageManager === 'yarn' ? 'add' : 'install'} express`
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// ─── Step 4: TypeScript ───────────────────────────────
|
|
22
|
+
if (typescript) {
|
|
23
|
+
utils.step(4, 'Installing TypeScript');
|
|
24
|
+
const installCmd =
|
|
25
|
+
packageManager === 'yarn'
|
|
26
|
+
? 'add -D'
|
|
27
|
+
: packageManager === 'pnpm'
|
|
28
|
+
? 'add -D'
|
|
29
|
+
: 'install -D';
|
|
30
|
+
await utils.runInProject(
|
|
31
|
+
projectName,
|
|
32
|
+
`${packageManager} ${installCmd} typescript @types/express @types/node ts-node`
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const tsConfig = `{
|
|
36
|
+
"compilerOptions": {
|
|
37
|
+
"target": "ES2020",
|
|
38
|
+
"module": "commonjs",
|
|
39
|
+
"lib": ["ES2020"],
|
|
40
|
+
"outDir": "./dist",
|
|
41
|
+
"rootDir": "./src",
|
|
42
|
+
"strict": true,
|
|
43
|
+
"esModuleInterop": true,
|
|
44
|
+
"skipLibCheck": true,
|
|
45
|
+
"forceConsistentCasingInFileNames": true,
|
|
46
|
+
"resolveJsonModule": true
|
|
47
|
+
},
|
|
48
|
+
"include": ["src/**/*"],
|
|
49
|
+
"exclude": ["node_modules", "dist"]
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
await utils.createFile(`${projectName}/tsconfig.json`, tsConfig);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ─── Step 5: Database ─────────────────────────────────
|
|
56
|
+
if (database !== 'none') {
|
|
57
|
+
utils.step(5, 'Installing database dependencies');
|
|
58
|
+
|
|
59
|
+
const installCmd = packageManager === 'yarn' ? 'add' : 'install';
|
|
60
|
+
|
|
61
|
+
if (database === 'mongodb') {
|
|
62
|
+
await utils.runInProject(
|
|
63
|
+
projectName,
|
|
64
|
+
`${packageManager} ${installCmd} mongoose`
|
|
65
|
+
);
|
|
66
|
+
if (typescript) {
|
|
67
|
+
await utils.runInProject(
|
|
68
|
+
projectName,
|
|
69
|
+
`${packageManager} ${installCmd === 'add' ? 'add -D' : 'install -D'} @types/mongoose`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (database === 'postgresql') {
|
|
75
|
+
await utils.runInProject(
|
|
76
|
+
projectName,
|
|
77
|
+
`${packageManager} ${installCmd} pg`
|
|
78
|
+
);
|
|
79
|
+
if (typescript) {
|
|
80
|
+
await utils.runInProject(
|
|
81
|
+
projectName,
|
|
82
|
+
`${packageManager} ${installCmd === 'add' ? 'add -D' : 'install -D'} @types/pg`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (database === 'mysql') {
|
|
88
|
+
await utils.runInProject(
|
|
89
|
+
projectName,
|
|
90
|
+
`${packageManager} ${installCmd} mysql2`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ─── Step 6: Generate entry point ─────────────────────
|
|
96
|
+
utils.step(6, 'Generating application files');
|
|
97
|
+
|
|
98
|
+
const srcDir = typescript ? `${projectName}/src` : projectName;
|
|
99
|
+
const entryFile = typescript ? 'index.ts' : 'index.js';
|
|
100
|
+
|
|
101
|
+
if (typescript) {
|
|
102
|
+
await utils.run(`mkdir ${projectName}/src`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const indexContent = typescript
|
|
106
|
+
? `import express, { Request, Response } from 'express'
|
|
107
|
+
|
|
108
|
+
const app = express()
|
|
109
|
+
const PORT = process.env.PORT || 3000
|
|
110
|
+
|
|
111
|
+
app.use(express.json())
|
|
112
|
+
app.use(express.urlencoded({ extended: true }))
|
|
113
|
+
|
|
114
|
+
app.get('/', (req: Request, res: Response) => {
|
|
115
|
+
res.json({ message: 'Hello from ${projectName}' })
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
app.get('/health', (req: Request, res: Response) => {
|
|
119
|
+
res.json({ status: 'ok' })
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
app.listen(PORT, () => {
|
|
123
|
+
console.log(\`Server running on http://localhost:\${PORT}\`)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
export default app
|
|
127
|
+
`
|
|
128
|
+
: `import express from 'express'
|
|
129
|
+
|
|
130
|
+
const app = express()
|
|
131
|
+
const PORT = process.env.PORT || 3000
|
|
132
|
+
|
|
133
|
+
app.use(express.json())
|
|
134
|
+
app.use(express.urlencoded({ extended: true }))
|
|
135
|
+
|
|
136
|
+
app.get('/', (req, res) => {
|
|
137
|
+
res.json({ message: 'Hello from ${projectName}' })
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
app.get('/health', (req, res) => {
|
|
141
|
+
res.json({ status: 'ok' })
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
app.listen(PORT, () => {
|
|
145
|
+
console.log(\`Server running on http://localhost:\${PORT}\`)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
export default app
|
|
149
|
+
`;
|
|
150
|
+
|
|
151
|
+
await utils.createFile(`${srcDir}/${entryFile}`, indexContent);
|
|
152
|
+
|
|
153
|
+
// ─── Step 7: .env ─────────────────────────────────────
|
|
154
|
+
const envContent = `PORT=3000
|
|
155
|
+
NODE_ENV=development
|
|
156
|
+
${database === 'mongodb' ? `MONGODB_URI=mongodb://localhost:27017/${projectName}` : ''}
|
|
157
|
+
${database === 'postgresql' ? `DATABASE_URL=postgresql://user:password@localhost:5432/${projectName}` : ''}
|
|
158
|
+
${database === 'mysql' ? `DATABASE_URL=mysql://user:password@localhost:3306/${projectName}` : ''}
|
|
159
|
+
`;
|
|
160
|
+
await utils.createFile(`${projectName}/.env`, envContent);
|
|
161
|
+
await utils.createFile(`${projectName}/.env.example`, envContent);
|
|
162
|
+
|
|
163
|
+
// ─── Step 8: .gitignore ───────────────────────────────
|
|
164
|
+
const gitignore = `node_modules/
|
|
165
|
+
dist/
|
|
166
|
+
.env
|
|
167
|
+
*.log
|
|
168
|
+
`;
|
|
169
|
+
await utils.createFile(`${projectName}/.gitignore`, gitignore);
|
|
170
|
+
|
|
171
|
+
// ─── Step 9: Docker ───────────────────────────────────
|
|
172
|
+
if (docker) {
|
|
173
|
+
utils.step(7, 'Creating Docker config');
|
|
174
|
+
|
|
175
|
+
const dockerfile = `FROM node:18-alpine
|
|
176
|
+
|
|
177
|
+
WORKDIR /app
|
|
178
|
+
|
|
179
|
+
COPY package*.json ./
|
|
180
|
+
RUN ${packageManager} install
|
|
181
|
+
|
|
182
|
+
COPY . .
|
|
183
|
+
${typescript ? 'RUN npm run build\n' : ''}
|
|
184
|
+
EXPOSE 3000
|
|
185
|
+
CMD [${typescript ? '"node", "dist/index.js"' : '"node", "index.js"'}]
|
|
186
|
+
`;
|
|
187
|
+
|
|
188
|
+
const dockerCompose = `version: '3.8'
|
|
189
|
+
services:
|
|
190
|
+
web:
|
|
191
|
+
build: .
|
|
192
|
+
ports:
|
|
193
|
+
- "3000:3000"
|
|
194
|
+
env_file:
|
|
195
|
+
- .env
|
|
196
|
+
${
|
|
197
|
+
database === 'mongodb'
|
|
198
|
+
? ` mongo:
|
|
199
|
+
image: mongo:7
|
|
200
|
+
ports:
|
|
201
|
+
- "27017:27017"`
|
|
202
|
+
: ''
|
|
203
|
+
}
|
|
204
|
+
${
|
|
205
|
+
database === 'postgresql'
|
|
206
|
+
? ` db:
|
|
207
|
+
image: postgres:15
|
|
208
|
+
environment:
|
|
209
|
+
POSTGRES_PASSWORD: password
|
|
210
|
+
POSTGRES_DB: ${projectName}
|
|
211
|
+
ports:
|
|
212
|
+
- "5432:5432"`
|
|
213
|
+
: ''
|
|
214
|
+
}
|
|
215
|
+
${
|
|
216
|
+
database === 'mysql'
|
|
217
|
+
? ` db:
|
|
218
|
+
image: mysql:8.0
|
|
219
|
+
environment:
|
|
220
|
+
MYSQL_ROOT_PASSWORD: password
|
|
221
|
+
MYSQL_DATABASE: ${projectName}
|
|
222
|
+
ports:
|
|
223
|
+
- "3306:3306"`
|
|
224
|
+
: ''
|
|
225
|
+
}
|
|
226
|
+
`;
|
|
227
|
+
|
|
228
|
+
await utils.createFile(`${projectName}/Dockerfile`, dockerfile);
|
|
229
|
+
await utils.createFile(`${projectName}/docker-compose.yml`, dockerCompose);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
utils.success(`ExpressJS v4 project "${projectName}" created successfully!`);
|
|
233
|
+
utils.log(` cd ${projectName}`);
|
|
234
|
+
utils.log(` ${typescript ? 'npx ts-node src/index.ts' : 'node index.js'}`);
|
|
235
|
+
utils.log(` Server running at http://localhost:3000`);
|
|
236
|
+
};
|