diff --git a/backend/backend/package.json b/backend/backend/package.json
index 8dc1141c..ca5aa85e 100644
--- a/backend/backend/package.json
+++ b/backend/backend/package.json
@@ -43,7 +43,7 @@
"test:unit": "cross-env NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true STAPPS_LOG_LEVEL=0 mocha --exit"
},
"dependencies": {
- "@elastic/elasticsearch": "8.4.0",
+ "@elastic/elasticsearch": "8.10.0",
"@openstapps/core": "workspace:*",
"@openstapps/core-tools": "workspace:*",
"@openstapps/logger": "workspace:*",
@@ -56,6 +56,8 @@
"@types/nodemailer": "6.4.7",
"@types/promise-queue": "2.2.0",
"@types/uuid": "8.3.4",
+ "ajv": "8.12.0",
+ "ajv-formats": "2.1.1",
"body-parser": "1.20.2",
"cors": "2.8.5",
"cosmiconfig": "8.1.3",
@@ -102,16 +104,6 @@
"tsup": "6.7.0",
"typescript": "5.1.6"
},
- "tsup": {
- "entry": [
- "src/cli.ts"
- ],
- "sourcemap": true,
- "clean": true,
- "target": "es2022",
- "format": "esm",
- "outDir": "lib"
- },
"prettier": "@openstapps/prettier-config",
"eslintConfig": {
"extends": [
diff --git a/backend/backend/src/app.ts b/backend/backend/src/app.ts
index ea4820bc..ce707d03 100644
--- a/backend/backend/src/app.ts
+++ b/backend/backend/src/app.ts
@@ -14,6 +14,7 @@
* along with this program. If not, see .
*/
import {
+ SCConfigFile,
SCNotFoundErrorResponse,
SCRequestBodyTooLargeErrorResponse,
SCSyntaxErrorResponse,
@@ -23,8 +24,7 @@ import {Logger} from '@openstapps/logger';
import cors from 'cors';
import {Express} from 'express';
import morgan from 'morgan';
-import path from 'path';
-import {DEFAULT_TIMEOUT, isTestEnvironment, mailer, plugins, validator} from './common.js';
+import {DEFAULT_TIMEOUT, isTestEnvironment, mailer, plugins} from './common.js';
import {getPrometheusMiddleware} from './middleware/prometheus.js';
import {MailQueue} from './notification/mail-queue.js';
import {bulkAddRouter} from './routes/bulk-add-route.js';
@@ -39,7 +39,7 @@ import {virtualPluginRoute} from './routes/virtual-plugin-route.js';
import {BulkStorage} from './storage/bulk-storage.js';
import {DatabaseConstructor} from './storage/database.js';
import {backendConfig} from './config.js';
-import {fileURLToPath} from 'url';
+import {createValidator} from './validator.js';
/**
* Configure the backend
@@ -143,19 +143,10 @@ export async function configureApp(app: Express, databases: {[name: string]: Dat
request.on('data', chunkGatherer).on('end', endCallback);
});
- // validate config file
- const directory = path.dirname(fileURLToPath(import.meta.url));
- await validator.addSchemas(
- path.join(directory, '..', 'node_modules', '@openstapps', 'core', 'lib', 'schema'),
- );
-
- // validate the config file
- const configValidation = validator.validate(backendConfig, 'SCConfigFile');
-
- // validation failed
- if (configValidation.errors.length > 0) {
+ const configFileValid = createValidator('SCConfigFile');
+ if (!configFileValid(backendConfig)) {
throw new Error(
- `Validation of config file failed. Errors were: ${JSON.stringify(configValidation.errors)}`,
+ `Validation of config file failed. Errors were: ${JSON.stringify(configFileValid.errors)}`,
);
}
diff --git a/backend/backend/src/common.ts b/backend/backend/src/common.ts
index da6b2a98..7c07d6a6 100644
--- a/backend/backend/src/common.ts
+++ b/backend/backend/src/common.ts
@@ -14,7 +14,6 @@
* along with this program. If not, see .
*/
import {SCPluginMetaData} from '@openstapps/core';
-import {Validator} from '@openstapps/core-tools';
import {BackendTransport} from './notification/backend-transport.js';
/**
@@ -22,11 +21,6 @@ import {BackendTransport} from './notification/backend-transport.js';
*/
export const mailer = BackendTransport.getTransportInstance();
-/**
- * A validator instance to check if something is a valid JSON object (e.g. a request or a thing)
- */
-export const validator = new Validator();
-
/**
* Provides information if the backend is executed in the "test" (non-production) environment
*/
diff --git a/backend/backend/src/routes/route.ts b/backend/backend/src/routes/route.ts
index 01280bba..fca535d8 100644
--- a/backend/backend/src/routes/route.ts
+++ b/backend/backend/src/routes/route.ts
@@ -19,12 +19,12 @@ import {
SCRoute,
SCValidationErrorResponse,
} from '@openstapps/core';
-import {ValidationError} from '@openstapps/core-tools/src/types/validator.js';
import {Logger} from '@openstapps/logger';
import {Application, Router} from 'express';
import PromiseRouter from 'express-promise-router';
-import {isTestEnvironment, validator} from '../common.js';
+import {isTestEnvironment} from '../common.js';
import {isHttpMethod} from './http-types.js';
+import {createValidator} from '../validator.js';
/**
* Creates a router from a route class and a handler function which implements the logic
@@ -44,6 +44,8 @@ export function createRoute(
): Router {
// create router
const router = PromiseRouter({mergeParams: true});
+ const requestValidator = createValidator(routeClass.requestBodyName);
+ const responseValidator = createValidator(routeClass.responseBodyName);
// create route
// the given type has no index signature so we have to cast to get the IRouteHandler when a HTTP method is given
@@ -56,11 +58,8 @@ export function createRoute(
// create a route handler for the given HTTP method
route[verb](async (request, response) => {
try {
- // validate request
- const requestValidation = validator.validate(request.body, routeClass.requestBodyName);
-
- if (requestValidation.errors.length > 0) {
- const error = new SCValidationErrorResponse(requestValidation.errors, isTestEnvironment);
+ if (!requestValidator(request.body)) {
+ const error = new SCValidationErrorResponse(requestValidator.errors as any, isTestEnvironment);
response.status(error.statusCode);
response.json(error);
await Logger.error(error);
@@ -68,17 +67,13 @@ export function createRoute(
return;
}
- // hand over request to handler with path parameters
const handlerResponse = await handler(request.body, request.app, request.params);
- // validate response generated by handler
- const responseErrors: ValidationError[] = validator.validate(
- handlerResponse,
- routeClass.responseBodyName,
- ).errors;
-
- if (responseErrors.length > 0) {
- const validationError = new SCValidationErrorResponse(responseErrors, isTestEnvironment);
+ if (!responseValidator(handlerResponse)) {
+ const validationError = new SCValidationErrorResponse(
+ responseValidator.errors as any,
+ isTestEnvironment,
+ );
// The validation error is not caused by faulty user input, but through an error that originates somewhere in
// the backend, therefore we use this "stacked" error.
const internalServerError = new SCInternalServerErrorResponse(validationError, isTestEnvironment);
diff --git a/backend/backend/src/routes/virtual-plugin-route.ts b/backend/backend/src/routes/virtual-plugin-route.ts
index a96bdf80..babc2434 100644
--- a/backend/backend/src/routes/virtual-plugin-route.ts
+++ b/backend/backend/src/routes/virtual-plugin-route.ts
@@ -17,8 +17,9 @@
import {SCInternalServerErrorResponse, SCPluginMetaData, SCValidationErrorResponse} from '@openstapps/core';
import {Request} from 'express';
import got from 'got';
-import {isTestEnvironment, validator} from '../common.js';
+import {isTestEnvironment} from '../common.js';
import {backendConfig} from '../config.js';
+import {validator} from '../validator.js';
/**
* Generic route function used to proxy actual requests to plugins
@@ -28,10 +29,9 @@ import {backendConfig} from '../config.js';
*/
export async function virtualPluginRoute(request: Request, plugin: SCPluginMetaData): Promise