kuzzle 2.56.0 → 2.57.0-beta.2

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 (408) hide show
  1. package/dist/bin/copy-binaries.js +71 -4
  2. package/dist/bin/start-kuzzle-server +191 -97
  3. package/dist/index.d.ts +31 -1
  4. package/dist/index.js +45 -2
  5. package/dist/lib/api/controllers/adminController.d.ts +4 -3
  6. package/dist/lib/api/controllers/adminController.js +1 -2
  7. package/dist/lib/api/controllers/authController.d.ts +37 -16
  8. package/dist/lib/api/controllers/authController.js +88 -39
  9. package/dist/lib/api/controllers/baseController.d.ts +10 -5
  10. package/dist/lib/api/controllers/baseController.js +36 -15
  11. package/dist/lib/api/controllers/bulkController.d.ts +11 -7
  12. package/dist/lib/api/controllers/bulkController.js +28 -5
  13. package/dist/lib/api/controllers/clusterController.d.ts +2 -2
  14. package/dist/lib/api/controllers/clusterController.js +3 -3
  15. package/dist/lib/api/controllers/collectionController.d.ts +57 -21
  16. package/dist/lib/api/controllers/collectionController.js +40 -11
  17. package/dist/lib/api/controllers/debugController.d.ts +1 -1
  18. package/dist/lib/api/controllers/documentController.d.ts +137 -28
  19. package/dist/lib/api/controllers/documentController.js +156 -125
  20. package/dist/lib/api/controllers/index.d.ts +27 -12
  21. package/dist/lib/api/controllers/index.js +28 -13
  22. package/dist/lib/api/controllers/indexController.d.ts +17 -10
  23. package/dist/lib/api/controllers/indexController.js +13 -11
  24. package/dist/lib/api/controllers/memoryStorageController.d.ts +2 -5
  25. package/dist/lib/api/controllers/memoryStorageController.js +199 -127
  26. package/dist/lib/api/controllers/realtimeController.d.ts +19 -9
  27. package/dist/lib/api/controllers/realtimeController.js +8 -4
  28. package/dist/lib/api/controllers/securityController.d.ts +42 -29
  29. package/dist/lib/api/controllers/securityController.js +35 -19
  30. package/dist/lib/api/controllers/serverController.d.ts +114 -19
  31. package/dist/lib/api/controllers/serverController.js +69 -29
  32. package/dist/lib/api/documentExtractor.d.ts +9 -7
  33. package/dist/lib/api/documentExtractor.js +105 -41
  34. package/dist/lib/api/funnel.d.ts +131 -29
  35. package/dist/lib/api/funnel.js +436 -225
  36. package/dist/lib/api/httpRoutes.d.ts +16 -11
  37. package/dist/lib/api/httpRoutes.js +272 -2
  38. package/dist/lib/api/openapi/OpenApiManager.d.ts +1 -1
  39. package/dist/lib/api/openapi/openApiGenerator.d.ts +1 -1
  40. package/dist/lib/api/rateLimiter.d.ts +15 -5
  41. package/dist/lib/api/rateLimiter.js +42 -14
  42. package/dist/lib/api/request/kuzzleRequest.d.ts +83 -12
  43. package/dist/lib/api/request/kuzzleRequest.js +88 -23
  44. package/dist/lib/api/request/requestContext.d.ts +20 -5
  45. package/dist/lib/api/request/requestContext.js +14 -4
  46. package/dist/lib/api/request/requestInput.d.ts +37 -6
  47. package/dist/lib/api/request/requestInput.js +22 -9
  48. package/dist/lib/api/request/requestResponse.d.ts +45 -9
  49. package/dist/lib/api/request/requestResponse.js +34 -3
  50. package/dist/lib/cluster/command.d.ts +131 -37
  51. package/dist/lib/cluster/command.js +243 -71
  52. package/dist/lib/cluster/idCardHandler.d.ts +18 -5
  53. package/dist/lib/cluster/idCardHandler.js +52 -19
  54. package/dist/lib/cluster/index.d.ts +8 -2
  55. package/dist/lib/cluster/index.js +6 -2
  56. package/dist/lib/cluster/node.d.ts +127 -49
  57. package/dist/lib/cluster/node.js +412 -179
  58. package/dist/lib/cluster/protobuf/command.proto +18 -0
  59. package/dist/lib/cluster/protobuf/commandMessages.d.ts +104 -0
  60. package/dist/lib/cluster/protobuf/commandMessages.js +30 -0
  61. package/dist/lib/cluster/protobuf/syncMessages.d.ts +184 -0
  62. package/dist/lib/cluster/protobuf/syncMessages.js +23 -0
  63. package/dist/lib/cluster/publisher.d.ts +118 -78
  64. package/dist/lib/cluster/publisher.js +174 -72
  65. package/dist/lib/cluster/state.d.ts +15 -9
  66. package/dist/lib/cluster/state.js +12 -8
  67. package/dist/lib/cluster/subscriber.d.ts +185 -131
  68. package/dist/lib/cluster/subscriber.js +357 -95
  69. package/dist/lib/cluster/workers/IDCardRenewer.d.ts +39 -8
  70. package/dist/lib/cluster/workers/IDCardRenewer.js +88 -23
  71. package/dist/lib/config/default.config.d.ts +2 -2
  72. package/dist/lib/config/default.config.js +10 -3
  73. package/dist/lib/config/documentEventAliases.d.ts +1 -1
  74. package/dist/lib/config/index.d.ts +2 -5
  75. package/dist/lib/config/index.js +30 -17
  76. package/dist/lib/core/auth/formatProcessing.d.ts +3 -3
  77. package/dist/lib/core/auth/passportResponse.d.ts +1 -1
  78. package/dist/lib/core/auth/passportWrapper.d.ts +1 -1
  79. package/dist/lib/core/auth/passportWrapper.js +14 -13
  80. package/dist/lib/core/auth/tokenManager.d.ts +24 -3
  81. package/dist/lib/core/auth/tokenManager.js +47 -19
  82. package/dist/lib/core/backend/applicationManager.d.ts +2 -2
  83. package/dist/lib/core/backend/backend.d.ts +16 -5
  84. package/dist/lib/core/backend/backend.js +14 -6
  85. package/dist/lib/core/backend/backendCluster.d.ts +1 -1
  86. package/dist/lib/core/backend/backendConfig.d.ts +17 -5
  87. package/dist/lib/core/backend/backendConfig.js +1 -0
  88. package/dist/lib/core/backend/backendController.d.ts +1 -1
  89. package/dist/lib/core/backend/backendController.js +8 -1
  90. package/dist/lib/core/backend/backendErrors.d.ts +15 -8
  91. package/dist/lib/core/backend/backendErrors.js +5 -0
  92. package/dist/lib/core/backend/backendHook.d.ts +1 -1
  93. package/dist/lib/core/backend/backendImport.d.ts +1 -1
  94. package/dist/lib/core/backend/backendOpenApi.d.ts +3 -2
  95. package/dist/lib/core/backend/backendPipe.d.ts +1 -1
  96. package/dist/lib/core/backend/backendPipe.js +9 -1
  97. package/dist/lib/core/backend/backendPlugin.d.ts +2 -2
  98. package/dist/lib/core/backend/backendSubscription.d.ts +2 -2
  99. package/dist/lib/core/backend/backendVault.d.ts +1 -1
  100. package/dist/lib/core/backend/backendVault.js +8 -1
  101. package/dist/lib/core/cache/cacheEngine.d.ts +7 -4
  102. package/dist/lib/core/cache/cacheEngine.js +25 -8
  103. package/dist/lib/core/debug/kuzzleDebugger.d.ts +2 -1
  104. package/dist/lib/core/debug/kuzzleDebugger.js +31 -17
  105. package/dist/lib/core/network/accessLogger.d.ts +33 -18
  106. package/dist/lib/core/network/accessLogger.js +135 -73
  107. package/dist/lib/core/network/clientConnection.d.ts +13 -11
  108. package/dist/lib/core/network/clientConnection.js +33 -9
  109. package/dist/lib/core/network/context.d.ts +17 -22
  110. package/dist/lib/core/network/context.js +43 -26
  111. package/dist/lib/core/network/entryPoint.d.ts +38 -16
  112. package/dist/lib/core/network/entryPoint.js +119 -48
  113. package/dist/lib/core/network/httpRouter/index.d.ts +20 -50
  114. package/dist/lib/core/network/httpRouter/index.js +61 -75
  115. package/dist/lib/core/network/httpRouter/routeHandler.d.ts +17 -32
  116. package/dist/lib/core/network/httpRouter/routeHandler.js +26 -36
  117. package/dist/lib/core/network/httpRouter/routePart.d.ts +9 -18
  118. package/dist/lib/core/network/httpRouter/routePart.js +61 -43
  119. package/dist/lib/core/network/httpRouter/routeTypes.d.ts +3 -0
  120. package/dist/lib/core/network/httpRouter/routeTypes.js +23 -0
  121. package/dist/lib/core/network/networkEntryPoint.d.ts +20 -0
  122. package/dist/lib/core/network/networkEntryPoint.js +23 -0
  123. package/dist/lib/core/network/protocolManifest.d.ts +5 -4
  124. package/dist/lib/core/network/protocolManifest.js +6 -3
  125. package/dist/lib/core/network/protocols/httpMessage.d.ts +25 -18
  126. package/dist/lib/core/network/protocols/httpMessage.js +14 -11
  127. package/dist/lib/core/network/protocols/httpwsProtocol.d.ts +84 -93
  128. package/dist/lib/core/network/protocols/httpwsProtocol.js +284 -129
  129. package/dist/lib/core/network/protocols/internalProtocol.d.ts +26 -15
  130. package/dist/lib/core/network/protocols/internalProtocol.js +17 -16
  131. package/dist/lib/core/network/protocols/mqttProtocol.d.ts +56 -32
  132. package/dist/lib/core/network/protocols/mqttProtocol.js +91 -44
  133. package/dist/lib/core/network/protocols/protocol.d.ts +85 -21
  134. package/dist/lib/core/network/protocols/protocol.js +83 -27
  135. package/dist/lib/core/network/router.d.ts +13 -22
  136. package/dist/lib/core/network/router.js +59 -46
  137. package/dist/lib/core/plugin/plugin.d.ts +57 -51
  138. package/dist/lib/core/plugin/plugin.js +218 -103
  139. package/dist/lib/core/plugin/pluginContext.d.ts +54 -11
  140. package/dist/lib/core/plugin/pluginContext.js +99 -58
  141. package/dist/lib/core/plugin/pluginManifest.d.ts +6 -2
  142. package/dist/lib/core/plugin/pluginManifest.js +18 -11
  143. package/dist/lib/core/plugin/pluginRepository.d.ts +35 -44
  144. package/dist/lib/core/plugin/pluginRepository.js +35 -50
  145. package/dist/lib/core/plugin/pluginsManager.d.ts +128 -46
  146. package/dist/lib/core/plugin/pluginsManager.js +468 -231
  147. package/dist/lib/core/plugin/privilegedContext.d.ts +4 -9
  148. package/dist/lib/core/plugin/privilegedContext.js +5 -10
  149. package/dist/lib/core/realtime/actionEnum.d.ts +12 -21
  150. package/dist/lib/core/realtime/actionEnum.js +6 -7
  151. package/dist/lib/core/realtime/channel.d.ts +11 -5
  152. package/dist/lib/core/realtime/channel.js +17 -2
  153. package/dist/lib/core/realtime/connectionRooms.d.ts +2 -2
  154. package/dist/lib/core/realtime/hotelClerk.d.ts +12 -6
  155. package/dist/lib/core/realtime/hotelClerk.js +29 -11
  156. package/dist/lib/core/realtime/index.d.ts +8 -3
  157. package/dist/lib/core/realtime/index.js +12 -5
  158. package/dist/lib/core/realtime/notification/document.d.ts +54 -25
  159. package/dist/lib/core/realtime/notification/document.js +10 -13
  160. package/dist/lib/core/realtime/notification/index.d.ts +9 -3
  161. package/dist/lib/core/realtime/notification/index.js +10 -4
  162. package/dist/lib/core/realtime/notification/server.d.ts +7 -10
  163. package/dist/lib/core/realtime/notification/server.js +4 -7
  164. package/dist/lib/core/realtime/notification/user.d.ts +45 -21
  165. package/dist/lib/core/realtime/notification/user.js +8 -9
  166. package/dist/lib/core/realtime/notifier.d.ts +52 -40
  167. package/dist/lib/core/realtime/notifier.js +60 -25
  168. package/dist/lib/core/realtime/room.d.ts +1 -1
  169. package/dist/lib/core/realtime/subscription.d.ts +11 -6
  170. package/dist/lib/core/realtime/subscription.js +5 -1
  171. package/dist/lib/core/security/index.d.ts +14 -6
  172. package/dist/lib/core/security/index.js +27 -13
  173. package/dist/lib/core/security/profileRepository.d.ts +24 -19
  174. package/dist/lib/core/security/profileRepository.js +23 -10
  175. package/dist/lib/core/security/roleRepository.d.ts +60 -23
  176. package/dist/lib/core/security/roleRepository.js +122 -53
  177. package/dist/lib/core/security/securityLoader.d.ts +33 -18
  178. package/dist/lib/core/security/securityLoader.js +43 -16
  179. package/dist/lib/core/security/tokenRepository.d.ts +21 -7
  180. package/dist/lib/core/security/tokenRepository.js +50 -23
  181. package/dist/lib/core/security/userRepository.d.ts +44 -21
  182. package/dist/lib/core/security/userRepository.js +59 -19
  183. package/dist/lib/core/shared/KoncordeWrapper.d.ts +1 -1
  184. package/dist/lib/core/shared/ObjectRepository.d.ts +80 -18
  185. package/dist/lib/core/shared/ObjectRepository.js +57 -29
  186. package/dist/lib/core/shared/abstractManifest.d.ts +21 -8
  187. package/dist/lib/core/shared/abstractManifest.js +57 -17
  188. package/dist/lib/core/shared/sdk/embeddedSdk.d.ts +3 -1
  189. package/dist/lib/core/shared/sdk/embeddedSdk.js +8 -7
  190. package/dist/lib/core/shared/sdk/funnelProtocol.d.ts +2 -1
  191. package/dist/lib/core/shared/sdk/funnelProtocol.js +12 -3
  192. package/dist/lib/core/shared/sdk/impersonatedSdk.d.ts +11 -5
  193. package/dist/lib/core/shared/sdk/impersonatedSdk.js +22 -9
  194. package/dist/lib/core/shared/store.d.ts +45 -29
  195. package/dist/lib/core/shared/store.js +48 -27
  196. package/dist/lib/core/statistics/statistics.d.ts +1 -1
  197. package/dist/lib/core/storage/clientAdapter.d.ts +39 -21
  198. package/dist/lib/core/storage/clientAdapter.js +88 -48
  199. package/dist/lib/core/storage/indexCache.d.ts +8 -0
  200. package/dist/lib/core/storage/indexCache.js +16 -7
  201. package/dist/lib/core/storage/storageEngine.d.ts +7 -6
  202. package/dist/lib/core/storage/storageEngine.js +11 -8
  203. package/dist/lib/core/validation/baseType.d.ts +22 -22
  204. package/dist/lib/core/validation/baseType.js +11 -26
  205. package/dist/lib/core/validation/specification.d.ts +148 -0
  206. package/dist/lib/core/validation/specification.js +34 -0
  207. package/dist/lib/core/validation/typeOptions.d.ts +62 -0
  208. package/dist/lib/core/validation/typeOptions.js +23 -0
  209. package/dist/lib/core/validation/types/anything.d.ts +3 -6
  210. package/dist/lib/core/validation/types/anything.js +7 -7
  211. package/dist/lib/core/validation/types/boolean.d.ts +5 -12
  212. package/dist/lib/core/validation/types/boolean.js +7 -12
  213. package/dist/lib/core/validation/types/date.d.ts +19 -11
  214. package/dist/lib/core/validation/types/date.js +212 -161
  215. package/dist/lib/core/validation/types/email.d.ts +7 -11
  216. package/dist/lib/core/validation/types/email.js +13 -17
  217. package/dist/lib/core/validation/types/enum.d.ts +7 -11
  218. package/dist/lib/core/validation/types/enum.js +39 -20
  219. package/dist/lib/core/validation/types/geoPoint.d.ts +5 -13
  220. package/dist/lib/core/validation/types/geoPoint.js +10 -15
  221. package/dist/lib/core/validation/types/geoShape.d.ts +22 -21
  222. package/dist/lib/core/validation/types/geoShape.js +113 -129
  223. package/dist/lib/core/validation/types/geoShapeUtils.d.ts +15 -0
  224. package/dist/lib/core/validation/types/geoShapeUtils.js +75 -0
  225. package/dist/lib/core/validation/types/integer.d.ts +7 -5
  226. package/dist/lib/core/validation/types/integer.js +7 -13
  227. package/dist/lib/core/validation/types/ipAddress.d.ts +7 -11
  228. package/dist/lib/core/validation/types/ipAddress.js +13 -17
  229. package/dist/lib/core/validation/types/numeric.d.ts +7 -11
  230. package/dist/lib/core/validation/types/numeric.js +22 -29
  231. package/dist/lib/core/validation/types/object.d.ts +8 -15
  232. package/dist/lib/core/validation/types/object.js +12 -21
  233. package/dist/lib/core/validation/types/string.d.ts +7 -11
  234. package/dist/lib/core/validation/types/string.js +22 -29
  235. package/dist/lib/core/validation/types/url.d.ts +7 -11
  236. package/dist/lib/core/validation/types/url.js +14 -18
  237. package/dist/lib/core/validation/validation.d.ts +119 -80
  238. package/dist/lib/core/validation/validation.js +470 -412
  239. package/dist/lib/core/validation/validationUtils.d.ts +31 -0
  240. package/dist/lib/core/validation/validationUtils.js +190 -0
  241. package/dist/lib/kerror/codes/4-plugin.json +0 -12
  242. package/dist/lib/kerror/codes/index.d.ts +12 -2
  243. package/dist/lib/kerror/codes/index.js +5 -4
  244. package/dist/lib/kerror/errors/badRequestError.d.ts +1 -1
  245. package/dist/lib/kerror/errors/badRequestError.js +1 -1
  246. package/dist/lib/kerror/errors/externalServiceError.d.ts +1 -1
  247. package/dist/lib/kerror/errors/externalServiceError.js +1 -1
  248. package/dist/lib/kerror/errors/forbiddenError.d.ts +1 -1
  249. package/dist/lib/kerror/errors/forbiddenError.js +1 -1
  250. package/dist/lib/kerror/errors/gatewayTimeoutError.d.ts +1 -1
  251. package/dist/lib/kerror/errors/gatewayTimeoutError.js +1 -1
  252. package/dist/lib/kerror/errors/internalError.d.ts +1 -1
  253. package/dist/lib/kerror/errors/internalError.js +1 -1
  254. package/dist/lib/kerror/errors/kuzzleError.d.ts +32 -3
  255. package/dist/lib/kerror/errors/kuzzleError.js +21 -7
  256. package/dist/lib/kerror/errors/multipleErrorsError.d.ts +2 -2
  257. package/dist/lib/kerror/errors/multipleErrorsError.js +2 -2
  258. package/dist/lib/kerror/errors/notFoundError.d.ts +1 -1
  259. package/dist/lib/kerror/errors/notFoundError.js +1 -1
  260. package/dist/lib/kerror/errors/partialError.d.ts +8 -2
  261. package/dist/lib/kerror/errors/partialError.js +22 -9
  262. package/dist/lib/kerror/errors/pluginImplementationError.d.ts +9 -1
  263. package/dist/lib/kerror/errors/pluginImplementationError.js +9 -3
  264. package/dist/lib/kerror/errors/preconditionError.d.ts +1 -1
  265. package/dist/lib/kerror/errors/preconditionError.js +1 -1
  266. package/dist/lib/kerror/errors/serviceUnavailableError.d.ts +1 -1
  267. package/dist/lib/kerror/errors/serviceUnavailableError.js +1 -1
  268. package/dist/lib/kerror/errors/sizeLimitError.d.ts +1 -1
  269. package/dist/lib/kerror/errors/sizeLimitError.js +1 -1
  270. package/dist/lib/kerror/errors/tooManyRequestsError.d.ts +1 -1
  271. package/dist/lib/kerror/errors/tooManyRequestsError.js +1 -1
  272. package/dist/lib/kerror/errors/unauthorizedError.d.ts +1 -1
  273. package/dist/lib/kerror/errors/unauthorizedError.js +1 -1
  274. package/dist/lib/kerror/index.d.ts +19 -13
  275. package/dist/lib/kerror/index.js +60 -19
  276. package/dist/lib/kuzzle/Logger.d.ts +2 -2
  277. package/dist/lib/kuzzle/dumpGenerator.d.ts +12 -8
  278. package/dist/lib/kuzzle/dumpGenerator.js +130 -62
  279. package/dist/lib/kuzzle/event/KuzzleEventEmitter.d.ts +18 -9
  280. package/dist/lib/kuzzle/event/KuzzleEventEmitter.js +45 -18
  281. package/dist/lib/kuzzle/event/pipeRunner.d.ts +37 -16
  282. package/dist/lib/kuzzle/event/pipeRunner.js +73 -26
  283. package/dist/lib/kuzzle/event/waterfall.d.ts +11 -1
  284. package/dist/lib/kuzzle/event/waterfall.js +38 -13
  285. package/dist/lib/kuzzle/internalIndexHandler.d.ts +11 -174
  286. package/dist/lib/kuzzle/internalIndexHandler.js +58 -29
  287. package/dist/lib/kuzzle/kuzzle.d.ts +25 -10
  288. package/dist/lib/kuzzle/kuzzle.js +74 -17
  289. package/dist/lib/kuzzle/kuzzleStateEnum.d.ts +16 -12
  290. package/dist/lib/kuzzle/kuzzleStateEnum.js +5 -7
  291. package/dist/lib/kuzzle/vault.d.ts +5 -1
  292. package/dist/lib/kuzzle/vault.js +29 -17
  293. package/dist/lib/model/security/profile.d.ts +34 -5
  294. package/dist/lib/model/security/profile.js +6 -5
  295. package/dist/lib/model/security/rights.d.ts +12 -4
  296. package/dist/lib/model/security/rights.js +7 -6
  297. package/dist/lib/model/security/role.d.ts +8 -4
  298. package/dist/lib/model/security/role.js +12 -6
  299. package/dist/lib/model/security/token.d.ts +8 -0
  300. package/dist/lib/model/security/user.d.ts +8 -2
  301. package/dist/lib/model/security/user.js +7 -4
  302. package/dist/lib/model/storage/apiKey.d.ts +55 -26
  303. package/dist/lib/model/storage/apiKey.js +97 -24
  304. package/dist/lib/model/storage/baseModel.d.ts +77 -66
  305. package/dist/lib/model/storage/baseModel.js +21 -34
  306. package/dist/lib/service/cache/redis.d.ts +53 -36
  307. package/dist/lib/service/cache/redis.js +148 -71
  308. package/dist/lib/service/service.d.ts +14 -19
  309. package/dist/lib/service/service.js +41 -22
  310. package/dist/lib/service/storage/7/elasticsearch.d.ts +136 -93
  311. package/dist/lib/service/storage/7/elasticsearch.js +218 -165
  312. package/dist/lib/service/storage/7/esWrapper.d.ts +30 -13
  313. package/dist/lib/service/storage/7/esWrapper.js +58 -37
  314. package/dist/lib/service/storage/8/elasticsearch.d.ts +153 -119
  315. package/dist/lib/service/storage/8/elasticsearch.js +286 -213
  316. package/dist/lib/service/storage/8/esWrapper.d.ts +30 -13
  317. package/dist/lib/service/storage/8/esWrapper.js +59 -38
  318. package/dist/lib/service/storage/commons/queryTranslator.d.ts +3 -3
  319. package/dist/lib/service/storage/commons/queryTranslator.js +71 -35
  320. package/dist/lib/types/ApiRoute.d.ts +12 -0
  321. package/dist/lib/types/ApiRoute.js +23 -0
  322. package/dist/lib/types/ClientConnection.d.ts +1 -1
  323. package/dist/lib/types/EventHandler.d.ts +10 -0
  324. package/dist/lib/types/Global.d.ts +8 -3
  325. package/dist/lib/types/HttpMessage.d.ts +2 -2
  326. package/dist/lib/types/HttpStream.d.ts +1 -1
  327. package/dist/lib/types/HttpStream.js +3 -1
  328. package/dist/lib/types/JSONObject.d.ts +9 -0
  329. package/dist/lib/types/JSONObject.js +23 -0
  330. package/dist/lib/types/Kuzzle.d.ts +5 -3
  331. package/dist/lib/types/KuzzleDocument.d.ts +1 -1
  332. package/dist/lib/types/KuzzleWebSocket.d.ts +24 -0
  333. package/dist/lib/types/KuzzleWebSocket.js +23 -0
  334. package/dist/lib/types/OpenApiDefinition.d.ts +1 -1
  335. package/dist/lib/types/Plugin.d.ts +33 -8
  336. package/dist/lib/types/PluginInstance.d.ts +67 -0
  337. package/dist/lib/types/PluginInstance.js +23 -0
  338. package/dist/lib/types/Policy.d.ts +1 -1
  339. package/dist/lib/types/Target.d.ts +8 -0
  340. package/dist/lib/types/Token.d.ts +14 -2
  341. package/dist/lib/types/config/HttpConfiguration.d.ts +5 -0
  342. package/dist/lib/types/config/KuzzleConfiguration.d.ts +102 -1
  343. package/dist/lib/types/config/PluginsConfiguration.d.ts +3 -2
  344. package/dist/lib/types/config/SecurityConfiguration.d.ts +6 -2
  345. package/dist/lib/types/config/ServerConfiguration.d.ts +2 -2
  346. package/dist/lib/types/config/ServicesConfiguration.d.ts +1 -1
  347. package/dist/lib/types/config/cache/BaseCacheRedisConfiguration.d.ts +131 -0
  348. package/dist/lib/types/config/cache/BaseCacheRedisConfiguration.js +3 -0
  349. package/dist/lib/types/config/internalCache/InternalCacheRedisConfiguration.d.ts +2 -106
  350. package/dist/lib/types/config/publicCache/PublicCacheRedisConfiguration.d.ts +2 -26
  351. package/dist/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.d.ts +3 -0
  352. package/dist/lib/types/controllers/Controller.d.ts +12 -3
  353. package/dist/lib/types/controllers/ControllerDefinition.d.ts +2 -2
  354. package/dist/lib/types/controllers/{adminControlller.type.js → adminController.type.js} +1 -1
  355. package/dist/lib/types/controllers/authController.type.d.ts +2 -2
  356. package/dist/lib/types/core/auth/formatProcessing.type.d.ts +7 -1
  357. package/dist/lib/types/errors/ErrorDomains.d.ts +1 -1
  358. package/dist/lib/types/events/EventGenericDocument.d.ts +10 -9
  359. package/dist/lib/types/events/EventProtocol.d.ts +4 -4
  360. package/dist/lib/types/index.d.ts +7 -0
  361. package/dist/lib/types/index.js +7 -0
  362. package/dist/lib/types/shared/StoreCollectionsDefinition.d.ts +1 -1
  363. package/dist/lib/types/storage/7/Elasticsearch.d.ts +62 -13
  364. package/dist/lib/types/storage/8/Elasticsearch.d.ts +62 -13
  365. package/dist/lib/util/Inflector.d.ts +4 -1
  366. package/dist/lib/util/Inflector.js +0 -3
  367. package/dist/lib/util/assertType.d.ts +24 -27
  368. package/dist/lib/util/assertType.js +28 -39
  369. package/dist/lib/util/async.js +19 -6
  370. package/dist/lib/util/asyncStore.js +1 -1
  371. package/dist/lib/util/bufferedPassThrough.d.ts +9 -0
  372. package/dist/lib/util/bufferedPassThrough.js +27 -13
  373. package/dist/lib/util/bytes.d.ts +1 -1
  374. package/dist/lib/util/bytes.js +6 -2
  375. package/dist/lib/util/debug.d.ts +3 -1
  376. package/dist/lib/util/debug.js +42 -10
  377. package/dist/lib/util/deprecate.d.ts +9 -1
  378. package/dist/lib/util/deprecate.js +10 -6
  379. package/dist/lib/util/didYouMean.d.ts +2 -1
  380. package/dist/lib/util/didYouMean.js +8 -4
  381. package/dist/lib/util/distributedLock.d.ts +56 -0
  382. package/dist/lib/util/distributedLock.js +166 -0
  383. package/dist/lib/util/dump-collection.d.ts +1 -1
  384. package/dist/lib/util/dump-collection.js +4 -5
  385. package/dist/lib/util/extractFields.d.ts +15 -11
  386. package/dist/lib/util/extractFields.js +8 -9
  387. package/dist/lib/util/koncordeCompat.d.ts +2 -2
  388. package/dist/lib/util/koncordeCompat.js +33 -0
  389. package/dist/lib/util/memoize.d.ts +7 -6
  390. package/dist/lib/util/memoize.js +3 -3
  391. package/dist/lib/util/mutex.d.ts +22 -2
  392. package/dist/lib/util/mutex.js +39 -1
  393. package/dist/lib/util/name-generator.js +14 -2
  394. package/dist/lib/util/promback.d.ts +20 -11
  395. package/dist/lib/util/promback.js +14 -7
  396. package/dist/lib/util/requestAssertions.d.ts +30 -10
  397. package/dist/lib/util/requestAssertions.js +125 -121
  398. package/dist/lib/util/safeObject.d.ts +3 -3
  399. package/dist/lib/util/safeObject.js +7 -3
  400. package/dist/lib/util/stackTrace.d.ts +13 -5
  401. package/dist/lib/util/stackTrace.js +17 -12
  402. package/dist/lib/util/thrown.d.ts +13 -0
  403. package/dist/lib/util/thrown.js +46 -0
  404. package/dist/package.json +26 -19
  405. package/package.json +26 -19
  406. package/dist/lib/util/wildcard.d.ts +0 -1
  407. package/dist/lib/util/wildcard.js +0 -46
  408. /package/dist/lib/types/controllers/{adminControlller.type.d.ts → adminController.type.d.ts} +0 -0
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /*
2
3
  * Kuzzle, a backend software, self-hostable and ready to use
3
4
  * to power modern apps
@@ -18,42 +19,123 @@
18
19
  * See the License for the specific language governing permissions and
19
20
  * limitations under the License.
20
21
  */
21
- "use strict";
22
- const { Reply, Request } = require("zeromq");
23
- const protobuf = require("protobufjs");
24
- const Bluebird = require("bluebird");
22
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ var desc = Object.getOwnPropertyDescriptor(m, k);
25
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
26
+ desc = { enumerable: true, get: function() { return m[k]; } };
27
+ }
28
+ Object.defineProperty(o, k2, desc);
29
+ }) : (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ o[k2] = m[k];
32
+ }));
33
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
34
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
35
+ }) : function(o, v) {
36
+ o["default"] = v;
37
+ });
38
+ var __importStar = (this && this.__importStar) || function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ var __importDefault = (this && this.__importDefault) || function (mod) {
46
+ return (mod && mod.__esModule) ? mod : { "default": mod };
47
+ };
48
+ const bluebird_1 = __importDefault(require("bluebird"));
49
+ const long_1 = __importDefault(require("long"));
50
+ const protobuf = __importStar(require("protobufjs"));
51
+ const zeromq_1 = require("zeromq");
52
+ const commandMessages_1 = require("./protobuf/commandMessages");
53
+ /**
54
+ * Annotated `number` rather than left to infer `1 | 2 | 3`: `state` is moved to
55
+ * `CLOSED` by `dispose()` while `listen()` is awaiting a socket read, and
56
+ * TypeScript's control-flow narrowing does not model that. Under the literal
57
+ * types the `while (state === RUNNING)` loop narrows `state` to `RUNNING`
58
+ * inside its own body, and the deliberate `state !== CLOSED` re-check after the
59
+ * `await` is then reported as a comparison with no overlap. That re-check is
60
+ * the point: it is how a socket error during shutdown is told apart from a real
61
+ * one.
62
+ */
25
63
  /* eslint-disable sort-keys */
26
64
  const stateEnum = Object.freeze({
27
65
  INITIALIZING: 1,
28
66
  RUNNING: 2,
29
67
  CLOSED: 3,
30
68
  });
31
- const topicEnum = Object.freeze({
32
- FULLSTATE: "fullstate",
33
- HANDSHAKE: "handshake",
34
- DISCARDED: "discarded", // 0 byte message expected
35
- });
36
- /* eslint-enable sort-keys */
37
69
  // Handles bidirectional requests between this node and other nodes
38
70
  class ClusterCommand {
39
71
  /**
40
- * @constructor
41
- * @param {ClusterNode} localNode
72
+ * The REP socket and the protobuf schema, both built by `init()`.
73
+ *
74
+ * Every method below runs on a command layer that has been initialised —
75
+ * `listen()` is started by `init()` itself, and the rest answer requests it
76
+ * received — and all eleven dereferenced them unchecked. Same shape as
77
+ * `Protocol.entryPoint`: said once, where it can fail.
78
+ */
79
+ get server() {
80
+ if (this._server === null) {
81
+ throw new Error("[CLUSTER] Command server used before init()");
82
+ }
83
+ return this._server;
84
+ }
85
+ set server(server) {
86
+ this._server = server;
87
+ }
88
+ get protoroot() {
89
+ if (this._protoroot === null) {
90
+ throw new Error("[CLUSTER] Command protobuf schema loaded by init()");
91
+ }
92
+ return this._protoroot;
93
+ }
94
+ set protoroot(protoroot) {
95
+ this._protoroot = protoroot;
96
+ }
97
+ /**
98
+ * Whether `listen()`'s loop is running: `init()` starts it without awaiting
99
+ * it, and `dispose()` is what stops it.
100
+ *
101
+ * The flag itself stays private — its values are this file's business — but
102
+ * *whether the command layer is listening* is a legitimate question from
103
+ * outside, and it is the one the spec was reading `state` to answer. See
104
+ * docs/adr-001/steps/14-test-program-strict.md (M6).
105
+ */
106
+ get running() {
107
+ return this.state === stateEnum.RUNNING;
108
+ }
109
+ /**
110
+ * @param localNode the cluster node this command layer belongs to
42
111
  */
43
112
  constructor(localNode) {
44
113
  this.node = localNode;
45
- this.server = null;
46
- this.protoroot = null;
114
+ this._server = null;
115
+ this._protoroot = null;
47
116
  this.state = stateEnum.INITIALIZING;
48
117
  this.logger = global.kuzzle.log.child("cluster:command");
49
118
  }
50
- async init() {
119
+ /**
120
+ * Loads the wire schema, and nothing else.
121
+ *
122
+ * This class is two things: the **server** every node runs, and the
123
+ * **client** `getFullState()` and `broadcastHandshake()` use to call its
124
+ * peers. Both need the codec; only the first needs a bound port. `init()`
125
+ * did both, so a client-only use had to either bind a port it does not serve
126
+ * on — the port it means to *dial*, which is already taken — or reach into
127
+ * `protoroot`, which is what the spec did before step 14's M6.
128
+ */
129
+ async loadProtobuf() {
51
130
  this.protoroot = await protobuf.load(`${__dirname}/protobuf/command.proto`);
131
+ }
132
+ async init() {
133
+ await this.loadProtobuf();
52
134
  await this.serve();
53
135
  this.listen();
54
136
  }
55
137
  async serve() {
56
- this.server = new Reply();
138
+ this.server = new zeromq_1.Reply();
57
139
  await this.server.bind(`tcp://*:${this.node.config.ports.command}`);
58
140
  }
59
141
  /**
@@ -61,25 +143,37 @@ class ClusterCommand {
61
143
  * Do NOT await this method, it's meant to run indefinitely until the close()
62
144
  * method is invoked.
63
145
  * This method can (and should) never return a rejected promise.
64
- *
65
- * @returns {void}
66
146
  */
67
147
  async listen() {
68
148
  this.state = stateEnum.RUNNING;
69
149
  while (this.state === stateEnum.RUNNING) {
70
150
  try {
71
151
  const [type, data] = await this.server.receive();
72
- switch (type.toString()) {
73
- case topicEnum.FULLSTATE:
152
+ // A REQ frame carries a topic and, for a handshake, a payload. A
153
+ // request missing either is answered with DISCARDED, which is what
154
+ // this socket owes every REQ — the two frames were read unchecked.
155
+ switch (type?.toString()) {
156
+ case commandMessages_1.commandTopic.FULLSTATE:
74
157
  await this.sendFullState();
75
158
  break;
76
- case topicEnum.HANDSHAKE:
159
+ case commandMessages_1.commandTopic.HANDSHAKE:
160
+ if (data === undefined) {
161
+ await this.server.send([commandMessages_1.commandTopic.DISCARDED, null]);
162
+ break;
163
+ }
77
164
  await this.handleHandshake(data);
78
165
  break;
166
+ case commandMessages_1.commandTopic.RETRANSMIT:
167
+ if (data === undefined) {
168
+ await this.server.send([commandMessages_1.commandTopic.DISCARDED, null]);
169
+ break;
170
+ }
171
+ await this.handleRetransmit(data);
172
+ break;
79
173
  default:
80
174
  // REP/REQ sockets expect a reply to each request made, so we have
81
175
  // to send some kind of response on an invalid request received
82
- await this.server.send([topicEnum.DISCARDED, null]);
176
+ await this.server.send([commandMessages_1.commandTopic.DISCARDED, null]);
83
177
  }
84
178
  }
85
179
  catch (e) {
@@ -91,72 +185,153 @@ class ClusterCommand {
91
185
  }
92
186
  /**
93
187
  * Closes opened sockets and marks this server as closed.
94
- * @return {void}
95
188
  */
96
189
  dispose() {
97
190
  this.state = stateEnum.CLOSED;
98
- this.server.close();
191
+ // `?.`: a command that never bound has nothing to close, and disposing of
192
+ // one is what the specs do to release the port after a failed init.
193
+ this._server?.close();
99
194
  }
100
195
  /**
101
196
  * Sends back the full state to the requesting node
102
- * @return {void}
103
197
  */
104
198
  async sendFullState() {
105
- const fullState = this.node.fullState.serialize();
106
- fullState.activity = this.node.activity;
107
- fullState.nodesState = [];
199
+ const serialized = this.node.fullState.serialize();
200
+ const nodesState = [];
108
201
  for (const [id, subscriber] of this.node.remoteNodes.entries()) {
109
- fullState.nodesState.push({
110
- id,
111
- lastMessageId: subscriber.lastMessageId,
112
- });
202
+ nodesState.push({ id, lastMessageId: subscriber.lastMessageId });
113
203
  }
114
- fullState.nodesState.push({
204
+ nodesState.push({
115
205
  id: this.node.nodeId,
116
206
  lastMessageId: this.node.publisher.lastMessageId,
117
207
  });
208
+ const fullState = {
209
+ activity: this.node.activity,
210
+ authStrategies: serialized.authStrategies,
211
+ nodesState,
212
+ rooms: serialized.rooms,
213
+ };
118
214
  const protoEncode = this.protoroot.lookupType("FullStateResponse");
119
215
  const buffer = protoEncode.encode(protoEncode.create(fullState)).finish();
120
- await this.server.send([topicEnum.FULLSTATE, buffer]);
216
+ await this.server.send([commandMessages_1.commandTopic.FULLSTATE, buffer]);
121
217
  }
122
218
  /**
123
219
  * Handles a handshake request from a remote node
124
- * @return {void}
125
220
  */
126
221
  async handleHandshake(data) {
127
222
  const decoder = this.protoroot.lookupType("HandshakeRequest");
128
- const { nodeId, ip, lastMessageId } = decoder.toObject(decoder.decode(data));
129
- const added = await this.node.addNode(nodeId, ip, lastMessageId);
223
+ // Annotated, not asserted: `toObject()` returns an index-signature object,
224
+ // so the schema type is a declaration of what the wire carries rather than
225
+ // a claim overriding the compiler. Same shape as `subscriber.ts`.
226
+ const request = decoder.toObject(decoder.decode(data));
227
+ const { nodeId, ip, lastMessageId } = request;
228
+ // Protobuf leaves an absent field undefined. A handshake that names no
229
+ // node or no address is not one this node can add; it is told so through
230
+ // the `added: false` the response already carries for a duplicate.
231
+ const added = nodeId === undefined || ip === undefined || lastMessageId === undefined
232
+ ? false
233
+ : await this.node.addNode(nodeId, ip, lastMessageId);
130
234
  const encoder = this.protoroot.lookupType("HandshakeResponse");
131
235
  const response = {
132
236
  added,
133
237
  lastMessageId: this.node.publisher.lastMessageId,
134
238
  };
135
239
  const buffer = encoder.encode(encoder.create(response)).finish();
136
- await this.server.send([topicEnum.HANDSHAKE, buffer]);
240
+ await this.server.send([commandMessages_1.commandTopic.HANDSHAKE, buffer]);
241
+ }
242
+ /**
243
+ * Answers a peer that missed messages of this node's sync stream with those
244
+ * messages, as they were published — or with DISCARDED when they are no
245
+ * longer kept, which the peer treats as it treats a node that predates
246
+ * retransmission: it evicts itself (#2785).
247
+ */
248
+ async handleRetransmit(data) {
249
+ const decoder = this.protoroot.lookupType("RetransmitRequest");
250
+ const request = decoder.toObject(decoder.decode(data));
251
+ const frames = request.from === undefined || request.to === undefined
252
+ ? null
253
+ : this.node.publisher.replay(long_1.default.fromValue(request.from), long_1.default.fromValue(request.to));
254
+ if (frames === null) {
255
+ await this.server.send([commandMessages_1.commandTopic.DISCARDED, null]);
256
+ return;
257
+ }
258
+ const encoder = this.protoroot.lookupType("RetransmitResponse");
259
+ const response = { frames };
260
+ const buffer = encoder.encode(encoder.create(response)).finish();
261
+ await this.server.send([commandMessages_1.commandTopic.RETRANSMIT, buffer]);
262
+ }
263
+ /**
264
+ * Asks the node at `ip` for the messages of its sync stream with ids `from`
265
+ * to `to`, both included.
266
+ *
267
+ * @returns the messages in order, as `[topic, data]` frames, or `null` if
268
+ * the node could not provide all of them: it no longer keeps them,
269
+ * predates retransmission (it answers DISCARDED to an unknown
270
+ * topic), or did not answer within `cluster.syncTimeout`.
271
+ */
272
+ async requestRetransmit(ip, from, to) {
273
+ const encoder = this.protoroot.lookupType("RetransmitRequest");
274
+ const payload = { from, to };
275
+ const encoded = encoder.encode(encoder.create(payload)).finish();
276
+ const req = new zeromq_1.Request();
277
+ req.receiveTimeout = this.node.config.syncTimeout;
278
+ req.connect(`tcp://${ip}:${this.node.config.ports.command}`);
279
+ let topic;
280
+ let response;
281
+ try {
282
+ await req.send([commandMessages_1.commandTopic.RETRANSMIT, encoded]);
283
+ [topic, response] = await req.receive();
284
+ }
285
+ catch {
286
+ return null;
287
+ }
288
+ finally {
289
+ req.close();
290
+ }
291
+ if (topic?.toString() !== commandMessages_1.commandTopic.RETRANSMIT || !response) {
292
+ return null;
293
+ }
294
+ const decoder = this.protoroot.lookupType("RetransmitResponse");
295
+ const decoded = decoder.toObject(decoder.decode(response));
296
+ const frames = decoded.frames ?? [];
297
+ // All of them or nothing: a partial answer cannot close the gap.
298
+ if (frames.length !== to.subtract(from).toNumber() + 1) {
299
+ return null;
300
+ }
301
+ return frames.map(({ data, topic: frameTopic }) => [
302
+ frameTopic,
303
+ Buffer.from(data),
304
+ ]);
137
305
  }
138
306
  /**
139
307
  * Request the full state from ONE of the remote nodes of the cluster, AT
140
308
  * RANDOM (necessary to make sure we distribute the full state serialization
141
309
  * load across all nodes)
142
310
  *
143
- * @param {Array.<IdCard>} nodes
144
- * @return {Object|null} Returns the fetched full state, or null if no node answered
311
+ * @returns the fetched full state, or null if no node answered
145
312
  */
146
313
  async getFullState(nodes) {
147
- let idx = Math.floor(Math.random() * Math.floor(nodes.length));
314
+ // NOSONAR (S2245): this picks which peer to ask for the full state, and the
315
+ // point is only to spread the serialization cost over the cluster instead
316
+ // of always loading the same node. Nothing here is a secret, a token or an
317
+ // identifier — a predictable choice would cost performance, not security.
318
+ let idx = Math.floor(Math.random() * Math.floor(nodes.length)); // NOSONAR
148
319
  let fullState = null;
149
320
  for (let retries = 0; fullState === null && retries < nodes.length; retries++) {
150
- const { id, ip } = nodes[idx];
151
- const req = new Request();
321
+ const node = nodes[idx];
322
+ if (node === undefined) {
323
+ break;
324
+ }
325
+ const { id, ip } = node;
326
+ const req = new zeromq_1.Request();
152
327
  req.receiveTimeout = this.node.config.syncTimeout;
153
328
  req.connect(`tcp://${ip}:${this.node.config.ports.command}`);
154
329
  // No payload message for a full state request
155
- await req.send([topicEnum.FULLSTATE, null]);
330
+ await req.send([commandMessages_1.commandTopic.FULLSTATE, null]);
156
331
  try {
157
- [, fullState] = await req.receive();
332
+ [, fullState = null] = await req.receive();
158
333
  }
159
- catch (e) {
334
+ catch {
160
335
  // no response from the remote node in a timely fashion... retrying
161
336
  // with another one
162
337
  this.logger.warn(`Unable to fetch a full state from node ${id} (no response received)`);
@@ -170,19 +345,14 @@ class ClusterCommand {
170
345
  return null;
171
346
  }
172
347
  const decoder = this.protoroot.lookupType("FullStateResponse");
173
- return decoder.toObject(decoder.decode(fullState));
348
+ const decoded = decoder.toObject(decoder.decode(fullState));
349
+ return decoded;
174
350
  }
175
351
  /**
176
352
  * Sends a handshake request to other remote nodes and process their response
177
- * Returns an object with the following structure:
178
- *
179
- * {
180
- * [nodeId]: { added: <boolean>, lastMessageId: <number> },
181
- * [nodeId]: null, // no response received, node is probably dead
182
- * }
183
353
  *
184
- * @param {Array.<IdCard>} nodes
185
- * @return {Object}
354
+ * @returns one entry per node: its decoded response, or `null` if it never
355
+ * answered (the node is probably dead)
186
356
  */
187
357
  async broadcastHandshake(nodes) {
188
358
  const payload = {
@@ -192,38 +362,40 @@ class ClusterCommand {
192
362
  };
193
363
  const encoder = this.protoroot.lookupType("HandshakeRequest");
194
364
  const encoded = encoder.encode(encoder.create(payload)).finish();
195
- const responses = await Bluebird.map(nodes, ({ id, ip }) => this._sendSingleHandshake(id, ip, encoded));
365
+ const responses = await bluebird_1.default.map(nodes, ({ id, ip }) => this._sendSingleHandshake(id, ip, encoded));
196
366
  const decoder = this.protoroot.lookupType("HandshakeResponse");
197
367
  const result = {};
198
- for (let i = 0; i < nodes.length; i++) {
199
- if (responses[i] === null) {
200
- result[nodes[i].id] = null;
201
- }
202
- else {
203
- result[nodes[i].id] = decoder.toObject(decoder.decode(responses[i]));
368
+ // `entries()`: the two lists are built in step by `Bluebird.map`, which
369
+ // is what indexing one with the other's counter relied on.
370
+ for (const [i, node] of nodes.entries()) {
371
+ const response = responses[i];
372
+ if (response === null || response === undefined) {
373
+ result[node.id] = null;
374
+ continue;
204
375
  }
376
+ const decoded = decoder.toObject(decoder.decode(response));
377
+ result[node.id] = decoded;
205
378
  }
206
379
  return result;
207
380
  }
208
381
  /**
209
382
  * Sends a handshake payload to a remote node, and waits for its response
210
383
  *
211
- * @param {string} id - remote node ID
212
- * @param {string} ip - remote node IP address
213
- * @param {Buffer} payload - handshake payload (protobuf encoded)
214
- * @return {Object|null} - handshake encoded response, or null if no
215
- * response was received
384
+ * @param id remote node ID
385
+ * @param ip remote node IP address
386
+ * @param payload handshake payload (protobuf encoded)
387
+ * @returns the handshake encoded response, or null if none was received
216
388
  */
217
389
  async _sendSingleHandshake(id, ip, payload) {
218
- const req = new Request();
390
+ const req = new zeromq_1.Request();
219
391
  req.receiveTimeout = 2000;
220
392
  req.connect(`tcp://${ip}:${this.node.config.ports.command}`);
221
- await req.send([topicEnum.HANDSHAKE, payload]);
393
+ await req.send([commandMessages_1.commandTopic.HANDSHAKE, payload]);
222
394
  let response = null;
223
395
  try {
224
- [, response] = await req.receive();
396
+ [, response = null] = await req.receive();
225
397
  }
226
- catch (e) {
398
+ catch {
227
399
  this.logger.warn(`Couldn't complete handshake with node ${id}: no response received`);
228
400
  }
229
401
  finally {
@@ -13,15 +13,17 @@ export declare class IdCard {
13
13
  *
14
14
  * knode-pensive-einstein-844221
15
15
  */
16
- private id;
16
+ /** Read by `node.ts` (consistency checks, status, logs): the class never
17
+ * reassigns it after construction, and nothing outside writes it. */
18
+ readonly id: string;
17
19
  /**
18
20
  * Node IP address
19
21
  */
20
- private ip;
22
+ readonly ip: string;
21
23
  /**
22
24
  * Node creation timestamp
23
25
  */
24
- private birthdate;
26
+ readonly birthdate: number;
25
27
  /**
26
28
  * Node known topology composed of node IDs
27
29
  *
@@ -43,7 +45,7 @@ export declare class ClusterIdCardHandler {
43
45
  /**
44
46
  * Local node ID Card
45
47
  */
46
- idCard: IdCard;
48
+ idCard: IdCard | null;
47
49
  /**
48
50
  * Local node IP address
49
51
  */
@@ -69,7 +71,8 @@ export declare class ClusterIdCardHandler {
69
71
  /**
70
72
  * Local node ID
71
73
  */
72
- private nodeId;
74
+ /** Read by `node.ts` once `createIdCard()` has reserved it. */
75
+ nodeId: string | null;
73
76
  /**
74
77
  * Local node Redis key
75
78
  */
@@ -86,6 +89,16 @@ export declare class ClusterIdCardHandler {
86
89
  /**
87
90
  * Generates and reserves a unique ID for this node instance.
88
91
  * Makes sure that the ID is not already taken by another node instance.
92
+ *
93
+ * The first candidate is `global.nodeId` — the id the rest of the process
94
+ * logs under. It used to draw its own from the same generator with the same
95
+ * `knode` prefix, so every node carried two indistinguishable identities and
96
+ * no cluster log line could be matched to a process (TD-59, #2764).
97
+ *
98
+ * The loop stays: `global.nodeId` is itself a random draw, but a stale IdCard
99
+ * left in Redis by a crashed incarnation can still hold the key, and Kuzzle
100
+ * can run without a `Backend`, in which case there is no `global.nodeId` at
101
+ * all. Either way the next turn draws a fresh name, exactly as before.
89
102
  */
90
103
  createIdCard(): Promise<void>;
91
104
  /**
@@ -25,7 +25,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.ClusterIdCardHandler = exports.IdCard = void 0;
27
27
  const name_generator_1 = require("../util/name-generator");
28
- const child_process_1 = require("child_process");
28
+ const node_child_process_1 = require("node:child_process");
29
+ const node_path_1 = require("node:path");
29
30
  const bluebird_1 = __importDefault(require("bluebird"));
30
31
  require("../types");
31
32
  const REDIS_PREFIX = "{cluster/node}/";
@@ -75,6 +76,7 @@ class ClusterIdCardHandler {
75
76
  /**
76
77
  * Local node ID
77
78
  */
79
+ /** Read by `node.ts` once `createIdCard()` has reserved it. */
78
80
  this.nodeId = null;
79
81
  /**
80
82
  * Local node Redis key
@@ -95,11 +97,26 @@ class ClusterIdCardHandler {
95
97
  /**
96
98
  * Generates and reserves a unique ID for this node instance.
97
99
  * Makes sure that the ID is not already taken by another node instance.
100
+ *
101
+ * The first candidate is `global.nodeId` — the id the rest of the process
102
+ * logs under. It used to draw its own from the same generator with the same
103
+ * `knode` prefix, so every node carried two indistinguishable identities and
104
+ * no cluster log line could be matched to a process (TD-59, #2764).
105
+ *
106
+ * The loop stays: `global.nodeId` is itself a random draw, but a stale IdCard
107
+ * left in Redis by a crashed incarnation can still hold the key, and Kuzzle
108
+ * can run without a `Backend`, in which case there is no `global.nodeId` at
109
+ * all. Either way the next turn draws a fresh name, exactly as before.
98
110
  */
99
111
  async createIdCard() {
100
- let reserved = false;
112
+ let reserved;
113
+ // `undefined` after the first turn, which is what makes the `??` below
114
+ // fall through to a fresh draw — so the declaration has to admit it.
115
+ let candidate = global.nodeId;
101
116
  do {
102
- this.nodeId = name_generator_1.NameGenerator.generateRandomName({ prefix: "knode" });
117
+ this.nodeId =
118
+ candidate ?? name_generator_1.NameGenerator.generateRandomName({ prefix: "knode" });
119
+ candidate = undefined;
103
120
  this.nodeIdKey = `${REDIS_PREFIX}${this.nodeId}`;
104
121
  this.idCard = new IdCard({
105
122
  birthdate: Date.now(),
@@ -110,20 +127,30 @@ class ClusterIdCardHandler {
110
127
  reserved = await this.save({ creation: true });
111
128
  } while (!reserved);
112
129
  await this.addIdCardToIndex();
113
- this.refreshWorker = this.constructWorker(`${__dirname}/workers/IDCardRenewer.js`);
114
- this.refreshWorker.on("message", async (message) => {
130
+ // Same extension as this module, not a hard-coded `.js`: the functional
131
+ // cluster starts Kuzzle from source with `-r ts-node/register`, where this
132
+ // file is `lib/cluster/idCardHandler.ts` and its neighbour is a `.ts` too;
133
+ // a built Kuzzle runs the same code from `dist/` with both as `.js`.
134
+ // `fork()` inherits `process.execArgv`, so a child spawned from a `.ts`
135
+ // parent gets the same loader and can require a `.ts`.
136
+ // Held in a local as well as on `this`: the field is nullable (it has no
137
+ // worker before this line) and the compiler drops that narrowing across the
138
+ // callbacks registered below.
139
+ const refreshWorker = this.constructWorker(`${__dirname}/workers/IDCardRenewer${(0, node_path_1.extname)(__filename)}`);
140
+ this.refreshWorker = refreshWorker;
141
+ refreshWorker.on("message", async (message) => {
115
142
  if (message.error) {
116
143
  await this.node.evictSelf(message.error);
117
144
  }
118
145
  });
119
- this.refreshWorker.on("close", async () => {
146
+ refreshWorker.on("close", async () => {
120
147
  if (!this.disposed) {
121
148
  this.disposed = true;
122
149
  await this.node.evictSelf("ID Card renewer worker closed unexpectedly");
123
150
  }
124
151
  });
125
152
  // Transfer informations to the worker
126
- this.refreshWorker.send({
153
+ refreshWorker.send({
127
154
  action: "start", // start the worker
128
155
  kuzzle: {
129
156
  config: global.kuzzle.config,
@@ -138,19 +165,19 @@ class ClusterIdCardHandler {
138
165
  refreshDelay: this.refreshDelay,
139
166
  refreshMultiplier: this.refreshMultiplier,
140
167
  });
141
- this.startTemporaryRefresh();
168
+ this.startTemporaryRefresh(refreshWorker);
142
169
  }
143
170
  /**
144
171
  * Helper method to mock worker instantiation in unit tests
145
172
  */
146
173
  constructWorker(path) {
147
- const childProcess = (0, child_process_1.fork)(path);
174
+ const childProcess = (0, node_child_process_1.fork)(path);
148
175
  const exitHandler = () => {
149
176
  if (!childProcess.killed || childProcess.connected) {
150
177
  try {
151
178
  childProcess.disconnect();
152
179
  }
153
- catch (e) {
180
+ catch {
154
181
  // It could happens that the worker has been killed before the dispose causing disconnect to fail
155
182
  }
156
183
  }
@@ -166,7 +193,7 @@ class ClusterIdCardHandler {
166
193
  *
167
194
  * Once the worker starts, this timer will be stopped.
168
195
  */
169
- startTemporaryRefresh() {
196
+ startTemporaryRefresh(refreshWorker) {
170
197
  this.refreshTimer = setInterval(async () => {
171
198
  try {
172
199
  await this.save();
@@ -175,7 +202,10 @@ class ClusterIdCardHandler {
175
202
  this.logger.error(`An error occurred while refreshing the ID card during WorkerThread startup: ${error}`);
176
203
  }
177
204
  }, this.refreshDelay * this.refreshMultiplier);
178
- this.refreshWorker.on("message", ({ initialized }) => {
205
+ // Handed the worker rather than reading `this.refreshWorker`, for the
206
+ // reason already stated where that field is assigned: it is nullable, and
207
+ // this method runs on the line after it is filled.
208
+ refreshWorker.on("message", ({ initialized }) => {
179
209
  if (initialized) {
180
210
  clearInterval(this.refreshTimer);
181
211
  this.refreshTimer = null;
@@ -194,7 +224,7 @@ class ClusterIdCardHandler {
194
224
  try {
195
225
  this.refreshWorker.send({ action: "dispose" });
196
226
  }
197
- catch (e) {
227
+ catch {
198
228
  // It could happens that the worker has been killed before the dispose causing send to fail
199
229
  }
200
230
  }
@@ -225,14 +255,17 @@ class ClusterIdCardHandler {
225
255
  }
226
256
  const rawIdCards = await global.kuzzle.ask("core:cache:internal:mget", keys);
227
257
  const expiredIdCards = [];
228
- for (let i = 0; i < keys.length; i++) {
258
+ // `entries()` over the keys: `rawIdCards` is the answer to a mget over
259
+ // exactly these keys, so the pair is what the loop is really walking.
260
+ for (const [i, key] of keys.entries()) {
229
261
  // filter keys that might have expired between the key search and their
230
262
  // values retrieval
231
- if (rawIdCards[i] !== null) {
232
- idCards.push(IdCard.unserialize(JSON.parse(rawIdCards[i])));
263
+ const raw = rawIdCards[i];
264
+ if (raw !== null && raw !== undefined) {
265
+ idCards.push(IdCard.unserialize(JSON.parse(raw)));
233
266
  }
234
267
  else {
235
- expiredIdCards.push(keys[i]);
268
+ expiredIdCards.push(key);
236
269
  }
237
270
  }
238
271
  // Clean expired ID Card's keys in the index
@@ -245,7 +278,7 @@ class ClusterIdCardHandler {
245
278
  * Adds a remote node IdCard to the node known topology
246
279
  */
247
280
  async addNode(id) {
248
- if (this.disposed || this.idCard.topology.has(id)) {
281
+ if (this.disposed || this.idCard === null || this.idCard.topology.has(id)) {
249
282
  return;
250
283
  }
251
284
  this.idCard.topology.add(id);
@@ -255,7 +288,7 @@ class ClusterIdCardHandler {
255
288
  * Removes a remote node IdCard from the node known topology
256
289
  */
257
290
  async removeNode(id) {
258
- if (!this.disposed && this.idCard.topology.delete(id)) {
291
+ if (!this.disposed && this.idCard?.topology.delete(id)) {
259
292
  await this.save();
260
293
  }
261
294
  }