@appxdigital/appx-core-cli 1.0.11 → 1.0.13
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/cli.js +578 -0
- package/package.json +5 -4
- package/scaffold/.env.template +33 -0
- package/scaffold/.eslintrc.js +26 -0
- package/scaffold/.gitattributes +2 -0
- package/scaffold/.prettierrc +9 -0
- package/scaffold/prisma/schema.prisma.template +47 -0
- package/scaffold/src/app.controller.ts +13 -0
- package/{templates/app.module.template.js → scaffold/src/app.module.ts} +8 -4
- package/scaffold/src/app.service.ts +8 -0
- package/{templates/adminjs/dashboard.template.js → scaffold/src/backoffice/components/dashboard.js} +0 -2
- package/{templates/permissions.config.template.js → scaffold/src/config/permissions.config.ts} +1 -4
- package/{templates/bootstrap.template.js → scaffold/src/main.ts} +9 -10
- package/{templates/prisma.module.template.js → scaffold/src/prisma/prisma.module.ts} +3 -3
- package/utils/fileUploadConfig.js +11 -11
- package/README.md +0 -159
- package/utils/dependency-versions.json +0 -28
- package/wizard.js +0 -599
- /package/{templates/admin.config.template.js → scaffold/src/config/admin.config.ts} +0 -0
package/wizard.js
DELETED
|
@@ -1,599 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { program } from 'commander';
|
|
4
|
-
import inquirer from 'inquirer';
|
|
5
|
-
import fs from 'fs-extra';
|
|
6
|
-
import fsCore from 'fs';
|
|
7
|
-
import { execSync } from 'child_process';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import { fileURLToPath } from 'url';
|
|
10
|
-
import cliProgress from 'cli-progress';
|
|
11
|
-
import { gatherFileUploadSettings, insertFileUploadConfiguration } from './utils/fileUploadConfig.js';
|
|
12
|
-
import packageJson from './package.json' assert { type: 'json' };
|
|
13
|
-
import crypto from 'crypto';
|
|
14
|
-
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = path.dirname(__filename);
|
|
17
|
-
|
|
18
|
-
const dependencyVersions = JSON.parse(
|
|
19
|
-
fsCore.readFileSync(path.join(__dirname, 'utils', 'dependency-versions.json'), 'utf-8')
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
const phaseDurations = {
|
|
23
|
-
nestjs: 20,
|
|
24
|
-
appmodule: 5,
|
|
25
|
-
installDependencies: 80,
|
|
26
|
-
installCore: 120,
|
|
27
|
-
prismaSetup: 10,
|
|
28
|
-
setupConcluded: 5,
|
|
29
|
-
end: 5
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const calculateTotalETA = (includeBackoffice) => {
|
|
33
|
-
let totalTime = phaseDurations.nestjs +
|
|
34
|
-
phaseDurations.appmodule +
|
|
35
|
-
phaseDurations.installDependencies +
|
|
36
|
-
phaseDurations.installCore +
|
|
37
|
-
phaseDurations.prismaSetup +
|
|
38
|
-
phaseDurations.setupConcluded
|
|
39
|
-
+ phaseDurations.end;
|
|
40
|
-
return totalTime;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const logo = `\x1b[36m
|
|
44
|
-
_ _______ _______ ____ ____
|
|
45
|
-
/ \\ |_ __ \\|_ __ \\|_ _||_ _|
|
|
46
|
-
/ _ \\ | |__) | | |__) | \\ \\ / /
|
|
47
|
-
/ ___ \\ | ___/ | ___/ > \`' <
|
|
48
|
-
_/ / \\ \\_ _| |_ _| |_ _/ /'\\ \\_
|
|
49
|
-
|____| |____||_____| |_____| |____||____|
|
|
50
|
-
\x1b[0m
|
|
51
|
-
CLI Version: ${packageJson.version}
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
console.log(logo);
|
|
55
|
-
program.version(packageJson.version).description('NestJS Project Initialization Wizard');
|
|
56
|
-
let progressBar;
|
|
57
|
-
let remainingETA = 0;
|
|
58
|
-
program
|
|
59
|
-
.command('create')
|
|
60
|
-
.description('Create a new NestJS project')
|
|
61
|
-
.action(() => {
|
|
62
|
-
console.log('Starting AppX Core...');
|
|
63
|
-
promptUser();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
program.command('generate')
|
|
67
|
-
.description('Updates Prisma client and generates the GraphQL schema')
|
|
68
|
-
.action(() => {
|
|
69
|
-
// run file inside node_modules/appx-core/dist/config/generate-all.js
|
|
70
|
-
const generatePath = path.join(process.cwd(), 'node_modules', '@appxdigital/appx-core', 'dist', 'config', 'generate-all.js');
|
|
71
|
-
if (!fsCore.existsSync(generatePath)) {
|
|
72
|
-
console.error('❌ Not inside a valid AppX Core project directory. Please run this command inside your project directory.');
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
// Execute the script
|
|
76
|
-
try {
|
|
77
|
-
execSync(`node ${generatePath}`, { stdio: 'inherit' });
|
|
78
|
-
console.log('✅ Prisma client and GraphQL schema generated successfully.');
|
|
79
|
-
} catch (error) {
|
|
80
|
-
console.error('❌ An error occurred while generating Prisma client and GraphQL schema:', error.message);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
program.command('setup:fileupload')
|
|
86
|
-
.description('Add file upload configuration to the project')
|
|
87
|
-
.action(() => {
|
|
88
|
-
// run file inside node_modules/appx-core/dist/config/setup-fileupload.js
|
|
89
|
-
const generatePath = path.join(process.cwd(), 'node_modules', '@appxdigital/appx-core', 'dist', 'config', 'setup-fileupload.js');
|
|
90
|
-
if (!fsCore.existsSync(generatePath)) {
|
|
91
|
-
console.error('❌ Not inside a valid AppX Core project directory. Please run this command inside your project directory.');
|
|
92
|
-
process.exit(1);
|
|
93
|
-
}
|
|
94
|
-
// Execute the script
|
|
95
|
-
try {
|
|
96
|
-
execSync(`node ${generatePath}`, { stdio: 'inherit' });
|
|
97
|
-
console.log('✅ File upload configuration added successfully.');
|
|
98
|
-
} catch (error) {
|
|
99
|
-
console.error('❌ An error occurred while adding file upload configuration:', error.message);
|
|
100
|
-
process.exit(1);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
async function promptUser() {
|
|
105
|
-
let fileUploadConfigData = {};
|
|
106
|
-
try {
|
|
107
|
-
const answers = await inquirer.prompt([
|
|
108
|
-
{
|
|
109
|
-
type: 'input',
|
|
110
|
-
name: 'projectName',
|
|
111
|
-
message: 'Project name:',
|
|
112
|
-
default: 'nestjs-project'
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
type: 'list',
|
|
116
|
-
name: 'dbProvider',
|
|
117
|
-
message: 'Database provider:',
|
|
118
|
-
choices: ['mysql', 'postgresql'],
|
|
119
|
-
default: 'mysql'
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
type: 'input',
|
|
123
|
-
name: 'dbHost',
|
|
124
|
-
message: 'Database Host:',
|
|
125
|
-
default: '127.0.0.1'
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
type: 'input',
|
|
129
|
-
name: 'dbPort',
|
|
130
|
-
message: 'Database Port:',
|
|
131
|
-
default: (answers) => answers.dbProvider === 'mysql' ? '3306' : '5432'
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
type: 'input',
|
|
135
|
-
name: 'dbUser',
|
|
136
|
-
message: 'Database User:',
|
|
137
|
-
default: 'root'
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
type: 'password',
|
|
141
|
-
name: 'dbPassword',
|
|
142
|
-
message: 'Database Password:',
|
|
143
|
-
mask: '*'
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
type: 'input',
|
|
147
|
-
name: 'dbName',
|
|
148
|
-
message: 'Database Name:',
|
|
149
|
-
default: 'generic'
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
type: 'confirm',
|
|
153
|
-
name: 'showOutput',
|
|
154
|
-
message: 'Show installation output?',
|
|
155
|
-
default: false
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
type: 'confirm',
|
|
159
|
-
name: 'configureFileUpload',
|
|
160
|
-
message: 'Configure file upload?',
|
|
161
|
-
default: false
|
|
162
|
-
}
|
|
163
|
-
]);
|
|
164
|
-
|
|
165
|
-
if (answers.configureFileUpload) {
|
|
166
|
-
fileUploadConfigData = await gatherFileUploadSettings();
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
remainingETA = calculateTotalETA(answers.backoffice);
|
|
170
|
-
createProject(answers, fileUploadConfigData);
|
|
171
|
-
} catch (error) {
|
|
172
|
-
console.error('Error prompting user:', error);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async function createProject(answers, fileUploadConfigData) {
|
|
177
|
-
const { projectName, dbProvider, dbHost, dbPort, dbUser, dbPassword, dbName, showOutput, backoffice, configureFileUpload } = answers;
|
|
178
|
-
console.log(`Creating project: ${projectName}`);
|
|
179
|
-
const projectPath = `${process.cwd()}/${projectName}`;
|
|
180
|
-
if (!showOutput) {
|
|
181
|
-
const phases = backoffice ? 8 : 7;
|
|
182
|
-
progressBar = new cliProgress.SingleBar(
|
|
183
|
-
{
|
|
184
|
-
format: `\x1b[36m{bar}\x1b[0m {percentage}% | ETA: {remainingETA}s | {value}/{total}`,
|
|
185
|
-
barCompleteChar: '\u2588',
|
|
186
|
-
barIncompleteChar: '\u2591'
|
|
187
|
-
},
|
|
188
|
-
cliProgress.Presets.shades_classic
|
|
189
|
-
);
|
|
190
|
-
progressBar.update(0, { remainingETA });
|
|
191
|
-
progressBar.start(phases, 0);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
fs.ensureDirSync(projectPath);
|
|
196
|
-
fs.emptyDirSync(projectPath);
|
|
197
|
-
process.chdir(projectPath);
|
|
198
|
-
|
|
199
|
-
setupProjectStructure(projectPath, answers);
|
|
200
|
-
incrementProgress(answers?.showOutput, "setupConcluded");
|
|
201
|
-
const envContent = `
|
|
202
|
-
##DataBase Configurations##
|
|
203
|
-
DB_HOST=${dbHost}
|
|
204
|
-
DB_PORT=${dbPort}
|
|
205
|
-
DB_USER=${dbUser}
|
|
206
|
-
DB_PASSWORD=${dbPassword}
|
|
207
|
-
DB_NAME=${dbName}
|
|
208
|
-
DB_PROVIDER=${dbProvider}
|
|
209
|
-
DB_URL="\${DB_PROVIDER}://\${DB_USER}:\${DB_PASSWORD}@\${DB_HOST}:\${DB_PORT}/\${DB_NAME}"
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
##Project configurations##
|
|
213
|
-
|
|
214
|
-
#Port
|
|
215
|
-
APP_PORT=3000
|
|
216
|
-
|
|
217
|
-
#Default behaviour for use of transactions
|
|
218
|
-
USE_TRANSACTION=true
|
|
219
|
-
|
|
220
|
-
#Session secret
|
|
221
|
-
SESSION_SECRET="${crypto.randomBytes(32).toString('hex')}"
|
|
222
|
-
|
|
223
|
-
#Cookie name for the session token
|
|
224
|
-
SESSION_COOKIE_NAME="APPXCORE"
|
|
225
|
-
|
|
226
|
-
#Expiration time for the session token in seconds
|
|
227
|
-
SESSION_TTL=86400
|
|
228
|
-
|
|
229
|
-
# JWT
|
|
230
|
-
JWT_SECRET="${crypto.randomBytes(32).toString('hex')}"
|
|
231
|
-
JWT_REFRESH_SECRET="${crypto.randomBytes(32).toString('hex')}"
|
|
232
|
-
`;
|
|
233
|
-
|
|
234
|
-
fs.writeFileSync(`${projectPath}/.env`, envContent);
|
|
235
|
-
if (fileUploadConfigData.provider) {
|
|
236
|
-
await insertFileUploadConfiguration(fileUploadConfigData, projectPath);
|
|
237
|
-
incrementProgress(showOutput, "fileUploadSetup");
|
|
238
|
-
}
|
|
239
|
-
updateGitignore(projectPath);
|
|
240
|
-
configureProjectSettings(projectPath);
|
|
241
|
-
executeCommand('npx prettier --write .', answers?.showOutput);
|
|
242
|
-
initializeGitRepo(projectPath);
|
|
243
|
-
incrementProgress(answers?.showOutput, "end");
|
|
244
|
-
if (!showOutput) {
|
|
245
|
-
progressBar.stop();
|
|
246
|
-
}
|
|
247
|
-
console.log('Project created successfully!');
|
|
248
|
-
} catch (error) {
|
|
249
|
-
console.error('❌ An error occurred during project creation:', error.message);
|
|
250
|
-
if (fs.existsSync(projectPath)) {
|
|
251
|
-
console.log('🧹 Cleaning up incomplete project files...');
|
|
252
|
-
fs.removeSync(projectPath);
|
|
253
|
-
}
|
|
254
|
-
console.error('🚫 Project creation aborted due to the above error.');
|
|
255
|
-
if (!showOutput && progressBar) {
|
|
256
|
-
progressBar.stop();
|
|
257
|
-
}
|
|
258
|
-
process.exit(1);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function setupProjectStructure(projectPath, answers) {
|
|
263
|
-
ensureAndRunNestCli(projectPath, answers?.showOutput);
|
|
264
|
-
incrementProgress(answers?.showOutput, "nestjs");
|
|
265
|
-
|
|
266
|
-
// Copy main README.md
|
|
267
|
-
const readmePath = path.join(__dirname, 'README.md');
|
|
268
|
-
fs.copyFileSync(readmePath, `${projectPath}/README.md`);
|
|
269
|
-
|
|
270
|
-
const bootstrapContent = getBootstrapContent();
|
|
271
|
-
fs.writeFileSync(`${projectPath}/src/main.ts`, bootstrapContent);
|
|
272
|
-
|
|
273
|
-
const tsConfigPath = path.join(projectPath, 'tsconfig.json');
|
|
274
|
-
if (fs.existsSync(tsConfigPath)) {
|
|
275
|
-
const tsConfig = fs.readJsonSync(tsConfigPath);
|
|
276
|
-
|
|
277
|
-
if (!tsConfig.compilerOptions) {
|
|
278
|
-
tsConfig.compilerOptions = {};
|
|
279
|
-
}
|
|
280
|
-
tsConfig.compilerOptions.target = 'ES2017';
|
|
281
|
-
fs.writeJsonSync(tsConfigPath, tsConfig, { spaces: 2 });
|
|
282
|
-
} else {
|
|
283
|
-
console.warn('Could not find generated tsconfig.json to modify.');
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const appModuleContent = getAppModuleTemplate();
|
|
287
|
-
fs.writeFileSync(`${projectPath}/src/app.module.ts`, appModuleContent);
|
|
288
|
-
incrementProgress(answers?.showOutput, "appmodule");
|
|
289
|
-
installDependenciesFromManifest(answers?.showOutput);
|
|
290
|
-
executeCommand('npm install --save-dev @types/multer @types/express cross-env', answers?.showOutput);
|
|
291
|
-
incrementProgress(answers?.showOutput, "installDependencies");
|
|
292
|
-
|
|
293
|
-
// const tgzPath = path.resolve('D:/Projects/core/appx-core', fs.readdirSync('D:/Projects/core/appx-core').find(f => f.startsWith('appx-core-package') && f.endsWith('.tgz')));
|
|
294
|
-
// executeCommand(`npm install "${tgzPath}"`, answers?.showOutput);
|
|
295
|
-
executeCommand('npm install @appxdigital/appx-core@latest', answers?.showOutput);
|
|
296
|
-
incrementProgress(answers?.showOutput, "installCore");
|
|
297
|
-
|
|
298
|
-
//Prisma setup
|
|
299
|
-
const prismaVersion = dependencyVersions.devDependencies?.prisma;
|
|
300
|
-
if (!prismaVersion) {
|
|
301
|
-
console.error('Prisma version not found in dependency-versions.json devDependencies. Cannot run prisma init.');
|
|
302
|
-
process.exit(1);
|
|
303
|
-
}
|
|
304
|
-
executeCommand(`npx prisma@${prismaVersion} init`, answers?.showOutput);
|
|
305
|
-
customizePrismaSchema(projectPath, answers);
|
|
306
|
-
incrementProgress(answers?.showOutput, "prismaSetup");
|
|
307
|
-
createPrismaModule(projectPath);
|
|
308
|
-
createPermissionsConfig(projectPath);
|
|
309
|
-
setupAdminJS(projectPath);
|
|
310
|
-
createAdminConfig(projectPath);
|
|
311
|
-
addScriptsToPackageJson(projectPath);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function ensureAndRunNestCli(projectPath, showOutput = false) {
|
|
315
|
-
const options = showOutput ? { stdio: 'inherit' } : { stdio: 'ignore' };
|
|
316
|
-
const command = 'npx --yes @nestjs/cli new . --skip-install --package-manager npm';
|
|
317
|
-
try {
|
|
318
|
-
execSync('npx --no-install @nestjs/cli --version', options);
|
|
319
|
-
} catch {
|
|
320
|
-
try {
|
|
321
|
-
execSync('npx @nestjs/cli --version', options);
|
|
322
|
-
} catch (fetchError) {
|
|
323
|
-
console.error('❌ Failed to fetch @nestjs/cli via npx. Please check your internet connection.');
|
|
324
|
-
process.exit(1);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
try {
|
|
328
|
-
execSync(command, { cwd: projectPath, ...options });
|
|
329
|
-
} catch (creationError) {
|
|
330
|
-
console.error(`❌ Failed to create the project: ${creationError.message}`);
|
|
331
|
-
process.exit(1);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function getBootstrapContent() {
|
|
336
|
-
const bootstrapFilePath = path.join(__dirname, 'templates', 'bootstrap.template.js');
|
|
337
|
-
return fs.readFileSync(bootstrapFilePath, 'utf8');
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
function getAppModuleTemplate() {
|
|
341
|
-
const appModuleTemplatePath = path.join(__dirname, 'templates', 'app.module.template.js');
|
|
342
|
-
return fs.readFileSync(appModuleTemplatePath, 'utf8');
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function setupAdminJS(projectPath) {
|
|
346
|
-
const backoffice = path.join(projectPath, 'src/backoffice');
|
|
347
|
-
fs.ensureDirSync(backoffice);
|
|
348
|
-
|
|
349
|
-
const backofficeComponents = path.join(backoffice, 'components');
|
|
350
|
-
fs.ensureDirSync(backofficeComponents);
|
|
351
|
-
|
|
352
|
-
const dashboardContent = getDashboardTemplate();
|
|
353
|
-
fs.writeFileSync(path.join(backofficeComponents, 'dashboard.tsx'), dashboardContent);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function getComponentLoaderTemplate() {
|
|
357
|
-
const template = path.join(__dirname, 'templates', 'adminjs', 'component-loader.template.js');
|
|
358
|
-
return fs.readFileSync(template, 'utf8');
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function getDashboardTemplate() {
|
|
362
|
-
const template = path.join(__dirname, 'templates', 'adminjs', 'dashboard.template.js');
|
|
363
|
-
return fs.readFileSync(template, 'utf8');
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function getUtilsTemplate() {
|
|
367
|
-
const template = path.join(__dirname, 'templates', 'adminjs', 'utils.template.js');
|
|
368
|
-
return fs.readFileSync(template, 'utf8');
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function getAdminTemplate() {
|
|
372
|
-
const template = path.join(__dirname, 'templates', 'adminjs', 'admin.template.js');
|
|
373
|
-
return fs.readFileSync(template, 'utf8');
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function getAdminAppModuleTemplate() {
|
|
377
|
-
const appModuleTemplatePath = path.join(__dirname, 'templates', 'adminjs', 'adminjs-app.module.template.js');
|
|
378
|
-
return fs.readFileSync(appModuleTemplatePath, 'utf8');
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
function createPermissionsConfig(projectPath) {
|
|
382
|
-
const configDir = path.join(projectPath, 'src/config');
|
|
383
|
-
fs.ensureDirSync(configDir);
|
|
384
|
-
|
|
385
|
-
const templatePath = path.join(__dirname, 'templates', 'permissions.config.template.js');
|
|
386
|
-
const permissionsConfigContent = fs.readFileSync(templatePath, 'utf-8');
|
|
387
|
-
|
|
388
|
-
fs.writeFileSync(path.join(configDir, 'permissions.config.ts'), permissionsConfigContent);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
function createAdminConfig (projectPath) {
|
|
392
|
-
const configDir = path.join(projectPath, 'src/config');
|
|
393
|
-
fs.ensureDirSync(configDir);
|
|
394
|
-
|
|
395
|
-
const templatePath = path.join(__dirname, 'templates', 'admin.config.template.js');
|
|
396
|
-
const permissionsConfigContent = fs.readFileSync(templatePath, 'utf-8');
|
|
397
|
-
|
|
398
|
-
fs.writeFileSync(path.join(configDir, 'admin.config.ts'), permissionsConfigContent);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function customizePrismaSchema(projectPath, answers) {
|
|
402
|
-
const prismaDir = `${projectPath}/prisma`;
|
|
403
|
-
const schemaFile = `${prismaDir}/schema.prisma`;
|
|
404
|
-
|
|
405
|
-
fs.ensureDirSync(prismaDir);
|
|
406
|
-
|
|
407
|
-
const schemaContent = `
|
|
408
|
-
datasource db {
|
|
409
|
-
provider = "${answers.dbProvider}"
|
|
410
|
-
url = env("DB_URL")
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
generator client {
|
|
414
|
-
provider = "prisma-client-js"
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
generator nestgraphql {
|
|
418
|
-
provider = "node node_modules/prisma-nestjs-graphql"
|
|
419
|
-
output = "../src/generated/"
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
model User {
|
|
423
|
-
id Int @id @default(autoincrement())
|
|
424
|
-
email String @unique
|
|
425
|
-
name String?
|
|
426
|
-
password String? /// @Role(none)
|
|
427
|
-
role Role @default(GUEST)
|
|
428
|
-
refreshTokens UserRefreshToken[]
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
model Session {
|
|
432
|
-
id String @id
|
|
433
|
-
sid String @unique
|
|
434
|
-
data String @db.Text
|
|
435
|
-
expiresAt DateTime
|
|
436
|
-
userId Int?
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
model UserRefreshToken {
|
|
440
|
-
id String @id @default(cuid())
|
|
441
|
-
token String @unique @db.VarChar(255)
|
|
442
|
-
userId Int
|
|
443
|
-
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
444
|
-
expiresAt DateTime
|
|
445
|
-
createdAt DateTime @default(now())
|
|
446
|
-
revokedAt DateTime?
|
|
447
|
-
|
|
448
|
-
@@index([userId])
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
enum Role {
|
|
452
|
-
ADMIN
|
|
453
|
-
GUEST
|
|
454
|
-
}
|
|
455
|
-
`;
|
|
456
|
-
|
|
457
|
-
fs.writeFileSync(schemaFile, schemaContent);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
function createPrismaModule(projectPath) {
|
|
461
|
-
const prismaDir = path.join(projectPath, 'src/prisma');
|
|
462
|
-
fs.ensureDirSync(prismaDir);
|
|
463
|
-
|
|
464
|
-
const templatePath = path.join(__dirname, 'templates', 'prisma.module.template.js');
|
|
465
|
-
const prismaModuleContent = fs.readFileSync(templatePath, 'utf-8');
|
|
466
|
-
|
|
467
|
-
fs.writeFileSync(path.join(prismaDir, 'prisma.module.ts'), prismaModuleContent);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function addScriptsToPackageJson(projectPath) {
|
|
471
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
472
|
-
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
473
|
-
|
|
474
|
-
packageJson.scripts = packageJson.scripts || {};
|
|
475
|
-
packageJson.scripts["start:dev"] = "cross-env NODE_ENV=development nest start --watch";
|
|
476
|
-
packageJson.scripts["start:prod"] = "cross-env NODE_ENV=production node dist/main";
|
|
477
|
-
packageJson.scripts["db-pull"] = "npm run db-pull --prefix ./node_modules/appx-core";
|
|
478
|
-
|
|
479
|
-
fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
function initializeGitRepo(projectPath) {
|
|
483
|
-
try {
|
|
484
|
-
execSync('git add .', { cwd: projectPath, stdio: 'ignore' });
|
|
485
|
-
execSync('git commit -m "Project init"', { cwd: projectPath, stdio: 'ignore' });
|
|
486
|
-
} catch (error) {
|
|
487
|
-
console.error("Failed to initialize git repository or make the initial commit:", error);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
function configureProjectSettings(projectPath) {
|
|
493
|
-
const prettierConfig = {
|
|
494
|
-
singleQuote: true,
|
|
495
|
-
trailingComma: 'all',
|
|
496
|
-
endOfLine: 'lf',
|
|
497
|
-
tabWidth: 2,
|
|
498
|
-
semi: true,
|
|
499
|
-
bracketSpacing: true,
|
|
500
|
-
jsxBracketSameLine: true
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
fs.writeFileSync(
|
|
504
|
-
path.join(projectPath, '.prettierrc'),
|
|
505
|
-
JSON.stringify(prettierConfig, null, 2)
|
|
506
|
-
);
|
|
507
|
-
|
|
508
|
-
const eslintConfig = `module.exports = {
|
|
509
|
-
parser: '@typescript-eslint/parser',
|
|
510
|
-
parserOptions: {
|
|
511
|
-
project: 'tsconfig.json',
|
|
512
|
-
tsconfigRootDir: __dirname,
|
|
513
|
-
sourceType: 'module',
|
|
514
|
-
},
|
|
515
|
-
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
516
|
-
extends: [
|
|
517
|
-
'plugin:@typescript-eslint/recommended',
|
|
518
|
-
'plugin:prettier/recommended',
|
|
519
|
-
],
|
|
520
|
-
root: true,
|
|
521
|
-
env: {
|
|
522
|
-
node: true,
|
|
523
|
-
jest: true,
|
|
524
|
-
},
|
|
525
|
-
ignorePatterns: ['.eslintrc.js'],
|
|
526
|
-
rules: {
|
|
527
|
-
'@typescript-eslint/interface-name-prefix': 'off',
|
|
528
|
-
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
529
|
-
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
530
|
-
'@typescript-eslint/no-explicit-any': 'off',
|
|
531
|
-
'prettier/prettier': ['error', { 'endOfLine': 'lf' }],
|
|
532
|
-
},
|
|
533
|
-
};`;
|
|
534
|
-
|
|
535
|
-
fs.writeFileSync(path.join(projectPath, '.eslintrc.js'), eslintConfig);
|
|
536
|
-
|
|
537
|
-
const gitattributesContent = `
|
|
538
|
-
* text=auto eol=lf
|
|
539
|
-
`;
|
|
540
|
-
fs.writeFileSync(path.join(projectPath, '.gitattributes'), gitattributesContent);
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
function updateGitignore(projectPath) {
|
|
544
|
-
const gitignorePath = path.join(projectPath, '.gitignore');
|
|
545
|
-
const envFilesToAdd = ['.env', '.env.production'];
|
|
546
|
-
let gitignoreContent = '';
|
|
547
|
-
if (fs.existsSync(gitignorePath)) {
|
|
548
|
-
gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
|
|
549
|
-
} else {
|
|
550
|
-
console.log(`.gitignore file not found. Creating a new one.`);
|
|
551
|
-
}
|
|
552
|
-
const existingLines = gitignoreContent.split('\n');
|
|
553
|
-
const updatedLines = new Set(existingLines);
|
|
554
|
-
envFilesToAdd.forEach((file) => {
|
|
555
|
-
if (!existingLines.includes(file)) {
|
|
556
|
-
updatedLines.add(file);
|
|
557
|
-
}
|
|
558
|
-
});
|
|
559
|
-
const finalContent = Array.from(updatedLines).join('\n').trim() + '\n';
|
|
560
|
-
fs.writeFileSync(gitignorePath, finalContent, 'utf-8');
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
function incrementProgress(showOutput, phase) {
|
|
565
|
-
if (!showOutput) {
|
|
566
|
-
remainingETA -= phaseDurations[phase];
|
|
567
|
-
progressBar.update(progressBar.value + phase === 'end' ? 0 : 1, { remainingETA });
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function executeCommand(command, showOutput = answers?.showOutput) {
|
|
572
|
-
const options = showOutput ? { stdio: 'inherit' } : { stdio: 'ignore' };
|
|
573
|
-
try {
|
|
574
|
-
execSync(command, options);
|
|
575
|
-
} catch (error) {
|
|
576
|
-
console.error(`Failed to execute command: ${command}`, error);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
function installDependenciesFromManifest(showOutput = true) {
|
|
581
|
-
const { dependencies, devDependencies } = dependencyVersions;
|
|
582
|
-
const depList = Object.entries(dependencies)
|
|
583
|
-
.map(([pkg, version]) => `${pkg}@${version}`)
|
|
584
|
-
.join(' ');
|
|
585
|
-
|
|
586
|
-
const devDepList = Object.entries(devDependencies)
|
|
587
|
-
.map(([pkg, version]) => `${pkg}@${version}`)
|
|
588
|
-
.join(' ');
|
|
589
|
-
|
|
590
|
-
if (depList) {
|
|
591
|
-
executeCommand(`npm install ${depList}`, showOutput);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if (devDepList) {
|
|
595
|
-
executeCommand(`npm install -D ${devDepList}`, showOutput);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
program.parse(process.argv);
|
|
File without changes
|