scaffy-tool 0.2.0 → 1.0.1
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 +21 -26
- package/cli.js +18 -41
- package/core/detector.js +5 -31
- package/core/executor.js +5 -27
- package/core/interviewer.js +15 -19
- package/core/plugin-validator.js +1 -1
- package/core/registry.js +47 -28
- 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 +4 -4
- 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 +6 -4
- 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 +5 -3
- package/registry/javascript/vuejs/v3/scaffold.js +3 -10
- package/registry/php/laravel/plugin.json +2 -2
- package/registry/php/laravel/v11/questions.js +3 -3
- 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 +19 -0
- package/registry/php/symfony/v7/scaffold.js +74 -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
|
@@ -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
|
+
};
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"name": "NestJS",
|
|
3
3
|
"alias": ["nestjs", "nest"],
|
|
4
4
|
"language": "javascript",
|
|
5
|
-
"latest": "
|
|
6
|
-
"versions": ["v10"],
|
|
5
|
+
"latest": "v11",
|
|
6
|
+
"versions": ["v11", "v10"],
|
|
7
7
|
"description": "A progressive Node.js framework for building efficient and scalable server-side applications",
|
|
8
8
|
"requires": [
|
|
9
9
|
{
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { detectAvailableChoices } from '../../../../core/detector.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
2
4
|
const pluginMeta = require('../plugin.json');
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
export default async () => {
|
|
5
7
|
const availableManagers = await detectAvailableChoices(
|
|
6
8
|
pluginMeta.packageManagerQuestion.choices
|
|
7
9
|
);
|
|
@@ -21,7 +23,7 @@ module.exports = async () => {
|
|
|
21
23
|
},
|
|
22
24
|
},
|
|
23
25
|
{
|
|
24
|
-
type: '
|
|
26
|
+
type: 'select',
|
|
25
27
|
name: 'packageManager',
|
|
26
28
|
message: pluginMeta.packageManagerQuestion.message,
|
|
27
29
|
choices: availableManagers.map(m => ({
|
|
@@ -31,7 +33,7 @@ module.exports = async () => {
|
|
|
31
33
|
default: availableManagers[0].value,
|
|
32
34
|
},
|
|
33
35
|
{
|
|
34
|
-
type: '
|
|
36
|
+
type: 'select',
|
|
35
37
|
name: 'database',
|
|
36
38
|
message: 'Database:',
|
|
37
39
|
choices: [
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { detectAvailableChoices } from '../../../../core/detector.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const pluginMeta = require('../plugin.json');
|
|
5
|
+
|
|
6
|
+
export default async () => {
|
|
7
|
+
const availableManagers = await detectAvailableChoices(
|
|
8
|
+
pluginMeta.packageManagerQuestion.choices
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
type: 'input',
|
|
14
|
+
name: 'projectName',
|
|
15
|
+
message: 'Project name:',
|
|
16
|
+
default: 'my-nest-app',
|
|
17
|
+
validate: input => {
|
|
18
|
+
if (!input.trim()) return 'Project name is required';
|
|
19
|
+
if (!/^[a-z0-9-_]+$/.test(input)) {
|
|
20
|
+
return 'Only lowercase letters, numbers, hyphens and underscores';
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'select',
|
|
27
|
+
name: 'packageManager',
|
|
28
|
+
message: pluginMeta.packageManagerQuestion.message,
|
|
29
|
+
choices: availableManagers.map(m => ({
|
|
30
|
+
name: m.name,
|
|
31
|
+
value: m.value,
|
|
32
|
+
})),
|
|
33
|
+
default: availableManagers[0].value,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: 'select',
|
|
37
|
+
name: 'database',
|
|
38
|
+
message: 'Database:',
|
|
39
|
+
choices: [
|
|
40
|
+
{ name: 'None', value: 'none' },
|
|
41
|
+
{ name: 'PostgreSQL (TypeORM)', value: 'postgres' },
|
|
42
|
+
{ name: 'MySQL (TypeORM)', value: 'mysql' },
|
|
43
|
+
{ name: 'MongoDB (Mongoose)', value: 'mongodb' },
|
|
44
|
+
{ name: 'SQLite (TypeORM)', value: 'sqlite' },
|
|
45
|
+
],
|
|
46
|
+
default: 'none',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'confirm',
|
|
50
|
+
name: 'auth',
|
|
51
|
+
message: 'Add JWT authentication (Passport)?',
|
|
52
|
+
default: false,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'confirm',
|
|
56
|
+
name: 'docker',
|
|
57
|
+
message: 'Add Dockerfile?',
|
|
58
|
+
default: false,
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const { projectName, packageManager, database, auth, docker } = answers;
|
|
3
|
+
|
|
4
|
+
// ─── Step 1 — Install NestJS CLI + Create Project ──
|
|
5
|
+
utils.title('Creating NestJS v11 Project');
|
|
6
|
+
utils.step(1, `Scaffolding ${projectName}...`);
|
|
7
|
+
|
|
8
|
+
await utils.run(
|
|
9
|
+
`npx @nestjs/cli@11 new ${projectName} --package-manager ${packageManager} --skip-git`
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
// ─── Step 2 — Database ────────────────────────────
|
|
13
|
+
if (database !== 'none') {
|
|
14
|
+
utils.step(2, `Installing ${database} database packages...`);
|
|
15
|
+
|
|
16
|
+
if (database === 'mongodb') {
|
|
17
|
+
await utils.runInProject(
|
|
18
|
+
projectName,
|
|
19
|
+
`${packageManager} ${packageManager === 'yarn' ? 'add' : 'install'} @nestjs/mongoose mongoose`
|
|
20
|
+
);
|
|
21
|
+
} else {
|
|
22
|
+
// TypeORM based (postgres, mysql, sqlite)
|
|
23
|
+
const dbDriver = {
|
|
24
|
+
postgres: 'pg',
|
|
25
|
+
mysql: 'mysql2',
|
|
26
|
+
sqlite: 'sqlite3',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
await utils.runInProject(
|
|
30
|
+
projectName,
|
|
31
|
+
`${packageManager} ${packageManager === 'yarn' ? 'add' : 'install'} @nestjs/typeorm typeorm ${dbDriver[database]}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ─── Step 3 — Auth ────────────────────────────────
|
|
37
|
+
if (auth) {
|
|
38
|
+
utils.step(3, 'Installing Passport JWT authentication...');
|
|
39
|
+
await utils.runInProject(
|
|
40
|
+
projectName,
|
|
41
|
+
`${packageManager} ${packageManager === 'yarn' ? 'add' : 'install'} @nestjs/passport passport passport-jwt @nestjs/jwt`
|
|
42
|
+
);
|
|
43
|
+
await utils.runInProject(
|
|
44
|
+
projectName,
|
|
45
|
+
`${packageManager} ${packageManager === 'yarn' ? 'add' : 'install'} -D @types/passport-jwt`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ─── Step 4 — Docker ──────────────────────────────
|
|
50
|
+
if (docker) {
|
|
51
|
+
utils.step(4, 'Adding Dockerfile...');
|
|
52
|
+
|
|
53
|
+
await utils.createFile(
|
|
54
|
+
`${projectName}/Dockerfile`,
|
|
55
|
+
`FROM node:20-alpine AS builder
|
|
56
|
+
WORKDIR /app
|
|
57
|
+
COPY package*.json ./
|
|
58
|
+
RUN npm ci
|
|
59
|
+
COPY . .
|
|
60
|
+
RUN npm run build
|
|
61
|
+
|
|
62
|
+
FROM node:20-alpine AS production
|
|
63
|
+
WORKDIR /app
|
|
64
|
+
COPY package*.json ./
|
|
65
|
+
RUN npm ci --only=production
|
|
66
|
+
COPY --from=builder /app/dist ./dist
|
|
67
|
+
EXPOSE 3000
|
|
68
|
+
CMD ["node", "dist/main"]
|
|
69
|
+
`
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
await utils.createFile(
|
|
73
|
+
`${projectName}/.dockerignore`,
|
|
74
|
+
`node_modules
|
|
75
|
+
dist
|
|
76
|
+
.git
|
|
77
|
+
.env
|
|
78
|
+
`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ─── Done ─────────────────────────────────────────
|
|
83
|
+
utils.success(`✅ NestJS v11 project ready!`);
|
|
84
|
+
utils.log(` cd ${projectName}`);
|
|
85
|
+
|
|
86
|
+
if (docker) {
|
|
87
|
+
utils.log(` docker build -t ${projectName} .`);
|
|
88
|
+
utils.log(` docker run -p 3000:3000 ${projectName}`);
|
|
89
|
+
} else {
|
|
90
|
+
utils.log(` ${packageManager} run start:dev`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
utils.log('');
|
|
94
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "NextJS",
|
|
3
|
+
"alias": ["next", "nextjs"],
|
|
4
|
+
"language": "javascript",
|
|
5
|
+
"latest": "v14",
|
|
6
|
+
"versions": ["v14"],
|
|
7
|
+
"description": "The React framework for production — SSR, SSG, and App Router",
|
|
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,44 @@
|
|
|
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: 'select',
|
|
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: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'confirm',
|
|
27
|
+
name: 'tailwind',
|
|
28
|
+
message: 'Use Tailwind CSS?',
|
|
29
|
+
default: true,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: 'confirm',
|
|
33
|
+
name: 'appRouter',
|
|
34
|
+
message: 'Use App Router? (recommended)',
|
|
35
|
+
default: true,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'confirm',
|
|
39
|
+
name: 'srcDir',
|
|
40
|
+
message: 'Use src/ directory?',
|
|
41
|
+
default: false,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const {
|
|
3
|
+
projectName,
|
|
4
|
+
packageManager,
|
|
5
|
+
typescript,
|
|
6
|
+
tailwind,
|
|
7
|
+
appRouter,
|
|
8
|
+
srcDir,
|
|
9
|
+
} = answers;
|
|
10
|
+
|
|
11
|
+
utils.title('Creating NextJS v14 Project');
|
|
12
|
+
|
|
13
|
+
// ─── Step 1: Build flags ───────────────────────────────
|
|
14
|
+
utils.step(1, 'Configuring create-next-app flags');
|
|
15
|
+
|
|
16
|
+
const flags = [
|
|
17
|
+
typescript ? '--typescript' : '--no-typescript',
|
|
18
|
+
tailwind ? '--tailwind' : '--no-tailwind',
|
|
19
|
+
appRouter ? '--app' : '--no-app',
|
|
20
|
+
srcDir ? '--src-dir' : '--no-src-dir',
|
|
21
|
+
`--use-${packageManager}`,
|
|
22
|
+
'--no-eslint',
|
|
23
|
+
'--skip-install',
|
|
24
|
+
].join(' ');
|
|
25
|
+
|
|
26
|
+
// ─── Step 2: Run create-next-app ──────────────────────
|
|
27
|
+
utils.step(2, 'Running create-next-app@14');
|
|
28
|
+
await utils.run(`npx create-next-app@14 ${projectName} ${flags}`);
|
|
29
|
+
|
|
30
|
+
// ─── Step 3: Install dependencies ─────────────────────
|
|
31
|
+
utils.step(3, 'Installing dependencies');
|
|
32
|
+
const installCmd = packageManager === 'yarn' ? 'install' : 'install';
|
|
33
|
+
await utils.runInProject(projectName, `${packageManager} ${installCmd}`);
|
|
34
|
+
|
|
35
|
+
// ─── Step 4: .env.local ───────────────────────────────
|
|
36
|
+
utils.step(4, 'Generating environment files');
|
|
37
|
+
|
|
38
|
+
const envLocal = `# Environment Variables
|
|
39
|
+
# Add your environment variables here
|
|
40
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
41
|
+
`;
|
|
42
|
+
await utils.createFile(`${projectName}/.env.local`, envLocal);
|
|
43
|
+
await utils.createFile(`${projectName}/.env.example`, envLocal);
|
|
44
|
+
|
|
45
|
+
// ─── Step 5: .gitignore addition ──────────────────────
|
|
46
|
+
await utils.appendToFile(
|
|
47
|
+
`${projectName}/.gitignore`,
|
|
48
|
+
'\n# Environment\n.env.local\n.env*.local\n'
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
utils.success(`NextJS v14 project "${projectName}" created successfully!`);
|
|
52
|
+
utils.log(` cd ${projectName}`);
|
|
53
|
+
utils.log(
|
|
54
|
+
` ${packageManager} ${packageManager === 'yarn' ? 'dev' : 'run dev'}`
|
|
55
|
+
);
|
|
56
|
+
utils.log(` App running at http://localhost:3000`);
|
|
57
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { detectAvailableChoices } from '../../../../core/detector.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
2
4
|
const pluginMeta = require('../plugin.json');
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
export default async () => {
|
|
5
7
|
const availableManagers = await detectAvailableChoices(
|
|
6
8
|
pluginMeta.packageManagerQuestion.choices
|
|
7
9
|
);
|
|
@@ -21,7 +23,7 @@ module.exports = async () => {
|
|
|
21
23
|
},
|
|
22
24
|
},
|
|
23
25
|
{
|
|
24
|
-
type: '
|
|
26
|
+
type: 'select',
|
|
25
27
|
name: 'packageManager',
|
|
26
28
|
message: pluginMeta.packageManagerQuestion.message,
|
|
27
29
|
choices: availableManagers.map(m => ({
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
packageManager,
|
|
5
|
-
router,
|
|
6
|
-
pinia,
|
|
7
|
-
vitest,
|
|
8
|
-
typescript,
|
|
9
|
-
eslint,
|
|
10
|
-
} = answers;
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const { projectName, packageManager, router, pinia, typescript, eslint } =
|
|
3
|
+
answers;
|
|
11
4
|
|
|
12
5
|
// ─── Step 1 — Build create-vue flags ──────────────
|
|
13
6
|
utils.title('Creating VueJS v3 Project');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export default [
|
|
2
2
|
{
|
|
3
3
|
type: 'input',
|
|
4
4
|
name: 'projectName',
|
|
@@ -13,7 +13,7 @@ module.exports = [
|
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
|
-
type: '
|
|
16
|
+
type: 'select',
|
|
17
17
|
name: 'starterKit',
|
|
18
18
|
message: 'Starter kit:',
|
|
19
19
|
choices: [
|
|
@@ -24,7 +24,7 @@ module.exports = [
|
|
|
24
24
|
default: 'none',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
type: '
|
|
27
|
+
type: 'select',
|
|
28
28
|
name: 'database',
|
|
29
29
|
message: 'Database:',
|
|
30
30
|
choices: [
|