@web-ts-toolkit/express-response-handler 0.1.0 → 0.2.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/LICENSE CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  Apache License
3
2
  Version 2.0, January 2004
4
3
  http://www.apache.org/licenses/
@@ -187,7 +186,7 @@
187
186
  same "printed page" as the copyright notice for easier
188
187
  identification within third-party archives.
189
188
 
190
- Copyright © 2017, Province of British Columbia, Canada.
189
+ Copyright Junmin Ahn
191
190
 
192
191
  Licensed under the Apache License, Version 2.0 (the "License");
193
192
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -243,9 +243,10 @@ If you want an AIP-193-inspired error envelope, create a handler instance with `
243
243
 
244
244
  ```ts
245
245
  import apiHandler from '@web-ts-toolkit/express-response-handler';
246
+ import { ErrorFormats } from '@web-ts-toolkit/express-response-handler';
246
247
 
247
- const structuredHandler = apiHandler.createExpressResponseHandler({
248
- errorFormat: 'aip193',
248
+ const structuredHandler = apiHandler.createHandler({
249
+ errorFormat: ErrorFormats.aip193,
249
250
  errorDomain: 'api.example.com',
250
251
  });
251
252
  ```
@@ -296,6 +297,59 @@ app.get(
296
297
  );
297
298
  ```
298
299
 
300
+ If you want RFC 9457 problem details instead, create a handler instance with `errorFormat: 'rfc9457'`:
301
+
302
+ ```ts
303
+ import apiHandler from '@web-ts-toolkit/express-response-handler';
304
+ import { ErrorFormats } from '@web-ts-toolkit/express-response-handler';
305
+
306
+ const problemHandler = apiHandler.createHandler({
307
+ errorFormat: ErrorFormats.rfc9457,
308
+ errorDomain: 'api.example.com',
309
+ });
310
+ ```
311
+
312
+ That mode returns `application/problem+json` payloads in this shape:
313
+
314
+ ```json
315
+ {
316
+ "type": "https://api.example.com/problems/invalid-project-id",
317
+ "title": "Invalid project id",
318
+ "status": 400,
319
+ "detail": "invalid project id",
320
+ "instance": "/problems/invalid-project-id/123",
321
+ "errors": [
322
+ {
323
+ "detail": "must be a valid project id",
324
+ "pointer": "#/id"
325
+ }
326
+ ]
327
+ }
328
+ ```
329
+
330
+ You can enrich HTTP errors with problem detail fields:
331
+
332
+ ```ts
333
+ import { BadRequestError } from '@web-ts-toolkit/http-errors';
334
+
335
+ app.get(
336
+ '/projects/:id',
337
+ problemHandler.handleResponse(async () => {
338
+ throw new BadRequestError('invalid project id', {
339
+ type: 'https://api.example.com/problems/invalid-project-id',
340
+ title: 'Invalid project id',
341
+ instance: '/problems/invalid-project-id/123',
342
+ errors: [
343
+ {
344
+ detail: 'must be a valid project id',
345
+ pointer: '#/id',
346
+ },
347
+ ],
348
+ });
349
+ }),
350
+ );
351
+ ```
352
+
299
353
  ## Isolated Instances
300
354
 
301
355
  The default export is a ready-to-use singleton. If you want separate hook configuration per router or module, create an isolated instance:
@@ -303,8 +357,8 @@ The default export is a ready-to-use singleton. If you want separate hook config
303
357
  ```ts
304
358
  import apiHandler from '@web-ts-toolkit/express-response-handler';
305
359
 
306
- const adminHandler = apiHandler.createExpressResponseHandler();
307
- const publicHandler = apiHandler.createExpressResponseHandler();
360
+ const adminHandler = apiHandler.createHandler();
361
+ const publicHandler = apiHandler.createHandler();
308
362
 
309
363
  adminHandler.preError = async function (err) {
310
364
  console.error('admin route failed', err);
@@ -4,7 +4,8 @@ import '@web-ts-toolkit/http-errors';
4
4
  import './responses/success.mjs';
5
5
  import './responses/index.mjs';
6
6
  import './responses/csv.mjs';
7
+ import './error-formats.mjs';
7
8
 
8
- declare function createExpressResponseHandler(options?: ExpressResponseHandlerOptions): ExpressResponseHandler;
9
+ declare function createHandler(options?: ExpressResponseHandlerOptions): ExpressResponseHandler;
9
10
 
10
- export { createExpressResponseHandler };
11
+ export { createHandler };
@@ -4,7 +4,8 @@ import '@web-ts-toolkit/http-errors';
4
4
  import './responses/success.js';
5
5
  import './responses/index.js';
6
6
  import './responses/csv.js';
7
+ import './error-formats.js';
7
8
 
8
- declare function createExpressResponseHandler(options?: ExpressResponseHandlerOptions): ExpressResponseHandler;
9
+ declare function createHandler(options?: ExpressResponseHandlerOptions): ExpressResponseHandler;
9
10
 
10
- export { createExpressResponseHandler };
11
+ export { createHandler };
@@ -26,25 +26,59 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var create_express_response_handler_exports = {};
30
- __export(create_express_response_handler_exports, {
31
- createExpressResponseHandler: () => createExpressResponseHandler
29
+ var create_handler_exports = {};
30
+ __export(create_handler_exports, {
31
+ createHandler: () => createHandler
32
32
  });
33
- module.exports = __toCommonJS(create_express_response_handler_exports);
33
+ module.exports = __toCommonJS(create_handler_exports);
34
34
  var import_assert = __toESM(require("assert"));
35
+ var import_utils = require("@web-ts-toolkit/utils");
35
36
  var import_csv = require("./responses/csv");
36
37
  var import_responses = require("./responses");
37
38
  var import_http_response = require("./http-response");
38
39
  var import_error_format = require("./error-format");
39
- const isFunction = (value) => typeof value === "function";
40
- const isPromise = (value) => Boolean(value) && isFunction(value.then);
40
+ var import_error_formats = require("./error-formats");
41
41
  const promisify = (fn) => (value) => Promise.resolve().then(() => fn(value));
42
- const { isArray } = Array;
43
42
  const invokePostHook = (hook, value) => {
44
43
  void hook(value).catch(() => void 0);
45
44
  };
45
+ const RFC_9457_CONTENT_TYPE = "application/problem+json";
46
+ const shouldSkipResponse = (res, event) => res.headersSent || event.canceled;
47
+ const sendProblemJson = (res, statusCode, payload, contentType) => {
48
+ res.status(statusCode);
49
+ res.set("Content-Type", contentType);
50
+ res.send(payload);
51
+ };
52
+ const sendHttpErrorByFormat = {
53
+ [import_error_formats.ErrorFormats.simple]: (res, error) => {
54
+ const payload = { message: error.message ?? "" };
55
+ if (error.errors !== void 0) {
56
+ payload.errors = error.errors;
57
+ }
58
+ res.status(error.statusCode ?? 500).send(payload);
59
+ },
60
+ [import_error_formats.ErrorFormats.aip193]: (res, error, domain) => {
61
+ res.status(error.statusCode ?? 500).send((0, import_error_format.toStructuredHttpErrorPayload)(error, domain));
62
+ },
63
+ [import_error_formats.ErrorFormats.rfc9457]: (res, error, domain) => {
64
+ sendProblemJson(res, error.statusCode ?? 500, (0, import_error_format.toRfc9457HttpErrorPayload)(error, domain), RFC_9457_CONTENT_TYPE);
65
+ }
66
+ };
67
+ const sendGenericErrorByFormat = {
68
+ [import_error_formats.ErrorFormats.simple]: (res, result) => {
69
+ res.status(422).send((0, import_error_format.toSimpleErrorPayload)(result));
70
+ },
71
+ [import_error_formats.ErrorFormats.aip193]: (res, result, domain) => {
72
+ const payload = (0, import_error_format.toStructuredGenericErrorPayload)(result, domain);
73
+ res.status(payload.error.code).send(payload);
74
+ },
75
+ [import_error_formats.ErrorFormats.rfc9457]: (res, result) => {
76
+ const payload = (0, import_error_format.toRfc9457GenericErrorPayload)(result);
77
+ sendProblemJson(res, payload.status ?? 422, payload, RFC_9457_CONTENT_TYPE);
78
+ }
79
+ };
46
80
  const assertMiddleware = (fn) => {
47
- import_assert.default.ok(isFunction(fn), "middleware handler must be a function");
81
+ import_assert.default.ok((0, import_utils.isFunction)(fn), "middleware handler must be a function");
48
82
  };
49
83
  const normalizeMiddlewareList = (fns) => {
50
84
  import_assert.default.ok(fns.length > 0, "at least one middleware handler is required");
@@ -52,7 +86,7 @@ const normalizeMiddlewareList = (fns) => {
52
86
  fns.forEach(assertMiddleware);
53
87
  return fns;
54
88
  }
55
- if (isArray(fns[0])) {
89
+ if ((0, import_utils.isArray)(fns[0])) {
56
90
  import_assert.default.ok(fns[0].length > 0, "at least one middleware handler is required");
57
91
  fns[0].forEach(assertMiddleware);
58
92
  return fns[0];
@@ -60,9 +94,10 @@ const normalizeMiddlewareList = (fns) => {
60
94
  assertMiddleware(fns[0]);
61
95
  return [fns[0]];
62
96
  };
63
- function createExpressResponseHandler(options = {}) {
64
- const errorFormat = options.errorFormat || "simple";
65
- const errorDomain = options.errorDomain || "express-response-handler";
97
+ function createHandler(options = {}) {
98
+ const errorFormat = options.errorFormat ?? import_error_formats.ErrorFormats.simple;
99
+ const errorDomain = options.errorDomain ?? "express-response-handler";
100
+ const rfc9457ContentType = options.rfc9457ContentType ?? RFC_9457_CONTENT_TYPE;
66
101
  let errorMessageProvider = import_error_format.defaultErrorMessageProvider;
67
102
  let preJson = null;
68
103
  let postJson = null;
@@ -72,8 +107,18 @@ function createExpressResponseHandler(options = {}) {
72
107
  let postJsonHook = null;
73
108
  let preErrorHook = null;
74
109
  let postErrorHook = null;
110
+ const updateHook = (fn, name, setState, rebuild) => {
111
+ if (fn === null) {
112
+ setState(null, null);
113
+ rebuild();
114
+ return;
115
+ }
116
+ import_assert.default.ok((0, import_utils.isFunction)(fn), `${name} hook must be a function`);
117
+ setState(fn, promisify(fn));
118
+ rebuild();
119
+ };
75
120
  const sendBaseJson = function(res, data, event) {
76
- if (res.headersSent || event.canceled) {
121
+ if (shouldSkipResponse(res, event)) {
77
122
  return;
78
123
  }
79
124
  if (data instanceof import_responses.Response) {
@@ -87,29 +132,30 @@ function createExpressResponseHandler(options = {}) {
87
132
  res.json(data);
88
133
  };
89
134
  const sendBaseError = function(res, err, event) {
90
- if (res.headersSent || event.canceled) {
135
+ if (shouldSkipResponse(res, event)) {
91
136
  return;
92
137
  }
93
138
  const error = err;
94
139
  if (error.statusCode) {
95
- if (errorFormat === "aip193") {
96
- res.status(error.statusCode).send((0, import_error_format.toStructuredHttpErrorPayload)(error, errorDomain));
140
+ if (errorFormat === import_error_formats.ErrorFormats.rfc9457) {
141
+ sendProblemJson(
142
+ res,
143
+ error.statusCode ?? 500,
144
+ (0, import_error_format.toRfc9457HttpErrorPayload)(error, errorDomain),
145
+ rfc9457ContentType
146
+ );
97
147
  return;
98
148
  }
99
- const payload = { message: error.message || "" };
100
- if (error.errors !== void 0) {
101
- payload.errors = error.errors;
102
- }
103
- res.status(error.statusCode).send(payload);
149
+ sendHttpErrorByFormat[errorFormat](res, error, errorDomain);
104
150
  return;
105
151
  }
106
152
  const result = errorMessageProvider(err);
107
- if (errorFormat === "aip193") {
108
- const payload = (0, import_error_format.toStructuredGenericErrorPayload)(result, errorDomain);
109
- res.status(payload.error.code).send(payload);
153
+ if (errorFormat === import_error_formats.ErrorFormats.rfc9457) {
154
+ const payload = (0, import_error_format.toRfc9457GenericErrorPayload)(result);
155
+ sendProblemJson(res, payload.status ?? 422, payload, rfc9457ContentType);
110
156
  return;
111
157
  }
112
- res.status(422).send((0, import_error_format.toSimpleErrorPayload)(result));
158
+ sendGenericErrorByFormat[errorFormat](res, result, errorDomain);
113
159
  };
114
160
  let sendJson = sendBaseJson;
115
161
  let sendError = sendBaseError;
@@ -157,7 +203,7 @@ function createExpressResponseHandler(options = {}) {
157
203
  };
158
204
  };
159
205
  const handlePromise = function(res, promise, event) {
160
- promise.then((data) => {
206
+ Promise.resolve(promise).then((data) => {
161
207
  if (event.nextError) {
162
208
  sendError(res, event.nextError, event);
163
209
  return;
@@ -166,14 +212,14 @@ function createExpressResponseHandler(options = {}) {
166
212
  }).catch((err) => sendError(res, err, event));
167
213
  };
168
214
  const handleResult = function(res, result, event) {
169
- if (res.headersSent || event.canceled) {
215
+ if (shouldSkipResponse(res, event)) {
170
216
  return;
171
217
  }
172
218
  if (event.nextError) {
173
219
  sendError(res, event.nextError, event);
174
220
  return;
175
221
  }
176
- if (isPromise(result)) {
222
+ if ((0, import_utils.isPromise)(result)) {
177
223
  handlePromise(res, result, event);
178
224
  return;
179
225
  }
@@ -216,77 +262,73 @@ function createExpressResponseHandler(options = {}) {
216
262
  handleResult,
217
263
  handlePromise,
218
264
  HttpResponse: import_http_response.HttpResponse,
219
- createExpressResponseHandler,
265
+ createHandler,
220
266
  get errorMessageProvider() {
221
267
  return errorMessageProvider;
222
268
  },
223
269
  set errorMessageProvider(fn) {
224
- import_assert.default.ok(isFunction(fn), "error message provider must be a function");
270
+ import_assert.default.ok((0, import_utils.isFunction)(fn), "error message provider must be a function");
225
271
  errorMessageProvider = fn;
226
272
  },
227
273
  get preJson() {
228
274
  return preJson;
229
275
  },
230
276
  set preJson(fn) {
231
- if (fn === null) {
232
- preJson = null;
233
- preJsonHook = null;
234
- rebuildSendJson();
235
- return;
236
- }
237
- import_assert.default.ok(isFunction(fn), "pre-json hook must be a function");
238
- preJson = fn;
239
- preJsonHook = promisify(fn);
240
- rebuildSendJson();
277
+ updateHook(
278
+ fn,
279
+ "pre-json",
280
+ (syncHook, asyncHook) => {
281
+ preJson = syncHook;
282
+ preJsonHook = asyncHook;
283
+ },
284
+ rebuildSendJson
285
+ );
241
286
  },
242
287
  get postJson() {
243
288
  return postJson;
244
289
  },
245
290
  set postJson(fn) {
246
- if (fn === null) {
247
- postJson = null;
248
- postJsonHook = null;
249
- rebuildSendJson();
250
- return;
251
- }
252
- import_assert.default.ok(isFunction(fn), "post-json hook must be a function");
253
- postJson = fn;
254
- postJsonHook = promisify(fn);
255
- rebuildSendJson();
291
+ updateHook(
292
+ fn,
293
+ "post-json",
294
+ (syncHook, asyncHook) => {
295
+ postJson = syncHook;
296
+ postJsonHook = asyncHook;
297
+ },
298
+ rebuildSendJson
299
+ );
256
300
  },
257
301
  get preError() {
258
302
  return preError;
259
303
  },
260
304
  set preError(fn) {
261
- if (fn === null) {
262
- preError = null;
263
- preErrorHook = null;
264
- rebuildSendError();
265
- return;
266
- }
267
- import_assert.default.ok(isFunction(fn), "pre-error hook must be a function");
268
- preError = fn;
269
- preErrorHook = promisify(fn);
270
- rebuildSendError();
305
+ updateHook(
306
+ fn,
307
+ "pre-error",
308
+ (syncHook, asyncHook) => {
309
+ preError = syncHook;
310
+ preErrorHook = asyncHook;
311
+ },
312
+ rebuildSendError
313
+ );
271
314
  },
272
315
  get postError() {
273
316
  return postError;
274
317
  },
275
318
  set postError(fn) {
276
- if (fn === null) {
277
- postError = null;
278
- postErrorHook = null;
279
- rebuildSendError();
280
- return;
281
- }
282
- import_assert.default.ok(isFunction(fn), "post-error hook must be a function");
283
- postError = fn;
284
- postErrorHook = promisify(fn);
285
- rebuildSendError();
319
+ updateHook(
320
+ fn,
321
+ "post-error",
322
+ (syncHook, asyncHook) => {
323
+ postError = syncHook;
324
+ postErrorHook = asyncHook;
325
+ },
326
+ rebuildSendError
327
+ );
286
328
  }
287
329
  };
288
330
  }
289
331
  // Annotate the CommonJS export names for ESM import in node:
290
332
  0 && (module.exports = {
291
- createExpressResponseHandler
333
+ createHandler
292
334
  });
@@ -1,21 +1,56 @@
1
- import "./chunk-PQJP2ZCI.mjs";
2
1
  import assert from "assert";
2
+ import { isArray, isFunction, isPromise } from "@web-ts-toolkit/utils";
3
3
  import { CSVResponse } from "./responses/csv";
4
4
  import { Response } from "./responses";
5
5
  import { HttpResponse } from "./http-response";
6
6
  import {
7
7
  defaultErrorMessageProvider,
8
+ toRfc9457GenericErrorPayload,
9
+ toRfc9457HttpErrorPayload,
8
10
  toSimpleErrorPayload,
9
11
  toStructuredGenericErrorPayload,
10
12
  toStructuredHttpErrorPayload
11
13
  } from "./error-format";
12
- const isFunction = (value) => typeof value === "function";
13
- const isPromise = (value) => Boolean(value) && isFunction(value.then);
14
+ import { ErrorFormats } from "./error-formats";
14
15
  const promisify = (fn) => (value) => Promise.resolve().then(() => fn(value));
15
- const { isArray } = Array;
16
16
  const invokePostHook = (hook, value) => {
17
17
  void hook(value).catch(() => void 0);
18
18
  };
19
+ const RFC_9457_CONTENT_TYPE = "application/problem+json";
20
+ const shouldSkipResponse = (res, event) => res.headersSent || event.canceled;
21
+ const sendProblemJson = (res, statusCode, payload, contentType) => {
22
+ res.status(statusCode);
23
+ res.set("Content-Type", contentType);
24
+ res.send(payload);
25
+ };
26
+ const sendHttpErrorByFormat = {
27
+ [ErrorFormats.simple]: (res, error) => {
28
+ const payload = { message: error.message ?? "" };
29
+ if (error.errors !== void 0) {
30
+ payload.errors = error.errors;
31
+ }
32
+ res.status(error.statusCode ?? 500).send(payload);
33
+ },
34
+ [ErrorFormats.aip193]: (res, error, domain) => {
35
+ res.status(error.statusCode ?? 500).send(toStructuredHttpErrorPayload(error, domain));
36
+ },
37
+ [ErrorFormats.rfc9457]: (res, error, domain) => {
38
+ sendProblemJson(res, error.statusCode ?? 500, toRfc9457HttpErrorPayload(error, domain), RFC_9457_CONTENT_TYPE);
39
+ }
40
+ };
41
+ const sendGenericErrorByFormat = {
42
+ [ErrorFormats.simple]: (res, result) => {
43
+ res.status(422).send(toSimpleErrorPayload(result));
44
+ },
45
+ [ErrorFormats.aip193]: (res, result, domain) => {
46
+ const payload = toStructuredGenericErrorPayload(result, domain);
47
+ res.status(payload.error.code).send(payload);
48
+ },
49
+ [ErrorFormats.rfc9457]: (res, result) => {
50
+ const payload = toRfc9457GenericErrorPayload(result);
51
+ sendProblemJson(res, payload.status ?? 422, payload, RFC_9457_CONTENT_TYPE);
52
+ }
53
+ };
19
54
  const assertMiddleware = (fn) => {
20
55
  assert.ok(isFunction(fn), "middleware handler must be a function");
21
56
  };
@@ -33,9 +68,10 @@ const normalizeMiddlewareList = (fns) => {
33
68
  assertMiddleware(fns[0]);
34
69
  return [fns[0]];
35
70
  };
36
- function createExpressResponseHandler(options = {}) {
37
- const errorFormat = options.errorFormat || "simple";
38
- const errorDomain = options.errorDomain || "express-response-handler";
71
+ function createHandler(options = {}) {
72
+ const errorFormat = options.errorFormat ?? ErrorFormats.simple;
73
+ const errorDomain = options.errorDomain ?? "express-response-handler";
74
+ const rfc9457ContentType = options.rfc9457ContentType ?? RFC_9457_CONTENT_TYPE;
39
75
  let errorMessageProvider = defaultErrorMessageProvider;
40
76
  let preJson = null;
41
77
  let postJson = null;
@@ -45,8 +81,18 @@ function createExpressResponseHandler(options = {}) {
45
81
  let postJsonHook = null;
46
82
  let preErrorHook = null;
47
83
  let postErrorHook = null;
84
+ const updateHook = (fn, name, setState, rebuild) => {
85
+ if (fn === null) {
86
+ setState(null, null);
87
+ rebuild();
88
+ return;
89
+ }
90
+ assert.ok(isFunction(fn), `${name} hook must be a function`);
91
+ setState(fn, promisify(fn));
92
+ rebuild();
93
+ };
48
94
  const sendBaseJson = function(res, data, event) {
49
- if (res.headersSent || event.canceled) {
95
+ if (shouldSkipResponse(res, event)) {
50
96
  return;
51
97
  }
52
98
  if (data instanceof Response) {
@@ -60,29 +106,30 @@ function createExpressResponseHandler(options = {}) {
60
106
  res.json(data);
61
107
  };
62
108
  const sendBaseError = function(res, err, event) {
63
- if (res.headersSent || event.canceled) {
109
+ if (shouldSkipResponse(res, event)) {
64
110
  return;
65
111
  }
66
112
  const error = err;
67
113
  if (error.statusCode) {
68
- if (errorFormat === "aip193") {
69
- res.status(error.statusCode).send(toStructuredHttpErrorPayload(error, errorDomain));
114
+ if (errorFormat === ErrorFormats.rfc9457) {
115
+ sendProblemJson(
116
+ res,
117
+ error.statusCode ?? 500,
118
+ toRfc9457HttpErrorPayload(error, errorDomain),
119
+ rfc9457ContentType
120
+ );
70
121
  return;
71
122
  }
72
- const payload = { message: error.message || "" };
73
- if (error.errors !== void 0) {
74
- payload.errors = error.errors;
75
- }
76
- res.status(error.statusCode).send(payload);
123
+ sendHttpErrorByFormat[errorFormat](res, error, errorDomain);
77
124
  return;
78
125
  }
79
126
  const result = errorMessageProvider(err);
80
- if (errorFormat === "aip193") {
81
- const payload = toStructuredGenericErrorPayload(result, errorDomain);
82
- res.status(payload.error.code).send(payload);
127
+ if (errorFormat === ErrorFormats.rfc9457) {
128
+ const payload = toRfc9457GenericErrorPayload(result);
129
+ sendProblemJson(res, payload.status ?? 422, payload, rfc9457ContentType);
83
130
  return;
84
131
  }
85
- res.status(422).send(toSimpleErrorPayload(result));
132
+ sendGenericErrorByFormat[errorFormat](res, result, errorDomain);
86
133
  };
87
134
  let sendJson = sendBaseJson;
88
135
  let sendError = sendBaseError;
@@ -130,7 +177,7 @@ function createExpressResponseHandler(options = {}) {
130
177
  };
131
178
  };
132
179
  const handlePromise = function(res, promise, event) {
133
- promise.then((data) => {
180
+ Promise.resolve(promise).then((data) => {
134
181
  if (event.nextError) {
135
182
  sendError(res, event.nextError, event);
136
183
  return;
@@ -139,7 +186,7 @@ function createExpressResponseHandler(options = {}) {
139
186
  }).catch((err) => sendError(res, err, event));
140
187
  };
141
188
  const handleResult = function(res, result, event) {
142
- if (res.headersSent || event.canceled) {
189
+ if (shouldSkipResponse(res, event)) {
143
190
  return;
144
191
  }
145
192
  if (event.nextError) {
@@ -189,7 +236,7 @@ function createExpressResponseHandler(options = {}) {
189
236
  handleResult,
190
237
  handlePromise,
191
238
  HttpResponse,
192
- createExpressResponseHandler,
239
+ createHandler,
193
240
  get errorMessageProvider() {
194
241
  return errorMessageProvider;
195
242
  },
@@ -201,64 +248,60 @@ function createExpressResponseHandler(options = {}) {
201
248
  return preJson;
202
249
  },
203
250
  set preJson(fn) {
204
- if (fn === null) {
205
- preJson = null;
206
- preJsonHook = null;
207
- rebuildSendJson();
208
- return;
209
- }
210
- assert.ok(isFunction(fn), "pre-json hook must be a function");
211
- preJson = fn;
212
- preJsonHook = promisify(fn);
213
- rebuildSendJson();
251
+ updateHook(
252
+ fn,
253
+ "pre-json",
254
+ (syncHook, asyncHook) => {
255
+ preJson = syncHook;
256
+ preJsonHook = asyncHook;
257
+ },
258
+ rebuildSendJson
259
+ );
214
260
  },
215
261
  get postJson() {
216
262
  return postJson;
217
263
  },
218
264
  set postJson(fn) {
219
- if (fn === null) {
220
- postJson = null;
221
- postJsonHook = null;
222
- rebuildSendJson();
223
- return;
224
- }
225
- assert.ok(isFunction(fn), "post-json hook must be a function");
226
- postJson = fn;
227
- postJsonHook = promisify(fn);
228
- rebuildSendJson();
265
+ updateHook(
266
+ fn,
267
+ "post-json",
268
+ (syncHook, asyncHook) => {
269
+ postJson = syncHook;
270
+ postJsonHook = asyncHook;
271
+ },
272
+ rebuildSendJson
273
+ );
229
274
  },
230
275
  get preError() {
231
276
  return preError;
232
277
  },
233
278
  set preError(fn) {
234
- if (fn === null) {
235
- preError = null;
236
- preErrorHook = null;
237
- rebuildSendError();
238
- return;
239
- }
240
- assert.ok(isFunction(fn), "pre-error hook must be a function");
241
- preError = fn;
242
- preErrorHook = promisify(fn);
243
- rebuildSendError();
279
+ updateHook(
280
+ fn,
281
+ "pre-error",
282
+ (syncHook, asyncHook) => {
283
+ preError = syncHook;
284
+ preErrorHook = asyncHook;
285
+ },
286
+ rebuildSendError
287
+ );
244
288
  },
245
289
  get postError() {
246
290
  return postError;
247
291
  },
248
292
  set postError(fn) {
249
- if (fn === null) {
250
- postError = null;
251
- postErrorHook = null;
252
- rebuildSendError();
253
- return;
254
- }
255
- assert.ok(isFunction(fn), "post-error hook must be a function");
256
- postError = fn;
257
- postErrorHook = promisify(fn);
258
- rebuildSendError();
293
+ updateHook(
294
+ fn,
295
+ "post-error",
296
+ (syncHook, asyncHook) => {
297
+ postError = syncHook;
298
+ postErrorHook = asyncHook;
299
+ },
300
+ rebuildSendError
301
+ );
259
302
  }
260
303
  };
261
304
  }
262
305
  export {
263
- createExpressResponseHandler
306
+ createHandler
264
307
  };