projects-init-cli 1.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/README.md +127 -0
- package/dist/generator.js +59 -0
- package/dist/index.js +32 -0
- package/dist/prompts.js +156 -0
- package/dist/templates/backend/cdk.js +211 -0
- package/dist/templates/backend/express.js +427 -0
- package/dist/templates/backend/fastapi.js +259 -0
- package/dist/templates/backend/nestjs.js +478 -0
- package/dist/templates/backend/sam.js +258 -0
- package/dist/templates/frontend/html.js +141 -0
- package/dist/templates/frontend/index.js +9 -0
- package/dist/templates/frontend/nextjs.js +240 -0
- package/dist/templates/frontend/react.js +249 -0
- package/dist/templates/index.js +341 -0
- package/dist/types.js +2 -0
- package/package.json +52 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateNestJS = generateNestJS;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
async function generateNestJS(backendPath, config) {
|
|
10
|
+
const dependencies = {
|
|
11
|
+
'@nestjs/common': '^10.4.8',
|
|
12
|
+
'@nestjs/core': '^10.4.8',
|
|
13
|
+
'@nestjs/platform-express': '^10.4.8',
|
|
14
|
+
'@nestjs/testing': '^10.4.8',
|
|
15
|
+
'reflect-metadata': '^0.2.2',
|
|
16
|
+
'rxjs': '^7.8.1'
|
|
17
|
+
};
|
|
18
|
+
const devDependencies = {
|
|
19
|
+
'@nestjs/cli': '^10.4.5',
|
|
20
|
+
'@nestjs/schematics': '^10.1.1',
|
|
21
|
+
'@types/express': '^5.0.0',
|
|
22
|
+
'@types/node': '^22.7.5',
|
|
23
|
+
'source-map-support': '^0.5.21',
|
|
24
|
+
'ts-loader': '^9.5.1',
|
|
25
|
+
'ts-node': '^10.9.2',
|
|
26
|
+
'tsconfig-paths': '^4.2.0',
|
|
27
|
+
typescript: '^5.6.3'
|
|
28
|
+
};
|
|
29
|
+
// Add database dependencies
|
|
30
|
+
if (config.storage === 'local-json') {
|
|
31
|
+
// No additional dependencies needed for JSON file storage
|
|
32
|
+
}
|
|
33
|
+
else if (config.storage === 'local-sqlite') {
|
|
34
|
+
if (config.databaseType === 'sql' && config.sqlOption === 'prisma') {
|
|
35
|
+
dependencies['@prisma/client'] = '^6.0.1';
|
|
36
|
+
dependencies['prisma'] = '^6.0.1';
|
|
37
|
+
}
|
|
38
|
+
else if (config.databaseType === 'sql') {
|
|
39
|
+
dependencies['typeorm'] = '^0.3.20';
|
|
40
|
+
dependencies['better-sqlite3'] = '^11.7.0';
|
|
41
|
+
devDependencies['@types/better-sqlite3'] = '^7.6.9';
|
|
42
|
+
}
|
|
43
|
+
else if (config.databaseType === 'nosql' && config.nosqlOption === 'mongodb') {
|
|
44
|
+
dependencies['@nestjs/mongoose'] = '^10.1.0';
|
|
45
|
+
dependencies['mongoose'] = '^8.8.4';
|
|
46
|
+
}
|
|
47
|
+
else if (config.databaseType === 'nosql' && config.nosqlOption === 'dynamodb') {
|
|
48
|
+
dependencies['@aws-sdk/client-dynamodb'] = '^3.699.0';
|
|
49
|
+
dependencies['@aws-sdk/lib-dynamodb'] = '^3.699.0';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (config.storage === 'external-url') {
|
|
53
|
+
if (config.databaseType === 'sql' && config.sqlOption === 'prisma') {
|
|
54
|
+
dependencies['@prisma/client'] = '^6.0.1';
|
|
55
|
+
dependencies['prisma'] = '^6.0.1';
|
|
56
|
+
}
|
|
57
|
+
else if (config.databaseType === 'sql') {
|
|
58
|
+
dependencies['typeorm'] = '^0.3.20';
|
|
59
|
+
dependencies['pg'] = '^8.13.1';
|
|
60
|
+
devDependencies['@types/pg'] = '^8.11.10';
|
|
61
|
+
}
|
|
62
|
+
else if (config.databaseType === 'nosql' && config.nosqlOption === 'mongodb') {
|
|
63
|
+
dependencies['@nestjs/mongoose'] = '^10.1.0';
|
|
64
|
+
dependencies['mongoose'] = '^8.8.4';
|
|
65
|
+
}
|
|
66
|
+
else if (config.databaseType === 'nosql' && config.nosqlOption === 'dynamodb') {
|
|
67
|
+
dependencies['@aws-sdk/client-dynamodb'] = '^3.699.0';
|
|
68
|
+
dependencies['@aws-sdk/lib-dynamodb'] = '^3.699.0';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Add API type dependencies
|
|
72
|
+
if (config.apiType === 'graphql') {
|
|
73
|
+
dependencies['@nestjs/graphql'] = '^12.1.0';
|
|
74
|
+
dependencies['@nestjs/apollo'] = '^12.1.0';
|
|
75
|
+
dependencies['apollo-server-express'] = '^3.12.1';
|
|
76
|
+
dependencies['graphql'] = '^16.9.0';
|
|
77
|
+
}
|
|
78
|
+
const packageJson = {
|
|
79
|
+
name: `${config.projectName}-backend`,
|
|
80
|
+
version: '1.0.0',
|
|
81
|
+
description: '',
|
|
82
|
+
author: '',
|
|
83
|
+
private: true,
|
|
84
|
+
license: 'MIT',
|
|
85
|
+
scripts: {
|
|
86
|
+
build: 'nest build',
|
|
87
|
+
format: 'prettier --write "src/**/*.ts" "test/**/*.ts"',
|
|
88
|
+
start: 'nest start',
|
|
89
|
+
'start:dev': 'nest start --watch',
|
|
90
|
+
'start:debug': 'nest start --debug --watch',
|
|
91
|
+
'start:prod': 'node dist/main',
|
|
92
|
+
lint: 'eslint "{src,apps,libs,test}/**/*.ts" --fix',
|
|
93
|
+
test: 'vitest',
|
|
94
|
+
'test:ui': 'vitest --ui',
|
|
95
|
+
'test:coverage': 'vitest --coverage',
|
|
96
|
+
'test:e2e': 'vitest --config vitest.e2e.config.ts'
|
|
97
|
+
},
|
|
98
|
+
dependencies,
|
|
99
|
+
devDependencies: {
|
|
100
|
+
...devDependencies,
|
|
101
|
+
'@typescript-eslint/eslint-plugin': '^8.15.0',
|
|
102
|
+
'@typescript-eslint/parser': '^8.15.0',
|
|
103
|
+
eslint: '^9.15.0',
|
|
104
|
+
'eslint-config-prettier': '^9.1.0',
|
|
105
|
+
'eslint-plugin-prettier': '^6.0.0',
|
|
106
|
+
prettier: '^3.3.3',
|
|
107
|
+
'vitest': '^2.1.3',
|
|
108
|
+
'@vitest/ui': '^2.1.3',
|
|
109
|
+
'@vitest/coverage-v8': '^2.1.3'
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(backendPath, 'package.json'), packageJson, { spaces: 2 });
|
|
113
|
+
// Create nest-cli.json
|
|
114
|
+
const nestCli = {
|
|
115
|
+
'$schema': 'https://json.schemastore.org/nest-cli',
|
|
116
|
+
collection: '@nestjs/schematics',
|
|
117
|
+
sourceRoot: 'src',
|
|
118
|
+
compilerOptions: {
|
|
119
|
+
deleteOutDir: true
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(backendPath, 'nest-cli.json'), nestCli, { spaces: 2 });
|
|
123
|
+
// Create tsconfig
|
|
124
|
+
const tsconfig = {
|
|
125
|
+
compilerOptions: {
|
|
126
|
+
module: 'commonjs',
|
|
127
|
+
declaration: true,
|
|
128
|
+
removeComments: true,
|
|
129
|
+
emitDecoratorMetadata: true,
|
|
130
|
+
experimentalDecorators: true,
|
|
131
|
+
allowSyntheticDefaultImports: true,
|
|
132
|
+
target: 'ES2021',
|
|
133
|
+
sourceMap: true,
|
|
134
|
+
outDir: './dist',
|
|
135
|
+
baseUrl: './',
|
|
136
|
+
incremental: true,
|
|
137
|
+
skipLibCheck: true,
|
|
138
|
+
strictNullChecks: false,
|
|
139
|
+
noImplicitAny: false,
|
|
140
|
+
strictBindCallApply: false,
|
|
141
|
+
forceConsistentCasingInFileNames: false,
|
|
142
|
+
noFallthroughCasesInSwitch: false
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(backendPath, 'tsconfig.json'), tsconfig, { spaces: 2 });
|
|
146
|
+
// Create src directory structure
|
|
147
|
+
const srcPath = path_1.default.join(backendPath, 'src');
|
|
148
|
+
await fs_extra_1.default.ensureDir(srcPath);
|
|
149
|
+
// Create main.ts
|
|
150
|
+
let mainContent = `import { NestFactory } from '@nestjs/core';
|
|
151
|
+
import { AppModule } from './app.module';
|
|
152
|
+
|
|
153
|
+
async function bootstrap() {
|
|
154
|
+
const app = await NestFactory.create(AppModule);
|
|
155
|
+
app.enableCors();
|
|
156
|
+
await app.listen(process.env.PORT || 3001);
|
|
157
|
+
console.log(\`Application is running on: http://localhost:\${process.env.PORT || 3001}\`);
|
|
158
|
+
}
|
|
159
|
+
bootstrap();
|
|
160
|
+
`;
|
|
161
|
+
await fs_extra_1.default.writeFile(path_1.default.join(srcPath, 'main.ts'), mainContent);
|
|
162
|
+
// Create app.module.ts
|
|
163
|
+
let appModuleContent = `import { Module } from '@nestjs/common';
|
|
164
|
+
import { AppController } from './app.controller';
|
|
165
|
+
import { AppService } from './app.service';
|
|
166
|
+
`;
|
|
167
|
+
if (config.apiType === 'graphql') {
|
|
168
|
+
appModuleContent += `import { GraphQLModule } from '@nestjs/graphql';
|
|
169
|
+
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
|
170
|
+
import { join } from 'path';
|
|
171
|
+
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
appModuleContent += `
|
|
175
|
+
@Module({
|
|
176
|
+
imports: [
|
|
177
|
+
`;
|
|
178
|
+
if (config.apiType === 'graphql') {
|
|
179
|
+
appModuleContent += ` GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
180
|
+
driver: ApolloDriver,
|
|
181
|
+
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
|
|
182
|
+
sortSchema: true,
|
|
183
|
+
}),
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
appModuleContent += ` ],
|
|
187
|
+
controllers: [AppController],
|
|
188
|
+
providers: [AppService],
|
|
189
|
+
})
|
|
190
|
+
export class AppModule {}
|
|
191
|
+
`;
|
|
192
|
+
await fs_extra_1.default.writeFile(path_1.default.join(srcPath, 'app.module.ts'), appModuleContent);
|
|
193
|
+
// Create app.controller.ts
|
|
194
|
+
const appController = `import { Controller, Get } from '@nestjs/common';
|
|
195
|
+
import { AppService } from './app.service';
|
|
196
|
+
|
|
197
|
+
@Controller()
|
|
198
|
+
export class AppController {
|
|
199
|
+
constructor(private readonly appService: AppService) {}
|
|
200
|
+
|
|
201
|
+
@Get()
|
|
202
|
+
getHello(): string {
|
|
203
|
+
return this.appService.getHello();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@Get('health')
|
|
207
|
+
getHealth() {
|
|
208
|
+
return { status: 'ok', message: 'Server is running' };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
`;
|
|
212
|
+
await fs_extra_1.default.writeFile(path_1.default.join(srcPath, 'app.controller.ts'), appController);
|
|
213
|
+
// Create app.service.ts
|
|
214
|
+
const appService = `import { Injectable } from '@nestjs/common';
|
|
215
|
+
|
|
216
|
+
@Injectable()
|
|
217
|
+
export class AppService {
|
|
218
|
+
getHello(): string {
|
|
219
|
+
return 'Hello World!';
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
`;
|
|
223
|
+
await fs_extra_1.default.writeFile(path_1.default.join(srcPath, 'app.service.ts'), appService);
|
|
224
|
+
// Create .env.example
|
|
225
|
+
let envExample = `PORT=3001
|
|
226
|
+
`;
|
|
227
|
+
if (config.storage === 'external-url' && config.databaseUrl) {
|
|
228
|
+
envExample += `DATABASE_URL=${config.databaseUrl}\n`;
|
|
229
|
+
}
|
|
230
|
+
await fs_extra_1.default.writeFile(path_1.default.join(backendPath, '.env.example'), envExample);
|
|
231
|
+
// Create Vitest config
|
|
232
|
+
const vitestConfig = `import { defineConfig } from 'vitest/config'
|
|
233
|
+
import path from 'path'
|
|
234
|
+
|
|
235
|
+
export default defineConfig({
|
|
236
|
+
test: {
|
|
237
|
+
globals: true,
|
|
238
|
+
environment: 'node',
|
|
239
|
+
coverage: {
|
|
240
|
+
provider: 'v8',
|
|
241
|
+
reporter: ['text', 'json', 'html'],
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
resolve: {
|
|
245
|
+
alias: {
|
|
246
|
+
'@': path.resolve(__dirname, './src'),
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
})
|
|
250
|
+
`;
|
|
251
|
+
await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'vitest.config.ts'), vitestConfig);
|
|
252
|
+
// Create test files
|
|
253
|
+
const testPath = path_1.default.join(srcPath, '__tests__');
|
|
254
|
+
await fs_extra_1.default.ensureDir(testPath);
|
|
255
|
+
const appControllerTest = `import { describe, it, expect, beforeEach } from 'vitest'
|
|
256
|
+
import { Test, TestingModule } from '@nestjs/testing'
|
|
257
|
+
import { AppController } from '../app.controller'
|
|
258
|
+
import { AppService } from '../app.service'
|
|
259
|
+
|
|
260
|
+
describe('AppController', () => {
|
|
261
|
+
let appController: AppController
|
|
262
|
+
let appService: AppService
|
|
263
|
+
|
|
264
|
+
beforeEach(async () => {
|
|
265
|
+
const moduleRef: TestingModule = await Test.createTestingModule({
|
|
266
|
+
controllers: [AppController],
|
|
267
|
+
providers: [AppService],
|
|
268
|
+
}).compile()
|
|
269
|
+
|
|
270
|
+
appService = moduleRef.get<AppService>(AppService)
|
|
271
|
+
appController = moduleRef.get<AppController>(AppController)
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('should return "Hello World!"', () => {
|
|
275
|
+
expect(appController.getHello()).toBe('Hello World!')
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
it('should return health check', () => {
|
|
279
|
+
const result = appController.getHealth()
|
|
280
|
+
expect(result.status).toBe('ok')
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
`;
|
|
284
|
+
await fs_extra_1.default.writeFile(path_1.default.join(testPath, 'app.controller.spec.ts'), appControllerTest);
|
|
285
|
+
const appServiceTest = `import { describe, it, expect } from 'vitest'
|
|
286
|
+
import { AppService } from '../app.service'
|
|
287
|
+
|
|
288
|
+
describe('AppService', () => {
|
|
289
|
+
it('should return "Hello World!"', () => {
|
|
290
|
+
const appService = new AppService()
|
|
291
|
+
expect(appService.getHello()).toBe('Hello World!')
|
|
292
|
+
})
|
|
293
|
+
})
|
|
294
|
+
`;
|
|
295
|
+
await fs_extra_1.default.writeFile(path_1.default.join(testPath, 'app.service.spec.ts'), appServiceTest);
|
|
296
|
+
// Create database setup if needed
|
|
297
|
+
if (config.storage === 'local-json') {
|
|
298
|
+
await generateJSONFileModule(srcPath, config);
|
|
299
|
+
}
|
|
300
|
+
else if (config.databaseType === 'sql' && config.sqlOption === 'prisma') {
|
|
301
|
+
await generatePrismaConfig(backendPath, config);
|
|
302
|
+
}
|
|
303
|
+
else if (config.databaseType === 'nosql' && config.nosqlOption === 'mongodb') {
|
|
304
|
+
await generateMongoDBModule(srcPath, config);
|
|
305
|
+
}
|
|
306
|
+
// Create deployment files
|
|
307
|
+
await generateBackendDeployment(backendPath, config);
|
|
308
|
+
}
|
|
309
|
+
async function generatePrismaConfig(backendPath, config) {
|
|
310
|
+
const prismaPath = path_1.default.join(backendPath, 'prisma');
|
|
311
|
+
await fs_extra_1.default.ensureDir(prismaPath);
|
|
312
|
+
let datasource = '';
|
|
313
|
+
if (config.storage === 'local-sqlite') {
|
|
314
|
+
datasource = `datasource db {
|
|
315
|
+
provider = "sqlite"
|
|
316
|
+
url = "file:./dev.db"
|
|
317
|
+
}`;
|
|
318
|
+
}
|
|
319
|
+
else if (config.storage === 'external-url') {
|
|
320
|
+
datasource = `datasource db {
|
|
321
|
+
provider = "postgresql"
|
|
322
|
+
url = env("DATABASE_URL")
|
|
323
|
+
}`;
|
|
324
|
+
}
|
|
325
|
+
const schema = `${datasource}
|
|
326
|
+
|
|
327
|
+
generator client {
|
|
328
|
+
provider = "prisma-client-js"
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
model User {
|
|
332
|
+
id Int @id @default(autoincrement())
|
|
333
|
+
email String @unique
|
|
334
|
+
name String?
|
|
335
|
+
createdAt DateTime @default(now())
|
|
336
|
+
updatedAt DateTime @updatedAt
|
|
337
|
+
}
|
|
338
|
+
`;
|
|
339
|
+
await fs_extra_1.default.writeFile(path_1.default.join(prismaPath, 'schema.prisma'), schema);
|
|
340
|
+
}
|
|
341
|
+
async function generateMongoDBModule(srcPath, config) {
|
|
342
|
+
const dbContent = `import { Module } from '@nestjs/common';
|
|
343
|
+
import { MongooseModule } from '@nestjs/mongoose';
|
|
344
|
+
import { User, UserSchema } from './schemas/user.schema';
|
|
345
|
+
|
|
346
|
+
@Module({
|
|
347
|
+
imports: [
|
|
348
|
+
MongooseModule.forRoot(process.env.DATABASE_URL || 'mongodb://localhost:27017/${config.projectName}'),
|
|
349
|
+
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
|
|
350
|
+
],
|
|
351
|
+
exports: [MongooseModule],
|
|
352
|
+
})
|
|
353
|
+
export class DatabaseModule {}
|
|
354
|
+
`;
|
|
355
|
+
await fs_extra_1.default.writeFile(path_1.default.join(srcPath, 'database.module.ts'), dbContent);
|
|
356
|
+
const schemasPath = path_1.default.join(srcPath, 'schemas');
|
|
357
|
+
await fs_extra_1.default.ensureDir(schemasPath);
|
|
358
|
+
const userSchema = `import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
|
359
|
+
import { Document } from 'mongoose';
|
|
360
|
+
|
|
361
|
+
export type UserDocument = User & Document;
|
|
362
|
+
|
|
363
|
+
@Schema()
|
|
364
|
+
export class User {
|
|
365
|
+
@Prop({ required: true, unique: true })
|
|
366
|
+
email: string;
|
|
367
|
+
|
|
368
|
+
@Prop()
|
|
369
|
+
name: string;
|
|
370
|
+
|
|
371
|
+
@Prop({ default: Date.now })
|
|
372
|
+
createdAt: Date;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export const UserSchema = SchemaFactory.createForClass(User);
|
|
376
|
+
`;
|
|
377
|
+
await fs_extra_1.default.writeFile(path_1.default.join(schemasPath, 'user.schema.ts'), userSchema);
|
|
378
|
+
}
|
|
379
|
+
async function generateJSONFileModule(srcPath, config) {
|
|
380
|
+
const backendPath = path_1.default.dirname(path_1.default.dirname(srcPath));
|
|
381
|
+
// Create JSON service
|
|
382
|
+
const jsonService = `import { Injectable } from '@nestjs/common';
|
|
383
|
+
import * as fs from 'fs-extra';
|
|
384
|
+
import * as path from 'path';
|
|
385
|
+
|
|
386
|
+
const DB_FILE = path.join(process.cwd(), 'data', 'database.json');
|
|
387
|
+
|
|
388
|
+
@Injectable()
|
|
389
|
+
export class JsonDatabaseService {
|
|
390
|
+
private ensureDataDir(): void {
|
|
391
|
+
const dataDir = path.dirname(DB_FILE);
|
|
392
|
+
fs.ensureDirSync(dataDir);
|
|
393
|
+
if (!fs.existsSync(DB_FILE)) {
|
|
394
|
+
fs.writeJSONSync(DB_FILE, { users: [] }, { spaces: 2 });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
private readDB(): any {
|
|
399
|
+
this.ensureDataDir();
|
|
400
|
+
try {
|
|
401
|
+
return fs.readJSONSync(DB_FILE);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
console.error('Error reading database:', error);
|
|
404
|
+
return { users: [] };
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private writeDB(data: any): void {
|
|
409
|
+
try {
|
|
410
|
+
fs.writeJSONSync(DB_FILE, data, { spaces: 2 });
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error('Error writing database:', error);
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
getUsers(): any[] {
|
|
418
|
+
const db = this.readDB();
|
|
419
|
+
return db.users || [];
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
addUser(user: any): any {
|
|
423
|
+
const db = this.readDB();
|
|
424
|
+
if (!db.users) db.users = [];
|
|
425
|
+
const newUser = { ...user, id: db.users.length + 1, createdAt: new Date().toISOString() };
|
|
426
|
+
db.users.push(newUser);
|
|
427
|
+
this.writeDB(db);
|
|
428
|
+
return newUser;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
getUserById(id: number): any {
|
|
432
|
+
const db = this.readDB();
|
|
433
|
+
return db.users?.find((u: any) => u.id === id);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
updateUser(id: number, updates: any): any {
|
|
437
|
+
const db = this.readDB();
|
|
438
|
+
const userIndex = db.users?.findIndex((u: any) => u.id === id);
|
|
439
|
+
if (userIndex !== -1 && userIndex !== undefined) {
|
|
440
|
+
db.users[userIndex] = { ...db.users[userIndex], ...updates, updatedAt: new Date().toISOString() };
|
|
441
|
+
this.writeDB(db);
|
|
442
|
+
return db.users[userIndex];
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
deleteUser(id: number): boolean {
|
|
448
|
+
const db = this.readDB();
|
|
449
|
+
db.users = db.users?.filter((u: any) => u.id !== id) || [];
|
|
450
|
+
this.writeDB(db);
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
`;
|
|
455
|
+
const servicesPath = path_1.default.join(srcPath, 'services');
|
|
456
|
+
await fs_extra_1.default.ensureDir(servicesPath);
|
|
457
|
+
await fs_extra_1.default.writeFile(path_1.default.join(servicesPath, 'json-database.service.ts'), jsonService);
|
|
458
|
+
// Create initial data directory and file
|
|
459
|
+
const dataPath = path_1.default.join(backendPath, 'data');
|
|
460
|
+
await fs_extra_1.default.ensureDir(dataPath);
|
|
461
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(dataPath, 'database.json'), { users: [] }, { spaces: 2 });
|
|
462
|
+
}
|
|
463
|
+
async function generateBackendDeployment(backendPath, config) {
|
|
464
|
+
// Render configuration
|
|
465
|
+
const renderYaml = `services:
|
|
466
|
+
- type: web
|
|
467
|
+
name: ${config.projectName}-backend
|
|
468
|
+
env: node
|
|
469
|
+
buildCommand: npm install && npm run build
|
|
470
|
+
startCommand: npm run start:prod
|
|
471
|
+
envVars:
|
|
472
|
+
- key: NODE_ENV
|
|
473
|
+
value: production
|
|
474
|
+
- key: PORT
|
|
475
|
+
value: 3001
|
|
476
|
+
`;
|
|
477
|
+
await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'render.yaml'), renderYaml);
|
|
478
|
+
}
|