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,172 +0,0 @@
1
- import { createPublicKey, createHash } from 'crypto';
2
- import { readFileSync } from 'fs';
3
- import { Method } from 'axios';
4
- import { KeySetOptions, KeySetValues, JWKS } from './KeySet.types';
5
- import { LogSeverity } from 'const';
6
- import { EngineError } from 'entities/EngineError';
7
- import { reportDebug, reportError } from 'utils/report';
8
- import { request } from 'utils/request';
9
- import { tlsRequest } from 'utils/tlsRequest';
10
-
11
- const namespace = 'engine:keySet';
12
-
13
- // Number of seconds between each key refresh
14
- const KEY_REFRESH_INTERVAL = 300;
15
-
16
- /**
17
- * Fetch Json Web Key Sets and cache them
18
- * Keys can then be used for Json Web Token authentication
19
- */
20
- export class KeySet {
21
- /** Latest known value for the keys in the set, indexed by the key id */
22
- private keySet: KeySetValues = {};
23
- /** URL at which the key set can be fetched */
24
- private url: string;
25
- /** This resource is located on a service inside of our private cluster */
26
- private internal: boolean;
27
- /** This URL is actually a path to a local key file encoded in PEM */
28
- private file: boolean;
29
- /** This input is actually a full PEM string representation of a key */
30
- private pem: boolean;
31
- /** Timer for the key fetching interval */
32
- private interval?: NodeJS.Timeout | string | number | undefined;
33
-
34
- /** Create a new Key Set */
35
- public constructor(url: string, options: KeySetOptions = {}) {
36
- this.url = url;
37
- this.internal = options.internal ?? false;
38
- this.file = options.file ?? false;
39
- this.pem = options.pem ?? false;
40
- }
41
-
42
- /** Calculate key ID from PEM string */
43
- private static calculateKeyId(pem: string): string {
44
- // We use the md5 hash of the PEM file to defined the key ID
45
- const hash = createHash('md5');
46
- hash.update(pem.trim());
47
- const kid = hash.digest('base64url');
48
- reportDebug({
49
- namespace,
50
- message: `Calculated Key ID: "${kid}"`,
51
- data: { key: pem }
52
- });
53
- return kid;
54
- }
55
-
56
- /** Initialize a KeySet, should be run on server startup to avoid any misconfiguration */
57
- public async init(): Promise<void> {
58
- await this.fetch();
59
- this.interval = setInterval(() => {
60
- (async (): Promise<void> => {
61
- try {
62
- await this.fetch();
63
- } catch (error) {
64
- reportError(error);
65
- }
66
- })().catch((error) => {
67
- reportError(error);
68
- });
69
- }, KEY_REFRESH_INTERVAL * 1000);
70
- }
71
-
72
- /** Clear any pending timers to avoid pending process */
73
- public shutdown(): void {
74
- if (this.interval) clearInterval(this.interval);
75
- }
76
-
77
- /** Get the PEM encoded version of a key by its id */
78
- public getKey(keyId: string): string | undefined {
79
- return this.keySet[keyId];
80
- }
81
-
82
- /** Get all the keys in the set mapped by their ID */
83
- public getKeys(): KeySetValues {
84
- return this.keySet;
85
- }
86
-
87
- /** Fetch the latest version of the key set */
88
- private async fetch(): Promise<void> {
89
- reportDebug({
90
- namespace,
91
- message: `Fetching JWKS`,
92
- data: { url: this.url }
93
- });
94
-
95
- if (this.pem) {
96
- // Read the key from the parameter directly
97
- reportDebug({
98
- namespace,
99
- message: 'Processing key from given PEM string'
100
- });
101
-
102
- const kid = KeySet.calculateKeyId(this.url);
103
-
104
- this.keySet = { [kid]: this.url };
105
- } else if (this.file) {
106
- // Read the key from a file
107
- reportDebug({
108
- namespace,
109
- message: `Reading key on disk at path "${this.url}"`
110
- });
111
- const set = JSON.parse(readFileSync(this.url, 'utf-8'));
112
-
113
- // Check that the returned data has the shape of a JWKS
114
- if (!(set.keys && set.keys instanceof Array))
115
- throw new EngineError({
116
- severity: LogSeverity.ERROR,
117
- message: 'Fetched key set is not in an appropriate format',
118
- data: { url: this.url, set }
119
- });
120
-
121
- // Create a node.crypto public key object for each key in the set
122
- this.keySet = set.keys.reduce(
123
- (set: { [x: string]: string; }, key: { kid: string | number; }) => {
124
- set[key.kid] = createPublicKey({ key, format: 'jwk' }).export({
125
- format: 'pem',
126
- type: 'spki'
127
- }) as string;
128
- return set;
129
- },
130
- {} as Record<string, string>
131
- );
132
- } else {
133
- // Fetch key by making a network request
134
- reportDebug({
135
- namespace,
136
- message: `Making network request to "${this.url}"`
137
- });
138
-
139
- const requestOptions = { url: this.url, method: 'get' as Method };
140
- // For services inside of our cluster we use the TLS authenticated request method
141
- const { data: set } = await (this.internal
142
- ? tlsRequest<JWKS>(requestOptions)
143
- : request<JWKS>(requestOptions));
144
-
145
- // Check that the returned data has the shape of a JWKS
146
- if (!(set.keys && set.keys instanceof Array))
147
- throw new EngineError({
148
- severity: LogSeverity.ERROR,
149
- message: 'Fetched key set is not in an appropriate format',
150
- data: { url: this.url, set }
151
- });
152
-
153
- // Create a node.crypto public key object for each key in the set
154
- this.keySet = set.keys.reduce(
155
- (set, key) => {
156
- set[key.kid] = createPublicKey({ key, format: 'jwk' }).export({
157
- format: 'pem',
158
- type: 'spki'
159
- }) as string;
160
- return set;
161
- },
162
- {} as Record<string, string>
163
- );
164
- }
165
-
166
- reportDebug({
167
- namespace,
168
- message: `Stored ${Object.keys(this.keySet).length} keys`,
169
- data: { keyIds: Object.keys(this.keySet) }
170
- });
171
- }
172
- }
@@ -1,28 +0,0 @@
1
- import { JsonWebKey } from 'crypto';
2
-
3
- /** KeySet initialization options */
4
- export interface KeySetOptions {
5
- /** This resource is located on a service inside of our private cluster */
6
- internal?: boolean;
7
- /** This URL is actually a path to a local key file encoded in PEM */
8
- file?: boolean;
9
- /** This input is actually a full PEM string representation of a key */
10
- pem?: boolean;
11
- }
12
-
13
- /** Keep a mapping ok keyId => PEM */
14
- export interface KeySetValues {
15
- [id: string]: string;
16
- }
17
-
18
- /** Object holding JWK keys */
19
- export interface JWKS {
20
- /** Key set is JWKS format */
21
- keys: Array<JWK>;
22
- }
23
-
24
- /** JWK key with custom claims */
25
- interface JWK extends JsonWebKey {
26
- /** ID of the key */
27
- kid: string;
28
- }
@@ -1,2 +0,0 @@
1
- export * from './KeySet';
2
- export * from './KeySet.types';
@@ -1,48 +0,0 @@
1
- import { expect } from 'chai';
2
- import { Request, Response } from 'express';
3
- import { stub, SinonStub } from 'sinon';
4
- import { Endpoint, EndpointMethod, EndpointAuthType } from '../Endpoint';
5
- import { runningInstances } from './LifecycleController';
6
- import { Localizator } from 'entities/Localizator';
7
- import { redisClient } from 'entities/Redis/Redis';
8
- import { Server } from 'entities/Server';
9
- import { stubPubSub } from 'test';
10
-
11
- describe('Entity - LifecycleController', function () {
12
- let localizatorShutdownStub: SinonStub;
13
-
14
- beforeEach(() => {
15
- stubPubSub();
16
- stub(Localizator, 'synchronize').resolves();
17
- localizatorShutdownStub = stub(Localizator, 'shutdown').resolves();
18
- });
19
-
20
- it('Shutdown the running entities', async () => {
21
- const server = new Server({
22
- endpoints: [
23
- new Endpoint({
24
- method: EndpointMethod.GET,
25
- authType: EndpointAuthType.NONE,
26
- validator: {},
27
- path: '/',
28
- handler: (req: Request, res: Response): void => {
29
- res.json({ message: 'success' });
30
- }
31
- })
32
- ],
33
- initCallbacks: [
34
- Localizator.init.bind(Localizator)
35
- ]
36
- });
37
-
38
- await server.init();
39
-
40
- // Redis will always have been init
41
- expect([...runningInstances]).to.include(Localizator);
42
-
43
- await server.shutdown();
44
-
45
- expect(localizatorShutdownStub).to.have.been.calledOnce;
46
- expect(redisClient).to.be.undefined;
47
- });
48
- });
@@ -1,24 +0,0 @@
1
- import { LifecycleControlledInstance } from './LifecycleController.types';
2
-
3
- /** List of initialized entities */
4
- export const runningInstances: Set<LifecycleControlledInstance> = new Set();
5
-
6
- /** LifecycleController is used to shutdown all the entities on server shutdown */
7
- export const LifecycleController = {
8
- /** Add the initialized instances into the runningInstance property */
9
- register(instance: LifecycleControlledInstance): void {
10
- runningInstances.add(instance);
11
- },
12
-
13
- /** Shutdown all the running instances */
14
- async shutdownRunningInstances(): Promise<void> {
15
- const promises = [];
16
- for (const instance of runningInstances) {
17
- if (instance) {
18
- promises.push(instance.shutdown.bind(instance)());
19
- }
20
- }
21
- await Promise.all(promises);
22
- runningInstances.clear();
23
- }
24
- };
@@ -1,5 +0,0 @@
1
- /** Service instance that can be auto-shutdown by the Lifecycle Controller */
2
- export interface LifecycleControlledInstance {
3
- /** Function that will be called on server shutdown, should trigger the instance cleanup */
4
- shutdown: () => void | Promise<void>;
5
- }
@@ -1,2 +0,0 @@
1
- export { LifecycleController } from './LifecycleController';
2
- export * from './LifecycleController.types';
@@ -1,139 +0,0 @@
1
- import { guessNamingConvention } from './guessNamingConvention';
2
- import {
3
- LocalizatorLocalizationData,
4
- LocalizatorLocalizationDataElement,
5
- LocalizatorScripts,
6
- LocalizatorNamingConventions
7
- } from './Localizator.types';
8
- import { EngineError } from 'entities/EngineError';
9
- import { LifecycleController } from 'entities/LifecycleController';
10
- import { Storage } from 'entities/Storage';
11
- import { checkEnvironment } from 'utils/checkEnvironment';
12
- import { envAssert } from 'utils/envAssert';
13
- import { reportError, reportDebug } from 'utils/report';
14
-
15
- const namespace = 'engine:localizator';
16
-
17
- const REFRESH_FREQUENCY = 10 * 60 * 1000;
18
-
19
- let localeData: undefined | LocalizatorLocalizationData;
20
- let scripts: undefined | LocalizatorScripts;
21
- let interval: NodeJS.Timeout | string | number | undefined;
22
-
23
- /** Service handling contextual localization */
24
- export const Localizator = {
25
- async init(): Promise<void> {
26
- checkEnvironment({ LOCALES_BUCKET: envAssert.isString() });
27
- await Localizator.synchronize();
28
- // Keep synchronizing
29
- interval = setInterval(() => {
30
- Localizator.synchronize().catch((error) => {
31
- reportError(error);
32
- });
33
- }, REFRESH_FREQUENCY);
34
- LifecycleController.register(Localizator);
35
- },
36
-
37
- /**
38
- * Fetch a JSON file from the locales bucket
39
- */
40
- async getLocaleFile<T>(file: string): Promise<T> {
41
- reportDebug({
42
- namespace,
43
- message: `Starting download of localization file [${file}]`,
44
- data: { bucket: process.env.LOCALES_BUCKET, file }
45
- });
46
- const { data } = await Storage.get(
47
- process.env.LOCALES_BUCKET as string,
48
- file
49
- );
50
- const stringified = data.toString('utf-8');
51
- const result = JSON.parse(stringified) as T;
52
- reportDebug({
53
- namespace,
54
- message: `Fetched localization file [${file}]`,
55
- data: { bucket: process.env.LOCALES_BUCKET, file, result }
56
- });
57
- return result;
58
- },
59
-
60
- /**
61
- * Synchronizes the localeData and scripts files
62
- * Should be called only once on startup
63
- */
64
- async synchronize(): Promise<void> {
65
- reportDebug({ namespace, message: `Starting synchronizing` });
66
- const [fetchedLocaleData, fetchedScripts] = await Promise.all([
67
- Localizator.getLocaleFile<LocalizatorLocalizationData>('localeData.json'),
68
- Localizator.getLocaleFile<LocalizatorScripts>('scripts.json')
69
- ]);
70
- localeData = fetchedLocaleData;
71
- scripts = Localizator.buildRangeRegex(fetchedScripts);
72
- reportDebug({ namespace, message: `Finished synchronizing` });
73
- },
74
-
75
- /** Transform unicode ranges in scripts data to regex */
76
- buildRangeRegex(script: LocalizatorScripts): LocalizatorScripts {
77
- for (const i of Object.keys(script)) {
78
- const ranges = script[i].ranges;
79
- if (ranges) {
80
- script[i].rangeRegex = new RegExp(`[${ranges.join('')}]`, 'u');
81
- }
82
- }
83
- return script;
84
- },
85
-
86
- /** Guess the naming convention to use for a given name and locale */
87
- guessNamingConvention(
88
- firstName: string,
89
- lastName: string,
90
- locale: string
91
- ): LocalizatorNamingConventions {
92
- if (!scripts || !localeData)
93
- throw new EngineError({ message: 'Localizator is not initialized' });
94
- const name = firstName + lastName; // merge two names if possible
95
- return guessNamingConvention(scripts, localeData, name, locale);
96
- },
97
-
98
- /**
99
- * Calculate the different display names for a user
100
- */
101
- getDisplayNames(
102
- firstName: string,
103
- lastName: string,
104
- locale: string
105
- ): LocalizatorNamingConventions {
106
- const convention = Localizator.guessNamingConvention(
107
- firstName,
108
- lastName,
109
- locale
110
- );
111
- return Object.keys(convention).reduce((convention, type) => {
112
- const safeType = type as keyof LocalizatorNamingConventions;
113
- convention[safeType] = convention[safeType]
114
- .replace('{firstName}', firstName)
115
- .replace('{lastName}', lastName ?? '')
116
- .trim();
117
- return convention;
118
- }, convention);
119
- },
120
-
121
- /** Get the localization data for a locale */
122
- getLocaleData(locale: string): LocalizatorLocalizationDataElement {
123
- if (!localeData)
124
- throw new EngineError({ message: 'Localizator is not initialized' });
125
- return localeData[locale];
126
- },
127
-
128
- /** Check if a locale exists */
129
- isValidLocale(locale: string): boolean {
130
- if (!localeData)
131
- throw new EngineError({ message: 'Localizator is not initialized' });
132
- return localeData[locale] !== undefined;
133
- },
134
-
135
- /** Cleanup the instance */
136
- shutdown(): void {
137
- if (interval) clearTimeout(interval);
138
- }
139
- };
@@ -1,52 +0,0 @@
1
- /** Defines how a name should be displayed for a locale in diferent context */
2
- export interface LocalizatorNamingConventions {
3
- /** How the name is displayed in a common way */
4
- regular: string;
5
- /** How the name is displayed in a formal way */
6
- formal: string;
7
- /** How the name is displayed in a casual way */
8
- casual: string;
9
- }
10
-
11
- /** Localization data for each of the locales */
12
- export interface LocalizatorLocalizationData {
13
- [locale: string]: LocalizatorLocalizationDataElement;
14
- }
15
-
16
- /** Describes localization settings for a locale */
17
- export interface LocalizatorLocalizationDataElement {
18
- /** Is this locale available to the public */
19
- enabled: boolean;
20
- /** How this locale is displayed to the user */
21
- display: string;
22
- /** Configuration on how to display names in that locale */
23
- names: {
24
- /** Should the first name or the last name be displayed first */
25
- firstNameFirst: boolean;
26
- /** Is there a space between the two parts of the name */
27
- spacing: boolean;
28
- /** In case the user's name is not displayed in this language's script, how should it be displayed */
29
- fallback?: LocalizatorNamingConventions;
30
- };
31
- /** Script used to identify text written in that language */
32
- script?: string;
33
- /** Key in google translation to identify that language */
34
- cloudTranslationKey: string;
35
- /** Unicode CLDR key to identify that language if it is different from the locale */
36
- unicode?: string;
37
- }
38
-
39
- /** Script config data indexed by the script id */
40
- export interface LocalizatorScripts {
41
- [script: string]: LocalizatorScript;
42
- }
43
-
44
- /** Localization config for a script */
45
- export interface LocalizatorScript {
46
- /** Unicode range used to detect the script */
47
- ranges: Array<string>;
48
- /** How names are displayed when written in the script */
49
- names: LocalizatorNamingConventions;
50
- /** Regex added by the Localizator, used to match with the script unicode ranges */
51
- rangeRegex?: RegExp;
52
- }
@@ -1,165 +0,0 @@
1
- import { expect } from 'chai';
2
- import { faker } from '@faker-js/faker';
3
- import {
4
- LocalizatorScript,
5
- LocalizatorLocalizationDataElement
6
- } from '../Localizator.types';
7
- import {
8
- guessNamingConvention,
9
- DEFAULT_NAMING_CONVENTION
10
- } from './guessNamingConvention';
11
-
12
- /** Generate fake script config */
13
- function generateScriptData(
14
- overrides: Partial<LocalizatorScript> = {}
15
- ): LocalizatorScript {
16
- return {
17
- rangeRegex: new RegExp(`^\b$`, 'u'),
18
- ranges: ['a'],
19
- names: {
20
- casual: faker.lorem.slug(),
21
- regular: faker.lorem.slug(),
22
- formal: faker.lorem.slug()
23
- },
24
- ...overrides
25
- };
26
- }
27
-
28
- /** Generate locales file random data */
29
- function generateLocalizationData(
30
- overrides: Partial<LocalizatorLocalizationDataElement> = {}
31
- ): LocalizatorLocalizationDataElement {
32
- return {
33
- script: faker.lorem.word(),
34
- enabled: true,
35
- display: faker.lorem.word(),
36
- names: {
37
- firstNameFirst: true,
38
- spacing: true
39
- },
40
- cloudTranslationKey: faker.location.countryCode(),
41
- ...overrides
42
- };
43
- }
44
-
45
- describe('Service - Localizator - Guess naming convention', function () {
46
- it('should return the convention for the locale specifc script', function () {
47
- const locale = faker.location.country();
48
- const userScript = faker.lorem.word();
49
- const name = faker.lorem.word();
50
- const scriptData = generateScriptData({
51
- rangeRegex: new RegExp(name, 'u')
52
- });
53
-
54
- const Localizator = {
55
- localeData: {
56
- [faker.location.countryCode()]: generateLocalizationData(),
57
- [locale]: generateLocalizationData({ script: userScript })
58
- },
59
- scripts: {
60
- [faker.lorem.word()]: generateScriptData(),
61
- [userScript]: scriptData
62
- }
63
- };
64
- const result = guessNamingConvention(
65
- Localizator.scripts,
66
- Localizator.localeData,
67
- name,
68
- locale
69
- );
70
-
71
- expect(result).to.equal(scriptData.names);
72
- });
73
-
74
- it('should return the convention for the the script detected in the name if no match wirth the default script', function () {
75
- const locale = faker.location.country();
76
- const expectedResult = {
77
- casual: faker.lorem.word(),
78
- regular: faker.lorem.word(),
79
- formal: faker.lorem.word()
80
- };
81
- const userScript = faker.lorem.word();
82
- const name = faker.lorem.word();
83
- const Localizator = {
84
- localeData: {
85
- [faker.location.countryCode()]: generateLocalizationData(),
86
- [locale]: generateLocalizationData({ script: userScript })
87
- },
88
- scripts: {
89
- [faker.lorem.word()]: generateScriptData(),
90
- [userScript]: generateScriptData(),
91
- [faker.lorem.word()]: generateScriptData({
92
- rangeRegex: new RegExp(name, 'u'),
93
- names: expectedResult
94
- })
95
- }
96
- };
97
- const result = guessNamingConvention(
98
- Localizator.scripts,
99
- Localizator.localeData,
100
- name,
101
- locale
102
- );
103
- expect(result).to.equal(expectedResult);
104
- });
105
-
106
- it('should return the convention for the locale if no script match', function () {
107
- const locale = faker.location.country();
108
- const expectedResult = {
109
- casual: faker.lorem.word(),
110
- regular: faker.lorem.word(),
111
- formal: faker.lorem.word()
112
- };
113
- const userScript = faker.lorem.word();
114
- const name = faker.lorem.word();
115
- const Localizator = {
116
- localeData: {
117
- [faker.location.countryCode()]: generateLocalizationData({
118
- script: faker.lorem.word()
119
- }),
120
- [locale]: generateLocalizationData({
121
- script: userScript,
122
- names: {
123
- firstNameFirst: true,
124
- spacing: true,
125
- fallback: expectedResult
126
- }
127
- })
128
- },
129
- scripts: {
130
- [faker.lorem.word()]: generateScriptData(),
131
- [userScript]: generateScriptData()
132
- }
133
- };
134
- const result = guessNamingConvention(
135
- Localizator.scripts,
136
- Localizator.localeData,
137
- name,
138
- locale
139
- );
140
- expect(result).to.equal(expectedResult);
141
- });
142
-
143
- it('should use the default if no fallback exist', function () {
144
- const locale = faker.location.country();
145
- const userScript = faker.lorem.word();
146
- const name = faker.lorem.word();
147
- const Localizator = {
148
- localeData: {
149
- [faker.location.countryCode()]: generateLocalizationData(),
150
- [locale]: generateLocalizationData({ script: userScript })
151
- },
152
- scripts: {
153
- [faker.lorem.word()]: generateScriptData(),
154
- [userScript]: generateScriptData()
155
- }
156
- };
157
- const result = guessNamingConvention(
158
- Localizator.scripts,
159
- Localizator.localeData,
160
- name,
161
- locale
162
- );
163
- expect(result).to.equal(DEFAULT_NAMING_CONVENTION);
164
- });
165
- });