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,30 +19,77 @@
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 assert = require("assert");
23
- const path = require("path");
24
- const fs = require("fs");
25
- const Bluebird = require("bluebird");
26
- const _ = require("lodash");
27
- const kerror = require("../../kerror");
28
- const didYouMean = require("../../util/didYouMean");
29
- const { Inflector } = require("../../util/Inflector");
30
- const debug = require("../../util/debug")("kuzzle:plugins");
31
- const { KuzzleError } = require("../../kerror/errors");
32
- const { has, get, isPlainObject } = require("../../util/safeObject");
33
- const { BaseController } = require("../../api/controllers/baseController");
34
- const Plugin = require("./plugin");
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 node_assert_1 = __importDefault(require("node:assert"));
49
+ const node_fs_1 = __importDefault(require("node:fs"));
50
+ const node_path_1 = __importDefault(require("node:path"));
51
+ const bluebird_1 = __importDefault(require("bluebird"));
52
+ const lodash_1 = require("lodash");
53
+ const baseController_1 = require("../../api/controllers/baseController");
54
+ const kerror = __importStar(require("../../kerror"));
55
+ const errors_1 = require("../../kerror/errors");
56
+ const debug_1 = __importDefault(require("../../util/debug"));
57
+ const didYouMean_1 = __importDefault(require("../../util/didYouMean"));
58
+ const Inflector_1 = require("../../util/Inflector");
59
+ const safeObject_1 = require("../../util/safeObject");
60
+ const thrown_1 = require("../../util/thrown");
61
+ const plugin_1 = __importDefault(require("./plugin"));
62
+ const debug = (0, debug_1.default)("kuzzle:plugins");
35
63
  const assertionError = kerror.wrap("plugin", "assert");
36
64
  const runtimeError = kerror.wrap("plugin", "runtime");
37
65
  const strategyError = kerror.wrap("plugin", "strategy");
38
66
  const controllerError = kerror.wrap("plugin", "controller");
39
67
  // Without those plugins, Kuzzle won't start at all.
40
- const CORE_PLUGINS = ["kuzzle-plugin-auth-passport-local"];
68
+ const CORE_PLUGINS = new Set(["kuzzle-plugin-auth-passport-local"]);
41
69
  /**
42
- * @class PluginsManager
43
- * @param {Kuzzle} kuzzle
70
+ * The `id` of whatever was thrown, when it carries one.
44
71
  */
72
+ function idOf(thrown) {
73
+ if (typeof thrown === "object" &&
74
+ thrown !== null &&
75
+ "id" in thrown &&
76
+ typeof thrown.id === "string") {
77
+ return thrown.id;
78
+ }
79
+ return undefined;
80
+ }
81
+ /**
82
+ * Whatever was thrown, as the `KuzzleError` the caller is about to forward.
83
+ * A plugin's own KuzzleError passes through untouched — that is the contract
84
+ * these two handlers have always honoured.
85
+ */
86
+ function asKuzzleError(thrown) {
87
+ if (thrown instanceof errors_1.KuzzleError) {
88
+ return thrown;
89
+ }
90
+ const cause = (0, thrown_1.causeOf)(thrown);
91
+ return runtimeError.getFrom(cause, "unexpected_error", cause.message);
92
+ }
45
93
  class PluginsManager {
46
94
  constructor() {
47
95
  Reflect.defineProperty(this, "kuzzle", {
@@ -52,8 +100,8 @@ class PluginsManager {
52
100
  this.controllers = new Map();
53
101
  this.strategies = {};
54
102
  this.routes = [];
55
- this.pluginsEnabledDir = path.resolve(path.join(global.kuzzle.rootPath, "plugins", "enabled"));
56
- this.pluginsAvailableDir = path.resolve(path.join(global.kuzzle.rootPath, "plugins", "available"));
103
+ this.pluginsEnabledDir = node_path_1.default.resolve(node_path_1.default.join(global.kuzzle.rootPath, "plugins", "enabled"));
104
+ this.pluginsAvailableDir = node_path_1.default.resolve(node_path_1.default.join(global.kuzzle.rootPath, "plugins", "available"));
57
105
  /**
58
106
  * @example
59
107
  * {
@@ -80,16 +128,53 @@ class PluginsManager {
80
128
  this.loadedPlugins = [];
81
129
  }
82
130
  set application(plugin) {
83
- assert(this._plugins.size === 0, "The application plugin can only be set before every other plugins are loaded");
84
- assert(plugin.application, 'The application plugin must have the "application" property equals to true');
131
+ (0, node_assert_1.default)(this._plugins.size === 0, "The application plugin can only be set before every other plugins are loaded");
132
+ (0, node_assert_1.default)(plugin.application, 'The application plugin must have the "application" property equals to true');
85
133
  this._plugins.set(plugin.name, plugin);
86
134
  }
87
135
  get plugins() {
88
136
  return Array.from(this._plugins.values()).filter((plugin) => !plugin.application);
89
137
  }
138
+ /**
139
+ * The application plugin, once `kuzzle.start` has registered one.
140
+ *
141
+ * `undefined` before that, and the shutdown path already read it that way —
142
+ * `pluginsManager?.application?.instance?.log?.flush?.()` defends against a
143
+ * start that failed before the assignment. The declared `Plugin` was the
144
+ * half of that the three eager readers assumed.
145
+ */
90
146
  get application() {
91
147
  return Array.from(this._plugins.values()).find((plugin) => plugin.application);
92
148
  }
149
+ /**
150
+ * The plugin registered under `pluginName`, which is the only thing the
151
+ * strategy methods below can act on. Pre-Kaaf plugin names may carry upper
152
+ * case, hence the lowercasing every call site did for itself.
153
+ *
154
+ * The three callers dereferenced the map's answer unchecked — a strategy
155
+ * registered for an unknown plugin read `undefined.initCalled`. The error
156
+ * is the one `Backend.plugin.get` already raises for the same question.
157
+ */
158
+ getPlugin(pluginName) {
159
+ const plugin = this._plugins.get(pluginName.toLowerCase());
160
+ if (plugin === undefined) {
161
+ throw assertionError.get("plugin_not_found", pluginName, (0, didYouMean_1.default)(pluginName, Array.from(this._plugins.keys())));
162
+ }
163
+ return plugin;
164
+ }
165
+ /**
166
+ * The strategy registered under `strategyName`. Reading it off the record
167
+ * and dereferencing straight away is what `getStrategyFields` and
168
+ * `getStrategyMethod` did; `hasStrategyMethod` is the guard that existed,
169
+ * and only one of the two call sites used it.
170
+ */
171
+ getStrategy(strategyName) {
172
+ const strategy = this.strategies[strategyName];
173
+ if (strategy === undefined) {
174
+ throw strategyError.get("strategy_not_found", strategyName);
175
+ }
176
+ return strategy;
177
+ }
93
178
  /**
94
179
  * Giving a controller name, tells if exists
95
180
  *
@@ -116,7 +201,11 @@ class PluginsManager {
116
201
  * @returns {Array}
117
202
  */
118
203
  getActions(controller) {
119
- return Array.from(this.controllers.get(controller)._actions);
204
+ const registered = this.controllers.get(controller);
205
+ // An unregistered controller has no actions. Reading `._actions` off the
206
+ // map's answer raised a TypeError instead, which is what `isAction`
207
+ // answered for a controller `isController` says does not exist.
208
+ return registered === undefined ? [] : Array.from(registered._actions);
120
209
  }
121
210
  /**
122
211
  * Returns an array filled with controller names
@@ -167,8 +256,7 @@ class PluginsManager {
167
256
  const loadPlugins = [];
168
257
  const defaultImports = {};
169
258
  for (const plugin of this._plugins.values()) {
170
- if (this.config.common.failsafeMode &&
171
- !CORE_PLUGINS.includes(plugin.name)) {
259
+ if (this.config.common.failsafeMode && !CORE_PLUGINS.has(plugin.name)) {
172
260
  this.logger.info(`Failsafe mode activated, skipping plugin "${plugin.name}"`);
173
261
  continue;
174
262
  }
@@ -177,9 +265,17 @@ class PluginsManager {
177
265
  }
178
266
  const { initTimeout } = this.config.common;
179
267
  debug('[%s] starting plugin in "%s" mode', plugin.name, plugin.config.privileged ? "privileged" : "standard");
180
- const promise = Bluebird.resolve((async () => {
268
+ const { init } = plugin.instance;
269
+ // Both loaders — `loadPlugins` here and `Backend.plugin.use` — refuse a
270
+ // plugin without one, so this is the third statement of the same
271
+ // precondition rather than a new one. It is the type of `init` on a
272
+ // user-supplied object that makes it appear.
273
+ if (!isPluginMethod(init)) {
274
+ throw assertionError.get("init_not_found", plugin.name);
275
+ }
276
+ const promise = bluebird_1.default.resolve((async () => {
181
277
  try {
182
- await plugin.instance.init(plugin.config, plugin.context);
278
+ await init.call(plugin.instance, plugin.config, plugin.context);
183
279
  }
184
280
  catch (error) {
185
281
  throw runtimeError.get("failed_init", plugin.name, error);
@@ -188,34 +284,34 @@ class PluginsManager {
188
284
  .timeout(initTimeout, `${plugin.logPrefix} Initialization timed out after ${initTimeout}ms. Try to increase the configuration "plugins.common.initTimeout".`)
189
285
  .then(async () => {
190
286
  plugin.initCalled = true;
191
- if (!_.isEmpty(plugin.instance.controllers) &&
192
- !_.isEmpty(plugin.instance.api)) {
287
+ if (!(0, lodash_1.isEmpty)(plugin.instance.controllers) &&
288
+ !(0, lodash_1.isEmpty)(plugin.instance.api)) {
193
289
  throw assertionError.get("duplicated_api_definition");
194
290
  }
195
- if (!_.isEmpty(plugin.instance.controllers)) {
291
+ if (!(0, lodash_1.isEmpty)(plugin.instance.controllers)) {
196
292
  this._initControllers(plugin);
197
293
  }
198
- if (!_.isEmpty(plugin.instance.api)) {
294
+ if (!(0, lodash_1.isEmpty)(plugin.instance.api)) {
199
295
  await this._initApi(plugin);
200
296
  }
201
- if (!_.isEmpty(plugin.instance.authenticators)) {
297
+ if (!(0, lodash_1.isEmpty)(plugin.instance.authenticators)) {
202
298
  this._initAuthenticators(plugin);
203
299
  }
204
- if (!_.isEmpty(plugin.instance.strategies)) {
300
+ if (!(0, lodash_1.isEmpty)(plugin.instance.strategies)) {
205
301
  this._initStrategies(plugin);
206
302
  }
207
- if (!_.isEmpty(plugin.instance.hooks)) {
303
+ if (!(0, lodash_1.isEmpty)(plugin.instance.hooks)) {
208
304
  this._initHooks(plugin);
209
305
  }
210
- if (!_.isEmpty(plugin.instance.pipes)) {
306
+ if (!(0, lodash_1.isEmpty)(plugin.instance.pipes)) {
211
307
  this._initPipes(plugin);
212
308
  }
213
309
  debug("[%s] plugin started", plugin.name);
214
310
  if (!plugin.application) {
215
311
  this.loadedPlugins.push(plugin.name);
216
312
  }
217
- if (!_.isEmpty(plugin.instance.imports)) {
218
- _.merge(defaultImports, plugin.instance.imports);
313
+ if (!(0, lodash_1.isEmpty)(plugin.instance.imports)) {
314
+ (0, lodash_1.merge)(defaultImports, plugin.instance.imports);
219
315
  }
220
316
  return null;
221
317
  });
@@ -230,7 +326,7 @@ class PluginsManager {
230
326
  * @returns {string[]}
231
327
  */
232
328
  getStrategyFields(strategyName) {
233
- return this.strategies[strategyName].strategy.config.fields || [];
329
+ return this.getStrategy(strategyName).strategy.config.fields || [];
234
330
  }
235
331
  /**
236
332
  * @param {string} strategyName
@@ -238,8 +334,10 @@ class PluginsManager {
238
334
  * @returns {boolean}
239
335
  */
240
336
  hasStrategyMethod(strategyName, methodName) {
241
- const strategy = get(this.strategies, strategyName);
242
- return strategy && has(strategy.methods, methodName);
337
+ const strategy = (0, safeObject_1.has)(this.strategies, strategyName)
338
+ ? this.strategies[strategyName]
339
+ : undefined;
340
+ return strategy !== undefined && (0, safeObject_1.has)(strategy.methods, methodName);
243
341
  }
244
342
  /**
245
343
  * @param {string} strategyName
@@ -247,7 +345,7 @@ class PluginsManager {
247
345
  * @returns {function}
248
346
  */
249
347
  getStrategyMethod(strategyName, methodName) {
250
- return this.strategies[strategyName].methods[methodName];
348
+ return this.getStrategy(strategyName).methods[methodName];
251
349
  }
252
350
  /**
253
351
  * Returns the list of registered passport strategies
@@ -266,51 +364,50 @@ class PluginsManager {
266
364
  */
267
365
  validateStrategy(pluginName, strategyName, strategy) {
268
366
  const errorPrefix = `[${pluginName}] Strategy ${strategyName}:`;
269
- if (!isPlainObject(strategy)) {
367
+ if (!(0, safeObject_1.isPlainObject)(strategy)) {
270
368
  throw strategyError.get("invalid_description", errorPrefix, strategy);
271
369
  }
272
- if (!isPlainObject(strategy.methods)) {
370
+ if (!(0, safeObject_1.isPlainObject)(strategy.methods)) {
273
371
  throw strategyError.get("invalid_methods", errorPrefix, strategy.methods);
274
372
  }
275
- const plugin = this._plugins.get(pluginName.toLowerCase());
373
+ const plugin = this.getPlugin(pluginName);
276
374
  // required methods check
277
375
  ["exists", "create", "update", "delete", "validate", "verify"].forEach((methodName) => {
278
- if (!_.isString(strategy.methods[methodName])) {
376
+ if (!(0, lodash_1.isString)(strategy.methods[methodName])) {
279
377
  throw strategyError.get("invalid_method_type", errorPrefix, methodName, strategy.methods[methodName]);
280
378
  }
281
- if (!_.isFunction(plugin.instance[strategy.methods[methodName]])) {
379
+ if (!(0, lodash_1.isFunction)(plugin.instance[strategy.methods[methodName]])) {
282
380
  throw strategyError.get("missing_method_function", errorPrefix, strategy.methods[methodName]);
283
381
  }
284
382
  });
285
383
  // optional methods check
286
384
  ["getInfo", "getById", "afterRegister"].forEach((name) => {
287
385
  const optionalMethodName = strategy.methods[name];
288
- if (!_.isNil(optionalMethodName)) {
289
- if (!_.isString(optionalMethodName)) {
386
+ if (!(0, lodash_1.isNil)(optionalMethodName)) {
387
+ if (!(0, lodash_1.isString)(optionalMethodName)) {
290
388
  throw strategyError.get("invalid_method_type", errorPrefix, name, optionalMethodName);
291
389
  }
292
- if (!_.isFunction(plugin.instance[optionalMethodName])) {
390
+ if (!(0, lodash_1.isFunction)(plugin.instance[optionalMethodName])) {
293
391
  throw strategyError.get("missing_method_function", errorPrefix, optionalMethodName);
294
392
  }
295
393
  }
296
394
  });
297
- if (!isPlainObject(strategy.config)) {
395
+ if (!(0, safeObject_1.isPlainObject)(strategy.config)) {
298
396
  throw strategyError.get("invalid_config", errorPrefix, strategy.config);
299
397
  }
300
398
  if (typeof strategy.config.authenticator !== "string") {
301
399
  throw strategyError.get("invalid_authenticator", errorPrefix, strategy.config.authenticator);
302
400
  }
303
- else if (!this.authenticators[pluginName] ||
304
- !this.authenticators[pluginName][strategy.config.authenticator]) {
401
+ else if (!this.authenticators[pluginName]?.[strategy.config.authenticator]) {
305
402
  throw strategyError.get("unknown_authenticator", errorPrefix, strategy.config.authenticator);
306
403
  }
307
404
  for (const optionName of ["strategyOptions", "authenticateOptions"]) {
308
405
  const options = strategy.config[optionName];
309
- if (!_.isNil(options) && !isPlainObject(options)) {
406
+ if (!(0, lodash_1.isNil)(options) && !(0, safeObject_1.isPlainObject)(options)) {
310
407
  throw strategyError.get("invalid_option", errorPrefix, optionName, options);
311
408
  }
312
409
  }
313
- if (!_.isNil(strategy.config.fields) &&
410
+ if (!(0, lodash_1.isNil)(strategy.config.fields) &&
314
411
  !Array.isArray(strategy.config.fields)) {
315
412
  throw strategyError.get("invalid_fields", errorPrefix, strategy.config.fields);
316
413
  }
@@ -331,11 +428,19 @@ class PluginsManager {
331
428
  ? plugin.config.pipeWarnTime
332
429
  : this.config.common.pipeWarnTime;
333
430
  const wrapper = (...data) => {
334
- const now = warnDelay ? Date.now() : null;
431
+ const startedAt = warnDelay ? Date.now() : null;
335
432
  const callback = data.pop();
433
+ // The pipe runner always calls a registered pipe with a trailing
434
+ // callback — the same narrowing `wrapStrategyVerify` makes, and the
435
+ // same branch that cannot be taken.
436
+ if (!isPluginMethod(callback)) {
437
+ return;
438
+ }
336
439
  const cb = (error, result) => {
337
- if (warnDelay) {
338
- const elapsed = Date.now() - now;
440
+ // `startedAt !== null` is `warnDelay` truthy, said in the form that
441
+ // proves there is a timestamp to subtract.
442
+ if (startedAt !== null) {
443
+ const elapsed = Date.now() - startedAt;
339
444
  if (elapsed > warnDelay) {
340
445
  this.logger.warn(`${plugin.logPrefix} pipe for event '${event}' is slow (${elapsed}ms)`);
341
446
  }
@@ -344,10 +449,7 @@ class PluginsManager {
344
449
  };
345
450
  try {
346
451
  const pipeResponse = data.length === 0 ? handler(null, cb) : handler(...data, cb);
347
- if (typeof pipeResponse === "object" &&
348
- pipeResponse !== null &&
349
- typeof pipeResponse.then === "function" &&
350
- typeof pipeResponse.catch === "function") {
452
+ if (isThenable(pipeResponse)) {
351
453
  pipeResponse
352
454
  .then((result) => {
353
455
  cb(null, result);
@@ -357,9 +459,7 @@ class PluginsManager {
357
459
  }
358
460
  }
359
461
  catch (error) {
360
- cb(error instanceof KuzzleError
361
- ? error
362
- : runtimeError.getFrom(error, "unexpected_error", error.message));
462
+ cb(asKuzzleError(error));
363
463
  }
364
464
  };
365
465
  return global.kuzzle.registerPluginPipe(event, wrapper);
@@ -379,8 +479,7 @@ class PluginsManager {
379
479
  * registration fails
380
480
  */
381
481
  registerStrategy(pluginName, strategyName, strategy) {
382
- // prior to Kaaf, plugin names can contains upper case
383
- const plugin = this._plugins.get(pluginName.toLowerCase());
482
+ const plugin = this.getPlugin(pluginName);
384
483
  // only add the strategy to the strategies object if the init method
385
484
  // has not been called
386
485
  if (!plugin.initCalled) {
@@ -389,7 +488,7 @@ class PluginsManager {
389
488
  return;
390
489
  }
391
490
  this.validateStrategy(plugin.name, strategyName, strategy);
392
- if (has(this.strategies, strategyName)) {
491
+ if ((0, safeObject_1.has)(this.strategies, strategyName)) {
393
492
  this.unregisterStrategy(plugin.name, strategyName);
394
493
  }
395
494
  const methods = {};
@@ -399,14 +498,11 @@ class PluginsManager {
399
498
  for (const methodName of Object.keys(strategy.methods).filter((name) => name !== "verify")) {
400
499
  methods[methodName] = async (...args) => {
401
500
  try {
402
- const boundFunction = plugin.instance[strategy.methods[methodName]].bind(plugin.instance);
501
+ const boundFunction = bindPluginMethod(plugin.instance, strategy.methods[methodName]);
403
502
  return await boundFunction(...args);
404
503
  }
405
504
  catch (error) {
406
- if (error instanceof KuzzleError) {
407
- throw error;
408
- }
409
- throw runtimeError.getFrom(error, "unexpected_error", error.message);
505
+ throw asKuzzleError(error);
410
506
  }
411
507
  };
412
508
  }
@@ -414,7 +510,7 @@ class PluginsManager {
414
510
  ...strategy.config.strategyOptions,
415
511
  passReqToCallback: true,
416
512
  };
417
- const verifyAdapter = this.wrapStrategyVerify(plugin.logPrefix, strategyName, plugin.instance[strategy.methods.verify].bind(plugin.instance));
513
+ const verifyAdapter = this.wrapStrategyVerify(plugin.logPrefix, strategyName, bindPluginMethod(plugin.instance, strategy.methods.verify));
418
514
  try {
419
515
  const Ctor = this.authenticators[plugin.name][strategy.config.authenticator], instance = new Ctor(opts, verifyAdapter);
420
516
  this.strategies[strategyName] = { methods, owner: plugin.name, strategy };
@@ -424,7 +520,8 @@ class PluginsManager {
424
520
  }
425
521
  }
426
522
  catch (e) {
427
- throw strategyError.getFrom(e, "failed_registration", strategyName, e.message);
523
+ const cause = (0, thrown_1.causeOf)(e);
524
+ throw strategyError.getFrom(cause, "failed_registration", strategyName, cause.message);
428
525
  }
429
526
  }
430
527
  /**
@@ -453,90 +550,70 @@ class PluginsManager {
453
550
  */
454
551
  _initPipes(plugin) {
455
552
  const methodsList = getMethods(plugin.instance);
456
- for (const [event, fn] of Object.entries(plugin.instance.pipes)) {
553
+ // `?? {}`: every member of a plugin's object is optional, and `init`
554
+ // guards each of these loops with an `isEmpty` the compiler cannot read.
555
+ for (const [event, fn] of Object.entries(plugin.instance.pipes ?? {})) {
457
556
  const list = Array.isArray(fn) ? fn : [fn];
458
557
  for (const target of list) {
459
- if (typeof target !== "function" &&
460
- typeof plugin.instance[target] !== "function") {
461
- const message = typeof target === "string" ? didYouMean(target, methodsList) : "";
462
- throw assertionError.get("invalid_pipe", event, target, message);
463
- }
464
- let handler = target;
465
- if (typeof target === "string") {
466
- // @deprecated - warn about using a string representing an instance method
467
- plugin.printDeprecation("Defining pipe handler using a string is deprecated. Pass a function instead.");
468
- handler = plugin.instance[target].bind(plugin.instance);
469
- }
470
- // if the function handler is a plugin instance method,
471
- // bound the context to the plugin instance
472
- if (target.name && typeof plugin.instance[target.name] === "function") {
473
- handler = target.bind(plugin.instance);
474
- }
558
+ const handler = this.resolveEventHandler(plugin, event, target, methodsList, "invalid_pipe", "Defining pipe handler using a string is deprecated. Pass a function instead.");
475
559
  this.registerPipe(plugin, event, handler);
476
560
  }
477
561
  }
478
562
  }
563
+ /**
564
+ * Resolves one pipe or hook target — a function, or the name of a plugin
565
+ * method — into the handler to register.
566
+ *
567
+ * Shared by `_initPipes` and `_initHooks`, which carried the same twenty
568
+ * lines with two words changed. The `.js` → `.ts` rename re-scored both as
569
+ * new code, so the gate asked for the deduplication the files already wanted.
570
+ *
571
+ * @throws {PluginImplementationError} when the target names nothing callable
572
+ */
573
+ resolveEventHandler(plugin, event, target, methodsList, errorId, deprecation) {
574
+ if (typeof target !== "function" &&
575
+ typeof plugin.instance[target] !== "function") {
576
+ const message = typeof target === "string" ? (0, didYouMean_1.default)(target, methodsList) : "";
577
+ throw assertionError.get(errorId, event, target, message);
578
+ }
579
+ // @deprecated - warn about using a string representing an instance method
580
+ if (typeof target === "string") {
581
+ plugin.printDeprecation(deprecation);
582
+ return bindPluginMethod(plugin.instance, target);
583
+ }
584
+ // if the function handler is a plugin instance method,
585
+ // bound the context to the plugin instance
586
+ if (target.name && typeof plugin.instance[target.name] === "function") {
587
+ return target.bind(plugin.instance);
588
+ }
589
+ return target;
590
+ }
479
591
  /**
480
592
  * @param {object} plugin
481
593
  */
482
594
  _initHooks(plugin) {
483
595
  const methodsList = getMethods(plugin.instance);
484
- for (const [event, fn] of Object.entries(plugin.instance.hooks)) {
596
+ for (const [event, fn] of Object.entries(plugin.instance.hooks ?? {})) {
485
597
  const list = Array.isArray(fn) ? fn : [fn];
486
598
  for (const target of list) {
487
- if (typeof target !== "function" &&
488
- typeof plugin.instance[target] !== "function") {
489
- const message = typeof target === "string" ? didYouMean(target, methodsList) : "";
490
- throw assertionError.get("invalid_hook", event, target, message);
491
- }
492
599
  debug('[%s] register hook on event "%s"', plugin.name, event);
493
- let handler = target;
494
- // @deprecated - warn about using a string representing an instance method
495
- if (typeof target === "string") {
496
- plugin.printDeprecation("Defining hook handler using a string is deprecated. Pass a function instead.");
497
- handler = plugin.instance[target].bind(plugin.instance);
498
- }
499
- // if the function handler is a plugin instance method,
500
- // bound the context to the plugin instance
501
- if (target.name && typeof plugin.instance[target.name] === "function") {
502
- handler = target.bind(plugin.instance);
503
- }
600
+ const handler = this.resolveEventHandler(plugin, event, target, methodsList, "invalid_hook", "Defining hook handler using a string is deprecated. Pass a function instead.");
504
601
  global.kuzzle.registerPluginHook(plugin.name, event, handler);
505
602
  }
506
603
  }
507
604
  }
508
605
  async _initApi(plugin) {
509
- for (const [controller, definition] of Object.entries(plugin.instance.api)) {
606
+ for (const [controller, definition] of Object.entries(plugin.instance.api ?? {})) {
510
607
  debug("[%s][%s] starting api controller registration", plugin.name, controller);
511
608
  if (await global.kuzzle.ask("kuzzle:api:funnel:controller:isNative", controller)) {
512
609
  throw assertionError.get("invalid_controller_definition", controller, "Native controllers cannot be overriden");
513
610
  }
514
- Plugin.checkControllerDefinition(controller, definition);
611
+ plugin_1.default.checkControllerDefinition(controller, definition);
515
612
  for (const [action, actionDefinition] of Object.entries(definition.actions)) {
516
- let apiController = this.controllers.get(controller);
517
- if (!apiController) {
518
- apiController = new BaseController();
519
- this.controllers.set(controller, apiController);
520
- }
521
- let handler = actionDefinition.handler;
522
- // if the function handler is a plugin instance method,
523
- // bind the context to the plugin instance
524
- if (handler.name &&
525
- typeof plugin.instance[handler.name] === "function") {
526
- handler = handler.bind(plugin.instance);
527
- }
528
- apiController._addAction(action, handler);
529
- const httpRoutes = actionDefinition.http || [];
530
- // Define default HTTP route if none have been provided
531
- if (httpRoutes.length === 0) {
532
- httpRoutes.push({
533
- path: `${Inflector.kebabCase(controller)}/${Inflector.kebabCase(action)}`,
534
- verb: "get",
535
- });
536
- }
613
+ const httpRoutes = this.registerApiAction(plugin, controller, action, actionDefinition);
537
614
  for (const httpRoute of httpRoutes) {
538
615
  debug('[%s] binding HTTP route "%s" to controller "%s"', plugin.name, httpRoute.path, controller);
539
- const routePath = httpRoute.path.charAt(0) === "/"
616
+ const routePath = httpRoute.path.startsWith("/")
540
617
  ? httpRoute.path
541
618
  : `/_/${httpRoute.path}`;
542
619
  this.routes.push({
@@ -558,39 +635,23 @@ class PluginsManager {
558
635
  */
559
636
  _initControllers(plugin) {
560
637
  // @deprecated - warn about using the obsolete "controllers" object
561
- if (!_.isEmpty(plugin.instance.controllers)) {
638
+ if (!(0, lodash_1.isEmpty)(plugin.instance.controllers)) {
562
639
  plugin.printDeprecation('Defining controllers using the "controllers" object is deprecated. You should use the "api" object instead.');
563
640
  }
564
- for (const controller of Object.keys(plugin.instance.controllers)) {
641
+ const legacyControllers = plugin.instance.controllers ?? {};
642
+ for (const controller of Object.keys(legacyControllers)) {
565
643
  debug("[%s][%s] starting controller registration", plugin.name, controller);
566
644
  const methodsList = getMethods(plugin.instance);
567
645
  const controllerName = `${plugin.name}/${controller}`;
568
- const definition = plugin.instance.controllers[controller];
646
+ const definition = legacyControllers[controller];
569
647
  const errorControllerPrefix = `Unable to inject controller "${controller}" from plugin "${plugin.name}":`;
570
- if (!isPlainObject(definition)) {
648
+ if (!(0, safeObject_1.isPlainObject)(definition)) {
571
649
  // @todo deprecate all those errors and use plugin.assert.invalid_controller_definition
572
650
  throw controllerError.get("invalid_description", errorControllerPrefix, typeof definition);
573
651
  }
574
652
  for (const action of Object.keys(definition)) {
575
653
  debug("[%s][%s][%s] starting action controller registration", plugin.name, controller, action);
576
- if (typeof definition[action] !== "function" &&
577
- typeof plugin.instance[definition[action]] !== "function") {
578
- const suggestion = typeof definition[action] === "string"
579
- ? didYouMean(definition[action], methodsList)
580
- : "";
581
- throw controllerError.get("invalid_action", errorControllerPrefix, controller, action, suggestion);
582
- }
583
- let apiController = this.controllers.get(controllerName);
584
- if (!apiController) {
585
- apiController = new BaseController();
586
- this.controllers.set(controllerName, apiController);
587
- }
588
- if (typeof definition[action] === "function") {
589
- apiController._addAction(action, definition[action]);
590
- }
591
- else {
592
- apiController._addAction(action, plugin.instance[definition[action]].bind(plugin.instance));
593
- }
654
+ this.registerLegacyAction(plugin, definition[action], { action, controller, controllerName, errorControllerPrefix }, methodsList);
594
655
  }
595
656
  }
596
657
  const httpVerbs = [
@@ -603,34 +664,21 @@ class PluginsManager {
603
664
  "options",
604
665
  ];
605
666
  const routeProperties = ["verb", "url", "controller", "action", "path"];
606
- const controllerNames = Object.keys(plugin.instance.controllers);
667
+ const controllerNames = Object.keys(legacyControllers);
607
668
  // @deprecated - warn about using the obsolete "routes" object
608
- if (!_.isEmpty(plugin.instance.routes)) {
669
+ if (!(0, lodash_1.isEmpty)(plugin.instance.routes)) {
609
670
  plugin.printDeprecation('Defining routes using the "routes" object is deprecated. You should use the "api" object instead.');
610
671
  }
611
672
  for (const route of plugin.instance.routes || []) {
612
673
  const controller = `${plugin.name}/${route.controller}`;
613
674
  const errorRoutePrefix = `Unable to inject API route "${JSON.stringify(route)}" from plugin "${plugin.name}":`;
614
- for (const key of Object.keys(route)) {
615
- if (routeProperties.indexOf(key) === -1) {
616
- throw controllerError.get("unexpected_route_property", errorRoutePrefix, key, didYouMean(key, routeProperties));
617
- }
618
- if (typeof route[key] !== "string" ||
619
- (route[key].length === 0 && key !== "url")) {
620
- throw controllerError.get("invalid_route_property", errorRoutePrefix, key);
621
- }
622
- }
623
- const apiController = this.controllers.get(controller);
624
- if (!apiController) {
625
- throw controllerError.get("undefined_controller", errorRoutePrefix, route.controller, didYouMean(route.controller, controllerNames));
626
- }
627
- if (!apiController._isAction(route.action)) {
628
- const actionNames = Array.from(apiController._actions);
629
- throw controllerError.get("undefined_action", errorRoutePrefix, route.action, didYouMean(route.action, actionNames));
630
- }
631
- if (httpVerbs.indexOf(route.verb.toLowerCase()) === -1) {
632
- throw controllerError.get("unsupported_verb", errorRoutePrefix, httpVerbs.join(", "), didYouMean(route.verb, httpVerbs));
633
- }
675
+ this.checkLegacyRoute(route, {
676
+ controller,
677
+ controllerNames,
678
+ errorRoutePrefix,
679
+ httpVerbs,
680
+ routeProperties,
681
+ });
634
682
  // @deprecated route.url is deprecated
635
683
  if (route.url) {
636
684
  plugin.printDeprecation('Usage of "url" property for routes is deprecated. Use "path" instead.');
@@ -655,13 +703,116 @@ class PluginsManager {
655
703
  });
656
704
  }
657
705
  }
706
+ /**
707
+ * Registers one action of the `api` object and answers the HTTP routes to
708
+ * bind for it — the declared ones, or the single default route built from the
709
+ * controller and action names.
710
+ *
711
+ * Lifted verbatim out of `_initApi` for the same gate reason as its siblings.
712
+ */
713
+ registerApiAction(plugin, controller, action, actionDefinition) {
714
+ let apiController = this.controllers.get(controller);
715
+ if (!apiController) {
716
+ apiController = new baseController_1.BaseController();
717
+ this.controllers.set(controller, apiController);
718
+ }
719
+ let handler = actionDefinition.handler;
720
+ // if the function handler is a plugin instance method,
721
+ // bind the context to the plugin instance
722
+ if (handler.name && typeof plugin.instance[handler.name] === "function") {
723
+ handler = handler.bind(plugin.instance);
724
+ }
725
+ apiController._addAction(action, handler);
726
+ const httpRoutes = actionDefinition.http || [];
727
+ // Define default HTTP route if none have been provided
728
+ if (httpRoutes.length === 0) {
729
+ httpRoutes.push({
730
+ path: `${Inflector_1.Inflector.kebabCase(controller)}/${Inflector_1.Inflector.kebabCase(action)}`,
731
+ verb: "get",
732
+ });
733
+ }
734
+ return httpRoutes;
735
+ }
736
+ /**
737
+ * Checks one entry of the deprecated `routes` object: its properties, the
738
+ * controller and action it names, and its HTTP verb.
739
+ *
740
+ * Lifted verbatim out of `_initControllers`, second half of the same
741
+ * gate-driven split as `registerLegacyAction`.
742
+ *
743
+ * @throws {PluginImplementationError}
744
+ */
745
+ checkLegacyRoute(route, names) {
746
+ const { controller, controllerNames, errorRoutePrefix, httpVerbs, routeProperties, } = names;
747
+ for (const key of Object.keys(route)) {
748
+ if (!routeProperties.includes(key)) {
749
+ throw controllerError.get("unexpected_route_property", errorRoutePrefix, key, (0, didYouMean_1.default)(key, routeProperties));
750
+ }
751
+ if (typeof route[key] !== "string" ||
752
+ (route[key].length === 0 && key !== "url")) {
753
+ throw controllerError.get("invalid_route_property", errorRoutePrefix, key);
754
+ }
755
+ }
756
+ const apiController = this.controllers.get(controller);
757
+ if (!apiController) {
758
+ throw controllerError.get("undefined_controller", errorRoutePrefix, route.controller, (0, didYouMean_1.default)(route.controller, controllerNames));
759
+ }
760
+ if (!apiController._isAction(route.action)) {
761
+ const actionNames = Array.from(apiController._actions);
762
+ throw controllerError.get("undefined_action", errorRoutePrefix, route.action, (0, didYouMean_1.default)(route.action, actionNames));
763
+ }
764
+ if (!httpVerbs.includes(route.verb.toLowerCase())) {
765
+ throw controllerError.get("unsupported_verb", errorRoutePrefix, httpVerbs.join(", "), (0, didYouMean_1.default)(route.verb, httpVerbs));
766
+ }
767
+ }
768
+ /**
769
+ * Registers one action of the pre-Kaaf `controllers` object: a handler given
770
+ * either as a function or as the name of a plugin method.
771
+ *
772
+ * Lifted verbatim out of `_initControllers`, whose cognitive complexity the
773
+ * `.js` → `.ts` rename re-scored as new code.
774
+ *
775
+ * @throws {PluginImplementationError} when the target names nothing callable
776
+ */
777
+ registerLegacyAction(plugin,
778
+ /**
779
+ * Unvalidated: it arrives from the plugin's own `controllers` object, which
780
+ * is `JSONObject`. The first check below is what makes the declared shape
781
+ * true, and is the reason this parameter may claim it.
782
+ */
783
+ target, names, methodsList) {
784
+ const { action, controller, controllerName, errorControllerPrefix } = names;
785
+ // Nested rather than one flat condition: what the throw leaves standing
786
+ // is "a function, or a name that resolves to one", and written this way
787
+ // that is what the compiler carries down to the two branches below —
788
+ // where the `null` the previous spelling introduced had to be asserted
789
+ // away again.
790
+ if (typeof target !== "function") {
791
+ if (typeof target !== "string" ||
792
+ typeof plugin.instance[target] !== "function") {
793
+ const suggestion = typeof target === "string" ? (0, didYouMean_1.default)(target, methodsList) : "";
794
+ throw controllerError.get("invalid_action", errorControllerPrefix, controller, action, suggestion);
795
+ }
796
+ }
797
+ let apiController = this.controllers.get(controllerName);
798
+ if (!apiController) {
799
+ apiController = new baseController_1.BaseController();
800
+ this.controllers.set(controllerName, apiController);
801
+ }
802
+ if (typeof target === "function") {
803
+ apiController._addAction(action, target);
804
+ }
805
+ else {
806
+ apiController._addAction(action, bindPluginMethod(plugin.instance, target));
807
+ }
808
+ }
658
809
  /**
659
810
  * @param {object} plugin
660
811
  * @throws {PluginImplementationError} If strategies registration fails
661
812
  */
662
813
  _initStrategies(plugin) {
663
- if (!isPlainObject(plugin.instance.strategies) ||
664
- _.isEmpty(plugin.instance.strategies)) {
814
+ if (!(0, safeObject_1.isPlainObject)(plugin.instance.strategies) ||
815
+ (0, lodash_1.isEmpty)(plugin.instance.strategies)) {
665
816
  throw strategyError.get("invalid_definition", plugin.logPrefix);
666
817
  }
667
818
  for (const name of Object.keys(plugin.instance.strategies)) {
@@ -673,7 +824,7 @@ class PluginsManager {
673
824
  * @throws {PluginImplementationError} If strategies registration fails
674
825
  */
675
826
  _initAuthenticators(plugin) {
676
- if (!isPlainObject(plugin.instance.authenticators)) {
827
+ if (!(0, safeObject_1.isPlainObject)(plugin.instance.authenticators)) {
677
828
  throw kerror.get("plugin", "authenticators", "not_an_object", plugin.logPrefix);
678
829
  }
679
830
  for (const authenticator of Object.keys(plugin.instance.authenticators)) {
@@ -681,7 +832,7 @@ class PluginsManager {
681
832
  throw kerror.get("plugin", "authenticators", "invalid_authenticator", plugin.logPrefix, authenticator);
682
833
  }
683
834
  }
684
- this.authenticators[plugin.name] = Object.assign({}, plugin.instance.authenticators);
835
+ this.authenticators[plugin.name] = { ...plugin.instance.authenticators };
685
836
  }
686
837
  /**
687
838
  * Load detected plugins in memory
@@ -692,7 +843,7 @@ class PluginsManager {
692
843
  const loadedPlugins = new Map();
693
844
  // first load plugins from Backend.plugin.use
694
845
  for (const [name, { plugin: instance, options }] of Object.entries(plugins)) {
695
- const plugin = new Plugin(instance, { name, ...options });
846
+ const plugin = new plugin_1.default(instance, { name, ...options });
696
847
  // the plugin cluster can be loaded in the startup script
697
848
  // and we need the manifest
698
849
  plugin.manifest = plugin.manifest || options.manifest;
@@ -703,23 +854,26 @@ class PluginsManager {
703
854
  loadedPlugins.set(plugin.name, plugin);
704
855
  }
705
856
  // then try to load plugins from the filesystem
706
- if (!fs.existsSync(this.pluginsEnabledDir)) {
857
+ if (!node_fs_1.default.existsSync(this.pluginsEnabledDir)) {
707
858
  return loadedPlugins;
708
859
  }
709
- let pluginsPath = [];
860
+ let pluginsPath;
710
861
  try {
711
- pluginsPath = fs
862
+ pluginsPath = node_fs_1.default
712
863
  .readdirSync(this.pluginsEnabledDir)
713
- .map((name) => path.join(this.pluginsEnabledDir, name))
714
- .filter((filePath) => fs.statSync(filePath).isDirectory());
864
+ .map((name) => node_path_1.default.join(this.pluginsEnabledDir, name))
865
+ .filter((filePath) => node_fs_1.default.statSync(filePath).isDirectory());
715
866
  }
716
867
  catch (e) {
717
- throw assertionError.get("invalid_plugins_dir", this.pluginsEnabledDir, e.message);
868
+ throw assertionError.get("invalid_plugins_dir", this.pluginsEnabledDir, (0, thrown_1.causeOf)(e).message);
718
869
  }
719
870
  debug("loading plugins: %a", pluginsPath);
720
871
  for (const relativePluginPath of pluginsPath) {
721
- const plugin = Plugin.loadFromDirectory(relativePluginPath);
722
- plugin.init(plugin.manifest.raw.name);
872
+ const plugin = plugin_1.default.loadFromDirectory(relativePluginPath);
873
+ // `loadFromDirectory` has already read the name out of the manifest —
874
+ // `manifest.load()` throws `missing_name` rather than leave it unset —
875
+ // so this is the same string without two nullable dereferences.
876
+ plugin.init(plugin.name);
723
877
  if (loadedPlugins.has(plugin.name)) {
724
878
  throw assertionError.get("name_already_exists", plugin.name);
725
879
  }
@@ -738,11 +892,16 @@ class PluginsManager {
738
892
  wrapStrategyVerify(pluginName, strategyName, verifyMethod) {
739
893
  const prefix = `${pluginName} Strategy ${strategyName}:`;
740
894
  return async (...args) => {
741
- const callback = args[args.length - 1];
895
+ const callback = args.at(-1);
896
+ // passport always calls the adapter with a trailing callback; the
897
+ // narrowing is what lets it be invoked, and the branch cannot be taken.
898
+ if (!isPluginMethod(callback)) {
899
+ return;
900
+ }
742
901
  const ret = verifyMethod(...args.slice(0, -1));
743
902
  // catching plugins returning non-thenable content
744
903
  // @todo - with async/await we might consider allowing non-promise results
745
- if (!ret || !_.isFunction(ret.then)) {
904
+ if (!hasThen(ret)) {
746
905
  callback(strategyError.get("invalid_verify_return", prefix, ret));
747
906
  return;
748
907
  }
@@ -754,63 +913,141 @@ class PluginsManager {
754
913
  callback(e);
755
914
  return;
756
915
  }
757
- if (result === false) {
758
- callback(null, result, { message: null });
759
- return;
760
- }
761
- if (!isPlainObject(result)) {
762
- callback(strategyError.get("invalid_verify_resolve", prefix));
763
- return;
764
- }
765
- if (result.kuid !== null && result.kuid !== undefined) {
766
- if (typeof result.kuid === "string") {
767
- try {
768
- const user = await global.kuzzle.ask("core:security:user:get", result.kuid);
769
- callback(null, user);
770
- }
771
- catch (e) {
772
- if (e.id === "security.user.not_found") {
773
- callback(strategyError.get("unknown_kuid", prefix));
774
- }
775
- else {
776
- callback(e);
777
- }
778
- }
779
- return;
780
- }
781
- callback(strategyError.get("invalid_kuid", prefix, typeof result.kuid));
782
- return;
783
- }
784
- let message;
785
- if (result.message && typeof result.message === "string") {
786
- message = result.message;
787
- }
788
- else {
789
- message = `Unable to log in using the strategy "${strategyName}"`;
790
- }
791
- callback(null, false, { message });
916
+ await resolveVerifiedUser(result, prefix, strategyName, callback);
792
917
  };
793
918
  }
794
919
  }
795
920
  /**
796
- * Test if the provided argument is a constructor or not
921
+ * Turns what a strategy's `verify` resolved into the passport callback call it
922
+ * stands for: the authenticated user, an explicit refusal, or an error.
797
923
  *
798
- * @param {*} arg
799
- * @returns {Boolean}
924
+ * Lifted verbatim out of `wrapStrategyVerify`, whose cognitive complexity the
925
+ * `.js` → `.ts` rename re-scored as new code.
800
926
  */
927
+ async function resolveVerifiedUser(result, prefix, strategyName, callback) {
928
+ if (result === false) {
929
+ callback(null, result, { message: null });
930
+ return;
931
+ }
932
+ if (!(0, safeObject_1.isPlainObject)(result)) {
933
+ callback(strategyError.get("invalid_verify_resolve", prefix));
934
+ return;
935
+ }
936
+ if (result.kuid !== null && result.kuid !== undefined) {
937
+ await resolveKuid(result.kuid, prefix, callback);
938
+ return;
939
+ }
940
+ const message = typeof result.message === "string" && result.message
941
+ ? result.message
942
+ : `Unable to log in using the strategy "${strategyName}"`;
943
+ callback(null, false, { message });
944
+ }
945
+ /**
946
+ * Loads the user a strategy named by `kuid` and hands it to the passport
947
+ * callback, turning a missing user into the dedicated `unknown_kuid` error.
948
+ *
949
+ * Split out of `resolveVerifiedUser` to keep both under the cognitive
950
+ * complexity ceiling the `.js` → `.ts` rename re-scores as new code.
951
+ */
952
+ async function resolveKuid(kuid, prefix, callback) {
953
+ if (typeof kuid !== "string") {
954
+ callback(strategyError.get("invalid_kuid", prefix, typeof kuid));
955
+ return;
956
+ }
957
+ try {
958
+ const user = await global.kuzzle.ask("core:security:user:get", kuid);
959
+ callback(null, user);
960
+ }
961
+ catch (e) {
962
+ // Duck-typed, as it always was: `core:security:user:get` rejects with a
963
+ // KuzzleError, but the id is all this branch reads and narrowing to the
964
+ // class would change which errors it recognises.
965
+ if (idOf(e) === "security.user.not_found") {
966
+ callback(strategyError.get("unknown_kuid", prefix));
967
+ }
968
+ else {
969
+ callback(e);
970
+ }
971
+ }
972
+ }
973
+ /**
974
+ * Resolves a handler a plugin referenced by name and binds it to the instance.
975
+ *
976
+ * `plugin.instance[name]` is `unknown` — a plugin may expose anything — so the
977
+ * `typeof` check is what makes the result callable. Every call site had already
978
+ * made that check; this is the same one, in the place that needs it.
979
+ *
980
+ * The name resolving to nothing callable is unreachable — all four call sites
981
+ * establish it first — and the previous annotation said so by answering
982
+ * `undefined`, deferring the choice to the day this file had to pass strict
983
+ * (TD-54, #2757). That is this slice: the branch throws, so
984
+ * the three callers that would each have had to guard a value that cannot
985
+ * exist do not, and the one thing that could produce it — a plugin whose
986
+ * member stopped being a function between the check and the bind — says so
987
+ * instead of returning something uncallable.
988
+ */
989
+ function bindPluginMethod(instance, name) {
990
+ const method = instance[name];
991
+ if (!isPluginMethod(method)) {
992
+ throw runtimeError.get("unexpected_error", `plugin member "${name}" is not a function`);
993
+ }
994
+ return method.bind(instance);
995
+ }
996
+ /**
997
+ * A declared narrowing from `unknown` to "callable", the same shape
998
+ * `safeObject.isPlainObject` has. A predicate rather than an assertion: it is
999
+ * what lets a plugin's member — `unknown` by construction — be invoked without
1000
+ * an `as`, which TD-43's `casts` ratchet now prices.
1001
+ */
1002
+ function isPluginMethod(value) {
1003
+ return typeof value === "function";
1004
+ }
1005
+ /**
1006
+ * The duck-typed promise check `registerPipe` has always made: a plugin's pipe
1007
+ * may answer a promise, a value, or nothing, and only the first is awaited.
1008
+ * A guard rather than an inline `typeof` chain so the branch narrows.
1009
+ *
1010
+ * `Promise` rather than `Bluebird`: nothing here proves the plugin returned a
1011
+ * Bluebird, and `then`/`catch` — which is exactly what the guard tests and what
1012
+ * `registerPipe` calls — is all of `Promise` the callers need (TD-56, #2759).
1013
+ */
1014
+ function isThenable(value) {
1015
+ return (typeof value === "object" &&
1016
+ value !== null &&
1017
+ "then" in value &&
1018
+ typeof value.then === "function" &&
1019
+ "catch" in value &&
1020
+ typeof value.catch === "function");
1021
+ }
1022
+ /**
1023
+ * What `wrapStrategyVerify` has always accepted from a strategy's `verify`:
1024
+ * anything with a callable `then`, which is all `await` needs. Looser than
1025
+ * `isThenable` on purpose — that one also requires `catch`, because
1026
+ * `registerPipe` calls it; reusing it here (#2748) had started rejecting the
1027
+ * `then`-only thenables v2.56.0 awaited.
1028
+ */
1029
+ function hasThen(value) {
1030
+ return ((typeof value === "object" || typeof value === "function") &&
1031
+ value !== null &&
1032
+ "then" in value &&
1033
+ typeof value.then === "function");
1034
+ }
801
1035
  function isConstructor(arg) {
1036
+ if (typeof arg !== "function") {
1037
+ return false;
1038
+ }
802
1039
  try {
803
1040
  Reflect.construct(Object, [], arg);
804
1041
  }
805
- catch (e) {
1042
+ catch {
806
1043
  return false;
807
1044
  }
808
1045
  return true;
809
1046
  }
810
1047
  function getMethods(object) {
811
1048
  const prototype = Object.getPrototypeOf(object);
812
- const instanceMethods = Object.getOwnPropertyNames(prototype).filter((method) => ["init", "constructor"].indexOf(method) === -1);
813
- const objectMethods = Object.getOwnPropertyNames(object).filter((key) => typeof object[key] === "function");
1049
+ const instanceMethods = Object.getOwnPropertyNames(prototype).filter((method) => !["init", "constructor"].includes(method));
1050
+ const objectMethods = Object.getOwnPropertyNames(object).filter((key) => typeof Reflect.get(object, key) === "function");
814
1051
  return [...instanceMethods, ...objectMethods];
815
1052
  }
816
1053
  module.exports = PluginsManager;