@openapi-typescript-infra/service 5.6.0 → 5.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openapi-typescript-infra/service",
3
- "version": "5.6.0",
3
+ "version": "5.7.0",
4
4
  "description": "An opinionated framework for building configuration driven services - web, api, or ob. Uses OpenAPI, pino logging, express, confit, Typescript and vitest.",
5
5
  "exports": {
6
6
  ".": {
@@ -10,6 +10,7 @@ import { ConfigurationSchema } from '../config/schema.js';
10
10
  import { getNodeEnv } from '../env.js';
11
11
 
12
12
  const LOG_PREFS = Symbol('Logging information');
13
+ const LOGGED_SEMAPHORE = Symbol('Logged semaphore');
13
14
 
14
15
  interface LogPrefs {
15
16
  start: [number, number];
@@ -57,9 +58,13 @@ function finishLog<SLocals extends AnyServiceLocals = ServiceLocals<Configuratio
57
58
  app: ServiceExpress<SLocals>,
58
59
  error: Error | undefined,
59
60
  req: Request,
60
- res: Response,
61
+ res: Response & { [LOGGED_SEMAPHORE]?: boolean },
61
62
  histogram: Histogram,
62
63
  ) {
64
+ if (res[LOGGED_SEMAPHORE]) {
65
+ return;
66
+ }
67
+
63
68
  const prefs = (res.locals as WithLogPrefs)[LOG_PREFS];
64
69
  if (prefs.logged) {
65
70
  // This happens when error handler runs, but onEnd hasn't fired yet. We only log the first one.
@@ -71,9 +76,22 @@ function finishLog<SLocals extends AnyServiceLocals = ServiceLocals<Configuratio
71
76
 
72
77
  const dur = hrdur[0] + hrdur[1] / 1000000000;
73
78
  const [url, preInfo] = getBasicInfo(req);
79
+
80
+ let responseType: string = 'finished';
81
+
82
+ // ts warning is known and incorrect—`aborted` is a subset of `destroyed`
83
+ if (req.aborted) {
84
+ responseType = 'aborted';
85
+ } else if (req.destroyed) {
86
+ responseType = 'destroyed';
87
+ } else if (error) {
88
+ responseType = 'errored';
89
+ }
90
+
74
91
  const endLog: Record<string, string | string[] | number | undefined> = {
75
92
  ...preInfo,
76
93
  t: 'req',
94
+ r: responseType,
77
95
  s: (error as ErrorWithStatus)?.status || res.statusCode || 0,
78
96
  dur,
79
97
  };
@@ -124,6 +142,8 @@ function finishLog<SLocals extends AnyServiceLocals = ServiceLocals<Configuratio
124
142
  } else {
125
143
  logger.info(endLog, msg);
126
144
  }
145
+
146
+ res[LOGGED_SEMAPHORE] = true;
127
147
  }
128
148
 
129
149
  export function loggerMiddleware<
@@ -180,8 +200,10 @@ export function loggerMiddleware<
180
200
  logger.info(preLog, msg);
181
201
  }
182
202
 
183
- const logWriter = () => finishLog(app, undefined, req, res, histogram);
203
+ const logWriter = (err?: Error) => finishLog(app, err, req, res, histogram);
184
204
  res.on('finish', logWriter);
205
+ res.on('close', logWriter);
206
+ res.on('error', logWriter);
185
207
  next();
186
208
  };
187
209
  }