diff --git a/README.md b/README.md index 9935336..864df9d 100644 --- a/README.md +++ b/README.md @@ -212,24 +212,26 @@ For the complete list of error classes, usage examples, and custom error creatio ## Validation & Sanitization -api-machine supports request validation and sanitization using [valsan](https://www.npmjs.com/package/valsan). You can declare ObjectSanitizer members on your endpoint classes for `body`, `query`, `params`, or `headers`: +api-machine supports request validation and sanitization using [valsan](https://www.npmjs.com/package/valsan). You can declare ObjectValSan members on your endpoint classes for `body`, `query`, `params`, or `headers`: ```typescript -import { ObjectSanitizer, EmailValidator } from 'valsan'; +import { ObjectValSan, EmailValidator } from 'valsan'; import { NameValSan } from './examples/complete-example/users/name-valsan'; class CreateUserEndpoint extends PostEndpoint { - override path = '/users'; + override path = '/users'; - override body = new ObjectSanitizer({ - name: new NameValSan(), - email: new EmailValidator(), - }); + override body = new ObjectValSan({ + schema: { + name: new NameValSan(), + email: new EmailValidator(), + } + }); - async handle(request, response) { - // request.body is validated & sanitized - // ... - } + async handle(request, response) { + // request.body is validated & sanitized + // ... + } } ``` diff --git a/examples/complete-example/users/create-user-endpoint.ts b/examples/complete-example/users/create-user-endpoint.ts index 819e286..0e84f48 100644 --- a/examples/complete-example/users/create-user-endpoint.ts +++ b/examples/complete-example/users/create-user-endpoint.ts @@ -1,6 +1,6 @@ import { ApiRequest, ApiResponse, PostEndpoint } from '../../../src/index'; import { usersRepo, User } from './users-repository'; -import { ObjectSanitizer, EmailValidator, IntegerValidator } from 'valsan'; +import { ObjectValSan, EmailValidator, IntegerValidator } from 'valsan'; import { NameValSan } from './name-valsan'; /** @@ -16,9 +16,11 @@ export class CreateUserEndpoint extends PostEndpoint { email: 'john@example.com', }; - override body = new ObjectSanitizer({ - name: new NameValSan(), - email: new EmailValidator(), + override body = new ObjectValSan({ + schema: { + name: new NameValSan(), + email: new EmailValidator(), + }, }); override responseExample = { @@ -28,10 +30,12 @@ export class CreateUserEndpoint extends PostEndpoint { created: new Date(), }; - override response = new ObjectSanitizer({ - id: new IntegerValidator(), - name: new NameValSan(), - email: new EmailValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + name: new NameValSan(), + email: new EmailValidator(), + }, }); async handle(request: ApiRequest, response: ApiResponse) { diff --git a/examples/complete-example/users/get-user-endpoint.ts b/examples/complete-example/users/get-user-endpoint.ts index d048162..ca56264 100644 --- a/examples/complete-example/users/get-user-endpoint.ts +++ b/examples/complete-example/users/get-user-endpoint.ts @@ -1,7 +1,7 @@ import { ApiRequest, ApiResponse, GetEndpoint } from '../../../src/index'; import { NotFoundError } from '../../../src/error'; import { usersRepo } from './users-repository'; -import { ObjectSanitizer, IntegerValidator, EmailValidator } from 'valsan'; +import { IntegerValidator, EmailValidator, ObjectValSan } from 'valsan'; import { NameValSan } from './name-valsan'; /** @@ -20,10 +20,12 @@ export class GetUserEndpoint extends GetEndpoint { created: new Date('2023-01-01'), }; - override response = new ObjectSanitizer({ - id: new IntegerValidator(), - name: new NameValSan(), - email: new EmailValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + name: new NameValSan(), + email: new EmailValidator(), + }, }); async handle(request: ApiRequest, response: ApiResponse) { diff --git a/examples/complete-example/users/list-users-endpoint.ts b/examples/complete-example/users/list-users-endpoint.ts index d948df4..e7787f5 100644 --- a/examples/complete-example/users/list-users-endpoint.ts +++ b/examples/complete-example/users/list-users-endpoint.ts @@ -1,7 +1,7 @@ import { ComposedValSan, LengthValidator, - ObjectSanitizer, + ObjectValSan, TrimSanitizer, } from 'valsan'; import { ApiRequest, ApiResponse, GetEndpoint } from '../../../src/index'; @@ -16,15 +16,17 @@ import { usersRepo } from './users-repository'; export class ListUsersEndpoint extends GetEndpoint { override path = '/'; - override params = new ObjectSanitizer({ - name: new ComposedValSan( - [new TrimSanitizer(), new LengthValidator({ minLength: 3 })], - { isOptional: true } - ), - email: new ComposedValSan( - [new TrimSanitizer(), new LengthValidator({ minLength: 5 })], - { isOptional: true } - ), + override params = new ObjectValSan({ + schema: { + name: new ComposedValSan( + [new TrimSanitizer(), new LengthValidator({ minLength: 3 })], + { isOptional: true } + ), + email: new ComposedValSan( + [new TrimSanitizer(), new LengthValidator({ minLength: 5 })], + { isOptional: true } + ), + }, }); async handle(request: ApiRequest, response: ApiResponse) { diff --git a/package-lock.json b/package-lock.json index 1ee8f75..b8f7341 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "api-machine", - "version": "1.2.0", + "version": "1.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "api-machine", - "version": "1.2.0", + "version": "1.2.1", "license": "MIT", "dependencies": { "auto-oas": "^1.3.0", @@ -1668,9 +1668,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.29.tgz", - "integrity": "sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==", + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1678,23 +1678,27 @@ } }, "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", - "debug": "^4.4.0", + "debug": "^4.4.3", "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/boolify": { @@ -1888,9 +1892,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001755", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", - "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==", + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", "dev": true, "funding": [ { @@ -2089,15 +2093,16 @@ "license": "MIT" }, "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/content-type": { @@ -2335,9 +2340,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.255", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.255.tgz", - "integrity": "sha512-Z9oIp4HrFF/cZkDPMpz2XSuVpc1THDpT4dlmATFlJUIBVCy9Vap5/rIXsASP1CscBacBqhabwh8vLctqBwEerQ==", + "version": "1.5.262", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz", + "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==", "dev": true, "license": "ISC" }, @@ -3262,40 +3267,39 @@ } }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ignore": { @@ -3981,9 +3985,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "dev": true, "license": "MIT", "dependencies": { @@ -4158,15 +4162,19 @@ } }, "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/minimatch": { @@ -4751,9 +4759,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.1.tgz", + "integrity": "sha512-RWKXE4qB3u5Z6yz7omJkjWwmTfLdcbv44jUVHC5NpfXwFGzvpQM798FGv/6WNK879tc+Cn0AAyherCl1KjbyZQ==", "dev": true, "license": "MIT", "bin": { @@ -5208,36 +5216,20 @@ } }, "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.10" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -5444,26 +5436,6 @@ "tslib": "^2.1.0" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/safe-identifier": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", @@ -5911,9 +5883,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.30.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.2.tgz", - "integrity": "sha512-HWCg1DTNE/Nmapt+0m2EPXFwNKNeKK4PwMjkwveN/zn1cV2Kxi9SURd+m0SpdcSgWEK/O64sf8bzXdtUhigtHA==", + "version": "5.30.3", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.3.tgz", + "integrity": "sha512-giQl7/ToPxCqnUAx2wpnSnDNGZtGzw1LyUw6ZitIpTmdrvpxKFY/94v1hihm0zYNpgp1/VY0jTDk//R0BBgnRQ==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -6423,9 +6395,9 @@ "license": "MIT" }, "node_modules/valsan": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/valsan/-/valsan-2.3.0.tgz", - "integrity": "sha512-365JCZqUuZBISYynUJwRzqP0FkLbJsr/I07DbvRPDyDwZY28P68HQOtdiOE2BaVCnfxOfX4RQWjU5IFlue0Vrg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/valsan/-/valsan-2.5.0.tgz", + "integrity": "sha512-8pHY2XFf/MKheMTwi/p2i98hMLLNoFg7KAOpth4bp9WrwliO2PWHqq+s7XKSpHbqppo53DTX3oo77+2mtdRG6A==", "license": "MIT" }, "node_modules/vary": { diff --git a/package.json b/package.json index 3d4416e..1a49297 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "api-machine", - "version": "1.2.0", + "version": "1.2.1", "description": "api-machine", "private": "true", "typescript-template": { diff --git a/src/router/endpoints/health-check-endpoint.ts b/src/router/endpoints/health-check-endpoint.ts index ea1cd6f..7287fd5 100644 --- a/src/router/endpoints/health-check-endpoint.ts +++ b/src/router/endpoints/health-check-endpoint.ts @@ -1,7 +1,7 @@ import { Iso8601TimestampValSan, MinLengthValidator, - ObjectSanitizer, + ObjectValSan, StringToNumberValSan, } from 'valsan'; import { GetEndpoint } from './get-endpoint'; @@ -16,11 +16,13 @@ export class HealthCheckEndpoint extends GetEndpoint { environment: 'development', }; - override response = new ObjectSanitizer({ - status: new MinLengthValidator(), - timestamp: new Iso8601TimestampValSan(), - uptime: new StringToNumberValSan(), - environment: new MinLengthValidator(), + override response = new ObjectValSan({ + schema: { + status: new MinLengthValidator(), + timestamp: new Iso8601TimestampValSan(), + uptime: new StringToNumberValSan(), + environment: new MinLengthValidator(), + }, }); async handle() { diff --git a/src/router/validation-middleware.ts b/src/router/validation-middleware.ts index 4b35dd4..b990bf9 100644 --- a/src/router/validation-middleware.ts +++ b/src/router/validation-middleware.ts @@ -8,7 +8,7 @@ import { ApiRequest, BaseApiEndpoint } from './endpoint'; import { UnprocessableEntityError } from '../error'; /** - * Runs a valsan ObjectSanitizer on a value, + * Runs a valsan ObjectValSan on a value, * throws with error details if validation fails. */ export async function runSanitizer( @@ -30,7 +30,7 @@ export async function runSanitizer( /** * Validates and sanitizes request parts * (body, query, params, headers) if the - * endpoint defines a ObjectSanitizers + * endpoint defines an ObjectValSan */ export async function validateRequest( endpoint: BaseApiEndpoint, diff --git a/test/spec/endpoint/validation.server.ts b/test/spec/endpoint/validation.server.ts index 74c1e3f..b226909 100644 --- a/test/spec/endpoint/validation.server.ts +++ b/test/spec/endpoint/validation.server.ts @@ -5,7 +5,6 @@ import { PostEndpoint, } from '../../../src/router'; import { - ObjectSanitizer, EmailValidator, LengthValidator, StringToNumberValSan, @@ -48,11 +47,13 @@ export class ValidationRouter extends BaseApiRouter { class TestQueryParamsEndpoint extends GetEndpoint { override path = '/query-params'; - override query = new ObjectSanitizer({ - search: new ComposedValSan([ - new TrimSanitizer(), - new LengthValidator({ minLength: 3 }), - ]), + override query = new ObjectValSan({ + schema: { + search: new ComposedValSan([ + new TrimSanitizer(), + new LengthValidator({ minLength: 3 }), + ]), + }, }); override async handle( @@ -64,11 +65,13 @@ export class ValidationRouter extends BaseApiRouter { class TestRouteParamsEndpoint extends PostEndpoint { override path = '/route-params/:itemId'; - override params = new ObjectSanitizer({ - itemId: new ComposedValSan([ - new StringToNumberValSan(), - new MinValidator({ min: 1 }), - ]), + override params = new ObjectValSan({ + schema: { + itemId: new ComposedValSan([ + new StringToNumberValSan(), + new MinValidator({ min: 1 }), + ]), + }, }); override async handle( @@ -80,9 +83,11 @@ export class ValidationRouter extends BaseApiRouter { class TestBodyEndpoint extends PostEndpoint { override path = '/body'; - override body = new ObjectSanitizer({ - name: new NameValSan(), - email: new EmailValidator(), + override body = new ObjectValSan({ + schema: { + name: new NameValSan(), + email: new EmailValidator(), + }, }); override async handle( @@ -97,30 +102,38 @@ export class ValidationRouter extends BaseApiRouter { class TestAllValidationEndpoint extends PostEndpoint { override path = '/all/:userId'; - override body = new ObjectSanitizer({ - name: new NameValSan(), - email: new EmailValidator(), + override body = new ObjectValSan({ + schema: { + name: new NameValSan(), + email: new EmailValidator(), + }, }); - override query = new ObjectSanitizer({ - age: new ComposedValSan([ - new StringToNumberValSan(), - new MinValidator({ min: 0 }), - ]), + override query = new ObjectValSan({ + schema: { + age: new ComposedValSan([ + new StringToNumberValSan(), + new MinValidator({ min: 0 }), + ]), + }, }); - override params = new ObjectSanitizer({ - userId: new ComposedValSan([ - new StringToNumberValSan(), - new MinValidator({ min: 1 }), - ]), + override params = new ObjectValSan({ + schema: { + userId: new ComposedValSan([ + new StringToNumberValSan(), + new MinValidator({ min: 1 }), + ]), + }, }); - override headers = new ObjectSanitizer({ - 'X-User-Token': new ComposedValSan([ - new TrimSanitizer(), - new LengthValidator({ minLength: 10 }), - ]), + override headers = new ObjectValSan({ + schema: { + 'X-User-Token': new ComposedValSan([ + new TrimSanitizer(), + new LengthValidator({ minLength: 10 }), + ]), + }, }); async handle(request: ApiRequest) { @@ -137,18 +150,20 @@ export class ValidationRouter extends BaseApiRouter { }, class OptionalValidationEndpoint extends GetEndpoint { override path = '/optional-validation'; - override query = new ObjectSanitizer({ - name: new ComposedValSan( - [ - new TrimSanitizer(), - new LengthValidator({ minLength: 3 }), - ], - { isOptional: true } - ), - email: new ComposedValSan( - [new TrimSanitizer(), new EmailValidator()], - { isOptional: true } - ), + override query = new ObjectValSan({ + schema: { + name: new ComposedValSan( + [ + new TrimSanitizer(), + new LengthValidator({ minLength: 3 }), + ], + { isOptional: true } + ), + email: new ComposedValSan( + [new TrimSanitizer(), new EmailValidator()], + { isOptional: true } + ), + }, }); override async handle( diff --git a/test/spec/openapi/oas-endpoint-component-converter-response.spec.ts b/test/spec/openapi/oas-endpoint-component-converter-response.spec.ts index 0fa71d0..04b5169 100644 --- a/test/spec/openapi/oas-endpoint-component-converter-response.spec.ts +++ b/test/spec/openapi/oas-endpoint-component-converter-response.spec.ts @@ -1,7 +1,7 @@ import 'jasmine'; // eslint-disable-next-line max-len import { OasEndpointComponentConverter } from '../../../src/oas/oas-endpoint-component-converter'; -import { ObjectSanitizer, IntegerValidator, EmailValidator } from 'valsan'; +import { IntegerValidator, EmailValidator, ObjectValSan } from 'valsan'; import { GetEndpoint } from '../../../src/router/endpoints/get-endpoint'; import { PostEndpoint } from '../../../src/router/endpoints/post-endpoint'; import { ApiRequest, ApiResponse, ApiNextFunction } from '../../../src/router'; @@ -15,9 +15,11 @@ describe('OasEndpointComponentConverter - Response Schemas', () => { it('generates response schema from response sanitizer', () => { class TestEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), - email: new EmailValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + email: new EmailValidator(), + }, }); override responseExample = { @@ -52,8 +54,10 @@ describe('OasEndpointComponentConverter - Response Schemas', () => { it('includes response example in schema', () => { class TestEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + }, }); override responseExample = { @@ -108,16 +112,20 @@ describe('OasEndpointComponentConverter - Response Schemas', () => { it('includes both body and response schemas', () => { class TestEndpoint extends PostEndpoint { - override body = new ObjectSanitizer({ - name: new IntegerValidator(), + override body = new ObjectValSan({ + schema: { + name: new IntegerValidator(), + }, }); override bodyExample = { name: 'test', }; - override response = new ObjectSanitizer({ - id: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + }, }); override responseExample = { @@ -148,10 +156,12 @@ describe('OasEndpointComponentConverter - Response Schemas', () => { it('generates correct schema structure for complex ' + 'response', () => { class TestEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), - email: new EmailValidator(), - status: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + email: new EmailValidator(), + status: new IntegerValidator(), + }, }); override responseExample = { diff --git a/test/spec/openapi/oas-endpoint-converter-response-schema.spec.ts b/test/spec/openapi/oas-endpoint-converter-response-schema.spec.ts index 9e9ed25..27d9ac9 100644 --- a/test/spec/openapi/oas-endpoint-converter-response-schema.spec.ts +++ b/test/spec/openapi/oas-endpoint-converter-response-schema.spec.ts @@ -1,6 +1,6 @@ import 'jasmine'; import { OasEndpointConverter } from '../../../src/oas/oas-endpoint-converter'; -import { ObjectSanitizer, IntegerValidator, EmailValidator } from 'valsan'; +import { IntegerValidator, EmailValidator, ObjectValSan } from 'valsan'; import { GetEndpoint } from '../../../src/router/endpoints/get-endpoint'; import { PostEndpoint } from '../../../src/router/endpoints/post-endpoint'; import { ApiRequest, ApiResponse, ApiNextFunction } from '../../../src/router'; @@ -18,9 +18,11 @@ describe('OasEndpointConverter - Response Schemas', () => { 'response sanitizer is defined', () => { class TestEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), - email: new EmailValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + email: new EmailValidator(), + }, }); override responseExample = { @@ -84,8 +86,10 @@ describe('OasEndpointConverter - Response Schemas', () => { it('respects custom status codes with response ' + 'schemas', () => { class TestEndpoint extends PostEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + }, }); override responseExample = { @@ -121,8 +125,10 @@ describe('OasEndpointConverter - Response Schemas', () => { it('generates both error and success responses', () => { class TestEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + }, }); override responseExample = { @@ -186,8 +192,10 @@ describe('OasEndpointConverter - Response Schemas', () => { it('handles endpoint names with special characters', () => { class MySpecialEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + }, }); override responseExample = { @@ -219,8 +227,10 @@ describe('OasEndpointConverter - Response Schemas', () => { it('preserves error responses when response schema ' + 'is defined', () => { class TestEndpoint extends GetEndpoint { - override response = new ObjectSanitizer({ - id: new IntegerValidator(), + override response = new ObjectValSan({ + schema: { + id: new IntegerValidator(), + }, }); override responseExample = {