@adaptivestone/framework 4.5.0 → 4.7.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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ### 4.7.0
2
+
3
+ [UPDATE] update logger init (refactor)
4
+ [UPDATE] updated deps
5
+
6
+ ### 4.6.0
7
+
8
+ [NEW] migrated from JEST to vitest
9
+
1
10
  ### 4.5.0
2
11
 
3
12
  [NEW] Now getSuper() available as a method on monsgoose models
package/cluster.js CHANGED
@@ -21,6 +21,5 @@ if (cluster.isMaster) {
21
21
  cluster.fork();
22
22
  });
23
23
  } else {
24
- // eslint-disable-next-line global-require
25
- require('./index');
24
+ import('./server.js');
26
25
  }
@@ -13,8 +13,7 @@ class GetOpenApiJson extends AbstractCommand {
13
13
  }
14
14
 
15
15
  try {
16
- // eslint-disable-next-line import/no-dynamic-require, global-require
17
- jsonFile = require(jsonFile);
16
+ jsonFile = JSON.parse(await fs.readFile(jsonFile, 'utf8'));
18
17
  } catch (e) {
19
18
  this.logger.error(
20
19
  'No npm package detected. Please start this command via NPM as it depends on package.json',
@@ -31,8 +31,8 @@ class Migrate extends AbstractCommand {
31
31
 
32
32
  for (const migration of migrations) {
33
33
  this.logger.info(`=== Start migration ${migration.file} ===`);
34
- // eslint-disable-next-line import/no-dynamic-require, global-require
35
- const MigrationCommand = require(migration.path);
34
+ // eslint-disable-next-line no-await-in-loop
35
+ const MigrationCommand = await import(migration.path);
36
36
  const migrationCommand = new MigrationCommand(this.app);
37
37
  // eslint-disable-next-line no-await-in-loop
38
38
  await migrationCommand.up();
@@ -1,3 +1,5 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
1
3
  const userEmail = 'testing@test.com';
2
4
  const userPassword = 'SuperNiceSecret123$';
3
5
 
@@ -1,3 +1,5 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
1
3
  describe('home', () => {
2
4
  it('can open home have', async () => {
3
5
  expect.assertions(1);
@@ -33,7 +33,6 @@ class ControllerManager extends Base {
33
33
  // TODO wait until https://github.com/nodejs/node/issues/35889
34
34
  controllers.push(
35
35
  import(controller.path).then(({ default: ControllerModule }) => {
36
- // eslint-disable-next-line import/no-dynamic-require, global-require
37
36
  // const ControllerModule = require(controller.path);
38
37
  const contollerName = ControllerModule.name.toLowerCase();
39
38
  let prefix = path.dirname(controller.file);
@@ -1,3 +1,5 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
1
3
  describe('sequence model', () => {
2
4
  it('should produce sequence', async () => {
3
5
  expect.assertions(1);
@@ -1,3 +1,5 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
1
3
  const userEmail = 'testing@test.com';
2
4
  const userPassword = 'SuperNiceSecret123$';
3
5
 
@@ -271,7 +271,7 @@ class AbstractController extends Base {
271
271
  */
272
272
  if (!this.app.httpServer) {
273
273
  this.app.documentation.push(
274
- DocumentationGenerator.convertDataToDocumentationElement(
274
+ new DocumentationGenerator(this.app).convertDataToDocumentationElement(
275
275
  this.getConstructorName(),
276
276
  routesInfo,
277
277
  middlewaresInfo,
package/modules/Base.js CHANGED
@@ -29,71 +29,10 @@ class Base {
29
29
 
30
30
  /**
31
31
  * Get winston loger for given label
32
- * @param {sting} label name of logger
32
+ * @param {string} label name of logger
33
33
  */
34
34
  getLogger(label) {
35
- // eslint-disable-next-line global-require
36
- const winston = require('winston'); // speed up optimisation
37
- const alignColorsAndTime = winston.format.combine(
38
- winston.format.colorize({
39
- all: true,
40
- }),
41
- winston.format.label({
42
- label: ` \x1B[32m[${label}]\x1B[39m`,
43
- }),
44
- winston.format.timestamp(),
45
- winston.format.printf(
46
- (info) =>
47
- `(${process.pid}) ${info.label} ${info.timestamp} ${info.level} : ${info.message}`,
48
- ),
49
- );
50
-
51
- const logConfig = this.app.getConfig('log').transports;
52
-
53
- function IsConstructor(f) {
54
- try {
55
- Reflect.construct(String, [], f);
56
- } catch (e) {
57
- return false;
58
- }
59
- return true;
60
- }
61
- const transports = [];
62
- for (const log of logConfig) {
63
- if (log.enable) {
64
- if (log.transport === 'console') {
65
- transports.push(
66
- new winston.transports.Console({
67
- level: log.transportOptions.level,
68
- format: winston.format.combine(
69
- winston.format.colorize(),
70
- alignColorsAndTime,
71
- ),
72
- }),
73
- );
74
- } else {
75
- // eslint-disable-next-line global-require, import/no-dynamic-require
76
- let Tr = require(log.transport);
77
- if (!IsConstructor(Tr) && Tr.default) {
78
- Tr = Tr.default;
79
- } else {
80
- // eslint-disable-next-line no-console
81
- console.error(
82
- `${log.transport} not a constructor. Please check it`,
83
- );
84
- // eslint-disable-next-line no-continue
85
- continue;
86
- }
87
-
88
- transports.push(new Tr(log.transportOptions));
89
- }
90
- }
91
- }
92
-
93
- return winston.createLogger({
94
- level: 'silly',
95
- transports,
96
- });
35
+ return this.app.logger.child({ label });
97
36
  }
98
37
 
99
38
  async getFilesPathWithInheritance(internalFolder, externalFolder) {
@@ -50,7 +50,6 @@ class Cli extends Base {
50
50
  // TODO wait until https://github.com/nodejs/node/issues/35889
51
51
  const { default: Command } = await import(this.commands[command]);
52
52
 
53
- // eslint-disable-next-line import/no-dynamic-require, global-require
54
53
  // const Command = require(this.commands[command]);
55
54
 
56
55
  const c = new Command(this.app, this.commands, args);
@@ -1,5 +1,6 @@
1
- const SomeController = require('../controllers/test/SomeController');
2
- const AbstractController = require('./AbstractController');
1
+ import { describe, it, expect } from 'vitest';
2
+ import SomeController from '../controllers/test/SomeController';
3
+ import AbstractController from './AbstractController';
3
4
 
4
5
  describe('abstract controller methods', () => {
5
6
  it('can get routes', async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptivestone/framework",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "description": "Adaptive stone node js framework",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -14,7 +14,7 @@
14
14
  "scripts": {
15
15
  "dev": "nodemon ./index.js",
16
16
  "prod": "nodemon ./cluster.js",
17
- "test": "jest --coverage=true",
17
+ "test": "vitest run --coverage",
18
18
  "prettier": "prettier --check '**/*.(js|jsx|ts|tsx|json|css|scss|md)'",
19
19
  "lint": "eslint '**/*.js'",
20
20
  "lint:fix": "eslint '**/*.js' --fix",
@@ -25,18 +25,6 @@
25
25
  "benchmark2": "h2load -n 10000 -c 50 https://localhost:3300/",
26
26
  "redis:docker": "docker run --rm -p 6379:6379 redis"
27
27
  },
28
- "jest": {
29
- "setupFilesAfterEnv": [
30
- "./tests/setup.js"
31
- ],
32
- "testEnvironment": "node",
33
- "verbose": true,
34
- "collectCoverage": true,
35
- "coverageReporters": [
36
- "text",
37
- "text-summary"
38
- ]
39
- },
40
28
  "author": "Andrey Logunov",
41
29
  "license": "MIT",
42
30
  "dependencies": {
@@ -63,17 +51,17 @@
63
51
  "yup": "^1.0.0"
64
52
  },
65
53
  "devDependencies": {
66
- "@babel/preset-env": "^7.22.15",
54
+ "@vitest/coverage-v8": "^0.34.3",
67
55
  "eslint": "^8.0.0",
68
56
  "eslint-config-airbnb-base": "^15.0.0",
69
57
  "eslint-config-prettier": "^9.0.0",
70
- "eslint-plugin-jest": "^27.0.0",
58
+ "eslint-plugin-vitest": "^0.3.1",
71
59
  "husky": "^8.0.0",
72
- "jest": "^29.0.0",
73
60
  "lint-staged": "^14.0.0",
74
61
  "mongodb-memory-server": "^8.0.2",
75
62
  "nodemon": "^3.0.1",
76
- "prettier": "^3.0.0"
63
+ "prettier": "^3.0.0",
64
+ "vitest": "^0.34.3"
77
65
  },
78
66
  "lint-staged": {
79
67
  "**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
package/server.d.ts CHANGED
@@ -7,6 +7,7 @@ import { Model as MongooseModel, Schema } from 'mongoose';
7
7
 
8
8
  import BaseCli from './modules/BaseCli';
9
9
  import Cache from './services/cache/Cache';
10
+ import winston from 'winston';
10
11
 
11
12
  type ServerConfig = {
12
13
  folders: ExpandDeep<TFolderConfig>;
@@ -22,6 +23,7 @@ declare class Server {
22
23
  foldersConfig: Server['config']['folders'];
23
24
  events: EventEmitter;
24
25
  get cache(): Server['cacheService'];
26
+ get logger(): winston.Logger;
25
27
  httpServer: null;
26
28
  controllerManager: null;
27
29
  };
@@ -39,7 +41,7 @@ declare class Server {
39
41
  constructor(config: ExpandDeep<ServerConfig>);
40
42
 
41
43
  /**
42
- * Start server (http + websocket + init all http and websocet ralated functions)
44
+ * Start server (http + init all http ralated functions)
43
45
  */
44
46
  startServer(callbackBefore404?: Promise<null>): Promise<null>;
45
47
 
@@ -54,6 +56,11 @@ declare class Server {
54
56
  */
55
57
  getConfig(configName: string): {};
56
58
 
59
+ /**
60
+ * Return or create new logger instance. This is a main logger instance
61
+ */
62
+ getLogger(): winston.Logger;
63
+
57
64
  /**
58
65
  * Primary designed for tests when we need to update some configs before start testing
59
66
  * Should be called before any initialization was done
package/server.js CHANGED
@@ -3,11 +3,14 @@ const EventEmitter = require('node:events');
3
3
 
4
4
  require('dotenv').config();
5
5
  const merge = require('deepmerge');
6
+ const winston = require('winston');
6
7
 
7
8
  /**
8
9
  * Main framework class.
9
10
  */
10
11
  class Server {
12
+ #realLogger = null;
13
+
11
14
  /**
12
15
  * Construct new server
13
16
  * @param {Object} config main config object
@@ -33,6 +36,9 @@ class Server {
33
36
  get cache() {
34
37
  return that.getCache();
35
38
  },
39
+ get logger() {
40
+ return that.getLogger();
41
+ },
36
42
  httpServer: null,
37
43
  controllerManager: null,
38
44
  };
@@ -46,21 +52,17 @@ class Server {
46
52
  }
47
53
 
48
54
  /**
49
- * Start server (http + websocket + init all http and websocet ralated functions)
55
+ * Start server (http + init all http ralated functions)
50
56
  * @param <Promise>callbackBefore404 code that should be executed before adding page 404
51
57
  * @returns {Promise}
52
58
  */
53
59
  async startServer(callbackBefore404 = async () => Promise.resolve()) {
54
- // eslint-disable-next-line global-require
55
60
  // const HttpServer = require('./services/http/HttpServer');
56
- // eslint-disable-next-line global-require
57
61
  // const ControllerManager = require('./controllers/index');
58
62
  // TODO wait until https://github.com/nodejs/node/issues/35889
59
63
  const [{ default: HttpServer }, { default: ControllerManager }] =
60
64
  await Promise.all([
61
- // eslint-disable-next-line import/extensions
62
65
  import('./services/http/HttpServer.js'), // Speed optimisation
63
- // eslint-disable-next-line import/extensions
64
66
  import('./controllers/index.js'), // Speed optimisation
65
67
  ]);
66
68
 
@@ -126,6 +128,80 @@ class Server {
126
128
  return this.cache.configs.get(configName);
127
129
  }
128
130
 
131
+ /**
132
+ * Return or create new logger instance. This is a main logger instance
133
+ */
134
+ getLogger() {
135
+ if (!this.#realLogger) {
136
+ this.#realLogger = this.#createLogger();
137
+ }
138
+ return this.#realLogger;
139
+ }
140
+
141
+ #createLogger() {
142
+ const alignColorsAndTime = winston.format.combine(
143
+ winston.format.colorize({
144
+ all: true,
145
+ }),
146
+ winston.format.timestamp(),
147
+ winston.format.printf(
148
+ (info) =>
149
+ `(${process.pid}) \x1B[32m[${info.label ?? 'SERVER'}]\x1B[39m ${
150
+ info.timestamp
151
+ } ${info.level} : ${info.message} ${info?.stack ?? ''} ${
152
+ info.durationMs ? `Duration: ${info.durationMs}ms` : ''
153
+ }`,
154
+ ),
155
+ );
156
+ const logConfig = this.app.getConfig('log').transports;
157
+ function IsConstructor(f) {
158
+ try {
159
+ Reflect.construct(String, [], f);
160
+ } catch (e) {
161
+ return false;
162
+ }
163
+ return true;
164
+ }
165
+
166
+ const logger = winston.createLogger({
167
+ format: winston.format.errors({ stack: true }),
168
+ level: 'silly',
169
+ });
170
+
171
+ for (const log of logConfig) {
172
+ if (log.enable) {
173
+ if (log.transport === 'console') {
174
+ logger.add(
175
+ new winston.transports.Console({
176
+ level: log.transportOptions.level,
177
+ format: winston.format.combine(
178
+ winston.format.colorize(),
179
+ alignColorsAndTime,
180
+ ),
181
+ }),
182
+ );
183
+ } else {
184
+ import(log.transport).then((Tr) => {
185
+ let Transport = Tr.default;
186
+ if (!IsConstructor(Transport) && Transport.default) {
187
+ Transport = Transport.default;
188
+ } else {
189
+ console.error(
190
+ `${log.transport} not a constructor. Please check it`,
191
+ );
192
+ return;
193
+ }
194
+ logger.profile(`Adding new logger ${log.transport}`);
195
+ logger.add(new Transport(log.transportOptions));
196
+ logger.profile(`Adding new logger ${log.transport}`);
197
+ });
198
+ }
199
+ }
200
+ }
201
+
202
+ return logger;
203
+ }
204
+
129
205
  /**
130
206
  * Primary designed for tests when we need to update some configs before start testing
131
207
  * Should be called before any initialization was done
@@ -178,11 +254,9 @@ class Server {
178
254
  */
179
255
  async runCliCommand(commandName, args) {
180
256
  if (!this.cli) {
181
- // eslint-disable-next-line import/extensions
182
257
  // TODO wait until https://github.com/nodejs/node/issues/35889
183
- // const { default: BaseCli } = await import('./modules/BaseCli.js'); // Speed optimisation
184
- // eslint-disable-next-line global-require
185
- const BaseCli = require('./modules/BaseCli');
258
+ const { default: BaseCli } = await import('./modules/BaseCli.js'); // Speed optimisation
259
+ // const BaseCli = require('./modules/BaseCli');
186
260
  this.cli = new BaseCli(this);
187
261
  }
188
262
  return this.cli.run(commandName, args);
@@ -2,7 +2,8 @@ const Base = require('../../modules/Base');
2
2
  const ValidateService = require('../validate/ValidateService');
3
3
 
4
4
  class DocumentationGenerator extends Base {
5
- static processingFields(fieldsByRoute) {
5
+ // eslint-disable-next-line class-methods-use-this
6
+ processingFields(fieldsByRoute) {
6
7
  const fields = [];
7
8
  if (!fieldsByRoute) {
8
9
  return fields;
@@ -36,7 +37,8 @@ class DocumentationGenerator extends Base {
36
37
  return fields;
37
38
  }
38
39
 
39
- static selectUniqueFields(fields) {
40
+ // eslint-disable-next-line class-methods-use-this
41
+ selectUniqueFields(fields) {
40
42
  return Array.from(
41
43
  new Map(fields.map((item) => [item.name, item])).values(),
42
44
  ).reduce((uniqueArray, item) => {
@@ -52,7 +54,7 @@ class DocumentationGenerator extends Base {
52
54
  }, []);
53
55
  }
54
56
 
55
- static groupFieldsFromSchemas(schemas) {
57
+ groupFieldsFromSchemas(schemas) {
56
58
  const result = [];
57
59
  schemas.forEach((schema) => {
58
60
  const convertedSchema = new ValidateService(this.app, schema).validator;
@@ -71,7 +73,7 @@ class DocumentationGenerator extends Base {
71
73
  return result;
72
74
  }
73
75
 
74
- static convertDataToDocumentationElement(
76
+ convertDataToDocumentationElement(
75
77
  controllerName,
76
78
  routesInfo,
77
79
  middlewaresInfo,
@@ -80,23 +82,19 @@ class DocumentationGenerator extends Base {
80
82
  return {
81
83
  contollerName: controllerName,
82
84
  routesInfo: routesInfo.map((route) => {
83
- const middlewareQueryParams = ValidateService.getMiddlewareParams(
84
- middlewaresInfo,
85
- routeMiddlewaresReg,
86
- {
87
- method: route.method.toLowerCase(),
88
- path: route.fullPath,
89
- },
90
- ).query;
85
+ const middlewareQueryParams = new ValidateService(
86
+ this.app,
87
+ ).getMiddlewareParams(middlewaresInfo, routeMiddlewaresReg, {
88
+ method: route.method.toLowerCase(),
89
+ path: route.fullPath,
90
+ }).query;
91
91
 
92
- const middlewareRequestParams = ValidateService.getMiddlewareParams(
93
- middlewaresInfo,
94
- routeMiddlewaresReg,
95
- {
96
- method: route.method.toLowerCase(),
97
- path: route.fullPath,
98
- },
99
- ).request;
92
+ const middlewareRequestParams = new ValidateService(
93
+ this.app,
94
+ ).getMiddlewareParams(middlewaresInfo, routeMiddlewaresReg, {
95
+ method: route.method.toLowerCase(),
96
+ path: route.fullPath,
97
+ }).request;
100
98
 
101
99
  const queryParams = this.groupFieldsFromSchemas(middlewareQueryParams);
102
100
 
@@ -1,4 +1,5 @@
1
- const I18n = require('./I18n');
1
+ import { beforeAll, describe, it, expect } from 'vitest';
2
+ import I18n from './I18n';
2
3
 
3
4
  describe('i18n middleware methods', () => {
4
5
  let middleware;
@@ -45,13 +46,16 @@ describe('i18n middleware methods', () => {
45
46
 
46
47
  it('middleware that works', async () => {
47
48
  expect.assertions(4);
48
- const nextFunction = jest.fn(() => {});
49
+ let isCalled = false;
50
+ const nextFunction = () => {
51
+ isCalled = true;
52
+ };
49
53
  const req = {
50
54
  get: () => 'en',
51
55
  appInfo: {},
52
56
  };
53
57
  await middleware.middleware(req, {}, nextFunction);
54
- expect(nextFunction).toHaveBeenCalledWith();
58
+ expect(isCalled).toBe(true);
55
59
  expect(req.appInfo.i18n).toBeDefined();
56
60
  expect(req.appInfo.i18n.t('aaaaa')).toBe('aaaaa');
57
61
  expect(req.i18n.t('aaaaa')).toBe('aaaaa'); // proxy test
@@ -62,13 +66,16 @@ describe('i18n middleware methods', () => {
62
66
  global.server.app.updateConfig('i18n', { enabled: false });
63
67
  middleware = new I18n(global.server.app);
64
68
 
65
- const nextFunction = jest.fn(() => {});
69
+ let isCalled = false;
70
+ const nextFunction = () => {
71
+ isCalled = true;
72
+ };
66
73
  const req = {
67
74
  get: () => 'en',
68
75
  appInfo: {},
69
76
  };
70
77
  await middleware.middleware(req, {}, nextFunction);
71
- expect(nextFunction).toHaveBeenCalledWith();
78
+ expect(isCalled).toBe(true);
72
79
  expect(req.appInfo.i18n).toBeDefined();
73
80
  expect(req.appInfo.i18n.t('aaaaa')).toBe('aaaaa');
74
81
  expect(req.i18n.t('aaaaa')).toBe('aaaaa'); // proxy test
@@ -1,4 +1,5 @@
1
- const PrepareAppInfo = require('./PrepareAppInfo');
1
+ import { describe, it, expect } from 'vitest';
2
+ import PrepareAppInfo from './PrepareAppInfo';
2
3
 
3
4
  describe('prepareAppInfo methods', () => {
4
5
  it('have description fields', async () => {
@@ -10,10 +11,13 @@ describe('prepareAppInfo methods', () => {
10
11
  it('middleware that works', async () => {
11
12
  expect.assertions(3);
12
13
  const middleware = new PrepareAppInfo(global.server.app);
13
- const nextFunction = jest.fn(() => {});
14
+ let isCalled = false;
15
+ const nextFunction = () => {
16
+ isCalled = true;
17
+ };
14
18
  const req = {};
15
19
  await middleware.middleware(req, {}, nextFunction);
16
- expect(nextFunction).toHaveBeenCalledWith();
20
+ expect(isCalled).toBe(true);
17
21
  expect(req.appInfo).toBeDefined();
18
22
  req.appInfo.test = 5;
19
23
  await middleware.middleware(req, {}, nextFunction);
@@ -1,14 +1,19 @@
1
- const { setTimeout } = require('node:timers/promises');
2
- const RateLimiter = require('./RateLimiter');
1
+ import { setTimeout } from 'node:timers/promises';
2
+ import crypto from 'node:crypto';
3
+ import { beforeAll, afterAll, describe, it, expect } from 'vitest';
4
+
5
+ import RateLimiter from './RateLimiter';
3
6
 
4
7
  let mongoRateLimiter;
5
8
 
6
9
  describe('rate limiter methods', () => {
7
- beforeAll(() => {
10
+ beforeAll(async () => {
11
+ await setTimeout(20);
12
+
8
13
  mongoRateLimiter = new RateLimiter(global.server.app, {
9
14
  driver: 'mongo',
10
15
  limiterOptions: {
11
- keyPrefix: `mongo_${Date.now()}`,
16
+ keyPrefix: `mongo_${Date.now()}_${crypto.randomUUID()}}`,
12
17
  },
13
18
  });
14
19
  });
@@ -89,7 +94,6 @@ describe('rate limiter methods', () => {
89
94
  const rateLimiter = new RateLimiter(global.server.app, {
90
95
  driver: 'unknown',
91
96
  });
92
- const nextFunction = jest.fn(() => {});
93
97
  const req = {
94
98
  appInfo: {},
95
99
  };
@@ -106,7 +110,7 @@ describe('rate limiter methods', () => {
106
110
  isSend = true;
107
111
  },
108
112
  },
109
- nextFunction,
113
+ () => {},
110
114
  );
111
115
  expect(status).toBe(500);
112
116
  expect(isSend).toBe(true);
@@ -1,7 +1,10 @@
1
- const { createServer } = require('node:http');
2
- const formidable = require('formidable');
1
+ import { createServer } from 'node:http';
2
+ import { describe, it, expect } from 'vitest';
3
+
4
+ import RequestParser from './RequestParser';
3
5
 
4
- const RequestParser = require('./RequestParser');
6
+ // TODO change on ESM
7
+ const formidable = require('formidable');
5
8
 
6
9
  describe('reqest parser limiter methods', () => {
7
10
  it('have description fields', async () => {
@@ -24,7 +27,7 @@ describe('reqest parser limiter methods', () => {
24
27
  expect(req.body.multipleFiles).toBeDefined();
25
28
  expect(
26
29
  req.body.multipleFiles[0] instanceof formidable.PersistentFile,
27
- ).toBe(true);
30
+ ).toBeTruthy();
28
31
 
29
32
  res.writeHead(200);
30
33
  res.end('ok');
@@ -41,7 +41,7 @@ class ValidateService extends Base {
41
41
  /**
42
42
  * Filter middlewares by route path and select all parameters
43
43
  */
44
- static filterRelatedParametersByRoute(middlewares, method, path) {
44
+ filterRelatedParametersByRoute(middlewares, method, path) {
45
45
  const middlewaresParams = middlewares
46
46
  .filter(
47
47
  (middleware) =>
@@ -63,11 +63,7 @@ class ValidateService extends Base {
63
63
  /**
64
64
  * Group all middleware(routes + controller) parameters
65
65
  */
66
- static getMiddlewareParams(
67
- controllerMiddlewares,
68
- AllrouteMiddlewares,
69
- options,
70
- ) {
66
+ getMiddlewareParams(controllerMiddlewares, AllrouteMiddlewares, options) {
71
67
  const { method, path } = options;
72
68
  const routeMiddlewaresParams = this.filterRelatedParametersByRoute(
73
69
  AllrouteMiddlewares,
@@ -134,7 +130,7 @@ class ValidateService extends Base {
134
130
  this.validator,
135
131
  selectedReqData,
136
132
  );
137
- const additionalMiddlewareSchemas = this.constructor.getMiddlewareParams(
133
+ const additionalMiddlewareSchemas = this.getMiddlewareParams(
138
134
  middlewaresInfo,
139
135
  routeMiddlewaresReg,
140
136
  routeOptions,
@@ -1,3 +1,5 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
1
3
  const yup = require('yup');
2
4
  const ValidateService = require('./ValidateService');
3
5
  const YupValidator = require('./drivers/YupValidator');
package/tests/setup.js CHANGED
@@ -1,5 +1,5 @@
1
+ /* eslint-disable no-undef */
1
2
  const path = require('node:path');
2
- /* eslint-disable jest/require-top-level-describe */
3
3
  const { MongoMemoryReplSet } = require('mongodb-memory-server');
4
4
  const mongoose = require('mongoose');
5
5
 
@@ -0,0 +1,119 @@
1
+ import path from 'node:path';
2
+ import { beforeAll, beforeEach, afterEach, afterAll } from 'vitest';
3
+
4
+ const { MongoMemoryReplSet } = require('mongodb-memory-server');
5
+
6
+ const mongoose = require('mongoose');
7
+
8
+ let mongoMemoryServerInstance;
9
+
10
+ const redis = require('redis');
11
+ const Server = require('../server');
12
+
13
+ const clearRedisNamespace = require('../helpers/redis/clearNamespace');
14
+
15
+ // eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
16
+ beforeAll(async () => {
17
+ mongoMemoryServerInstance = await MongoMemoryReplSet.create({
18
+ // binary: { version: '4.4.6' },
19
+ replSet: { count: 1, storageEngine: 'wiredTiger' },
20
+ });
21
+ await mongoMemoryServerInstance.waitUntilRunning();
22
+ process.env.LOGGER_CONSOLE_LEVEL = 'error';
23
+ const connectionStringMongo = await mongoMemoryServerInstance.getUri();
24
+ // console.info('MONGO_URI: ', connectionStringMongo);
25
+ global.server = new Server({
26
+ folders: {
27
+ config: process.env.TEST_FOLDER_CONFIG || path.resolve('./config'),
28
+ controllers:
29
+ process.env.TEST_FOLDER_CONTROLLERS || path.resolve('./controllers'),
30
+ views: process.env.TEST_FOLDER_VIEWS || path.resolve('./views'),
31
+ public: process.env.TEST_FOLDER_PUBLIC || path.resolve('./public'),
32
+ models: process.env.TEST_FOLDER_MODELS || path.resolve('./models'),
33
+ emails:
34
+ process.env.TEST_FOLDER_EMAIL ||
35
+ process.env.TEST_FOLDER_EMAILS ||
36
+ path.resolve('./services/messaging/email/templates'),
37
+ locales: process.env.TEST_FOLDER_LOCALES || path.resolve('./locales'),
38
+ commands: process.env.TEST_FOLDER_COMMANDS || path.resolve('./commands'),
39
+ migrations:
40
+ process.env.TEST_FOLDER_MIGRATIONS || path.resolve('./migrations'),
41
+ },
42
+ });
43
+ global.server.updateConfig('mongo', {
44
+ connectionString: connectionStringMongo,
45
+ });
46
+ global.server.updateConfig('http', { port: 0 }); // allow to use random
47
+ global.server.updateConfig('mail', { transport: 'stub' });
48
+ if (!global.testSetup) {
49
+ global.testSetup = {};
50
+ }
51
+ global.server.testingGetUrl = (urlPart) =>
52
+ `http://127.0.0.1:${global.server.getConfig('http').port}${urlPart}`;
53
+ if (!global.testSetup.disableUserCreate) {
54
+ const User = global.server.app.getModel('User');
55
+ global.user = await User.create({
56
+ email: 'test@test.com',
57
+ password: 'testPassword',
58
+ isVerified: true,
59
+ name: {
60
+ nick: 'testUserNickName',
61
+ },
62
+ }).catch((e) => {
63
+ // eslint-disable-next-line no-console
64
+ console.error(e);
65
+ // eslint-disable-next-line no-console
66
+ console.info(
67
+ 'That error can happens in case you have custom user model. Please use global.testSetup.disableUserCreate flag to skip user creating',
68
+ );
69
+ });
70
+ global.authToken = await global.user.generateToken();
71
+ }
72
+ if (typeof global.testSetup.beforeAll === 'function') {
73
+ await global.testSetup.beforeAll();
74
+ }
75
+ await global.server.startServer();
76
+ });
77
+
78
+ // eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
79
+ beforeEach(() => {
80
+ if (global.server) {
81
+ const key = `test-${Math.random().toString(36).substring(7)}`;
82
+ global.server.app.updateConfig('redis', {
83
+ namespace: key,
84
+ });
85
+ }
86
+ });
87
+
88
+ // eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
89
+ afterEach(async () => {
90
+ if (global.server) {
91
+ const { url, namespace } = global.server.getConfig('redis');
92
+ const redisClient = redis.createClient({ url });
93
+
94
+ try {
95
+ await redisClient.connect();
96
+ await clearRedisNamespace(redisClient, namespace);
97
+ await redisClient.disconnect();
98
+ } catch (err) {
99
+ // that ok. No redis connection
100
+ }
101
+ }
102
+ });
103
+
104
+ // eslint-disable-next-line vitest/no-hooks, vitest/require-top-level-describe
105
+ afterAll(async () => {
106
+ if (global.server) {
107
+ global.server.app.httpServer.shutdown();
108
+ global.server.app.events.emit('shutdown');
109
+ }
110
+ // setTimeout(async () => {
111
+ if (typeof global.testSetup.afterAll === 'function') {
112
+ await global.testSetup.afterAll();
113
+ }
114
+
115
+ await mongoose.disconnect();
116
+ await mongoMemoryServerInstance.stop();
117
+
118
+ // }, 2000);
119
+ });
@@ -0,0 +1,9 @@
1
+ // eslint-disable-next-line import/no-unresolved
2
+ import { defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ setupFiles: './tests/setupVitest.js',
7
+ testTimeout: 10000,
8
+ },
9
+ });
package/babel.config.js DELETED
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
3
- };