Skip to content

Commit

Permalink
feat: add express-openapi-validator
Browse files Browse the repository at this point in the history
  • Loading branch information
AliKdhim87 committed Oct 4, 2024
1 parent 8322757 commit fee9af1
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 16 deletions.
3 changes: 2 additions & 1 deletion apps/kennisbank-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"dotenv": "16.4.5",
"express": "4.21.0",
"js-yaml": "4.1.0",
"swagger-ui-express": "5.0.1"
"swagger-ui-express": "5.0.1",
"express-openapi-validator": "5.3.7"
},
"devDependencies": {
"@types/cors": "2.8.17",
Expand Down
6 changes: 3 additions & 3 deletions apps/kennisbank-api/src/docs/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
openapi: 3.0.3
openapi: "3.0.0"
info:
title: Kennisbank API
description: API to manage Kennisbank resources
version: 1.0.0
servers:
- url: http://localhost:4001
- url: http://localhost:4001/api/v1
description: Example server

paths:
/kennisartikelen:
/kennisartikel:
get:
summary: List all Kennisartikelen
operationId: getKennisartikelen
Expand Down
12 changes: 10 additions & 2 deletions apps/kennisbank-api/src/queries/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
const gql = (query: any) => query;
export const SEARCH_PRODUCT = gql(`
query searchProduct($locale: I18NLocaleCode, $query: String) {
products(locale: $locale, pagination: {start: 0, limit: -1}, filters: { title: {containsi: $query}}) {
query searchProduct($locale: I18NLocaleCode) {
products(
locale: $locale,
pagination: {start: 0, limit: -1},
filters: { slug: {eq: "aansprakelijk-stellen-gemeente-schade-melden"}}
) {
data {
id
attributes {
title
slug
uuid
locale
updatedAt
createdAt
Expand Down Expand Up @@ -44,6 +49,9 @@ export const SEARCH_PRODUCT = gql(`
}
pdc_metadata {
uplProductNaam
productCode
uitvoeringsorganisatie
doelgroep
}
}
}
Expand Down
32 changes: 30 additions & 2 deletions apps/kennisbank-api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@ import cors from 'cors';
import { config } from 'dotenv';
import express from 'express';
import { NextFunction, Request, Response } from 'express';
import * as OpenApiValidator from 'express-openapi-validator';
import path from 'node:path';
import { kennisartikel, openapi } from './routers';
import { envAvailability, ErrorHandler } from './utils';
config();

type OpenOpenApiValidationError = {
path: string;
message: string;
errorCode: string;
};
interface OpenApiValidationErrorTypes {
errors: OpenOpenApiValidationError[];
}

// Validate environment variables
envAvailability({
env: process.env,
Expand All @@ -27,8 +38,20 @@ const corsOption: CorsOptions = {
},
optionsSuccessStatus: 200,
};
// eslint-disable-next-line no-undef
const apiSpec = path.join(__dirname, './docs/openapi.yaml');
const app = express();

app.use(express.json());
/**
* OpenAPI Validator
* Validate requests and responses according to the OpenAPI specification
*/
app.use(
OpenApiValidator.middleware({
apiSpec,
validateResponses: true, // false by default
}),
);
const port = process.env.KENNIS_BANK_API_PORT;
// Centralized error handler middleware
const globalErrorHandler = (err: ErrorHandler, _req: Request, res: Response, _next: NextFunction) => {
Expand All @@ -39,10 +62,15 @@ const globalErrorHandler = (err: ErrorHandler, _req: Request, res: Response, _ne
});
}

const isOpenApiValidatorError = (err as OpenApiValidationErrorTypes)?.errors?.find(
({ errorCode }) => errorCode?.includes('format.openapi.validation'),
);
if (isOpenApiValidatorError) {
return res.status(400).json((err as OpenApiValidationErrorTypes).errors);
}
// If it's an unknown error (not an operational error), log it and send a generic response
// eslint-disable-next-line no-console
console.error('Unexpected error:', err);

return res.status(500).json({
message: 'An unexpected error occurred.',
});
Expand Down
106 changes: 98 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,15 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"

"@apidevtools/json-schema-ref-parser@^11.7.0":
version "11.7.0"
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.0.tgz#228d72018a0e7cbee744b677eaa01a8968f302d9"
integrity sha512-pRrmXMCwnmrkS3MLgAIW5dXRzeTv6GLjkjb4HmxNnvAKXN1Nfzp4KmGADBQvlVUcqi+a5D+hfGDLLnd5NnYxog==
dependencies:
"@jsdevtools/ono" "^7.1.3"
"@types/json-schema" "^7.0.15"
js-yaml "^4.1.0"

"@apollo/[email protected]":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.6.tgz#d601e65211e06ae1432bf5993a1a0105f2862f27"
Expand Down Expand Up @@ -4020,6 +4029,11 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"

"@jsdevtools/[email protected]", "@jsdevtools/ono@^7.1.3":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==

"@juggle/resize-observer@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
Expand Down Expand Up @@ -7424,7 +7438,7 @@
"@types/tough-cookie" "*"
parse5 "^7.0.0"

"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
"@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
Expand Down Expand Up @@ -7560,6 +7574,13 @@
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==

"@types/multer@^1.4.12":
version "1.4.12"
resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.12.tgz#da67bd0c809f3a63fe097c458c0d4af1fea50ab7"
integrity sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==
dependencies:
"@types/express" "*"

"@types/node-forge@^1.3.0":
version "1.3.11"
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
Expand Down Expand Up @@ -8447,7 +8468,7 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"

ajv-draft-04@~1.0.0:
ajv-draft-04@^1.0.0, ajv-draft-04@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8"
integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==
Expand Down Expand Up @@ -8493,7 +8514,7 @@ ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.12.6:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

ajv@^8.0.0, ajv@^8.0.1, ajv@^8.11.0, ajv@^8.9.0:
ajv@^8.0.0, ajv@^8.0.1, ajv@^8.11.0, ajv@^8.17.1, ajv@^8.9.0:
version "8.17.1"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
Expand Down Expand Up @@ -8761,6 +8782,11 @@ apollo-server-types@^3.6.2, apollo-server-types@^3.8.0:
apollo-reporting-protobuf "^3.4.0"
apollo-server-env "^4.2.1"

append-field@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==

"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
Expand Down Expand Up @@ -9768,7 +9794,7 @@ bundle-name@^3.0.0:
dependencies:
run-applescript "^5.0.0"

[email protected], busboy@^1.6.0:
[email protected], busboy@^1.0.0, busboy@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
Expand Down Expand Up @@ -10738,6 +10764,16 @@ [email protected]:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==

concat-stream@^1.5.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^2.2.2"
typedarray "^0.0.6"

concat-with-sourcemaps@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e"
Expand Down Expand Up @@ -10850,7 +10886,7 @@ [email protected], content-disposition@~0.5.2:
dependencies:
safe-buffer "5.2.1"

content-type@^1.0.4, content-type@~1.0.4, content-type@~1.0.5:
content-type@^1.0.4, content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
Expand Down Expand Up @@ -13297,6 +13333,25 @@ exponential-backoff@^3.1.1:
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==

[email protected]:
version "5.3.7"
resolved "https://registry.yarnpkg.com/express-openapi-validator/-/express-openapi-validator-5.3.7.tgz#e93cabd9a3b4be4f62e748d239128a217118c00c"
integrity sha512-AFlIXvICrPWJvWtrsfpL212kyvmyzThcZ1ASnnsRqmzxSo/3SV+J7M1oEsFYbqo7AYQPGtSBKy7eheGM6wPwag==
dependencies:
"@apidevtools/json-schema-ref-parser" "^11.7.0"
"@types/multer" "^1.4.12"
ajv "^8.17.1"
ajv-draft-04 "^1.0.0"
ajv-formats "^2.1.1"
content-type "^1.0.5"
json-schema-traverse "^1.0.0"
lodash.clonedeep "^4.5.0"
lodash.get "^4.4.2"
media-typer "^1.1.0"
multer "^1.4.5-lts.1"
ono "^7.1.3"
path-to-regexp "^8.1.0"

[email protected]:
version "4.18.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
Expand Down Expand Up @@ -18913,6 +18968,11 @@ [email protected]:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==

media-typer@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561"
integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==

memfs@^3.1.2, memfs@^3.4.1, memfs@^3.4.12, memfs@^3.4.3:
version "3.6.0"
resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6"
Expand Down Expand Up @@ -19757,7 +19817,7 @@ mkdirp-infer-owner@^2.0.0:
infer-owner "^1.0.4"
mkdirp "^1.0.3"

mkdirp@^0.5.1:
mkdirp@^0.5.1, mkdirp@^0.5.4:
version "0.5.6"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
Expand Down Expand Up @@ -19823,6 +19883,19 @@ [email protected], ms@^2.0.0, ms@^2.1.1, ms@^2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

multer@^1.4.5-lts.1:
version "1.4.5-lts.1"
resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac"
integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==
dependencies:
append-field "^1.0.0"
busboy "^1.0.0"
concat-stream "^1.5.2"
mkdirp "^0.5.4"
object-assign "^4.1.1"
type-is "^1.6.4"
xtend "^4.0.0"

[email protected]:
version "3.0.2"
resolved "https://registry.yarnpkg.com/multi-semantic-release/-/multi-semantic-release-3.0.2.tgz#a714bb66a30a669d64386f566f728416ff59cae8"
Expand Down Expand Up @@ -20885,6 +20958,13 @@ only@~0.0.2:
resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==

ono@^7.1.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/ono/-/ono-7.1.3.tgz#a054e96a388f566a6c4c95e1e92b9b253722d286"
integrity sha512-9jnfVriq7uJM4o5ganUY54ntUm+5EK21EGaQ5NWnkWg3zz5ywbbonlBguRcnmF1/HDiIe3zxNxXcO1YPBmPcQQ==
dependencies:
"@jsdevtools/ono" "7.1.3"

[email protected]:
version "8.4.0"
resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
Expand Down Expand Up @@ -21562,6 +21642,11 @@ path-to-regexp@^6.1.0:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36"
integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==

path-to-regexp@^8.1.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4"
integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==

path-type@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
Expand Down Expand Up @@ -23563,7 +23648,7 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stre
string_decoder "^1.1.1"
util-deprecate "^1.0.1"

readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@~2.3.6:
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@~2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
Expand Down Expand Up @@ -26794,7 +26879,7 @@ type-func@^1.0.1:
resolved "https://registry.yarnpkg.com/type-func/-/type-func-1.0.3.tgz#ab184234ae80d8d50057cefeff3b2d97d08ae9b0"
integrity sha512-YA90CUk+i00tWESPNRMahywXhAz+12NLJLKlOWrgHIbqaFXjdZrWstRghaibOW/IxhPjui4SmXxO/03XSGRIjA==

type-is@^1.6.14, type-is@^1.6.16, type-is@^1.6.18, type-is@~1.6.18:
type-is@^1.6.14, type-is@^1.6.16, type-is@^1.6.18, type-is@^1.6.4, type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
Expand Down Expand Up @@ -26853,6 +26938,11 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"

typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==

[email protected]:
version "5.0.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
Expand Down

0 comments on commit fee9af1

Please sign in to comment.