nestforge-generator 0.1.1 → 0.3.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 +39 -23
- package/README.pt-BR.md +39 -23
- package/dist/features/database.js +35 -0
- package/dist/features/database.js.map +1 -1
- package/dist/features/language.js +19 -1
- package/dist/features/language.js.map +1 -1
- package/dist/features/no-orm.js +493 -0
- package/dist/features/no-orm.js.map +1 -0
- package/dist/generator.js +27 -7
- package/dist/generator.js.map +1 -1
- package/dist/index.js +24 -13
- package/dist/index.js.map +1 -1
- package/dist/prompts.js +32 -22
- package/dist/prompts.js.map +1 -1
- package/package.json +2 -1
- package/templates/drizzle/README.md +2 -0
- package/templates/drizzle/README.pt-BR.md +2 -0
- package/templates/prisma/.github/workflows/ci.yml +24 -1
- package/templates/prisma/ARCHITECTURE.md +7 -1
- package/templates/prisma/ARCHITECTURE.pt-BR.md +7 -1
- package/templates/prisma/README.md +11 -7
- package/templates/prisma/README.pt-BR.md +11 -7
- package/templates/prisma/ROADMAP.md +5 -1
- package/templates/prisma/ROADMAP.pt-BR.md +5 -1
- package/templates/prisma/TESTING.md +25 -3
- package/templates/prisma/TESTING.pt-BR.md +25 -3
- package/templates/prisma/docker-compose.yml +29 -1
- package/templates/prisma/docs/adding-a-module.md +246 -230
- package/templates/prisma/docs/features-markers.md +11 -1
- package/templates/prisma/prisma/schema.prisma +4 -0
- package/templates/prisma/src/auth/token.service.ts +12 -3
- package/templates/prisma/src/health/indicators/prisma-health.indicator.spec.ts +39 -22
- package/templates/prisma/src/health/indicators/prisma-health.indicator.ts +24 -19
- package/templates/typeorm/README.md +2 -0
- package/templates/typeorm/README.pt-BR.md +2 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const ORM_PATHS = [
|
|
4
|
+
'prisma',
|
|
5
|
+
'src/database',
|
|
6
|
+
'src/health/indicators/prisma-health.indicator.ts',
|
|
7
|
+
'src/health/indicators/prisma-health.indicator.spec.ts',
|
|
8
|
+
'src/common/utils/avatar-storage.util.ts',
|
|
9
|
+
'src/common/utils/hash.util.ts',
|
|
10
|
+
'test/utils/clean-database.ts',
|
|
11
|
+
'docs',
|
|
12
|
+
'ARCHITECTURE.md',
|
|
13
|
+
'ARCHITECTURE.pt-BR.md',
|
|
14
|
+
'ROADMAP.md',
|
|
15
|
+
'ROADMAP.pt-BR.md',
|
|
16
|
+
'TESTING.md',
|
|
17
|
+
'TESTING.pt-BR.md',
|
|
18
|
+
];
|
|
19
|
+
const AUTH_PACKAGES = [
|
|
20
|
+
'@nestjs/jwt',
|
|
21
|
+
'@nestjs/passport',
|
|
22
|
+
'@quixo3/prisma-session-store',
|
|
23
|
+
'@prisma/client',
|
|
24
|
+
'bcryptjs',
|
|
25
|
+
'express-session',
|
|
26
|
+
'multer',
|
|
27
|
+
'passport',
|
|
28
|
+
'passport-github2',
|
|
29
|
+
'passport-google-oauth20',
|
|
30
|
+
'passport-jwt',
|
|
31
|
+
'@types/bcryptjs',
|
|
32
|
+
'@types/express-session',
|
|
33
|
+
'@types/multer',
|
|
34
|
+
'@types/passport-github2',
|
|
35
|
+
'@types/passport-google-oauth20',
|
|
36
|
+
'@types/passport-jwt',
|
|
37
|
+
'prisma',
|
|
38
|
+
'ts-node',
|
|
39
|
+
];
|
|
40
|
+
export async function applyNoOrmTransform(targetDir, enabledFeatures) {
|
|
41
|
+
for (const relativePath of ORM_PATHS) {
|
|
42
|
+
await fs.remove(path.join(targetDir, relativePath));
|
|
43
|
+
}
|
|
44
|
+
await updatePackageJson(targetDir);
|
|
45
|
+
await writeApplicationModule(targetDir, enabledFeatures);
|
|
46
|
+
await writeHealthFiles(targetDir, enabledFeatures);
|
|
47
|
+
await writeEnvironmentFiles(targetDir);
|
|
48
|
+
await writeDockerFiles(targetDir, enabledFeatures);
|
|
49
|
+
await writeCiWorkflow(targetDir, enabledFeatures);
|
|
50
|
+
await writeReadmes(targetDir, enabledFeatures);
|
|
51
|
+
await writeDatabaseFreeTests(targetDir);
|
|
52
|
+
}
|
|
53
|
+
async function updatePackageJson(targetDir) {
|
|
54
|
+
const packagePath = path.join(targetDir, 'package.json');
|
|
55
|
+
const packageJson = await fs.readJson(packagePath);
|
|
56
|
+
packageJson.description =
|
|
57
|
+
'Production-ready NestJS starter without an ORM or database integration.';
|
|
58
|
+
delete packageJson.prisma;
|
|
59
|
+
delete packageJson.scripts['pretest:e2e'];
|
|
60
|
+
for (const scriptName of Object.keys(packageJson.scripts)) {
|
|
61
|
+
if (scriptName.startsWith('prisma:')) {
|
|
62
|
+
delete packageJson.scripts[scriptName];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const packageName of AUTH_PACKAGES) {
|
|
66
|
+
delete packageJson.dependencies?.[packageName];
|
|
67
|
+
delete packageJson.devDependencies?.[packageName];
|
|
68
|
+
}
|
|
69
|
+
packageJson.devDependencies['@types/express'] ??= '^5.0.0';
|
|
70
|
+
await fs.writeJson(packagePath, packageJson, { spaces: 2 });
|
|
71
|
+
}
|
|
72
|
+
async function writeApplicationModule(targetDir, enabledFeatures) {
|
|
73
|
+
const redisEnabled = enabledFeatures.has('redis');
|
|
74
|
+
const redisImport = redisEnabled
|
|
75
|
+
? "import { BullModule } from '@nestjs/bullmq';\nimport { MailModule } from './mail/mail.module';\n"
|
|
76
|
+
: '';
|
|
77
|
+
const redisModules = redisEnabled
|
|
78
|
+
? `
|
|
79
|
+
BullModule.forRoot({
|
|
80
|
+
connection: {
|
|
81
|
+
host: process.env.REDIS_HOST ?? 'localhost',
|
|
82
|
+
port: Number(process.env.REDIS_PORT ?? 6379),
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
MailModule,`
|
|
86
|
+
: '';
|
|
87
|
+
await writeText(targetDir, 'src/app.module.ts', `import { Module } from '@nestjs/common';
|
|
88
|
+
import { ConfigModule } from '@nestjs/config';
|
|
89
|
+
import { ThrottlerModule } from '@nestjs/throttler';
|
|
90
|
+
${redisImport}import { LoggerModule } from 'nestjs-pino';
|
|
91
|
+
import { HealthModule } from './health/health.module';
|
|
92
|
+
import { MetricsModule } from './metrics/metrics.module';
|
|
93
|
+
import { validateEnv } from './config/env.validation';
|
|
94
|
+
|
|
95
|
+
@Module({
|
|
96
|
+
imports: [
|
|
97
|
+
ConfigModule.forRoot({
|
|
98
|
+
isGlobal: true,
|
|
99
|
+
validate: validateEnv,
|
|
100
|
+
}),
|
|
101
|
+
LoggerModule.forRoot({
|
|
102
|
+
pinoHttp: {
|
|
103
|
+
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
|
|
104
|
+
transport:
|
|
105
|
+
process.env.NODE_ENV === 'development'
|
|
106
|
+
? { target: 'pino-pretty', options: { singleLine: true } }
|
|
107
|
+
: undefined,
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
ThrottlerModule.forRoot([
|
|
111
|
+
{
|
|
112
|
+
ttl: Number(process.env.THROTTLE_TTL ?? 60) * 1000,
|
|
113
|
+
limit: Number(process.env.THROTTLE_LIMIT ?? 100),
|
|
114
|
+
},
|
|
115
|
+
]),${redisModules}
|
|
116
|
+
HealthModule,
|
|
117
|
+
MetricsModule,
|
|
118
|
+
],
|
|
119
|
+
})
|
|
120
|
+
export class AppModule {}
|
|
121
|
+
`);
|
|
122
|
+
}
|
|
123
|
+
async function writeHealthFiles(targetDir, enabledFeatures) {
|
|
124
|
+
const redisEnabled = enabledFeatures.has('redis');
|
|
125
|
+
const redisImport = redisEnabled
|
|
126
|
+
? "import { RedisHealthIndicator } from './indicators/redis-health.indicator';\n"
|
|
127
|
+
: '';
|
|
128
|
+
const redisConstructor = redisEnabled
|
|
129
|
+
? ' private readonly redisIndicator: RedisHealthIndicator,\n'
|
|
130
|
+
: '';
|
|
131
|
+
const redisCheck = redisEnabled
|
|
132
|
+
? " () => this.redisIndicator.isHealthy('redis'),\n"
|
|
133
|
+
: '';
|
|
134
|
+
const redisProvider = redisEnabled ? ' RedisHealthIndicator,\n' : '';
|
|
135
|
+
await writeText(targetDir, 'src/health/health.controller.ts', `import { Controller, Get } from '@nestjs/common';
|
|
136
|
+
import {
|
|
137
|
+
DiskHealthIndicator,
|
|
138
|
+
HealthCheck,
|
|
139
|
+
HealthCheckService,
|
|
140
|
+
MemoryHealthIndicator,
|
|
141
|
+
} from '@nestjs/terminus';
|
|
142
|
+
${redisImport}import { Public } from '../common/decorators/public.decorator';
|
|
143
|
+
|
|
144
|
+
@Controller('health')
|
|
145
|
+
export class HealthController {
|
|
146
|
+
constructor(
|
|
147
|
+
private readonly health: HealthCheckService,
|
|
148
|
+
${redisConstructor} private readonly memory: MemoryHealthIndicator,
|
|
149
|
+
private readonly disk: DiskHealthIndicator,
|
|
150
|
+
) {}
|
|
151
|
+
|
|
152
|
+
@Public()
|
|
153
|
+
@Get()
|
|
154
|
+
@HealthCheck()
|
|
155
|
+
check() {
|
|
156
|
+
return this.health.check([
|
|
157
|
+
${redisCheck} () => this.memory.checkHeap('memory_heap', 300 * 1024 * 1024),
|
|
158
|
+
() => this.memory.checkRSS('memory_rss', 300 * 1024 * 1024),
|
|
159
|
+
() => this.disk.checkStorage('disk', { path: '/', thresholdPercent: 0.9 }),
|
|
160
|
+
]);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
`);
|
|
164
|
+
await writeText(targetDir, 'src/health/health.module.ts', `import { Module } from '@nestjs/common';
|
|
165
|
+
import { TerminusModule } from '@nestjs/terminus';
|
|
166
|
+
import { HealthController } from './health.controller';
|
|
167
|
+
${redisImport}
|
|
168
|
+
@Module({
|
|
169
|
+
imports: [TerminusModule],
|
|
170
|
+
controllers: [HealthController],
|
|
171
|
+
providers: [
|
|
172
|
+
${redisProvider} ],
|
|
173
|
+
})
|
|
174
|
+
export class HealthModule {}
|
|
175
|
+
`);
|
|
176
|
+
}
|
|
177
|
+
async function writeEnvironmentFiles(targetDir) {
|
|
178
|
+
await writeText(targetDir, '.env.example', `# App
|
|
179
|
+
NODE_ENV=development
|
|
180
|
+
PORT=3000
|
|
181
|
+
APP_URL=http://localhost:3000
|
|
182
|
+
CORS_ORIGINS=http://localhost:5173
|
|
183
|
+
|
|
184
|
+
# Redis
|
|
185
|
+
REDIS_HOST=localhost
|
|
186
|
+
REDIS_PORT=6379
|
|
187
|
+
|
|
188
|
+
# Mail (Mailpit in development)
|
|
189
|
+
MAIL_HOST=localhost
|
|
190
|
+
MAIL_PORT=1025
|
|
191
|
+
MAIL_FROM="NestForge <no-reply@nestforge.dev>"
|
|
192
|
+
|
|
193
|
+
# Rate limit
|
|
194
|
+
THROTTLE_TTL=60
|
|
195
|
+
THROTTLE_LIMIT=100
|
|
196
|
+
`);
|
|
197
|
+
await writeText(targetDir, '.env.test', `NODE_ENV=test
|
|
198
|
+
PORT=3000
|
|
199
|
+
APP_URL=http://localhost:3000
|
|
200
|
+
CORS_ORIGINS=http://localhost:5173
|
|
201
|
+
|
|
202
|
+
REDIS_HOST=localhost
|
|
203
|
+
REDIS_PORT=6379
|
|
204
|
+
|
|
205
|
+
MAIL_HOST=localhost
|
|
206
|
+
MAIL_PORT=1025
|
|
207
|
+
MAIL_FROM="NestForge <no-reply@nestforge.dev>"
|
|
208
|
+
|
|
209
|
+
THROTTLE_TTL=60
|
|
210
|
+
THROTTLE_LIMIT=1000
|
|
211
|
+
`);
|
|
212
|
+
await writeText(targetDir, 'src/config/env.validation.ts', `import { z } from 'zod';
|
|
213
|
+
|
|
214
|
+
const envSchema = z.object({
|
|
215
|
+
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
|
|
216
|
+
PORT: z.coerce.number().default(3000),
|
|
217
|
+
APP_URL: z.string().url().default('http://localhost:3000'),
|
|
218
|
+
CORS_ORIGINS: z.string().min(1).default('http://localhost:5173'),
|
|
219
|
+
REDIS_HOST: z.string().default('localhost'),
|
|
220
|
+
REDIS_PORT: z.coerce.number().default(6379),
|
|
221
|
+
MAIL_HOST: z.string().default('localhost'),
|
|
222
|
+
MAIL_PORT: z.coerce.number().default(1025),
|
|
223
|
+
MAIL_FROM: z.string().default('NestForge <no-reply@nestforge.dev>'),
|
|
224
|
+
THROTTLE_TTL: z.coerce.number().default(60),
|
|
225
|
+
THROTTLE_LIMIT: z.coerce.number().default(100),
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
export type EnvConfig = z.infer<typeof envSchema>;
|
|
229
|
+
|
|
230
|
+
export function validateEnv(config: Record<string, unknown>): EnvConfig {
|
|
231
|
+
const parsed = envSchema.safeParse(config);
|
|
232
|
+
|
|
233
|
+
if (!parsed.success) {
|
|
234
|
+
const issues = parsed.error.issues
|
|
235
|
+
.map((issue) => \`${'${issue.path.join(\'.\')}: ${issue.message}'}\`)
|
|
236
|
+
.join('\\n');
|
|
237
|
+
throw new Error(\`Invalid environment variables:\\n${'${issues}'}\`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return parsed.data;
|
|
241
|
+
}
|
|
242
|
+
`);
|
|
243
|
+
}
|
|
244
|
+
async function writeDockerFiles(targetDir, enabledFeatures) {
|
|
245
|
+
const dockerfilePath = path.join(targetDir, 'Dockerfile');
|
|
246
|
+
if (!(await fs.pathExists(dockerfilePath)))
|
|
247
|
+
return;
|
|
248
|
+
await fs.writeFile(dockerfilePath, `# --- Base ---
|
|
249
|
+
FROM node:20-alpine AS base
|
|
250
|
+
WORKDIR /app
|
|
251
|
+
COPY package*.json ./
|
|
252
|
+
|
|
253
|
+
# --- Dependencies ---
|
|
254
|
+
FROM base AS deps
|
|
255
|
+
RUN npm ci
|
|
256
|
+
|
|
257
|
+
# --- Development ---
|
|
258
|
+
FROM deps AS development
|
|
259
|
+
COPY . .
|
|
260
|
+
EXPOSE 3000
|
|
261
|
+
CMD ["npm", "run", "start:dev"]
|
|
262
|
+
|
|
263
|
+
# --- Build ---
|
|
264
|
+
FROM deps AS build
|
|
265
|
+
COPY . .
|
|
266
|
+
RUN npm run build
|
|
267
|
+
RUN npm prune --production
|
|
268
|
+
|
|
269
|
+
# --- Production ---
|
|
270
|
+
FROM node:20-alpine AS production
|
|
271
|
+
WORKDIR /app
|
|
272
|
+
ENV NODE_ENV=production
|
|
273
|
+
COPY --from=build /app/node_modules ./node_modules
|
|
274
|
+
COPY --from=build /app/dist ./dist
|
|
275
|
+
EXPOSE 3000
|
|
276
|
+
CMD ["node", "dist/main.js"]
|
|
277
|
+
`, 'utf-8');
|
|
278
|
+
const redisEnabled = enabledFeatures.has('redis');
|
|
279
|
+
const dependsOn = redisEnabled
|
|
280
|
+
? ` depends_on:
|
|
281
|
+
- redis
|
|
282
|
+
`
|
|
283
|
+
: '';
|
|
284
|
+
const redisServices = redisEnabled
|
|
285
|
+
? `
|
|
286
|
+
redis:
|
|
287
|
+
image: redis:7-alpine
|
|
288
|
+
container_name: nestforge-redis
|
|
289
|
+
restart: unless-stopped
|
|
290
|
+
ports:
|
|
291
|
+
- "6379:6379"
|
|
292
|
+
|
|
293
|
+
mailpit:
|
|
294
|
+
image: axllent/mailpit:latest
|
|
295
|
+
container_name: nestforge-mailpit
|
|
296
|
+
restart: unless-stopped
|
|
297
|
+
ports:
|
|
298
|
+
- "8025:8025"
|
|
299
|
+
- "1025:1025"
|
|
300
|
+
`
|
|
301
|
+
: '';
|
|
302
|
+
await writeText(targetDir, 'docker-compose.yml', `services:
|
|
303
|
+
api:
|
|
304
|
+
build:
|
|
305
|
+
context: .
|
|
306
|
+
dockerfile: Dockerfile
|
|
307
|
+
container_name: nestforge-api
|
|
308
|
+
ports:
|
|
309
|
+
- "3000:3000"
|
|
310
|
+
env_file:
|
|
311
|
+
- .env
|
|
312
|
+
${dependsOn} volumes:
|
|
313
|
+
- ./src:/app/src
|
|
314
|
+
command: npm run start:dev
|
|
315
|
+
${redisServices}`);
|
|
316
|
+
}
|
|
317
|
+
async function writeCiWorkflow(targetDir, enabledFeatures) {
|
|
318
|
+
const redisEnabled = enabledFeatures.has('redis');
|
|
319
|
+
const redisService = redisEnabled
|
|
320
|
+
? `
|
|
321
|
+
services:
|
|
322
|
+
redis:
|
|
323
|
+
image: redis:7-alpine
|
|
324
|
+
ports:
|
|
325
|
+
- 6379:6379
|
|
326
|
+
options: >-
|
|
327
|
+
--health-cmd "redis-cli ping"
|
|
328
|
+
--health-interval 10s
|
|
329
|
+
--health-timeout 5s
|
|
330
|
+
--health-retries 5
|
|
331
|
+
`
|
|
332
|
+
: '';
|
|
333
|
+
await writeText(targetDir, '.github/workflows/ci.yml', `name: CI
|
|
334
|
+
|
|
335
|
+
on:
|
|
336
|
+
push:
|
|
337
|
+
branches: [main]
|
|
338
|
+
pull_request:
|
|
339
|
+
branches: [main]
|
|
340
|
+
|
|
341
|
+
jobs:
|
|
342
|
+
build-test-lint:
|
|
343
|
+
runs-on: ubuntu-latest
|
|
344
|
+
${redisService}
|
|
345
|
+
steps:
|
|
346
|
+
- name: Checkout
|
|
347
|
+
uses: actions/checkout@v4
|
|
348
|
+
|
|
349
|
+
- name: Setup Node
|
|
350
|
+
uses: actions/setup-node@v4
|
|
351
|
+
with:
|
|
352
|
+
node-version: 20
|
|
353
|
+
cache: npm
|
|
354
|
+
|
|
355
|
+
- name: Install dependencies
|
|
356
|
+
run: npm ci
|
|
357
|
+
|
|
358
|
+
- name: Lint
|
|
359
|
+
run: npm run lint
|
|
360
|
+
|
|
361
|
+
- name: Build
|
|
362
|
+
run: npm run build
|
|
363
|
+
|
|
364
|
+
- name: Unit tests
|
|
365
|
+
run: npm test
|
|
366
|
+
|
|
367
|
+
- name: End-to-end tests
|
|
368
|
+
run: npm run test:e2e
|
|
369
|
+
`);
|
|
370
|
+
}
|
|
371
|
+
async function writeReadmes(targetDir, enabledFeatures) {
|
|
372
|
+
const english = ['health checks', 'metrics', 'structured logging', 'rate limiting'];
|
|
373
|
+
const portuguese = [
|
|
374
|
+
'verificações de saúde',
|
|
375
|
+
'métricas',
|
|
376
|
+
'logs estruturados',
|
|
377
|
+
'limitação de requisições',
|
|
378
|
+
];
|
|
379
|
+
if (enabledFeatures.has('docker')) {
|
|
380
|
+
english.push('Docker');
|
|
381
|
+
portuguese.push('Docker');
|
|
382
|
+
}
|
|
383
|
+
if (enabledFeatures.has('swagger')) {
|
|
384
|
+
english.push('Swagger/OpenAPI');
|
|
385
|
+
portuguese.push('Swagger/OpenAPI');
|
|
386
|
+
}
|
|
387
|
+
if (enabledFeatures.has('validation')) {
|
|
388
|
+
english.push('global Zod validation');
|
|
389
|
+
portuguese.push('validação global com Zod');
|
|
390
|
+
}
|
|
391
|
+
if (enabledFeatures.has('redis')) {
|
|
392
|
+
english.push('Redis, BullMQ, and email');
|
|
393
|
+
portuguese.push('Redis, BullMQ e e-mail');
|
|
394
|
+
}
|
|
395
|
+
const englishFeatures = english.map((feature) => `- ${feature}`).join('\n');
|
|
396
|
+
const portugueseFeatures = portuguese.map((feature) => `- ${feature}`).join('\n');
|
|
397
|
+
await writeText(targetDir, 'README.md', `# NestForge
|
|
398
|
+
|
|
399
|
+
**English** | [Português](README.pt-BR.md)
|
|
400
|
+
|
|
401
|
+
NestJS starter generated without an ORM, database integration, or authentication.
|
|
402
|
+
|
|
403
|
+
## Included features
|
|
404
|
+
|
|
405
|
+
${englishFeatures}
|
|
406
|
+
|
|
407
|
+
## Getting started
|
|
408
|
+
|
|
409
|
+
\`\`\`bash
|
|
410
|
+
npm install
|
|
411
|
+
cp .env.example .env
|
|
412
|
+
npm run start:dev
|
|
413
|
+
\`\`\`
|
|
414
|
+
|
|
415
|
+
## Tests
|
|
416
|
+
|
|
417
|
+
\`\`\`bash
|
|
418
|
+
npm test
|
|
419
|
+
npm run test:e2e
|
|
420
|
+
\`\`\`
|
|
421
|
+
`);
|
|
422
|
+
await writeText(targetDir, 'README.pt-BR.md', `# NestForge
|
|
423
|
+
|
|
424
|
+
[English](README.md) | **Português**
|
|
425
|
+
|
|
426
|
+
Starter NestJS gerado sem ORM, integração com banco de dados ou autenticação.
|
|
427
|
+
|
|
428
|
+
## Recursos incluídos
|
|
429
|
+
|
|
430
|
+
${portugueseFeatures}
|
|
431
|
+
|
|
432
|
+
## Primeiros passos
|
|
433
|
+
|
|
434
|
+
\`\`\`bash
|
|
435
|
+
npm install
|
|
436
|
+
cp .env.example .env
|
|
437
|
+
npm run start:dev
|
|
438
|
+
\`\`\`
|
|
439
|
+
|
|
440
|
+
## Testes
|
|
441
|
+
|
|
442
|
+
\`\`\`bash
|
|
443
|
+
npm test
|
|
444
|
+
npm run test:e2e
|
|
445
|
+
\`\`\`
|
|
446
|
+
`);
|
|
447
|
+
}
|
|
448
|
+
async function writeDatabaseFreeTests(targetDir) {
|
|
449
|
+
await writeText(targetDir, 'src/config/env.validation.spec.ts', `import { describe, expect, it } from 'vitest';
|
|
450
|
+
import { validateEnv } from './env.validation';
|
|
451
|
+
|
|
452
|
+
describe('validateEnv', () => {
|
|
453
|
+
it('uses safe defaults without requiring database variables', () => {
|
|
454
|
+
const config = validateEnv({ NODE_ENV: 'test' });
|
|
455
|
+
|
|
456
|
+
expect(config.NODE_ENV).toBe('test');
|
|
457
|
+
expect(config.PORT).toBe(3000);
|
|
458
|
+
expect(config).not.toHaveProperty('DATABASE_URL');
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
`);
|
|
462
|
+
await writeText(targetDir, 'test/app.e2e-spec.ts', `import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
463
|
+
import request from 'supertest';
|
|
464
|
+
import type { INestApplication } from '@nestjs/common';
|
|
465
|
+
import { createTestApp } from './utils/e2e-setup';
|
|
466
|
+
|
|
467
|
+
describe('Application (e2e)', () => {
|
|
468
|
+
let app: INestApplication;
|
|
469
|
+
|
|
470
|
+
beforeAll(async () => {
|
|
471
|
+
app = await createTestApp();
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
afterAll(async () => {
|
|
475
|
+
await app.close();
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it('exposes application metrics without a database', async () => {
|
|
479
|
+
const response = await request(app.getHttpServer())
|
|
480
|
+
.get('/metrics')
|
|
481
|
+
.expect(200);
|
|
482
|
+
|
|
483
|
+
expect(response.text).toContain('# HELP');
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
`);
|
|
487
|
+
}
|
|
488
|
+
async function writeText(targetDir, relativePath, content) {
|
|
489
|
+
const filePath = path.join(targetDir, relativePath);
|
|
490
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
491
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=no-orm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-orm.js","sourceRoot":"","sources":["../../src/features/no-orm.ts"],"names":[],"mappings":"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"}
|
package/dist/generator.js
CHANGED
|
@@ -6,6 +6,7 @@ import { removeDisabledDependencies } from './features/dependencies.js';
|
|
|
6
6
|
import { applyDatabaseConfig } from './features/database.js';
|
|
7
7
|
import { applyAuthStrategyRemoval } from './features/auth-strategy.js';
|
|
8
8
|
import { applyLanguageTransform } from './features/language.js';
|
|
9
|
+
import { applyNoOrmTransform } from './features/no-orm.js';
|
|
9
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
11
|
const PACKAGE_TEMPLATES_ROOT = path.resolve(__dirname, '../templates');
|
|
11
12
|
const MONOREPO_TEMPLATES_ROOT = path.resolve(__dirname, '../../../templates');
|
|
@@ -14,9 +15,10 @@ const IMPLEMENTED_ORMS = [
|
|
|
14
15
|
'prisma',
|
|
15
16
|
'typeorm',
|
|
16
17
|
'drizzle',
|
|
18
|
+
'none',
|
|
17
19
|
];
|
|
18
20
|
const IMPLEMENTED_LANGUAGES = ['typescript', 'javascript'];
|
|
19
|
-
const IMPLEMENTED_DATABASES = ['postgres', 'mysql', 'sqlite'];
|
|
21
|
+
const IMPLEMENTED_DATABASES = ['postgres', 'mysql', 'sqlite', 'mongodb'];
|
|
20
22
|
const IMPLEMENTED_AUTH_STRATEGIES = ['jwt', 'session', 'oauth', 'none'];
|
|
21
23
|
async function resolveTemplatesRoot() {
|
|
22
24
|
if (await fs.pathExists(PACKAGE_TEMPLATES_ROOT)) {
|
|
@@ -29,20 +31,30 @@ export async function generateProject(options) {
|
|
|
29
31
|
if (!IMPLEMENTED_LANGUAGES.includes(language)) {
|
|
30
32
|
throw new Error(`Generation in "${language}" is not ready yet — only "typescript" is currently implemented. Contributions are welcome!`);
|
|
31
33
|
}
|
|
32
|
-
if (orm === 'none') {
|
|
33
|
-
throw new Error('A template without an ORM is not available yet. Choose "prisma", "typeorm", or "drizzle".');
|
|
34
|
-
}
|
|
35
34
|
if (!IMPLEMENTED_ORMS.includes(orm)) {
|
|
36
35
|
throw new Error(`The template for "${orm}" is not ready yet — currently available: ${IMPLEMENTED_ORMS.join(', ')}. Contributions are welcome!`);
|
|
37
36
|
}
|
|
38
|
-
if (
|
|
37
|
+
if (orm === 'none' && database !== 'none') {
|
|
38
|
+
throw new Error('Projects without an ORM must use "none" as their database option.');
|
|
39
|
+
}
|
|
40
|
+
if (orm !== 'none' && !IMPLEMENTED_DATABASES.includes(database)) {
|
|
39
41
|
throw new Error(`The "${database}" database is not ready yet — currently implemented: ${IMPLEMENTED_DATABASES.join(', ')}. Contributions are welcome!`);
|
|
40
42
|
}
|
|
43
|
+
if (database === 'mongodb' && orm !== 'prisma') {
|
|
44
|
+
throw new Error('MongoDB is currently available only with Prisma.');
|
|
45
|
+
}
|
|
46
|
+
if (orm === 'none' && authStrategy !== 'none') {
|
|
47
|
+
throw new Error('Projects without an ORM currently support only the "none" authentication strategy.');
|
|
48
|
+
}
|
|
49
|
+
if (orm === 'none' && accessControl) {
|
|
50
|
+
throw new Error('Access control requires authentication and is not available without an ORM.');
|
|
51
|
+
}
|
|
41
52
|
if (!IMPLEMENTED_AUTH_STRATEGIES.includes(authStrategy)) {
|
|
42
53
|
throw new Error(`The "${authStrategy}" authentication strategy is not ready yet — currently implemented: ${IMPLEMENTED_AUTH_STRATEGIES.join(', ')} ("jwt" already includes Google/GitHub OAuth). Contributions are welcome!`);
|
|
43
54
|
}
|
|
44
55
|
const templatesRoot = await resolveTemplatesRoot();
|
|
45
|
-
const
|
|
56
|
+
const templateName = orm === 'none' ? 'prisma' : orm;
|
|
57
|
+
const templateDir = path.join(templatesRoot, templateName);
|
|
46
58
|
const targetDir = path.resolve(process.cwd(), projectName);
|
|
47
59
|
if (await fs.pathExists(targetDir)) {
|
|
48
60
|
throw new Error(`The "${projectName}" directory already exists. Choose another name or remove the directory.`);
|
|
@@ -50,10 +62,15 @@ export async function generateProject(options) {
|
|
|
50
62
|
await fs.copy(templateDir, targetDir);
|
|
51
63
|
const enabledFeatures = buildEnabledFeatures(features, accessControl, database, authStrategy);
|
|
52
64
|
await applyDockerToggle(targetDir, enabledFeatures);
|
|
53
|
-
|
|
65
|
+
if (orm !== 'none') {
|
|
66
|
+
await applyDatabaseConfig(targetDir, database);
|
|
67
|
+
}
|
|
54
68
|
await applyAuthStrategyRemoval(targetDir, enabledFeatures);
|
|
55
69
|
await applyFeatureMarkers(targetDir, enabledFeatures);
|
|
56
70
|
await removeDisabledDependencies(targetDir, enabledFeatures);
|
|
71
|
+
if (orm === 'none') {
|
|
72
|
+
await applyNoOrmTransform(targetDir, enabledFeatures);
|
|
73
|
+
}
|
|
57
74
|
await applyLanguageTransform(targetDir, language, orm);
|
|
58
75
|
await renameProject(targetDir, projectName);
|
|
59
76
|
if (createEnv) {
|
|
@@ -68,6 +85,9 @@ function buildEnabledFeatures(features, accessControl, database, authStrategy) {
|
|
|
68
85
|
}
|
|
69
86
|
enabled.add(`database:${database}`);
|
|
70
87
|
enabled.add(`auth:${authStrategy}`);
|
|
88
|
+
if (['postgres', 'mysql', 'sqlite'].includes(database)) {
|
|
89
|
+
enabled.add('database:relational');
|
|
90
|
+
}
|
|
71
91
|
if (authStrategy !== 'none') {
|
|
72
92
|
enabled.add('auth:enabled');
|
|
73
93
|
}
|
package/dist/generator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,9 @@ async function main() {
|
|
|
10
10
|
const targetDir = await generateProject(options);
|
|
11
11
|
const relativeDir = path.relative(process.cwd(), targetDir) || '.';
|
|
12
12
|
const dockerServices = [
|
|
13
|
-
|
|
13
|
+
!['sqlite', 'none'].includes(options.database)
|
|
14
|
+
? options.database
|
|
15
|
+
: null,
|
|
14
16
|
options.features.includes('redis') ? 'redis' : null,
|
|
15
17
|
]
|
|
16
18
|
.filter(Boolean)
|
|
@@ -22,21 +24,30 @@ async function main() {
|
|
|
22
24
|
const seedSteps = shouldRunSeed
|
|
23
25
|
? ['npm run seed']
|
|
24
26
|
: [];
|
|
25
|
-
const databaseSteps = options.orm === '
|
|
26
|
-
? [
|
|
27
|
-
|
|
28
|
-
'npm run migration:run',
|
|
29
|
-
...seedSteps,
|
|
30
|
-
]
|
|
31
|
-
: options.orm === 'drizzle'
|
|
27
|
+
const databaseSteps = options.orm === 'none'
|
|
28
|
+
? []
|
|
29
|
+
: options.orm === 'typeorm'
|
|
32
30
|
? [
|
|
33
|
-
'npm run
|
|
34
|
-
'npm run
|
|
31
|
+
'npm run migration:generate -- src/database/migrations/InitialSchema',
|
|
32
|
+
'npm run migration:run',
|
|
35
33
|
...seedSteps,
|
|
36
34
|
]
|
|
37
|
-
:
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
: options.orm === 'drizzle'
|
|
36
|
+
? [
|
|
37
|
+
'npm run drizzle:generate',
|
|
38
|
+
'npm run drizzle:migrate',
|
|
39
|
+
...seedSteps,
|
|
40
|
+
]
|
|
41
|
+
: [
|
|
42
|
+
...(options.database === 'mongodb'
|
|
43
|
+
? [
|
|
44
|
+
'npm run prisma:push',
|
|
45
|
+
...(shouldRunSeed
|
|
46
|
+
? ['npm run prisma:seed']
|
|
47
|
+
: []),
|
|
48
|
+
]
|
|
49
|
+
: ['npx prisma migrate dev']),
|
|
50
|
+
];
|
|
40
51
|
const steps = [
|
|
41
52
|
`cd ${relativeDir}`,
|
|
42
53
|
...(options.createEnv ? [] : ['cp .env.example .env']),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,KAAK,UAAU,IAAI;IACf,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,IAAI,GAAG,CAAC;QACnE,MAAM,cAAc,GAAG;YACnB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|