@unito/integration-sdk 1.0.26 → 1.0.28

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.
Files changed (68) hide show
  1. package/dist/src/helpers.d.ts +2 -2
  2. package/dist/src/helpers.js +2 -2
  3. package/dist/src/index.cjs +267 -215
  4. package/dist/src/integration.js +8 -8
  5. package/dist/src/middlewares/correlationId.d.ts +2 -2
  6. package/dist/src/middlewares/correlationId.js +3 -3
  7. package/dist/src/middlewares/credentials.d.ts +2 -2
  8. package/dist/src/middlewares/credentials.js +3 -3
  9. package/dist/src/middlewares/errors.d.ts +2 -2
  10. package/dist/src/middlewares/errors.js +3 -3
  11. package/dist/src/middlewares/filters.d.ts +2 -2
  12. package/dist/src/middlewares/filters.js +4 -4
  13. package/dist/src/middlewares/finish.d.ts +2 -2
  14. package/dist/src/middlewares/finish.js +3 -3
  15. package/dist/src/middlewares/logger.d.ts +2 -2
  16. package/dist/src/middlewares/logger.js +3 -3
  17. package/dist/src/middlewares/notFound.d.ts +2 -2
  18. package/dist/src/middlewares/notFound.js +3 -3
  19. package/dist/src/middlewares/secrets.d.ts +2 -2
  20. package/dist/src/middlewares/secrets.js +3 -3
  21. package/dist/src/middlewares/selects.d.ts +2 -2
  22. package/dist/src/middlewares/selects.js +3 -3
  23. package/dist/src/middlewares/signal.d.ts +2 -2
  24. package/dist/src/middlewares/signal.js +3 -3
  25. package/dist/src/middlewares/{requestStartTime.d.ts → start.d.ts} +2 -2
  26. package/dist/src/middlewares/{requestStartTime.js → start.js} +3 -3
  27. package/dist/src/resources/logger.d.ts +2 -1
  28. package/dist/src/resources/logger.js +59 -7
  29. package/dist/test/middlewares/correlationId.test.js +3 -3
  30. package/dist/test/middlewares/credentials.test.js +4 -4
  31. package/dist/test/middlewares/errors.test.js +4 -4
  32. package/dist/test/middlewares/filters.test.js +20 -12
  33. package/dist/test/middlewares/finish.test.js +4 -4
  34. package/dist/test/middlewares/logger.test.js +5 -5
  35. package/dist/test/middlewares/notFound.test.js +2 -2
  36. package/dist/test/middlewares/secrets.test.js +3 -3
  37. package/dist/test/middlewares/selects.test.js +3 -3
  38. package/dist/test/middlewares/signal.test.js +3 -3
  39. package/dist/test/middlewares/start.test.d.ts +1 -0
  40. package/dist/test/middlewares/start.test.js +11 -0
  41. package/dist/test/resources/logger.test.js +71 -45
  42. package/package.json +1 -1
  43. package/src/helpers.ts +2 -2
  44. package/src/integration.ts +8 -8
  45. package/src/middlewares/correlationId.ts +3 -3
  46. package/src/middlewares/credentials.ts +3 -3
  47. package/src/middlewares/errors.ts +3 -3
  48. package/src/middlewares/filters.ts +4 -4
  49. package/src/middlewares/finish.ts +3 -3
  50. package/src/middlewares/logger.ts +3 -3
  51. package/src/middlewares/notFound.ts +3 -3
  52. package/src/middlewares/secrets.ts +3 -3
  53. package/src/middlewares/selects.ts +3 -3
  54. package/src/middlewares/signal.ts +3 -3
  55. package/src/middlewares/{requestStartTime.ts → start.ts} +3 -3
  56. package/src/resources/logger.ts +66 -8
  57. package/test/middlewares/correlationId.test.ts +3 -3
  58. package/test/middlewares/credentials.test.ts +4 -4
  59. package/test/middlewares/errors.test.ts +4 -4
  60. package/test/middlewares/filters.test.ts +31 -12
  61. package/test/middlewares/finish.test.ts +4 -4
  62. package/test/middlewares/logger.test.ts +5 -5
  63. package/test/middlewares/notFound.test.ts +2 -2
  64. package/test/middlewares/secrets.test.ts +3 -3
  65. package/test/middlewares/selects.test.ts +3 -3
  66. package/test/middlewares/signal.test.ts +3 -3
  67. package/test/middlewares/start.test.ts +14 -0
  68. package/test/resources/logger.test.ts +82 -47
@@ -21,5 +21,5 @@ export type Filter = {
21
21
  operator: OperatorType;
22
22
  values: string[] | undefined;
23
23
  };
24
- declare const middleware: (req: Request, res: Response, next: NextFunction) => void;
25
- export default middleware;
24
+ declare function extractFilters(req: Request, res: Response, next: NextFunction): void;
25
+ export default extractFilters;
@@ -4,8 +4,8 @@ import { OperatorType } from '@unito/integration-api';
4
4
  // a subset of the symbol of another operator.
5
5
  //
6
6
  // For example, the symbol "=" (EQUAL) is a subset of the symbol "!=" (NOT_EQUAL).
7
- const ORDERED_OPERATORS = Object.values(OperatorType).sort((o1, o2) => o1.length - o2.length);
8
- const middleware = (req, res, next) => {
7
+ const ORDERED_OPERATORS = Object.values(OperatorType).sort((o1, o2) => o2.length - o1.length);
8
+ function extractFilters(req, res, next) {
9
9
  const rawFilters = req.query.filter;
10
10
  res.locals.filters = [];
11
11
  if (typeof rawFilters === 'string') {
@@ -21,5 +21,5 @@ const middleware = (req, res, next) => {
21
21
  }
22
22
  }
23
23
  next();
24
- };
25
- export default middleware;
24
+ }
25
+ export default extractFilters;
@@ -10,5 +10,5 @@ declare global {
10
10
  }
11
11
  }
12
12
  }
13
- declare const middleware: (req: Request, res: Response, next: NextFunction) => void;
14
- export default middleware;
13
+ declare function onFinish(req: Request, res: Response, next: NextFunction): void;
14
+ export default onFinish;
@@ -1,4 +1,4 @@
1
- const middleware = (req, res, next) => {
1
+ function onFinish(req, res, next) {
2
2
  if (req.originalUrl !== '/health') {
3
3
  res.on('finish', function () {
4
4
  const error = res.locals.error;
@@ -32,5 +32,5 @@ const middleware = (req, res, next) => {
32
32
  });
33
33
  }
34
34
  next();
35
- };
36
- export default middleware;
35
+ }
36
+ export default onFinish;
@@ -8,5 +8,5 @@ declare global {
8
8
  }
9
9
  }
10
10
  }
11
- declare const middleware: (req: Request, res: Response, next: NextFunction) => void;
12
- export default middleware;
11
+ declare function injectLogger(req: Request, res: Response, next: NextFunction): void;
12
+ export default injectLogger;
@@ -1,6 +1,6 @@
1
1
  import Logger from '../resources/logger.js';
2
2
  const ADDITIONAL_CONTEXT_HEADER = 'X-Unito-Additional-Logging-Context';
3
- const middleware = (req, res, next) => {
3
+ function injectLogger(req, res, next) {
4
4
  const logger = new Logger({ correlation_id: res.locals.correlationId });
5
5
  res.locals.logger = logger;
6
6
  const rawAdditionalContext = req.header(ADDITIONAL_CONTEXT_HEADER);
@@ -14,5 +14,5 @@ const middleware = (req, res, next) => {
14
14
  }
15
15
  }
16
16
  next();
17
- };
18
- export default middleware;
17
+ }
18
+ export default injectLogger;
@@ -1,3 +1,3 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
- declare const middleware: (req: Request, res: Response, _next: NextFunction) => void;
3
- export default middleware;
2
+ declare function notFound(req: Request, res: Response, _next: NextFunction): void;
3
+ export default notFound;
@@ -1,8 +1,8 @@
1
- const middleware = (req, res, _next) => {
1
+ function notFound(req, res, _next) {
2
2
  const error = {
3
3
  code: '404',
4
4
  message: `Path ${req.path} not found.`,
5
5
  };
6
6
  res.status(404).json(error);
7
- };
8
- export default middleware;
7
+ }
8
+ export default notFound;
@@ -14,5 +14,5 @@ declare global {
14
14
  export type Secrets = {
15
15
  [keys: string]: unknown;
16
16
  };
17
- declare const middleware: (req: Request, res: Response, next: NextFunction) => void;
18
- export default middleware;
17
+ declare function extractSecrets(req: Request, res: Response, next: NextFunction): void;
18
+ export default extractSecrets;
@@ -1,6 +1,6 @@
1
1
  import { BadRequestError } from '../httpErrors.js';
2
2
  const SECRETS_HEADER = 'X-Unito-Secrets';
3
- const middleware = (req, res, next) => {
3
+ function extractSecrets(req, res, next) {
4
4
  const secretsHeader = req.header(SECRETS_HEADER);
5
5
  if (secretsHeader) {
6
6
  let secrets;
@@ -13,5 +13,5 @@ const middleware = (req, res, next) => {
13
13
  res.locals.secrets = secrets;
14
14
  }
15
15
  next();
16
- };
17
- export default middleware;
16
+ }
17
+ export default extractSecrets;
@@ -6,5 +6,5 @@ declare global {
6
6
  }
7
7
  }
8
8
  }
9
- declare const middleware: (req: Request, res: Response, next: NextFunction) => void;
10
- export default middleware;
9
+ declare function extractSelects(req: Request, res: Response, next: NextFunction): void;
10
+ export default extractSelects;
@@ -1,4 +1,4 @@
1
- const middleware = (req, res, next) => {
1
+ function extractSelects(req, res, next) {
2
2
  const rawSelect = req.query.select;
3
3
  if (typeof rawSelect === 'string') {
4
4
  res.locals.selects = rawSelect.split(',');
@@ -7,5 +7,5 @@ const middleware = (req, res, next) => {
7
7
  res.locals.selects = [];
8
8
  }
9
9
  next();
10
- };
11
- export default middleware;
10
+ }
11
+ export default extractSelects;
@@ -11,5 +11,5 @@ declare global {
11
11
  }
12
12
  }
13
13
  }
14
- declare const middleware: (req: Request, res: Response, next: NextFunction) => void;
15
- export default middleware;
14
+ declare function extractOperationDeadline(req: Request, res: Response, next: NextFunction): void;
15
+ export default extractOperationDeadline;
@@ -1,6 +1,6 @@
1
1
  import { TimeoutError } from '../httpErrors.js';
2
2
  const OPERATION_DEADLINE_HEADER = 'X-Unito-Operation-Deadline';
3
- const middleware = (req, res, next) => {
3
+ function extractOperationDeadline(req, res, next) {
4
4
  const operationDeadlineHeader = Number(req.header(OPERATION_DEADLINE_HEADER));
5
5
  if (operationDeadlineHeader) {
6
6
  // `operationDeadlineHeader` represents a timestamp in the future, in seconds.
@@ -18,5 +18,5 @@ const middleware = (req, res, next) => {
18
18
  res.locals.signal = AbortSignal.timeout(20000);
19
19
  }
20
20
  next();
21
- };
22
- export default middleware;
21
+ }
22
+ export default extractOperationDeadline;
@@ -6,5 +6,5 @@ declare global {
6
6
  }
7
7
  }
8
8
  }
9
- declare const middleware: (_: Request, res: Response, next: NextFunction) => void;
10
- export default middleware;
9
+ declare function start(_: Request, res: Response, next: NextFunction): void;
10
+ export default start;
@@ -1,5 +1,5 @@
1
- const middleware = (_, res, next) => {
1
+ function start(_, res, next) {
2
2
  res.locals.requestStartTime = process.hrtime.bigint();
3
3
  next();
4
- };
5
- export default middleware;
4
+ }
5
+ export default start;
@@ -65,6 +65,7 @@ export default class Logger {
65
65
  */
66
66
  clearMetadata(): void;
67
67
  private send;
68
- private snakifyKeys;
68
+ private static snakifyKeys;
69
+ private static pruneSensitiveMetadata;
69
70
  }
70
71
  export {};
@@ -6,6 +6,35 @@ var LogLevel;
6
6
  LogLevel["LOG"] = "log";
7
7
  LogLevel["DEBUG"] = "debug";
8
8
  })(LogLevel || (LogLevel = {}));
9
+ /**
10
+ * See https://docs.datadoghq.com/logs/log_collection/?tab=host#custom-log-forwarding
11
+ * - Datadog Agent splits at 256kB (256000 bytes)...
12
+ * - ... but the same docs say that "for optimal performance, it is
13
+ * recommended that an individual log be no greater than 25kB"
14
+ * -> Truncating at 25kB - a bit of wiggle room for metadata = 20kB.
15
+ */
16
+ const MAX_LOG_MESSAGE_SIZE = parseInt(process.env.MAX_LOG_MESSAGE_SIZE ?? '20000', 10);
17
+ const LOG_LINE_TRUNCATED_SUFFIX = ' - LOG LINE TRUNCATED';
18
+ /**
19
+ * For *LogMeta* sanitization, we let in anything that was passed, except for clearly-problematic keys
20
+ */
21
+ const LOGMETA_BLACKLIST = [
22
+ // Security
23
+ 'access_token',
24
+ 'bot_auth_code',
25
+ 'client_secret',
26
+ 'jwt',
27
+ 'oauth_token',
28
+ 'password',
29
+ 'refresh_token',
30
+ 'shared_secret',
31
+ 'token',
32
+ // Privacy
33
+ 'billing_email',
34
+ 'email',
35
+ 'first_name',
36
+ 'last_name',
37
+ ];
9
38
  /**
10
39
  * Logger class that can be configured with metadata add creation and when logging to add additional context to your logs.
11
40
  */
@@ -85,20 +114,27 @@ export default class Logger {
85
114
  this.metadata = {};
86
115
  }
87
116
  send(logLevel, message, metadata) {
88
- const processedMessage = this.snakifyKeys({
89
- ...this.metadata,
90
- ...metadata,
117
+ // We need to provide the date to Datadog. Otherwise, the date is set to when they receive the log.
118
+ const date = Date.now();
119
+ if (message.length > MAX_LOG_MESSAGE_SIZE) {
120
+ message = `${message.substring(0, MAX_LOG_MESSAGE_SIZE)}${LOG_LINE_TRUNCATED_SUFFIX}`;
121
+ }
122
+ let processedMetadata = Logger.snakifyKeys({ ...this.metadata, ...metadata, logMessageSize: message.length });
123
+ processedMetadata = Logger.pruneSensitiveMetadata(processedMetadata);
124
+ const processedLogs = {
125
+ ...processedMetadata,
91
126
  message,
127
+ date,
92
128
  status: logLevel,
93
- });
129
+ };
94
130
  if (process.env.NODE_ENV === 'development') {
95
- console[logLevel](JSON.stringify(processedMessage, null, 2));
131
+ console[logLevel](JSON.stringify(processedLogs, null, 2));
96
132
  }
97
133
  else {
98
- console[logLevel](JSON.stringify(processedMessage));
134
+ console[logLevel](JSON.stringify(processedLogs));
99
135
  }
100
136
  }
101
- snakifyKeys(value) {
137
+ static snakifyKeys(value) {
102
138
  const result = {};
103
139
  for (const key in value) {
104
140
  const deepValue = typeof value[key] === 'object' ? this.snakifyKeys(value[key]) : value[key];
@@ -107,4 +143,20 @@ export default class Logger {
107
143
  }
108
144
  return result;
109
145
  }
146
+ static pruneSensitiveMetadata(metadata, topLevelMeta) {
147
+ const prunedMetadata = {};
148
+ for (const key in metadata) {
149
+ if (LOGMETA_BLACKLIST.includes(key)) {
150
+ prunedMetadata[key] = '[REDACTED]';
151
+ (topLevelMeta ?? prunedMetadata).has_sensitive_attribute = true;
152
+ }
153
+ else if (typeof metadata[key] === 'object') {
154
+ prunedMetadata[key] = Logger.pruneSensitiveMetadata(metadata[key], topLevelMeta ?? prunedMetadata);
155
+ }
156
+ else {
157
+ prunedMetadata[key] = metadata[key];
158
+ }
159
+ }
160
+ return prunedMetadata;
161
+ }
110
162
  }
@@ -1,11 +1,11 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/correlationId.js';
3
+ import extractCorrelationId from '../../src/middlewares/correlationId.js';
4
4
  describe('correlationId middleware', () => {
5
5
  it('uses header', () => {
6
6
  const request = { header: (_key) => '123' };
7
7
  const response = { locals: {} };
8
- middleware(request, response, () => { });
8
+ extractCorrelationId(request, response, () => { });
9
9
  assert.deepEqual(response.locals, {
10
10
  correlationId: '123',
11
11
  });
@@ -13,7 +13,7 @@ describe('correlationId middleware', () => {
13
13
  it('fallback', () => {
14
14
  const request = { header: (_key) => undefined };
15
15
  const response = { locals: {} };
16
- middleware(request, response, () => { });
16
+ extractCorrelationId(request, response, () => { });
17
17
  assert(response.locals.correlationId);
18
18
  });
19
19
  });
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/credentials.js';
3
+ import extractCredentials from '../../src/middlewares/credentials.js';
4
4
  import { BadRequestError } from '../../src/httpErrors.js';
5
5
  describe('credentials middleware', () => {
6
6
  it('generates', async () => {
@@ -9,7 +9,7 @@ describe('credentials middleware', () => {
9
9
  })).toString('base64');
10
10
  const request = { header: (_key) => credentials };
11
11
  const response = { locals: {} };
12
- middleware(request, response, () => { });
12
+ extractCredentials(request, response, () => { });
13
13
  assert.deepEqual(response.locals, {
14
14
  credentials: {
15
15
  accessToken: 'abc',
@@ -19,7 +19,7 @@ describe('credentials middleware', () => {
19
19
  it('malformed header', async () => {
20
20
  const request = { header: (_key) => 'nope' };
21
21
  const response = { locals: {} };
22
- assert.throws(() => middleware(request, response, () => { }), BadRequestError);
22
+ assert.throws(() => extractCredentials(request, response, () => { }), BadRequestError);
23
23
  });
24
24
  it('variables', async () => {
25
25
  const credentials = Buffer.from(JSON.stringify({
@@ -27,7 +27,7 @@ describe('credentials middleware', () => {
27
27
  })).toString('base64');
28
28
  const request = { header: (_key) => credentials };
29
29
  const response = { locals: {} };
30
- middleware(request, response, () => { });
30
+ extractCredentials(request, response, () => { });
31
31
  assert.deepEqual(response.locals, {
32
32
  credentials: {
33
33
  apiKey: 'abc',
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/errors.js';
3
+ import onError from '../../src/middlewares/errors.js';
4
4
  import { HttpError } from '../../src/httpErrors.js';
5
5
  describe('errors middleware', () => {
6
6
  it('headers sent, do nothing', () => {
@@ -18,7 +18,7 @@ describe('errors middleware', () => {
18
18
  },
19
19
  locals: { logger: { error: () => undefined } },
20
20
  };
21
- middleware(new Error(), {}, response, () => { });
21
+ onError(new Error(), {}, response, () => { });
22
22
  assert.strictEqual(actualStatus, undefined);
23
23
  assert.strictEqual(actualJson, undefined);
24
24
  });
@@ -37,7 +37,7 @@ describe('errors middleware', () => {
37
37
  },
38
38
  locals: { logger: { error: () => undefined } },
39
39
  };
40
- middleware(new HttpError('httpError', 429), {}, response, () => { });
40
+ onError(new HttpError('httpError', 429), {}, response, () => { });
41
41
  assert.strictEqual(actualStatus, 429);
42
42
  assert.deepEqual(actualJson, { code: '429', message: 'httpError' });
43
43
  });
@@ -56,7 +56,7 @@ describe('errors middleware', () => {
56
56
  },
57
57
  locals: { logger: { error: () => undefined } },
58
58
  };
59
- middleware(new Error('error'), {}, response, () => { });
59
+ onError(new Error('error'), {}, response, () => { });
60
60
  assert.strictEqual(actualStatus, 500);
61
61
  assert.strictEqual(actualJson?.code, '500');
62
62
  assert.deepEqual(actualJson?.originalError, { code: 'Error', message: 'error' });
@@ -1,24 +1,32 @@
1
1
  import { OperatorType } from '@unito/integration-api';
2
2
  import assert from 'node:assert/strict';
3
3
  import { describe, it } from 'node:test';
4
- import middleware from '../../src/middlewares/filters.js';
4
+ import extractFilters from '../../src/middlewares/filters.js';
5
5
  describe('filters middleware', () => {
6
- it('data', () => {
7
- const request = { query: { filter: 'status=active|pending,createdAt>2022-01-01,email!!' } };
6
+ it('properly parse operators', () => {
7
+ Object.values(OperatorType).forEach(operator => {
8
+ const request = {
9
+ query: { filter: `aKey${operator}value` },
10
+ };
11
+ const response = { locals: {} };
12
+ extractFilters(request, response, () => { });
13
+ assert.deepEqual(response.locals, {
14
+ filters: [{ field: 'aKey', operator, values: ['value'] }],
15
+ });
16
+ });
17
+ const request = {
18
+ query: { filter: `aKey!!` },
19
+ };
8
20
  const response = { locals: {} };
9
- middleware(request, response, () => { });
21
+ extractFilters(request, response, () => { });
10
22
  assert.deepEqual(response.locals, {
11
- filters: [
12
- { field: 'status', operator: OperatorType.EQUAL, values: ['active', 'pending'] },
13
- { field: 'createdAt', operator: OperatorType.GREATER_THAN, values: ['2022-01-01'] },
14
- { field: 'email', operator: OperatorType.IS_NOT_NULL, values: [] },
15
- ],
23
+ filters: [{ field: 'aKey', operator: OperatorType.IS_NULL, values: [] }],
16
24
  });
17
25
  });
18
26
  it('decodes URI components', () => {
19
- const request = { query: { filter: 'status=foo%2Cbar!!%2C%3Fbaz%3D!%3Equx' } };
27
+ const request = { query: { filter: 'status=foo%2Cbar%21%21%2C%3Fbaz%3D!%3Equx' } };
20
28
  const response = { locals: {} };
21
- middleware(request, response, () => { });
29
+ extractFilters(request, response, () => { });
22
30
  assert.deepEqual(response.locals, {
23
31
  filters: [{ field: 'status', operator: OperatorType.EQUAL, values: ['foo,bar!!,?baz=!>qux'] }],
24
32
  });
@@ -26,7 +34,7 @@ describe('filters middleware', () => {
26
34
  it('no data', () => {
27
35
  const request = { query: {} };
28
36
  const response = { locals: {} };
29
- middleware(request, response, () => { });
37
+ extractFilters(request, response, () => { });
30
38
  assert.deepEqual(response.locals, {
31
39
  filters: [],
32
40
  });
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/finish.js';
3
+ import onFinish from '../../src/middlewares/finish.js';
4
4
  describe('finish middleware', () => {
5
5
  it('logs info', () => {
6
6
  let expected = '';
@@ -20,7 +20,7 @@ describe('finish middleware', () => {
20
20
  },
21
21
  statusCode: 200,
22
22
  };
23
- middleware(request, response, () => { });
23
+ onFinish(request, response, () => { });
24
24
  eventHandler();
25
25
  assert.equal(expected, 'works!');
26
26
  });
@@ -42,7 +42,7 @@ describe('finish middleware', () => {
42
42
  },
43
43
  statusCode: 500,
44
44
  };
45
- middleware(request, response, () => { });
45
+ onFinish(request, response, () => { });
46
46
  eventHandler();
47
47
  assert.equal(expected, 'works!');
48
48
  });
@@ -64,7 +64,7 @@ describe('finish middleware', () => {
64
64
  },
65
65
  statusCode: 200,
66
66
  };
67
- middleware(request, response, () => { });
67
+ onFinish(request, response, () => { });
68
68
  eventHandler();
69
69
  assert.equal(expected, '');
70
70
  });
@@ -1,11 +1,11 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/logger.js';
3
+ import injectLogger from '../../src/middlewares/logger.js';
4
4
  describe('logger middleware', () => {
5
5
  it('initializes', () => {
6
6
  const request = { header: (_key) => undefined };
7
7
  const response = { locals: {} };
8
- middleware(request, response, () => { });
8
+ injectLogger(request, response, () => { });
9
9
  assert.deepEqual(response.locals.logger.getMetadata(), {
10
10
  correlation_id: undefined,
11
11
  });
@@ -13,7 +13,7 @@ describe('logger middleware', () => {
13
13
  it('correlation id', () => {
14
14
  const request = { header: (_key) => undefined };
15
15
  const response = { locals: { correlationId: '123' } };
16
- middleware(request, response, () => { });
16
+ injectLogger(request, response, () => { });
17
17
  assert.deepEqual(response.locals.logger.getMetadata(), {
18
18
  correlation_id: '123',
19
19
  });
@@ -24,7 +24,7 @@ describe('logger middleware', () => {
24
24
  });
25
25
  const request = { header: (_key) => additional };
26
26
  const response = { locals: { correlationId: '123' } };
27
- middleware(request, response, () => { });
27
+ injectLogger(request, response, () => { });
28
28
  assert.deepEqual(response.locals.logger.getMetadata(), {
29
29
  correlation_id: '123',
30
30
  foo: 'bar',
@@ -33,7 +33,7 @@ describe('logger middleware', () => {
33
33
  it('malformed additional context', () => {
34
34
  const request = { header: (_key) => 'nope' };
35
35
  const response = { locals: { correlationId: '123' } };
36
- middleware(request, response, () => { });
36
+ injectLogger(request, response, () => { });
37
37
  assert.deepEqual(response.locals.logger.getMetadata(), {
38
38
  correlation_id: '123',
39
39
  });
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/notFound.js';
3
+ import notFound from '../../src/middlewares/notFound.js';
4
4
  describe('notFound middleware', () => {
5
5
  it('respond with error without calling next', () => {
6
6
  let actualStatus;
@@ -17,7 +17,7 @@ describe('notFound middleware', () => {
17
17
  },
18
18
  locals: { logger: { error: () => undefined } },
19
19
  };
20
- middleware({ path: 'unknownPath' }, response, () => {
20
+ notFound({ path: 'unknownPath' }, response, () => {
21
21
  throw new Error('next should not be called');
22
22
  });
23
23
  assert.strictEqual(actualStatus, 404);
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/secrets.js';
3
+ import extractSecrets from '../../src/middlewares/secrets.js';
4
4
  import { BadRequestError } from '../../src/httpErrors.js';
5
5
  describe('secrets middleware', () => {
6
6
  it('uses header', () => {
@@ -9,7 +9,7 @@ describe('secrets middleware', () => {
9
9
  })).toString('base64');
10
10
  const request = { header: (_key) => secrets };
11
11
  const response = { locals: {} };
12
- middleware(request, response, () => { });
12
+ extractSecrets(request, response, () => { });
13
13
  assert.deepEqual(response.locals, {
14
14
  secrets: {
15
15
  chut: 'abc',
@@ -19,7 +19,7 @@ describe('secrets middleware', () => {
19
19
  it('malformed header', async () => {
20
20
  const request = { header: (_key) => 'nope' };
21
21
  const response = { locals: {} };
22
- assert.throws(() => middleware(request, response, () => { }), BadRequestError);
22
+ assert.throws(() => extractSecrets(request, response, () => { }), BadRequestError);
23
23
  });
24
24
  it('undefined', () => {
25
25
  const response = { locals: {} };
@@ -1,11 +1,11 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/selects.js';
3
+ import extractSelects from '../../src/middlewares/selects.js';
4
4
  describe('selects middleware', () => {
5
5
  it('data', () => {
6
6
  const request = { query: { select: 'foo,bar.spam,baz' } };
7
7
  const response = { locals: {} };
8
- middleware(request, response, () => { });
8
+ extractSelects(request, response, () => { });
9
9
  assert.deepEqual(response.locals, {
10
10
  selects: ['foo', 'bar.spam', 'baz'],
11
11
  });
@@ -13,7 +13,7 @@ describe('selects middleware', () => {
13
13
  it('no data', () => {
14
14
  const request = { query: {} };
15
15
  const response = { locals: {} };
16
- middleware(request, response, () => { });
16
+ extractSelects(request, response, () => { });
17
17
  assert.deepEqual(response.locals, {
18
18
  selects: [],
19
19
  });
@@ -1,19 +1,19 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
- import middleware from '../../src/middlewares/signal.js';
3
+ import extractOperationDeadline from '../../src/middlewares/signal.js';
4
4
  describe('signal middleware', () => {
5
5
  it('uses header', () => {
6
6
  const deadline = Math.floor((Date.now() + 5000) / 1000);
7
7
  const request = { header: (_key) => deadline };
8
8
  const response = { locals: {} };
9
- middleware(request, response, () => { });
9
+ extractOperationDeadline(request, response, () => { });
10
10
  assert.ok(response.locals.signal instanceof AbortSignal);
11
11
  assert.equal(response.locals.signal.aborted, false);
12
12
  });
13
13
  it('defaults', () => {
14
14
  const request = { header: (_key) => undefined };
15
15
  const response = { locals: {} };
16
- middleware(request, response, () => { });
16
+ extractOperationDeadline(request, response, () => { });
17
17
  assert.ok(response.locals.signal instanceof AbortSignal);
18
18
  assert.equal(response.locals.signal.aborted, false);
19
19
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+ import start from '../../src/middlewares/start.js';
4
+ describe('start middleware', () => {
5
+ it('adds request start time to locals', () => {
6
+ const request = {};
7
+ const response = { locals: {} };
8
+ start(request, response, () => { });
9
+ assert.ok(response.locals.requestStartTime);
10
+ });
11
+ });