node-server-engine 1.4.9 → 1.5.1

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.
Files changed (277) hide show
  1. package/.commitlintrc.js +27 -0
  2. package/.releaserc.js +56 -0
  3. package/README.md +154 -2
  4. package/dist/const/tokenIssuer.js +1 -0
  5. package/dist/const/tokenIssuer.js.map +1 -1
  6. package/dist/db/models/SequelizeMeta.js +3 -1
  7. package/dist/db/models/SequelizeMeta.js.map +1 -1
  8. package/dist/entities/ElasticSearch/ElasticSearch.js +1 -2
  9. package/dist/entities/ElasticSearch/ElasticSearch.js.map +1 -1
  10. package/dist/entities/Sequelize/Sequelize.js +4 -1
  11. package/dist/entities/Sequelize/Sequelize.js.map +1 -1
  12. package/dist/entities/Server/Server.js +8 -11
  13. package/dist/entities/Server/Server.js.map +1 -1
  14. package/dist/entities/SocketClient/SocketClient.d.ts +4 -1
  15. package/dist/entities/SocketClient/SocketClient.js +5 -1
  16. package/dist/entities/SocketClient/SocketClient.js.map +1 -1
  17. package/dist/index.js +1 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/middleware/checkPermission/checkPermission.d.ts +1 -1
  20. package/dist/middleware/checkPermission/checkPermission.js +4 -2
  21. package/dist/middleware/checkPermission/checkPermission.js.map +1 -1
  22. package/dist/utils/createSortedObject/createSortedObject.d.ts +5 -1
  23. package/dist/utils/createSortedObject/createSortedObject.js +13 -4
  24. package/dist/utils/createSortedObject/createSortedObject.js.map +1 -1
  25. package/dist/utils/dbMigration/dbMigration.js +34 -15
  26. package/dist/utils/dbMigration/dbMigration.js.map +1 -1
  27. package/dist/utils/geminiFileUpload/geminiFileUpload.js +2 -1
  28. package/dist/utils/geminiFileUpload/geminiFileUpload.js.map +1 -1
  29. package/dist/utils/jwt/jwt.js +1 -1
  30. package/dist/utils/jwt/jwt.js.map +1 -1
  31. package/dist/utils/report/report.d.ts +9 -3
  32. package/dist/utils/report/report.js +29 -12
  33. package/dist/utils/report/report.js.map +1 -1
  34. package/dist/utils/secretManager/secretLoader.js +5 -1
  35. package/dist/utils/secretManager/secretLoader.js.map +1 -1
  36. package/dist/utils/semverCompare/semverCompare.d.ts +4 -4
  37. package/dist/utils/semverCompare/semverCompare.js +16 -18
  38. package/dist/utils/semverCompare/semverCompare.js.map +1 -1
  39. package/package.json +30 -19
  40. package/.env.example +0 -186
  41. package/.github/workflows/publish.yml +0 -41
  42. package/.prettierrc +0 -7
  43. package/Dockerfile +0 -31
  44. package/babel.config.json +0 -34
  45. package/eslint.config.mjs +0 -11
  46. package/src/const/DebeziumEvent.ts +0 -6
  47. package/src/const/LogSeverity.ts +0 -7
  48. package/src/const/index.ts +0 -5
  49. package/src/const/metrics.ts +0 -6
  50. package/src/const/mime.ts +0 -37
  51. package/src/const/tokenIssuer.ts +0 -7
  52. package/src/db/migrations/20241030121500-create-sequelize-meta-table.ts +0 -29
  53. package/src/db/models/SequelizeMeta.ts +0 -16
  54. package/src/db/models/index.ts +0 -2
  55. package/src/entities/ElasticSearch/ElasticSearch.ts +0 -103
  56. package/src/entities/ElasticSearch/ElasticSearch.types.ts +0 -7
  57. package/src/entities/ElasticSearch/index.ts +0 -2
  58. package/src/entities/Endpoint/Endpoint.test.ts +0 -248
  59. package/src/entities/Endpoint/Endpoint.ts +0 -221
  60. package/src/entities/Endpoint/Endpoint.types.ts +0 -181
  61. package/src/entities/Endpoint/index.ts +0 -2
  62. package/src/entities/EngineError/EngineError.ts +0 -28
  63. package/src/entities/EngineError/EngineError.types.ts +0 -15
  64. package/src/entities/EngineError/index.ts +0 -2
  65. package/src/entities/KeySet/KeySet.test.ts +0 -126
  66. package/src/entities/KeySet/KeySet.ts +0 -172
  67. package/src/entities/KeySet/KeySet.types.ts +0 -28
  68. package/src/entities/KeySet/index.ts +0 -2
  69. package/src/entities/LifecycleController/LifecycleController.test.ts +0 -48
  70. package/src/entities/LifecycleController/LifecycleController.ts +0 -24
  71. package/src/entities/LifecycleController/LifecycleController.types.ts +0 -5
  72. package/src/entities/LifecycleController/index.ts +0 -2
  73. package/src/entities/Localizator/Localizator.ts +0 -139
  74. package/src/entities/Localizator/Localizator.types.ts +0 -52
  75. package/src/entities/Localizator/guessNamingConvention/guessNamingConvention.test.ts +0 -165
  76. package/src/entities/Localizator/guessNamingConvention/guessNamingConvention.ts +0 -58
  77. package/src/entities/Localizator/guessNamingConvention/index.ts +0 -1
  78. package/src/entities/Localizator/index.ts +0 -2
  79. package/src/entities/MessageHandler/MessageHandler.test.ts +0 -130
  80. package/src/entities/MessageHandler/MessageHandler.ts +0 -72
  81. package/src/entities/MessageHandler/MessageHandler.types.ts +0 -15
  82. package/src/entities/MessageHandler/index.ts +0 -2
  83. package/src/entities/PubSub/PubSub.test.ts +0 -297
  84. package/src/entities/PubSub/PubSub.ts +0 -202
  85. package/src/entities/PubSub/PubSub.types.ts +0 -76
  86. package/src/entities/PubSub/handleMessage/handleMessage.test.ts +0 -102
  87. package/src/entities/PubSub/handleMessage/handleMessage.ts +0 -65
  88. package/src/entities/PubSub/handleMessage/index.ts +0 -1
  89. package/src/entities/PubSub/index.ts +0 -2
  90. package/src/entities/PushNotification/PushNotification.test.ts +0 -35
  91. package/src/entities/PushNotification/PushNotification.ts +0 -44
  92. package/src/entities/PushNotification/PushNotification.types.ts +0 -25
  93. package/src/entities/PushNotification/index.ts +0 -2
  94. package/src/entities/Redis/Redis.ts +0 -71
  95. package/src/entities/Redis/Redis.types.ts +0 -19
  96. package/src/entities/Redis/Redis.validate.ts +0 -17
  97. package/src/entities/Redis/index.ts +0 -2
  98. package/src/entities/Sequelize/Sequelize.config.ts +0 -59
  99. package/src/entities/Sequelize/Sequelize.test.ts +0 -21
  100. package/src/entities/Sequelize/Sequelize.ts +0 -75
  101. package/src/entities/Sequelize/Sequelize.types.ts +0 -10
  102. package/src/entities/Sequelize/Sequelize.validate.ts +0 -15
  103. package/src/entities/Sequelize/index.ts +0 -2
  104. package/src/entities/Server/Server.const.ts +0 -56
  105. package/src/entities/Server/Server.test.ts +0 -272
  106. package/src/entities/Server/Server.ts +0 -471
  107. package/src/entities/Server/Server.types.ts +0 -88
  108. package/src/entities/Server/index.ts +0 -2
  109. package/src/entities/SocketClient/SocketClient.test.ts +0 -392
  110. package/src/entities/SocketClient/SocketClient.ts +0 -401
  111. package/src/entities/SocketClient/SocketClient.types.ts +0 -62
  112. package/src/entities/SocketClient/index.ts +0 -2
  113. package/src/entities/SocketClient/parseMessage/index.ts +0 -1
  114. package/src/entities/SocketClient/parseMessage/parseMessage.test.ts +0 -20
  115. package/src/entities/SocketClient/parseMessage/parseMessage.ts +0 -26
  116. package/src/entities/Storage/Storage.test.ts +0 -58
  117. package/src/entities/Storage/Storage.ts +0 -219
  118. package/src/entities/Storage/Storage.types.ts +0 -57
  119. package/src/entities/Storage/index.ts +0 -2
  120. package/src/entities/ValidationError/ValidationError.ts +0 -34
  121. package/src/entities/ValidationError/index.ts +0 -1
  122. package/src/entities/WebError/WebError.test.ts +0 -18
  123. package/src/entities/WebError/WebError.ts +0 -23
  124. package/src/entities/WebError/WebError.types.ts +0 -9
  125. package/src/entities/WebError/index.ts +0 -2
  126. package/src/entities/index.ts +0 -16
  127. package/src/index.ts +0 -6
  128. package/src/metrics/debug.ts +0 -10
  129. package/src/metrics/index.ts +0 -2
  130. package/src/metrics/request.ts +0 -17
  131. package/src/middleware/authHmac/authHmac.test.ts +0 -86
  132. package/src/middleware/authHmac/authHmac.ts +0 -56
  133. package/src/middleware/authHmac/authHmac.types.ts +0 -7
  134. package/src/middleware/authHmac/index.ts +0 -2
  135. package/src/middleware/authJwt/authJwt.test.ts +0 -54
  136. package/src/middleware/authJwt/authJwt.ts +0 -55
  137. package/src/middleware/authJwt/authJwt.types.ts +0 -14
  138. package/src/middleware/authJwt/index.ts +0 -2
  139. package/src/middleware/authStatic/authStatic.test.ts +0 -36
  140. package/src/middleware/authStatic/authStatic.ts +0 -45
  141. package/src/middleware/authStatic/index.ts +0 -1
  142. package/src/middleware/authTls/authTls.test.ts +0 -138
  143. package/src/middleware/authTls/authTls.ts +0 -119
  144. package/src/middleware/authTls/authTls.types.ts +0 -13
  145. package/src/middleware/authTls/index.ts +0 -2
  146. package/src/middleware/checkPermission/checkPermission.ts +0 -33
  147. package/src/middleware/checkPermission/index.ts +0 -1
  148. package/src/middleware/error/error.test.ts +0 -60
  149. package/src/middleware/error/error.ts +0 -25
  150. package/src/middleware/error/index.ts +0 -1
  151. package/src/middleware/fileUploader/fileUploader.ts +0 -154
  152. package/src/middleware/fileUploader/fileUploader.types.ts +0 -35
  153. package/src/middleware/fileUploader/index.ts +0 -2
  154. package/src/middleware/fileUploader/isMultiPart/index.ts +0 -1
  155. package/src/middleware/fileUploader/isMultiPart/isMultipart.ts +0 -9
  156. package/src/middleware/fileUploader/validate/index.ts +0 -1
  157. package/src/middleware/fileUploader/validate/validate.ts +0 -27
  158. package/src/middleware/fourOhFour/fourOhFour.test.ts +0 -14
  159. package/src/middleware/fourOhFour/fourOhFour.ts +0 -13
  160. package/src/middleware/fourOhFour/index.ts +0 -1
  161. package/src/middleware/geminiFileUploader/geminiFileUploader.ts +0 -68
  162. package/src/middleware/geminiFileUploader/index.ts +0 -1
  163. package/src/middleware/healthCheck/healthCheck.test.ts +0 -12
  164. package/src/middleware/healthCheck/healthCheck.ts +0 -14
  165. package/src/middleware/healthCheck/index.ts +0 -1
  166. package/src/middleware/index.ts +0 -17
  167. package/src/middleware/metrics/index.ts +0 -1
  168. package/src/middleware/metrics/metrics.test.ts +0 -46
  169. package/src/middleware/metrics/metrics.ts +0 -24
  170. package/src/middleware/multiPartFileUploader/index.ts +0 -2
  171. package/src/middleware/multiPartFileUploader/multiPartFileUploader.ts +0 -249
  172. package/src/middleware/multiPartFileUploader/multiPartFileUploader.types.ts +0 -23
  173. package/src/middleware/multiPartFileUploader/validate/index.ts +0 -1
  174. package/src/middleware/multiPartFileUploader/validate/validate.ts +0 -27
  175. package/src/middleware/requestMetrics/index.ts +0 -1
  176. package/src/middleware/requestMetrics/requestMetrics.test.ts +0 -77
  177. package/src/middleware/requestMetrics/requestMetrics.ts +0 -20
  178. package/src/middleware/swaggerDocs/index.ts +0 -2
  179. package/src/middleware/swaggerDocs/swaggerDocs.ts +0 -114
  180. package/src/middleware/swaggerDocs/swaggerDocs.types.ts +0 -41
  181. package/src/middleware/userResolver/index.ts +0 -1
  182. package/src/middleware/userResolver/userResolver.ts +0 -53
  183. package/src/middleware/validate/index.ts +0 -1
  184. package/src/middleware/validate/validate.test.ts +0 -43
  185. package/src/middleware/validate/validate.ts +0 -25
  186. package/src/middleware/version/index.ts +0 -1
  187. package/src/middleware/version/version.test.ts +0 -23
  188. package/src/middleware/version/version.ts +0 -12
  189. package/src/utils/checkEnvironment/index.ts +0 -49
  190. package/src/utils/createHttpServer/createHttpServer.test.ts +0 -24
  191. package/src/utils/createHttpServer/createHttpServer.ts +0 -34
  192. package/src/utils/createHttpServer/createHttpServer.validate.ts +0 -17
  193. package/src/utils/createHttpServer/index.ts +0 -1
  194. package/src/utils/createSortedObject/createSortedObject.ts +0 -20
  195. package/src/utils/createSortedObject/createSortedObjet.test.ts +0 -47
  196. package/src/utils/createSortedObject/index.ts +0 -1
  197. package/src/utils/dbMigration/dbMigration.test.ts +0 -209
  198. package/src/utils/dbMigration/dbMigration.ts +0 -199
  199. package/src/utils/dbMigration/dbMigration.types.ts +0 -11
  200. package/src/utils/dbMigration/index.ts +0 -2
  201. package/src/utils/dbMigration/migrateMetadataTable/index.ts +0 -1
  202. package/src/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.test.ts +0 -59
  203. package/src/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.ts +0 -102
  204. package/src/utils/envAssert/envAssert.ts +0 -31
  205. package/src/utils/envAssert/index.ts +0 -1
  206. package/src/utils/envAssert/validators/hostList.ts +0 -17
  207. package/src/utils/envAssert/validators/index.ts +0 -5
  208. package/src/utils/envAssert/validators/ipList.ts +0 -13
  209. package/src/utils/envAssert/validators/path.ts +0 -13
  210. package/src/utils/envAssert/validators/string.ts +0 -9
  211. package/src/utils/envAssert/validators/stringList.ts +0 -13
  212. package/src/utils/filter/filter.ts +0 -17
  213. package/src/utils/filter/index.ts +0 -1
  214. package/src/utils/geminiFileUpload/geminiFileUpload.ts +0 -93
  215. package/src/utils/geminiFileUpload/index.ts +0 -1
  216. package/src/utils/hmac/checkEnv/checkEnv.test.ts +0 -18
  217. package/src/utils/hmac/checkEnv/checkEnv.ts +0 -9
  218. package/src/utils/hmac/checkEnv/index.ts +0 -1
  219. package/src/utils/hmac/createHmac/createHmac.ts +0 -33
  220. package/src/utils/hmac/createHmac/index.ts +0 -1
  221. package/src/utils/hmac/index.ts +0 -4
  222. package/src/utils/hmac/index.types.ts +0 -13
  223. package/src/utils/hmac/signPayload/index.ts +0 -1
  224. package/src/utils/hmac/signPayload/signPayload.ts +0 -16
  225. package/src/utils/hmac/verifySignature/index.ts +0 -1
  226. package/src/utils/hmac/verifySignature/verifySignature.ts +0 -24
  227. package/src/utils/index.ts +0 -29
  228. package/src/utils/jwt/index.ts +0 -2
  229. package/src/utils/jwt/jwt.test.ts +0 -28
  230. package/src/utils/jwt/jwt.ts +0 -182
  231. package/src/utils/jwt/jwt.types.ts +0 -21
  232. package/src/utils/report/index.ts +0 -3
  233. package/src/utils/report/output.ts +0 -45
  234. package/src/utils/report/output.types.ts +0 -70
  235. package/src/utils/report/report.test.ts +0 -133
  236. package/src/utils/report/report.ts +0 -133
  237. package/src/utils/report/report.types.ts +0 -13
  238. package/src/utils/request/index.ts +0 -1
  239. package/src/utils/request/request.test.ts +0 -26
  240. package/src/utils/request/request.ts +0 -48
  241. package/src/utils/secretManager/index.ts +0 -2
  242. package/src/utils/secretManager/secretLoader.ts +0 -62
  243. package/src/utils/secretManager/secretResolver.ts +0 -35
  244. package/src/utils/semverCompare/index.ts +0 -1
  245. package/src/utils/semverCompare/semverCompare.test.ts +0 -49
  246. package/src/utils/semverCompare/semverCompare.ts +0 -60
  247. package/src/utils/sendEmail/index.ts +0 -2
  248. package/src/utils/sendEmail/sendEmail.ts +0 -61
  249. package/src/utils/sendEmail/sendEmail.types.ts +0 -61
  250. package/src/utils/sendPush/index.ts +0 -2
  251. package/src/utils/sendPush/sendPush.ts +0 -20
  252. package/src/utils/sendPush/sendPush.types.ts +0 -25
  253. package/src/utils/tlsConfig/index.ts +0 -2
  254. package/src/utils/tlsConfig/tlsConfig.test.ts +0 -32
  255. package/src/utils/tlsConfig/tlsConfig.ts +0 -47
  256. package/src/utils/tlsConfig/tlsConfig.types.ts +0 -11
  257. package/src/utils/tlsConfig/tlsConfig.validate.ts +0 -25
  258. package/src/utils/tlsRequest/index.ts +0 -1
  259. package/src/utils/tlsRequest/tlsRequest.test.ts +0 -63
  260. package/src/utils/tlsRequest/tlsRequest.ts +0 -12
  261. package/src/utils/trimPathSlash/index.ts +0 -1
  262. package/src/utils/trimPathSlash/trimPathSlash.test.ts +0 -26
  263. package/src/utils/trimPathSlash/trimPathSlash.ts +0 -8
  264. package/test/env.ts +0 -53
  265. package/test/factory/index.ts +0 -8
  266. package/test/factory/sequelizeMeta.ts +0 -12
  267. package/test/hooks.ts +0 -35
  268. package/test/index.ts +0 -3
  269. package/test/stub/index.ts +0 -3
  270. package/test/stub/stubLocales.ts +0 -68
  271. package/test/stub/stubPubSub.ts +0 -7
  272. package/test/stub/stubStorage.ts +0 -77
  273. package/test/stub/stubStorage.types.ts +0 -11
  274. package/test/utils/app.ts +0 -31
  275. package/test/utils/index.ts +0 -1
  276. package/tsconfig.build.json +0 -5
  277. package/tsconfig.json +0 -32
@@ -1,58 +0,0 @@
1
- import {
2
- LocalizatorLocalizationData,
3
- LocalizatorScripts,
4
- LocalizatorNamingConventions
5
- } from '../Localizator.types';
6
-
7
- export const DEFAULT_NAMING_CONVENTION = {
8
- regular: '{firstName} {lastName}',
9
- formal: '{firstName}',
10
- casual: '{firstName}'
11
- };
12
-
13
- /** Guess the naming convention to use for a given name and locale */
14
- export function guessNamingConvention(
15
- scripts: LocalizatorScripts,
16
- localeData: LocalizatorLocalizationData,
17
- name: string,
18
- locale: string
19
- ): LocalizatorNamingConventions {
20
- // When the locale has a specific script
21
- // Check if the name matches that script, and use its naming convention
22
- if (localeData[locale]?.script) {
23
- const defaultScript = localeData[locale].script as string;
24
- if (
25
- testScriptMatch(scripts, defaultScript, name) &&
26
- scripts[defaultScript].names
27
- ) {
28
- return scripts[defaultScript].names;
29
- }
30
- }
31
-
32
- // Check if there is a match with any given script and use its naming convention
33
- for (const script of Object.keys(scripts)) {
34
- if (testScriptMatch(scripts, script, name) && scripts[script].names) {
35
- return scripts[script].names;
36
- }
37
- }
38
-
39
- // Use the current locale's fallback convention
40
- if (localeData[locale]?.names?.fallback) {
41
- return localeData[locale].names.fallback as LocalizatorNamingConventions;
42
- }
43
-
44
- // If everything fails, use the default convention
45
- return DEFAULT_NAMING_CONVENTION;
46
- }
47
-
48
- /** Test if a given string is in a given script */
49
- function testScriptMatch(
50
- scripts: LocalizatorScripts,
51
- script: string,
52
- string: string
53
- ): boolean {
54
- if (scripts[script]?.rangeRegex) {
55
- return (scripts[script].rangeRegex as RegExp).test(string);
56
- }
57
- return false;
58
- }
@@ -1 +0,0 @@
1
- export * from './guessNamingConvention';
@@ -1,2 +0,0 @@
1
- export * from './Localizator';
2
- export * from './Localizator.types';
@@ -1,130 +0,0 @@
1
- import Ajv, { JSONSchemaType } from 'ajv';
2
- import { expect } from 'chai';
3
- import { faker } from '@faker-js/faker';
4
- import { fake, match } from 'sinon';
5
- import { MessageHandler } from './MessageHandler';
6
- import { SocketClient } from 'entities/SocketClient';
7
-
8
- const ajv = new Ajv();
9
-
10
- /** */
11
- interface TestPayload {
12
- /** */
13
- test?: string;
14
- }
15
-
16
- type TestSchema = JSONSchemaType<TestPayload>;
17
-
18
- const schema: TestSchema = {
19
- type: 'object',
20
- properties: {
21
- test: { type: 'string', nullable: true }
22
- }
23
- };
24
-
25
- const validator = ajv.compile(schema);
26
-
27
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
28
- // @ts-ignore
29
- const client = { isAuthenticated: () => true } as SocketClient;
30
-
31
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
32
- // @ts-ignore
33
- const unauthenticatedClient = { isAuthenticated: () => false } as SocketClient;
34
-
35
- describe('Entities - Message Handler', () => {
36
- it('should call the handler', async () => {
37
- const type = faker.lorem.word();
38
- const handler = fake();
39
- const entity = new MessageHandler(type, handler, validator);
40
- const message = { type, payload: {} };
41
-
42
- await entity.handle(message, client);
43
-
44
- expect(handler).to.have.been.calledOnceWithExactly(
45
- message.payload,
46
- match(client)
47
- );
48
- });
49
-
50
- it('should not call the handler if the type is different', async () => {
51
- const handler = fake();
52
- const entity = new MessageHandler(faker.lorem.word(), handler, validator);
53
- const message = { type: faker.lorem.word(), payload: {} };
54
-
55
- await entity.handle(message, client);
56
-
57
- expect(handler).to.not.have.been.called;
58
- });
59
-
60
- it('should not call the handler if the client is not authenticated', async () => {
61
- const type = faker.lorem.word();
62
- const handler = fake();
63
- const entity = new MessageHandler(type, handler, validator);
64
- const message = { type, payload: {} };
65
-
66
- await entity.handle(message, unauthenticatedClient);
67
-
68
- expect(handler).to.not.have.been.called;
69
- });
70
-
71
- it('should call the handler if the client is not authenticated, but that it is not required', async () => {
72
- const type = faker.lorem.word();
73
- const handler = fake();
74
- const entity = new MessageHandler(type, handler, validator, {
75
- authenticated: false
76
- });
77
- const message = { type, payload: {} };
78
-
79
- await entity.handle(message, unauthenticatedClient);
80
-
81
- expect(handler).to.have.been.calledOnceWithExactly(
82
- message.payload,
83
- match(unauthenticatedClient)
84
- );
85
- });
86
-
87
- describe('schema validation', () => {
88
- /** */
89
- interface TestPayload {
90
- /** */
91
- test: string;
92
- }
93
-
94
- type TestSchema = JSONSchemaType<TestPayload>;
95
-
96
- const schema: TestSchema = {
97
- type: 'object',
98
- properties: {
99
- test: { type: 'string' }
100
- },
101
- required: ['test']
102
- };
103
-
104
- const validator = ajv.compile(schema);
105
-
106
- it('should call the handler if the payload passes validation', async () => {
107
- const type = faker.lorem.word();
108
- const handler = fake();
109
- const entity = new MessageHandler(type, handler, validator);
110
- const message = { type, payload: { test: faker.lorem.word() } };
111
-
112
- await entity.handle(message, client);
113
-
114
- expect(handler).to.have.been.calledOnceWithExactly(
115
- message.payload,
116
- match(client)
117
- );
118
- });
119
-
120
- it('should throw an error if the payload does not pass validation', async () => {
121
- const type = faker.lorem.word();
122
- const handler = fake();
123
- const entity = new MessageHandler(type, handler, validator);
124
- const message = { type, payload: { test: faker.number.int() } };
125
-
126
- const result = entity.handle(message, client);
127
- await expect(result).to.be.rejected;
128
- });
129
- });
130
- });
@@ -1,72 +0,0 @@
1
- import { ValidateFunction } from 'ajv';
2
- import { EngineError } from '../EngineError';
3
- import {
4
- MessageHandlerOptions,
5
- MessageHandlerHandler
6
- } from './MessageHandler.types';
7
- import { SocketMessage, SocketClient } from 'entities/SocketClient';
8
- import { WebError } from 'entities/WebError';
9
-
10
- /**
11
- * Message handlers should be used to define how messages should be handled in web socket servers
12
- */
13
- export class MessageHandler {
14
- /** The type of messages that are handled by the instance */
15
- public readonly type: string;
16
- /** Function that should handle the message */
17
- private handler: MessageHandlerHandler;
18
- /** Schema against which incoming messages should be validated */
19
- private validator: ValidateFunction;
20
- /** Indicates that this handler should only run when the client is authenticated */
21
- private authenticated: boolean;
22
-
23
- /** Create a new websocket message handler */
24
- public constructor(
25
- type: string,
26
- handler: MessageHandlerHandler,
27
- validator: ValidateFunction,
28
- options: MessageHandlerOptions = {}
29
- ) {
30
- if (!type)
31
- throw new EngineError({ message: 'MessageHandler has no type defined' });
32
- this.type = type;
33
- if (!handler)
34
- throw new EngineError({
35
- message: 'MessageHandler should have a handler function'
36
- });
37
- this.handler = handler;
38
- this.validator = validator;
39
- this.authenticated = options.authenticated ?? true;
40
- }
41
-
42
- /** Handle received messages, and propagate them to the handler if needed */
43
- public async handle(
44
- message: SocketMessage,
45
- client: SocketClient
46
- ): Promise<void> {
47
- const valid = this.validator(message.payload);
48
- if (!valid) {
49
- const hint = this.validator.errors?.reduce(
50
- (hint, error) => ({
51
- ...hint,
52
- [error.instancePath]: error.message
53
- ? `${error.keyword}: ${error.message}`
54
- : error.keyword
55
- }),
56
- {}
57
- );
58
- throw new WebError({
59
- statusCode: 400,
60
- errorCode: 'invalid-message',
61
- message: 'Message validation failed',
62
- data: hint,
63
- hint
64
- });
65
- }
66
- // Do not handle if it not for this type of handler
67
- if (this.type !== message.type) return;
68
- // When handler requires authentication but that client is not authenticated, do not handle the message.
69
- if (this.authenticated && !client.isAuthenticated()) return;
70
- await this.handler(message.payload ?? {}, client);
71
- }
72
- }
@@ -1,15 +0,0 @@
1
- import { ValidateFunction } from 'ajv';
2
- import { SocketClient } from 'entities/SocketClient';
3
-
4
- /** Initialization options for the message handler */
5
- export interface MessageHandlerOptions {
6
- /** The handler will only be called for authenticated clients (default: true) */
7
- authenticated?: boolean;
8
- /** Schema to validate the message before passing it to the handler */
9
- validator?: ValidateFunction;
10
- }
11
-
12
- export type MessageHandlerHandler = (
13
- payload: unknown,
14
- client: SocketClient
15
- ) => unknown | Promise<unknown>;
@@ -1,2 +0,0 @@
1
- export * from './MessageHandler';
2
- export * from './MessageHandler.types';
@@ -1,297 +0,0 @@
1
- import {
2
- PubSub as PubsubClient,
3
- IAM,
4
- Topic,
5
- Subscription
6
- } from '@google-cloud/pubsub';
7
- import { expect } from 'chai';
8
- import { faker } from '@faker-js/faker';
9
- import { stub, fake, match, SinonSpy, SinonStub } from 'sinon';
10
- import { PubSub } from './PubSub';
11
- import { EngineError } from 'entities/EngineError';
12
-
13
- describe('Entities - Pub/Sub', function () {
14
- let topicExistsFake: SinonSpy;
15
- let topicIamFake: SinonSpy;
16
- let topicPublishFake: SinonSpy;
17
- let topicFlushFake: SinonSpy;
18
- let topicStub: SinonStub;
19
- let subscriptionExistsFake: SinonSpy;
20
- let subscriptionIamFake: SinonSpy;
21
- let subscriptionOnFake: SinonSpy;
22
- let subscriptionCloseFake: SinonSpy;
23
- let subscriptionStub: SinonStub;
24
-
25
- beforeEach(() => {
26
- topicExistsFake = fake.resolves([true]);
27
-
28
- topicIamFake = fake(async (permissions: Array<string>) =>
29
- permissions.reduce(
30
- (result, permission) => {
31
- result[0][permission] = true;
32
- return result;
33
- },
34
- [{} as Record<string, boolean>]
35
- )
36
- );
37
- topicPublishFake = fake.resolves(undefined);
38
- topicFlushFake = fake.resolves(undefined);
39
- topicStub = stub(PubsubClient.prototype, 'topic').callsFake(
40
- () =>
41
- ({
42
- exists: topicExistsFake,
43
- iam: { testPermissions: topicIamFake } as unknown as IAM,
44
- publishMessage: topicPublishFake,
45
- flush: topicFlushFake
46
- }) as unknown as Topic
47
- );
48
-
49
- subscriptionExistsFake = fake.resolves([true]);
50
-
51
- subscriptionIamFake = fake(async (permissions: Array<string>) =>
52
- permissions.reduce(
53
- (result, permission) => {
54
- result[0][permission] = true;
55
- return result;
56
- },
57
- [{} as Record<string, boolean>]
58
- )
59
- );
60
- subscriptionOnFake = fake();
61
- subscriptionCloseFake = fake.resolves(undefined);
62
- subscriptionStub = stub(PubsubClient.prototype, 'subscription').callsFake(
63
- () =>
64
- ({
65
- exists: subscriptionExistsFake,
66
- iam: { testPermissions: subscriptionIamFake } as unknown as IAM,
67
- on: subscriptionOnFake,
68
- close: subscriptionCloseFake
69
- }) as unknown as Subscription
70
- );
71
- });
72
-
73
- afterEach(async () => {
74
- await PubSub.shutdown();
75
- });
76
-
77
- describe('addPublisher', () => {
78
- it('should register a publisher only once', () => {
79
- const topic = faker.lorem.slug();
80
-
81
- PubSub.addPublisher(topic);
82
- PubSub.addPublisher(topic);
83
- PubSub.addPublisher(topic);
84
-
85
- expect(topicStub).to.have.been.calledOnceWithExactly(topic, match.object);
86
- });
87
-
88
- it('should register multiple publishers', () => {
89
- const [topic1, topic2, topic3] = [
90
- faker.lorem.slug(),
91
- faker.lorem.slug(),
92
- faker.lorem.slug()
93
- ];
94
-
95
- PubSub.addPublisher(topic1);
96
- PubSub.addPublisher([topic2, topic3]);
97
-
98
- expect(topicStub).to.have.been.callCount(3);
99
- expect(topicStub).to.have.been.calledWithExactly(topic1, match.object);
100
- expect(topicStub).to.have.been.calledWithExactly(topic2, match.object);
101
- expect(topicStub).to.have.been.calledWithExactly(topic3, match.object);
102
- });
103
- });
104
-
105
- describe('addSubscriber', () => {
106
- it('should register a subscription only once', () => {
107
- const subscription = faker.lorem.slug();
108
- const handler = fake();
109
-
110
- PubSub.addSubscriber(subscription, handler);
111
- PubSub.addSubscriber(subscription, handler);
112
- PubSub.addSubscriber(subscription, handler);
113
-
114
- expect(subscriptionStub).to.have.been.calledOnceWithExactly(
115
- subscription,
116
- match.object
117
- );
118
- });
119
-
120
- it('should register a subscription and making them run first when a new message arrives', () => {
121
- const subscription = faker.lorem.slug();
122
- const handler = fake();
123
-
124
- PubSub.addSubscriber(subscription, handler, { first: true });
125
- expect(subscriptionStub).to.have.been.calledOnceWithExactly(
126
- subscription,
127
- match.object
128
- );
129
- });
130
-
131
- it('should register a subscription with debezium events', () => {
132
- const subscription = faker.lorem.slug();
133
- const handler = fake();
134
-
135
- PubSub.addSubscriber(subscription, handler, { isDebezium: true });
136
- expect(subscriptionStub).to.have.been.calledOnceWithExactly(
137
- subscription,
138
- match.object
139
- );
140
- });
141
-
142
- it('should register multiple subscriptions', () => {
143
- const handler = fake();
144
- const [subscription1, subscription2, subscription3] = [
145
- faker.lorem.slug(),
146
- faker.lorem.slug(),
147
- faker.lorem.slug()
148
- ];
149
-
150
- PubSub.addSubscriber(subscription1, handler);
151
- PubSub.addSubscriber(subscription2, handler);
152
- PubSub.addSubscriber(subscription3, handler);
153
-
154
- expect(subscriptionStub).to.have.been.callCount(3);
155
- expect(subscriptionStub).to.have.been.calledWithExactly(
156
- subscription1,
157
- match.object
158
- );
159
- expect(subscriptionStub).to.have.been.calledWithExactly(
160
- subscription2,
161
- match.object
162
- );
163
- expect(subscriptionStub).to.have.been.calledWithExactly(
164
- subscription3,
165
- match.object
166
- );
167
- });
168
- });
169
-
170
- describe('init', () => {
171
- it('should throw an error if a topic does not exist', async () => {
172
- topicExistsFake = fake.resolves([false]);
173
-
174
- PubSub.addPublisher(faker.lorem.slug());
175
-
176
- await expect(PubSub.init()).to.be.rejectedWith(EngineError);
177
- });
178
-
179
- it('should throw an error if an instance has no permission on the topic', async () => {
180
- topicIamFake = fake(async (permissions: Array<string>) =>
181
- permissions.reduce(
182
- (result, permission) => {
183
- result[0][permission] = false;
184
- return result;
185
- },
186
- [{} as Record<string, boolean>]
187
- )
188
- );
189
-
190
- PubSub.addPublisher(faker.lorem.slug());
191
-
192
- await expect(PubSub.init()).to.be.rejectedWith(EngineError);
193
- });
194
-
195
- it('should throw an error if a subscription does not exist', async () => {
196
- const handler = fake();
197
- subscriptionExistsFake = fake.resolves([false]);
198
-
199
- PubSub.addSubscriber(faker.lorem.slug(), handler);
200
-
201
- await expect(PubSub.init()).to.be.rejectedWith(EngineError);
202
- });
203
-
204
- it('should throw an error if an instance has no permission on the subscription', async () => {
205
- const handler = fake();
206
-
207
- subscriptionIamFake = fake(async (permissions: Array<string>) =>
208
- permissions.reduce(
209
- (result, permission) => {
210
- result[0][permission] = false;
211
- return result;
212
- },
213
- [{} as Record<string, boolean>]
214
- )
215
- );
216
-
217
- PubSub.addSubscriber(faker.lorem.slug(), handler);
218
-
219
- await expect(PubSub.init()).to.be.rejectedWith(EngineError);
220
- });
221
-
222
- it('should successfully init', async () => {
223
- const topic = faker.lorem.slug();
224
- const subscription = faker.lorem.slug();
225
- const subscriptionHandler = fake();
226
-
227
- PubSub.addPublisher(topic);
228
- PubSub.addSubscriber(subscription, subscriptionHandler);
229
-
230
- await PubSub.init();
231
-
232
- expect(topicExistsFake).to.have.been.calledOnceWithExactly();
233
- expect(topicIamFake).to.have.been.calledOnceWithExactly([
234
- 'pubsub.topics.publish'
235
- ]);
236
- expect(subscriptionExistsFake).to.have.been.calledOnceWithExactly();
237
- expect(subscriptionIamFake).to.have.been.calledOnceWithExactly([
238
- 'pubsub.subscriptions.consume'
239
- ]);
240
- expect(subscriptionOnFake).to.have.been.calledOnceWithExactly(
241
- 'message',
242
- match.func
243
- );
244
- });
245
- });
246
-
247
- describe('shutdown', () => {
248
- it('should flush all publishers', async () => {
249
- PubSub.addPublisher([
250
- faker.lorem.slug(),
251
- faker.lorem.slug(),
252
- faker.lorem.slug()
253
- ]);
254
-
255
- await PubSub.shutdown();
256
-
257
- expect(topicFlushFake).to.have.callCount(3);
258
- });
259
-
260
- it('should close all subscriptions', async () => {
261
- const handler = fake();
262
- PubSub.addSubscriber(faker.lorem.slug(), handler);
263
- PubSub.addSubscriber(faker.lorem.slug(), handler);
264
- PubSub.addSubscriber(faker.lorem.slug(), handler);
265
-
266
- await PubSub.shutdown();
267
-
268
- expect(subscriptionCloseFake).to.have.callCount(3);
269
- });
270
- });
271
-
272
- describe('publish', () => {
273
- it('should throw an error if the topi was not previously declared', async () => {
274
- const message = { [faker.lorem.word()]: faker.lorem.word() };
275
- const attributes = { [faker.lorem.word()]: faker.lorem.word() };
276
-
277
- await expect(
278
- PubSub.publish(faker.lorem.slug(), message, attributes)
279
- ).to.be.rejectedWith(EngineError);
280
- });
281
-
282
- it('should publish a message', async () => {
283
- const topic = faker.lorem.slug();
284
- const message = { [faker.lorem.word()]: faker.lorem.word() };
285
- const attributes = { [faker.lorem.word()]: faker.lorem.word() };
286
-
287
- PubSub.addPublisher(topic);
288
- await PubSub.publish(topic, message, attributes);
289
-
290
- expect(topicPublishFake).to.have.been.calledOnceWithExactly({
291
- json: message,
292
- attributes,
293
- orderingKey: undefined
294
- });
295
- });
296
- });
297
- });