create-forgeon 0.1.30 → 0.1.32

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-forgeon",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Forgeon project generator CLI",
5
5
  "license": "MIT",
6
6
  "author": "Forgeon",
@@ -299,6 +299,12 @@ describe('addModule', () => {
299
299
  assert.match(apiDockerfile, /COPY packages\/logger packages\/logger/);
300
300
  assert.match(apiDockerfile, /RUN pnpm --filter @forgeon\/logger build/);
301
301
 
302
+ const loggerTsconfig = fs.readFileSync(
303
+ path.join(projectRoot, 'packages', 'logger', 'tsconfig.json'),
304
+ 'utf8',
305
+ );
306
+ assert.match(loggerTsconfig, /"extends": "\.\.\/\.\.\/tsconfig\.base\.node\.json"/);
307
+
302
308
  const apiEnv = fs.readFileSync(path.join(projectRoot, 'apps', 'api', '.env.example'), 'utf8');
303
309
  assert.match(apiEnv, /LOGGER_LEVEL=log/);
304
310
  assert.match(apiEnv, /LOGGER_HTTP_ENABLED=true/);
@@ -317,6 +323,11 @@ describe('addModule', () => {
317
323
  assert.match(compose, /LOGGER_HTTP_ENABLED: \$\{LOGGER_HTTP_ENABLED\}/);
318
324
  assert.match(compose, /LOGGER_REQUEST_ID_HEADER: \$\{LOGGER_REQUEST_ID_HEADER\}/);
319
325
 
326
+ const rootReadme = fs.readFileSync(path.join(projectRoot, 'README.md'), 'utf8');
327
+ assert.match(rootReadme, /## Logger Module/);
328
+ assert.match(rootReadme, /LOGGER_LEVEL=log/);
329
+ assert.match(rootReadme, /docker compose logs api/);
330
+
320
331
  const moduleDoc = fs.readFileSync(result.docsPath, 'utf8');
321
332
  assert.match(moduleDoc, /Logger/);
322
333
  assert.match(moduleDoc, /Status: implemented/);
@@ -218,6 +218,44 @@ function patchCompose(targetRoot) {
218
218
  fs.writeFileSync(composePath, `${content.trimEnd()}\n`, 'utf8');
219
219
  }
220
220
 
221
+ function patchReadme(targetRoot) {
222
+ const readmePath = path.join(targetRoot, 'README.md');
223
+ if (!fs.existsSync(readmePath)) {
224
+ return;
225
+ }
226
+
227
+ const marker = '## Logger Module';
228
+ let content = fs.readFileSync(readmePath, 'utf8').replace(/\r\n/g, '\n');
229
+ if (content.includes(marker)) {
230
+ return;
231
+ }
232
+
233
+ const section = `## Logger Module
234
+
235
+ The logger add-module provides:
236
+ - request id middleware (default header: \`x-request-id\`)
237
+ - HTTP access logs with method/path/status/duration/ip/requestId
238
+ - Nest logger integration via \`app.useLogger(...)\`
239
+
240
+ Configuration (env):
241
+ - \`LOGGER_LEVEL=log\` (\`error|warn|log|debug|verbose\`)
242
+ - \`LOGGER_HTTP_ENABLED=true\`
243
+ - \`LOGGER_REQUEST_ID_HEADER=x-request-id\`
244
+
245
+ Where to see logs:
246
+ - local dev: API terminal output
247
+ - Docker: \`docker compose logs api\`
248
+ `;
249
+
250
+ if (content.includes('## Prisma In Docker Start')) {
251
+ content = content.replace('## Prisma In Docker Start', `${section}\n## Prisma In Docker Start`);
252
+ } else {
253
+ content = `${content.trimEnd()}\n\n${section}\n`;
254
+ }
255
+
256
+ fs.writeFileSync(readmePath, `${content.trimEnd()}\n`, 'utf8');
257
+ }
258
+
221
259
  export function applyLoggerModule({ packageRoot, targetRoot }) {
222
260
  copyFromPreset(packageRoot, targetRoot, path.join('packages', 'logger'));
223
261
  patchApiPackage(targetRoot);
@@ -225,6 +263,7 @@ export function applyLoggerModule({ packageRoot, targetRoot }) {
225
263
  patchAppModule(targetRoot);
226
264
  patchApiDockerfile(targetRoot);
227
265
  patchCompose(targetRoot);
266
+ patchReadme(targetRoot);
228
267
 
229
268
  upsertEnvLines(path.join(targetRoot, 'apps', 'api', '.env.example'), [
230
269
  'LOGGER_LEVEL=log',
@@ -238,4 +277,3 @@ export function applyLoggerModule({ packageRoot, targetRoot }) {
238
277
  'LOGGER_REQUEST_ID_HEADER=x-request-id',
239
278
  ]);
240
279
  }
241
-
@@ -1,5 +1,5 @@
1
1
  import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
2
- import { Observable, tap } from 'rxjs';
2
+ import { Observable } from 'rxjs';
3
3
  import { ForgeonLoggerService } from './forgeon-logger.service';
4
4
  import { LoggerConfigService } from './logger-config.service';
5
5
 
@@ -17,6 +17,7 @@ interface RequestLike {
17
17
 
18
18
  interface ResponseLike {
19
19
  statusCode?: number;
20
+ once?: (event: string, listener: () => void) => void;
20
21
  }
21
22
 
22
23
  @Injectable()
@@ -46,30 +47,34 @@ export class ForgeonHttpLoggingInterceptor implements NestInterceptor {
46
47
  request.requestId ?? this.readHeader(request.headers, this.loggerConfig.requestIdHeader);
47
48
  const startedAt = Date.now();
48
49
 
49
- return next.handle().pipe(
50
- tap({
51
- next: () => {
52
- this.logger.logHttpRequest({
53
- method,
54
- path,
55
- statusCode: response.statusCode ?? 200,
56
- durationMs: Date.now() - startedAt,
57
- requestId,
58
- ip,
59
- });
60
- },
61
- error: () => {
62
- this.logger.logHttpRequest({
63
- method,
64
- path,
65
- statusCode: response.statusCode ?? 500,
66
- durationMs: Date.now() - startedAt,
67
- requestId,
68
- ip,
69
- });
70
- },
71
- }),
72
- );
50
+ if (typeof response.once === 'function') {
51
+ response.once('finish', () => {
52
+ this.logger.logHttpRequest({
53
+ method,
54
+ path,
55
+ statusCode: response.statusCode ?? 200,
56
+ durationMs: Date.now() - startedAt,
57
+ requestId,
58
+ ip,
59
+ });
60
+ });
61
+ } else {
62
+ // Fallback for non-standard response mocks.
63
+ try {
64
+ this.logger.logHttpRequest({
65
+ method,
66
+ path,
67
+ statusCode: response.statusCode ?? 200,
68
+ durationMs: Date.now() - startedAt,
69
+ requestId,
70
+ ip,
71
+ });
72
+ } catch {
73
+ // no-op
74
+ }
75
+ }
76
+
77
+ return next.handle();
73
78
  }
74
79
 
75
80
  private readHeader(headers: HeadersRecord | undefined, name: string): string | undefined {
@@ -87,4 +92,3 @@ export class ForgeonHttpLoggingInterceptor implements NestInterceptor {
87
92
  return undefined;
88
93
  }
89
94
  }
90
-
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "../../../../../tsconfig.base.node.json",
2
+ "extends": "../../tsconfig.base.node.json",
3
3
  "compilerOptions": {
4
4
  "rootDir": "src",
5
5
  "outDir": "dist",
@@ -7,4 +7,3 @@
7
7
  },
8
8
  "include": ["src/**/*.ts"]
9
9
  }
10
-