fastify-txstate 3.2.4 → 3.2.6

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/lib/error.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type FastifySchemaValidationError } from 'fastify/types/schema';
1
2
  export declare class HttpError extends Error {
2
3
  statusCode: number;
3
4
  constructor(statusCode: number, message?: string);
@@ -7,4 +8,9 @@ export declare class FailedValidationError extends HttpError {
7
8
  errors: ValidationErrors;
8
9
  constructor(errors: ValidationErrors);
9
10
  }
11
+ export declare function fstValidationToMessage(v: FastifySchemaValidationError): {
12
+ message: string | undefined;
13
+ path: string;
14
+ type: string;
15
+ };
10
16
  export {};
package/lib/error.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FailedValidationError = exports.HttpError = void 0;
3
+ exports.fstValidationToMessage = exports.FailedValidationError = exports.HttpError = void 0;
4
4
  const http_status_codes_1 = require("http-status-codes");
5
5
  class HttpError extends Error {
6
6
  constructor(statusCode, message) {
@@ -24,3 +24,8 @@ class FailedValidationError extends HttpError {
24
24
  }
25
25
  }
26
26
  exports.FailedValidationError = FailedValidationError;
27
+ function fstValidationToMessage(v) {
28
+ const instancePath = v.keyword === 'required' ? v.instancePath + '/' + v.params.missingProperty : v.instancePath;
29
+ return { message: v.message, path: instancePath.substring(1).replace(/\//g, '.'), type: 'error' };
30
+ }
31
+ exports.fstValidationToMessage = fstValidationToMessage;
package/lib/index.d.ts CHANGED
@@ -77,7 +77,7 @@ export interface FastifyTxStateOptions extends Partial<FastifyServerOptions> {
77
77
  *
78
78
  * If this function throws, the client will receive a 401 response.
79
79
  */
80
- authenticate?: <T extends FastifyTxStateAuthInfo>(req: FastifyRequest) => Promise<T | undefined>;
80
+ authenticate?: (req: FastifyRequest) => Promise<FastifyTxStateAuthInfo | undefined>;
81
81
  }
82
82
  declare module 'fastify' {
83
83
  interface FastifyRequest {
package/lib/index.js CHANGED
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  exports.prodLogger = exports.devLogger = void 0;
21
21
  const swagger_1 = __importDefault(require("@fastify/swagger"));
22
22
  const swagger_ui_1 = __importDefault(require("@fastify/swagger-ui"));
23
+ const fastify_shared_1 = require("@txstate-mws/fastify-shared");
23
24
  const ajv_errors_1 = __importDefault(require("ajv-errors"));
24
25
  const ajv_formats_1 = __importDefault(require("ajv-formats"));
25
26
  const fastify_1 = require("fastify");
@@ -108,25 +109,10 @@ class Server {
108
109
  if (!((_a = route.schema) === null || _a === void 0 ? void 0 : _a.body))
109
110
  return;
110
111
  const missingResponse = ((_b = route.schema) === null || _b === void 0 ? void 0 : _b.response) == null;
111
- const newSchema = (0, txstate_utils_1.set)((_c = route.schema) !== null && _c !== void 0 ? _c : {}, 'response.422', {
112
- description: 'Validation failure.',
113
- type: 'object',
114
- properties: {
115
- errors: {
116
- type: 'array',
117
- items: {
118
- type: 'object',
119
- properties: {
120
- type: { type: 'string', enum: ['error', 'warning', 'success', 'system'], example: 'error' },
121
- message: { type: 'string', example: 'must be an integer' },
122
- path: { type: 'string', example: 'cart.item.0.quantity', description: 'Dot-separated path to the field in the request body that caused the validation error.' }
123
- },
124
- required: ['type', 'message'],
125
- additionalProperties: false
126
- }
127
- }
128
- }
129
- });
112
+ const response400 = (0, txstate_utils_1.set)(fastify_shared_1.validatedResponse.properties.messages, 'description', 'Basic validation failure. This means that the UI provided input that failed validation as defined in the openapi specification published by the API. The UI is at fault and should be re-coded to avoid sending invalid data.');
113
+ let newSchema = (0, txstate_utils_1.set)((_c = route.schema) !== null && _c !== void 0 ? _c : {}, 'response.400', response400);
114
+ const response422 = (0, txstate_utils_1.set)(fastify_shared_1.validatedResponse, 'description', 'Validation failure. This means that the user provided an invalid object. The user should be shown their error so that they can correct it.');
115
+ newSchema = (0, txstate_utils_1.set)(newSchema, 'response.422', response422);
130
116
  if (missingResponse) {
131
117
  newSchema.response['200'] = {
132
118
  description: 'Success. Return type has not been specified.',
@@ -213,7 +199,7 @@ class Server {
213
199
  });
214
200
  this.app.setNotFoundHandler((req, res) => { void res.status(404).send('Not Found.'); });
215
201
  this.app.setErrorHandler(async (err, req, res) => {
216
- var _a, _b;
202
+ var _a;
217
203
  req.log.warn(err);
218
204
  for (const errorHandler of this.errorHandlers) {
219
205
  if (!res.sent)
@@ -227,7 +213,28 @@ class Server {
227
213
  await res.status(err.statusCode).send(err.message);
228
214
  }
229
215
  else if (err.code === 'FST_ERR_VALIDATION') {
230
- await res.status(422).send({ errors: (_b = (_a = err.validation) === null || _a === void 0 ? void 0 : _a.map(err => ({ message: err.message, path: err.instancePath.substring(1).replace(/\//g, '.'), type: 'error' }))) !== null && _b !== void 0 ? _b : [] });
216
+ const developerErrors = [];
217
+ const userErrors = [];
218
+ for (const v of (_a = err.validation) !== null && _a !== void 0 ? _a : []) {
219
+ if (v.keyword === 'errorMessage') {
220
+ for (const ov of v.params.errors) {
221
+ if (['type', 'additionalProperties'].includes(ov.keyword))
222
+ developerErrors.push({ ...ov, message: v.message });
223
+ else
224
+ userErrors.push({ ...ov, message: v.message });
225
+ }
226
+ }
227
+ else {
228
+ if (['type', 'additionalProperties'].includes(v.keyword))
229
+ developerErrors.push(v);
230
+ else
231
+ userErrors.push(v);
232
+ }
233
+ }
234
+ if (userErrors.length)
235
+ await res.status(422).send({ success: false, messages: userErrors.map(error_1.fstValidationToMessage) });
236
+ else
237
+ await res.status(400).send(developerErrors.map(error_1.fstValidationToMessage));
231
238
  }
232
239
  else if (err.statusCode) {
233
240
  await res.status(err.statusCode).send(new error_1.HttpError(err.statusCode).message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify-txstate",
3
- "version": "3.2.4",
3
+ "version": "3.2.6",
4
4
  "description": "A small wrapper for fastify providing a set of common conventions & utility functions we use.",
5
5
  "exports": {
6
6
  ".": {
@@ -22,7 +22,7 @@
22
22
  "@fastify/swagger": "^8.14.0",
23
23
  "@fastify/swagger-ui": "^3.0.0",
24
24
  "@fastify/type-provider-json-schema-to-ts": "^3.0.0",
25
- "@txstate-mws/fastify-shared": "^1.0.4",
25
+ "@txstate-mws/fastify-shared": "^1.0.9",
26
26
  "ajv-errors": "^3.0.0",
27
27
  "ajv-formats": "^2.1.1",
28
28
  "fastify": "^4.9.2",