@webda/core 4.0.0-beta.1 → 4.0.0-beta.3

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 (675) hide show
  1. package/README.md +252 -0
  2. package/lib/application/application.d.ts +437 -0
  3. package/lib/application/application.d.ts.map +1 -0
  4. package/lib/application/application.js +792 -0
  5. package/lib/application/application.js.map +1 -0
  6. package/lib/application/hooks.d.ts +34 -0
  7. package/lib/application/hooks.d.ts.map +1 -0
  8. package/lib/application/hooks.js +57 -0
  9. package/lib/application/hooks.js.map +1 -0
  10. package/lib/application/iapplication.d.ts +43 -0
  11. package/lib/application/iapplication.d.ts.map +1 -0
  12. package/lib/application/iapplication.js +2 -0
  13. package/lib/application/iapplication.js.map +1 -0
  14. package/lib/application/iconfiguration.d.ts +176 -0
  15. package/lib/application/iconfiguration.d.ts.map +1 -0
  16. package/lib/application/iconfiguration.js +8 -0
  17. package/lib/application/iconfiguration.js.map +1 -0
  18. package/lib/application/runner.d.ts +8 -0
  19. package/lib/application/runner.d.ts.map +1 -0
  20. package/lib/application/runner.js +26 -0
  21. package/lib/application/runner.js.map +1 -0
  22. package/lib/application/unpackedapplication.d.ts +104 -0
  23. package/lib/application/unpackedapplication.d.ts.map +1 -0
  24. package/lib/application/unpackedapplication.js +492 -0
  25. package/lib/application/unpackedapplication.js.map +1 -0
  26. package/lib/bin/cli-phase.d.ts +28 -0
  27. package/lib/bin/cli-phase.d.ts.map +1 -0
  28. package/lib/bin/cli-phase.js +44 -0
  29. package/lib/bin/cli-phase.js.map +1 -0
  30. package/lib/bin/cli.d.ts +161 -0
  31. package/lib/bin/cli.d.ts.map +1 -0
  32. package/lib/bin/cli.js +828 -0
  33. package/lib/bin/cli.js.map +1 -0
  34. package/lib/bin/launcher.d.ts +3 -0
  35. package/lib/bin/launcher.d.ts.map +1 -0
  36. package/lib/bin/launcher.js +50 -0
  37. package/lib/bin/launcher.js.map +1 -0
  38. package/lib/cache/cache.d.ts +33 -0
  39. package/lib/cache/cache.d.ts.map +1 -0
  40. package/lib/cache/cache.js +8 -0
  41. package/lib/cache/cache.js.map +1 -0
  42. package/lib/{services/configuration.d.ts → configurations/configuration.service.d.ts} +58 -49
  43. package/lib/configurations/configuration.service.d.ts.map +1 -0
  44. package/lib/configurations/configuration.service.js +248 -0
  45. package/lib/configurations/configuration.service.js.map +1 -0
  46. package/lib/configurations/fileconfiguration.service.d.ts +30 -0
  47. package/lib/configurations/fileconfiguration.service.d.ts.map +1 -0
  48. package/lib/configurations/fileconfiguration.service.js +65 -0
  49. package/lib/configurations/fileconfiguration.service.js.map +1 -0
  50. package/lib/configurations/kubernetesconfiguration.service.d.ts +43 -0
  51. package/lib/configurations/kubernetesconfiguration.service.d.ts.map +1 -0
  52. package/lib/configurations/kubernetesconfiguration.service.js +83 -0
  53. package/lib/configurations/kubernetesconfiguration.service.js.map +1 -0
  54. package/lib/contexts/execution.d.ts +33 -0
  55. package/lib/contexts/execution.d.ts.map +1 -0
  56. package/lib/contexts/execution.js +73 -0
  57. package/lib/contexts/execution.js.map +1 -0
  58. package/lib/contexts/globalcontext.d.ts +29 -0
  59. package/lib/contexts/globalcontext.d.ts.map +1 -0
  60. package/lib/contexts/globalcontext.js +38 -0
  61. package/lib/contexts/globalcontext.js.map +1 -0
  62. package/lib/{utils → contexts}/httpcontext.d.ts +45 -19
  63. package/lib/contexts/httpcontext.d.ts.map +1 -0
  64. package/lib/{utils → contexts}/httpcontext.js +102 -34
  65. package/lib/contexts/httpcontext.js.map +1 -0
  66. package/lib/contexts/icontext.d.ts +236 -0
  67. package/lib/contexts/icontext.d.ts.map +1 -0
  68. package/lib/contexts/icontext.js +230 -0
  69. package/lib/contexts/icontext.js.map +1 -0
  70. package/lib/contexts/operationcontext.d.ts +179 -0
  71. package/lib/contexts/operationcontext.d.ts.map +1 -0
  72. package/lib/contexts/operationcontext.js +358 -0
  73. package/lib/contexts/operationcontext.js.map +1 -0
  74. package/lib/contexts/simplecontext.d.ts +31 -0
  75. package/lib/contexts/simplecontext.d.ts.map +1 -0
  76. package/lib/contexts/simplecontext.js +45 -0
  77. package/lib/contexts/simplecontext.js.map +1 -0
  78. package/lib/contexts/webcontext.d.ts +218 -0
  79. package/lib/contexts/webcontext.d.ts.map +1 -0
  80. package/lib/contexts/webcontext.js +389 -0
  81. package/lib/contexts/webcontext.js.map +1 -0
  82. package/lib/core/authorizer.d.ts +23 -0
  83. package/lib/core/authorizer.d.ts.map +1 -0
  84. package/lib/core/authorizer.js +17 -0
  85. package/lib/core/authorizer.js.map +1 -0
  86. package/lib/core/core.d.ts +225 -0
  87. package/lib/core/core.d.ts.map +1 -0
  88. package/lib/core/core.js +576 -0
  89. package/lib/core/core.js.map +1 -0
  90. package/lib/core/hooks.d.ts +72 -0
  91. package/lib/core/hooks.d.ts.map +1 -0
  92. package/lib/core/hooks.js +73 -0
  93. package/lib/core/hooks.js.map +1 -0
  94. package/lib/core/icore.d.ts +249 -0
  95. package/lib/core/icore.d.ts.map +1 -0
  96. package/lib/core/icore.js +15 -0
  97. package/lib/core/icore.js.map +1 -0
  98. package/lib/core/instancestorage.d.ts +61 -0
  99. package/lib/core/instancestorage.d.ts.map +1 -0
  100. package/lib/core/instancestorage.js +75 -0
  101. package/lib/core/instancestorage.js.map +1 -0
  102. package/lib/core/operations.d.ts +181 -0
  103. package/lib/core/operations.d.ts.map +1 -0
  104. package/lib/core/operations.js +559 -0
  105. package/lib/core/operations.js.map +1 -0
  106. package/lib/errors/errors.d.ts +126 -0
  107. package/lib/errors/errors.d.ts.map +1 -0
  108. package/lib/errors/errors.js +165 -0
  109. package/lib/errors/errors.js.map +1 -0
  110. package/lib/events/asynceventemitter.d.ts +159 -0
  111. package/lib/events/asynceventemitter.d.ts.map +1 -0
  112. package/lib/events/asynceventemitter.js +152 -0
  113. package/lib/events/asynceventemitter.js.map +1 -0
  114. package/lib/events/events.d.ts +112 -0
  115. package/lib/events/events.d.ts.map +1 -0
  116. package/lib/events/events.js +45 -0
  117. package/lib/events/events.js.map +1 -0
  118. package/lib/index.d.ts +84 -51
  119. package/lib/index.d.ts.map +1 -0
  120. package/lib/index.js +82 -59
  121. package/lib/index.js.map +1 -1
  122. package/lib/loggers/console.service.d.ts +24 -0
  123. package/lib/loggers/console.service.d.ts.map +1 -0
  124. package/lib/loggers/console.service.js +30 -0
  125. package/lib/loggers/console.service.js.map +1 -0
  126. package/lib/loggers/file.service.d.ts +25 -0
  127. package/lib/loggers/file.service.d.ts.map +1 -0
  128. package/lib/loggers/file.service.js +33 -0
  129. package/lib/loggers/file.service.js.map +1 -0
  130. package/lib/loggers/hooks.d.ts +20 -0
  131. package/lib/loggers/hooks.d.ts.map +1 -0
  132. package/lib/loggers/hooks.js +40 -0
  133. package/lib/loggers/hooks.js.map +1 -0
  134. package/lib/loggers/ilogger.d.ts +76 -0
  135. package/lib/loggers/ilogger.d.ts.map +1 -0
  136. package/lib/loggers/ilogger.js +108 -0
  137. package/lib/loggers/ilogger.js.map +1 -0
  138. package/lib/loggers/logger.d.ts +13 -0
  139. package/lib/loggers/logger.d.ts.map +1 -0
  140. package/lib/loggers/logger.js +18 -0
  141. package/lib/loggers/logger.js.map +1 -0
  142. package/lib/loggers/memory.service.d.ts +18 -0
  143. package/lib/loggers/memory.service.d.ts.map +1 -0
  144. package/lib/loggers/memory.service.js +21 -0
  145. package/lib/loggers/memory.service.js.map +1 -0
  146. package/lib/loggers/params.d.ts +47 -0
  147. package/lib/loggers/params.d.ts.map +1 -0
  148. package/lib/loggers/params.js +56 -0
  149. package/lib/loggers/params.js.map +1 -0
  150. package/lib/metrics/metrics.d.ts +25 -0
  151. package/lib/metrics/metrics.d.ts.map +1 -0
  152. package/lib/metrics/metrics.js +51 -0
  153. package/lib/metrics/metrics.js.map +1 -0
  154. package/lib/models/aclmodel.d.ts +21 -77
  155. package/lib/models/aclmodel.d.ts.map +1 -0
  156. package/lib/models/aclmodel.js +27 -204
  157. package/lib/models/aclmodel.js.map +1 -1
  158. package/lib/models/coremodel.model.d.ts +5 -0
  159. package/lib/models/coremodel.model.d.ts.map +1 -0
  160. package/lib/models/coremodel.model.js +5 -0
  161. package/lib/models/coremodel.model.js.map +1 -0
  162. package/lib/models/decorator.d.ts +63 -0
  163. package/lib/models/decorator.d.ts.map +1 -0
  164. package/lib/models/decorator.js +63 -0
  165. package/lib/models/decorator.js.map +1 -0
  166. package/lib/models/deployment.d.ts +2 -1
  167. package/lib/models/deployment.d.ts.map +1 -0
  168. package/lib/models/ident.model.d.ts +89 -0
  169. package/lib/models/ident.model.d.ts.map +1 -0
  170. package/lib/models/ident.model.js +115 -0
  171. package/lib/models/ident.model.js.map +1 -0
  172. package/lib/models/ownermodel.model.d.ts +68 -0
  173. package/lib/models/ownermodel.model.d.ts.map +1 -0
  174. package/lib/models/ownermodel.model.js +112 -0
  175. package/lib/models/ownermodel.model.js.map +1 -0
  176. package/lib/models/registry.model.d.ts +76 -0
  177. package/lib/models/registry.model.d.ts.map +1 -0
  178. package/lib/models/registry.model.js +104 -0
  179. package/lib/models/registry.model.js.map +1 -0
  180. package/lib/models/rolemodel.model.d.ts +28 -0
  181. package/lib/models/rolemodel.model.d.ts.map +1 -0
  182. package/lib/models/rolemodel.model.js +53 -0
  183. package/lib/models/rolemodel.model.js.map +1 -0
  184. package/lib/models/simpleuser.model.d.ts +78 -0
  185. package/lib/models/simpleuser.model.d.ts.map +1 -0
  186. package/lib/models/simpleuser.model.js +123 -0
  187. package/lib/models/simpleuser.model.js.map +1 -0
  188. package/lib/models/types.d.ts +113 -0
  189. package/lib/models/types.d.ts.map +1 -0
  190. package/lib/models/types.js +2 -0
  191. package/lib/models/types.js.map +1 -0
  192. package/lib/models/user.model.d.ts +103 -0
  193. package/lib/models/user.model.d.ts.map +1 -0
  194. package/lib/models/user.model.js +125 -0
  195. package/lib/models/user.model.js.map +1 -0
  196. package/lib/queues/memoryqueue.service.d.ts +72 -0
  197. package/lib/queues/memoryqueue.service.d.ts.map +1 -0
  198. package/lib/queues/memoryqueue.service.js +136 -0
  199. package/lib/queues/memoryqueue.service.js.map +1 -0
  200. package/lib/queues/pubsubservice.d.ts +9 -6
  201. package/lib/queues/pubsubservice.d.ts.map +1 -0
  202. package/lib/queues/pubsubservice.js +5 -4
  203. package/lib/queues/pubsubservice.js.map +1 -1
  204. package/lib/queues/queueservice.d.ts +10 -11
  205. package/lib/queues/queueservice.d.ts.map +1 -0
  206. package/lib/queues/queueservice.js +48 -20
  207. package/lib/queues/queueservice.js.map +1 -1
  208. package/lib/rest/hooks.d.ts +8 -0
  209. package/lib/rest/hooks.d.ts.map +1 -0
  210. package/lib/rest/hooks.js +10 -0
  211. package/lib/rest/hooks.js.map +1 -0
  212. package/lib/rest/irest.d.ts +212 -0
  213. package/lib/rest/irest.d.ts.map +1 -0
  214. package/lib/rest/irest.js +39 -0
  215. package/lib/rest/irest.js.map +1 -0
  216. package/lib/rest/originfilter.d.ts +38 -0
  217. package/lib/rest/originfilter.d.ts.map +1 -0
  218. package/lib/rest/originfilter.js +61 -0
  219. package/lib/rest/originfilter.js.map +1 -0
  220. package/lib/rest/restoperationstransport.service.d.ts +193 -0
  221. package/lib/rest/restoperationstransport.service.d.ts.map +1 -0
  222. package/lib/rest/restoperationstransport.service.js +780 -0
  223. package/lib/rest/restoperationstransport.service.js.map +1 -0
  224. package/lib/rest/router.service.d.ts +244 -0
  225. package/lib/rest/router.service.d.ts.map +1 -0
  226. package/lib/rest/router.service.js +843 -0
  227. package/lib/rest/router.service.js.map +1 -0
  228. package/lib/schemas/hooks.d.ts +48 -0
  229. package/lib/schemas/hooks.d.ts.map +1 -0
  230. package/lib/schemas/hooks.js +152 -0
  231. package/lib/schemas/hooks.js.map +1 -0
  232. package/lib/services/audit.model.d.ts +208 -0
  233. package/lib/services/audit.model.d.ts.map +1 -0
  234. package/lib/services/audit.model.js +431 -0
  235. package/lib/services/audit.model.js.map +1 -0
  236. package/lib/services/{authentication.d.ts → authentication.service.d.ts} +140 -58
  237. package/lib/services/authentication.service.d.ts.map +1 -0
  238. package/lib/services/authentication.service.js +932 -0
  239. package/lib/services/authentication.service.js.map +1 -0
  240. package/lib/services/binary.service.d.ts +808 -0
  241. package/lib/services/binary.service.d.ts.map +1 -0
  242. package/lib/services/binary.service.js +1365 -0
  243. package/lib/services/binary.service.js.map +1 -0
  244. package/lib/services/cloudbinary.d.ts +19 -13
  245. package/lib/services/cloudbinary.d.ts.map +1 -0
  246. package/lib/services/cloudbinary.js +24 -18
  247. package/lib/services/cloudbinary.js.map +1 -1
  248. package/lib/services/command.d.ts +118 -0
  249. package/lib/services/command.d.ts.map +1 -0
  250. package/lib/services/command.js +97 -0
  251. package/lib/services/command.js.map +1 -0
  252. package/lib/services/cron.service.d.ts +142 -0
  253. package/lib/services/cron.service.d.ts.map +1 -0
  254. package/lib/services/cron.service.js +291 -0
  255. package/lib/services/cron.service.js.map +1 -0
  256. package/lib/services/{cryptoservice.d.ts → cryptoservice.service.d.ts} +77 -142
  257. package/lib/services/cryptoservice.service.d.ts.map +1 -0
  258. package/lib/services/cryptoservice.service.js +527 -0
  259. package/lib/services/cryptoservice.service.js.map +1 -0
  260. package/lib/services/debugmailer.service.d.ts +49 -0
  261. package/lib/services/debugmailer.service.d.ts.map +1 -0
  262. package/lib/services/debugmailer.service.js +66 -0
  263. package/lib/services/debugmailer.service.js.map +1 -0
  264. package/lib/services/domainservice.service.d.ts +203 -0
  265. package/lib/services/domainservice.service.d.ts.map +1 -0
  266. package/lib/services/domainservice.service.js +600 -0
  267. package/lib/services/domainservice.service.js.map +1 -0
  268. package/lib/services/httpserver.service.d.ts +248 -0
  269. package/lib/services/httpserver.service.d.ts.map +1 -0
  270. package/lib/services/httpserver.service.js +673 -0
  271. package/lib/services/httpserver.service.js.map +1 -0
  272. package/lib/services/iauthentication.d.ts +9 -0
  273. package/lib/services/iauthentication.d.ts.map +1 -0
  274. package/lib/services/iauthentication.js +2 -0
  275. package/lib/services/iauthentication.js.map +1 -0
  276. package/lib/services/icryptoservice.d.ts +127 -0
  277. package/lib/services/icryptoservice.d.ts.map +1 -0
  278. package/lib/services/icryptoservice.js +68 -0
  279. package/lib/services/icryptoservice.js.map +1 -0
  280. package/lib/services/imailer.d.ts +17 -0
  281. package/lib/services/imailer.d.ts.map +1 -0
  282. package/lib/services/imailer.js +2 -0
  283. package/lib/services/imailer.js.map +1 -0
  284. package/lib/services/iservice.d.ts +104 -0
  285. package/lib/services/iservice.d.ts.map +1 -0
  286. package/lib/services/iservice.js +63 -0
  287. package/lib/services/iservice.js.map +1 -0
  288. package/lib/services/mailer.service.d.ts +220 -0
  289. package/lib/services/mailer.service.d.ts.map +1 -0
  290. package/lib/services/mailer.service.js +251 -0
  291. package/lib/services/mailer.service.js.map +1 -0
  292. package/lib/services/{notificationservice.d.ts → notificationservice.service.d.ts} +10 -10
  293. package/lib/services/notificationservice.service.d.ts.map +1 -0
  294. package/lib/services/{notificationservice.js → notificationservice.service.js} +24 -12
  295. package/lib/services/notificationservice.service.js.map +1 -0
  296. package/lib/services/oauth.d.ts +58 -31
  297. package/lib/services/oauth.d.ts.map +1 -0
  298. package/lib/services/oauth.js +365 -251
  299. package/lib/services/oauth.js.map +1 -1
  300. package/lib/services/operationstransport.d.ts +65 -0
  301. package/lib/services/operationstransport.d.ts.map +1 -0
  302. package/lib/services/operationstransport.js +103 -0
  303. package/lib/services/operationstransport.js.map +1 -0
  304. package/lib/services/{prometheus.d.ts → prometheus.service.d.ts} +13 -11
  305. package/lib/services/prometheus.service.d.ts.map +1 -0
  306. package/lib/services/prometheus.service.js +203 -0
  307. package/lib/services/prometheus.service.js.map +1 -0
  308. package/lib/services/resource.service.d.ts +121 -0
  309. package/lib/services/resource.service.d.ts.map +1 -0
  310. package/lib/services/resource.service.js +301 -0
  311. package/lib/services/resource.service.js.map +1 -0
  312. package/lib/services/service.d.ts +88 -189
  313. package/lib/services/service.d.ts.map +1 -0
  314. package/lib/services/service.js +407 -432
  315. package/lib/services/service.js.map +1 -1
  316. package/lib/services/servicecommands.d.ts +99 -0
  317. package/lib/services/servicecommands.d.ts.map +1 -0
  318. package/lib/services/servicecommands.js +165 -0
  319. package/lib/services/servicecommands.js.map +1 -0
  320. package/lib/services/serviceparameters.d.ts +33 -0
  321. package/lib/services/serviceparameters.d.ts.map +1 -0
  322. package/lib/services/serviceparameters.js +79 -0
  323. package/lib/services/serviceparameters.js.map +1 -0
  324. package/lib/{utils → session}/cookie.d.ts +32 -18
  325. package/lib/session/cookie.d.ts.map +1 -0
  326. package/lib/{utils → session}/cookie.js +76 -23
  327. package/lib/session/cookie.js.map +1 -0
  328. package/lib/session/manager.model.d.ts +71 -0
  329. package/lib/session/manager.model.d.ts.map +1 -0
  330. package/lib/session/manager.model.js +155 -0
  331. package/lib/session/manager.model.js.map +1 -0
  332. package/lib/session/session.d.ts +57 -0
  333. package/lib/session/session.d.ts.map +1 -0
  334. package/lib/session/session.js +126 -0
  335. package/lib/session/session.js.map +1 -0
  336. package/lib/stores/istore.d.ts +99 -0
  337. package/lib/stores/istore.d.ts.map +1 -0
  338. package/lib/stores/istore.js +26 -0
  339. package/lib/stores/istore.js.map +1 -0
  340. package/lib/stores/memory.service.d.ts +114 -0
  341. package/lib/stores/memory.service.d.ts.map +1 -0
  342. package/lib/stores/memory.service.js +343 -0
  343. package/lib/stores/memory.service.js.map +1 -0
  344. package/lib/stores/store.d.ts +127 -768
  345. package/lib/stores/store.d.ts.map +1 -0
  346. package/lib/stores/store.js +258 -1718
  347. package/lib/stores/store.js.map +1 -1
  348. package/lib/templates/templates.d.ts +39 -0
  349. package/lib/templates/templates.d.ts.map +1 -0
  350. package/lib/templates/templates.js +92 -0
  351. package/lib/templates/templates.js.map +1 -0
  352. package/lib/test/application.d.ts +174 -0
  353. package/lib/test/application.d.ts.map +1 -0
  354. package/lib/test/application.js +288 -0
  355. package/lib/test/application.js.map +1 -0
  356. package/lib/test/asyncstorage.d.ts +16 -0
  357. package/lib/test/asyncstorage.d.ts.map +1 -0
  358. package/lib/test/asyncstorage.js +32 -0
  359. package/lib/test/asyncstorage.js.map +1 -0
  360. package/lib/test/core.d.ts +63 -0
  361. package/lib/test/core.d.ts.map +1 -0
  362. package/lib/test/core.js +190 -0
  363. package/lib/test/core.js.map +1 -0
  364. package/lib/test/index.d.ts +7 -0
  365. package/lib/test/index.d.ts.map +1 -0
  366. package/lib/test/index.js +8 -0
  367. package/lib/test/index.js.map +1 -0
  368. package/lib/test/internal.d.ts +34 -0
  369. package/lib/test/internal.d.ts.map +1 -0
  370. package/lib/test/internal.js +156 -0
  371. package/lib/test/internal.js.map +1 -0
  372. package/lib/test/objects.d.ts +318 -0
  373. package/lib/test/objects.d.ts.map +1 -0
  374. package/lib/test/objects.js +443 -0
  375. package/lib/test/objects.js.map +1 -0
  376. package/lib/utils/abstractdeployer.d.ts +5 -2
  377. package/lib/utils/abstractdeployer.d.ts.map +1 -0
  378. package/lib/utils/abstractdeployer.js +3 -0
  379. package/lib/utils/abstractdeployer.js.map +1 -1
  380. package/package.json +85 -56
  381. package/test/cachedapp/webda.config.json +1 -5
  382. package/test/config-cached.json +1 -5
  383. package/test/config.json +6 -99
  384. package/test/data/.env +1 -0
  385. package/test/my-cnf.json +9 -0
  386. package/webda.module.json +3462 -2231
  387. package/lib/application.d.ts +0 -876
  388. package/lib/application.js +0 -741
  389. package/lib/application.js.map +0 -1
  390. package/lib/application.spec.d.ts +0 -1
  391. package/lib/application.spec.js +0 -234
  392. package/lib/application.spec.js.map +0 -1
  393. package/lib/core.d.ts +0 -740
  394. package/lib/core.js +0 -1310
  395. package/lib/core.js.map +0 -1
  396. package/lib/core.spec.d.ts +0 -1
  397. package/lib/core.spec.js +0 -761
  398. package/lib/core.spec.js.map +0 -1
  399. package/lib/errors.d.ts +0 -65
  400. package/lib/errors.js +0 -113
  401. package/lib/errors.js.map +0 -1
  402. package/lib/errors.spec.d.ts +0 -1
  403. package/lib/errors.spec.js +0 -33
  404. package/lib/errors.spec.js.map +0 -1
  405. package/lib/models/aclmodel.spec.d.ts +0 -1
  406. package/lib/models/aclmodel.spec.js +0 -187
  407. package/lib/models/aclmodel.spec.js.map +0 -1
  408. package/lib/models/coremodel.d.ts +0 -887
  409. package/lib/models/coremodel.js +0 -1208
  410. package/lib/models/coremodel.js.map +0 -1
  411. package/lib/models/coremodel.spec.d.ts +0 -1
  412. package/lib/models/coremodel.spec.js +0 -462
  413. package/lib/models/coremodel.spec.js.map +0 -1
  414. package/lib/models/ident.d.ts +0 -53
  415. package/lib/models/ident.js +0 -40
  416. package/lib/models/ident.js.map +0 -1
  417. package/lib/models/ident.spec.d.ts +0 -1
  418. package/lib/models/ident.spec.js +0 -43
  419. package/lib/models/ident.spec.js.map +0 -1
  420. package/lib/models/ownermodel.d.ts +0 -50
  421. package/lib/models/ownermodel.js +0 -65
  422. package/lib/models/ownermodel.js.map +0 -1
  423. package/lib/models/ownermodel.spec.d.ts +0 -1
  424. package/lib/models/ownermodel.spec.js +0 -191
  425. package/lib/models/ownermodel.spec.js.map +0 -1
  426. package/lib/models/relations.d.ts +0 -181
  427. package/lib/models/relations.js +0 -157
  428. package/lib/models/relations.js.map +0 -1
  429. package/lib/models/relations.spec.d.ts +0 -12
  430. package/lib/models/relations.spec.js +0 -224
  431. package/lib/models/relations.spec.js.map +0 -1
  432. package/lib/models/rolemodel.d.ts +0 -10
  433. package/lib/models/rolemodel.js +0 -35
  434. package/lib/models/rolemodel.js.map +0 -1
  435. package/lib/models/rolemodel.spec.d.ts +0 -1
  436. package/lib/models/rolemodel.spec.js +0 -86
  437. package/lib/models/rolemodel.spec.js.map +0 -1
  438. package/lib/models/user.d.ts +0 -100
  439. package/lib/models/user.js +0 -157
  440. package/lib/models/user.js.map +0 -1
  441. package/lib/models/user.spec.d.ts +0 -1
  442. package/lib/models/user.spec.js +0 -88
  443. package/lib/models/user.spec.js.map +0 -1
  444. package/lib/queues/filequeue.d.ts +0 -58
  445. package/lib/queues/filequeue.js +0 -131
  446. package/lib/queues/filequeue.js.map +0 -1
  447. package/lib/queues/filequeue.spec.d.ts +0 -1
  448. package/lib/queues/filequeue.spec.js +0 -78
  449. package/lib/queues/filequeue.spec.js.map +0 -1
  450. package/lib/queues/memoryqueue.d.ts +0 -45
  451. package/lib/queues/memoryqueue.js +0 -81
  452. package/lib/queues/memoryqueue.js.map +0 -1
  453. package/lib/queues/memoryqueue.spec.d.ts +0 -1
  454. package/lib/queues/memoryqueue.spec.js +0 -192
  455. package/lib/queues/memoryqueue.spec.js.map +0 -1
  456. package/lib/queues/queue.spec.d.ts +0 -5
  457. package/lib/queues/queue.spec.js +0 -55
  458. package/lib/queues/queue.spec.js.map +0 -1
  459. package/lib/router.d.ts +0 -172
  460. package/lib/router.js +0 -419
  461. package/lib/router.js.map +0 -1
  462. package/lib/router.spec.d.ts +0 -1
  463. package/lib/router.spec.js +0 -229
  464. package/lib/router.spec.js.map +0 -1
  465. package/lib/services/asyncevents.d.ts +0 -151
  466. package/lib/services/asyncevents.js +0 -217
  467. package/lib/services/asyncevents.js.map +0 -1
  468. package/lib/services/asyncevents.spec.d.ts +0 -1
  469. package/lib/services/asyncevents.spec.js +0 -118
  470. package/lib/services/asyncevents.spec.js.map +0 -1
  471. package/lib/services/authentication.js +0 -772
  472. package/lib/services/authentication.js.map +0 -1
  473. package/lib/services/authentication.spec.d.ts +0 -1
  474. package/lib/services/authentication.spec.js +0 -458
  475. package/lib/services/authentication.spec.js.map +0 -1
  476. package/lib/services/binary.d.ts +0 -549
  477. package/lib/services/binary.js +0 -986
  478. package/lib/services/binary.js.map +0 -1
  479. package/lib/services/binary.spec.d.ts +0 -44
  480. package/lib/services/binary.spec.js +0 -438
  481. package/lib/services/binary.spec.js.map +0 -1
  482. package/lib/services/cloudbinary.spec.d.ts +0 -13
  483. package/lib/services/cloudbinary.spec.js +0 -192
  484. package/lib/services/cloudbinary.spec.js.map +0 -1
  485. package/lib/services/configuration.js +0 -178
  486. package/lib/services/configuration.js.map +0 -1
  487. package/lib/services/configuration.spec.d.ts +0 -1
  488. package/lib/services/configuration.spec.js +0 -87
  489. package/lib/services/configuration.spec.js.map +0 -1
  490. package/lib/services/cron.d.ts +0 -73
  491. package/lib/services/cron.js +0 -141
  492. package/lib/services/cron.js.map +0 -1
  493. package/lib/services/cron.spec.d.ts +0 -1
  494. package/lib/services/cron.spec.js +0 -76
  495. package/lib/services/cron.spec.js.map +0 -1
  496. package/lib/services/cryptoservice.js +0 -434
  497. package/lib/services/cryptoservice.js.map +0 -1
  498. package/lib/services/cryptoservice.spec.d.ts +0 -1
  499. package/lib/services/cryptoservice.spec.js +0 -177
  500. package/lib/services/cryptoservice.spec.js.map +0 -1
  501. package/lib/services/debugmailer.d.ts +0 -36
  502. package/lib/services/debugmailer.js +0 -52
  503. package/lib/services/debugmailer.js.map +0 -1
  504. package/lib/services/debugmailer.spec.d.ts +0 -1
  505. package/lib/services/debugmailer.spec.js +0 -29
  506. package/lib/services/debugmailer.spec.js.map +0 -1
  507. package/lib/services/domainservice.d.ts +0 -152
  508. package/lib/services/domainservice.js +0 -881
  509. package/lib/services/domainservice.js.map +0 -1
  510. package/lib/services/domainservice.spec.d.ts +0 -1
  511. package/lib/services/domainservice.spec.js +0 -401
  512. package/lib/services/domainservice.spec.js.map +0 -1
  513. package/lib/services/filebinary.d.ts +0 -133
  514. package/lib/services/filebinary.js +0 -371
  515. package/lib/services/filebinary.js.map +0 -1
  516. package/lib/services/filebinary.spec.d.ts +0 -21
  517. package/lib/services/filebinary.spec.js +0 -415
  518. package/lib/services/filebinary.spec.js.map +0 -1
  519. package/lib/services/fileconfiguration.d.ts +0 -22
  520. package/lib/services/fileconfiguration.js +0 -48
  521. package/lib/services/fileconfiguration.js.map +0 -1
  522. package/lib/services/fileconfiguration.spec.d.ts +0 -1
  523. package/lib/services/fileconfiguration.spec.js +0 -177
  524. package/lib/services/fileconfiguration.spec.js.map +0 -1
  525. package/lib/services/invitationservice.d.ts +0 -222
  526. package/lib/services/invitationservice.js +0 -526
  527. package/lib/services/invitationservice.js.map +0 -1
  528. package/lib/services/invitationservice.spec.d.ts +0 -1
  529. package/lib/services/invitationservice.spec.js +0 -516
  530. package/lib/services/invitationservice.spec.js.map +0 -1
  531. package/lib/services/kubernetesconfiguration.d.ts +0 -26
  532. package/lib/services/kubernetesconfiguration.js +0 -54
  533. package/lib/services/kubernetesconfiguration.js.map +0 -1
  534. package/lib/services/kubernetesconfiguration.spec.d.ts +0 -1
  535. package/lib/services/kubernetesconfiguration.spec.js +0 -147
  536. package/lib/services/kubernetesconfiguration.spec.js.map +0 -1
  537. package/lib/services/mailer.d.ts +0 -165
  538. package/lib/services/mailer.js +0 -176
  539. package/lib/services/mailer.js.map +0 -1
  540. package/lib/services/mailer.spec.d.ts +0 -1
  541. package/lib/services/mailer.spec.js +0 -144
  542. package/lib/services/mailer.spec.js.map +0 -1
  543. package/lib/services/notificationservice.js.map +0 -1
  544. package/lib/services/notificationservice.spec.d.ts +0 -1
  545. package/lib/services/notificationservice.spec.js +0 -78
  546. package/lib/services/notificationservice.spec.js.map +0 -1
  547. package/lib/services/oauth.spec.d.ts +0 -1
  548. package/lib/services/oauth.spec.js +0 -184
  549. package/lib/services/oauth.spec.js.map +0 -1
  550. package/lib/services/prometheus.js +0 -160
  551. package/lib/services/prometheus.js.map +0 -1
  552. package/lib/services/prometheus.spec.d.ts +0 -1
  553. package/lib/services/prometheus.spec.js +0 -57
  554. package/lib/services/prometheus.spec.js.map +0 -1
  555. package/lib/services/resource.d.ts +0 -87
  556. package/lib/services/resource.js +0 -156
  557. package/lib/services/resource.js.map +0 -1
  558. package/lib/services/resource.spec.d.ts +0 -1
  559. package/lib/services/resource.spec.js +0 -122
  560. package/lib/services/resource.spec.js.map +0 -1
  561. package/lib/services/service.spec.d.ts +0 -1
  562. package/lib/services/service.spec.js +0 -268
  563. package/lib/services/service.spec.js.map +0 -1
  564. package/lib/stores/aggregator.d.ts +0 -41
  565. package/lib/stores/aggregator.js +0 -80
  566. package/lib/stores/aggregator.js.map +0 -1
  567. package/lib/stores/aliasstore.d.ts +0 -108
  568. package/lib/stores/aliasstore.js +0 -168
  569. package/lib/stores/aliasstore.js.map +0 -1
  570. package/lib/stores/aliasstore.spec.d.ts +0 -11
  571. package/lib/stores/aliasstore.spec.js +0 -89
  572. package/lib/stores/aliasstore.spec.js.map +0 -1
  573. package/lib/stores/file.d.ts +0 -107
  574. package/lib/stores/file.js +0 -188
  575. package/lib/stores/file.js.map +0 -1
  576. package/lib/stores/file.spec.d.ts +0 -19
  577. package/lib/stores/file.spec.js +0 -232
  578. package/lib/stores/file.spec.js.map +0 -1
  579. package/lib/stores/mapper.d.ts +0 -149
  580. package/lib/stores/mapper.js +0 -293
  581. package/lib/stores/mapper.js.map +0 -1
  582. package/lib/stores/mapper.spec.d.ts +0 -1
  583. package/lib/stores/mapper.spec.js +0 -160
  584. package/lib/stores/mapper.spec.js.map +0 -1
  585. package/lib/stores/memory.d.ts +0 -151
  586. package/lib/stores/memory.js +0 -371
  587. package/lib/stores/memory.js.map +0 -1
  588. package/lib/stores/memory.spec.d.ts +0 -20
  589. package/lib/stores/memory.spec.js +0 -328
  590. package/lib/stores/memory.spec.js.map +0 -1
  591. package/lib/stores/modelmapper.d.ts +0 -61
  592. package/lib/stores/modelmapper.js +0 -199
  593. package/lib/stores/modelmapper.js.map +0 -1
  594. package/lib/stores/store.spec.d.ts +0 -65
  595. package/lib/stores/store.spec.js +0 -906
  596. package/lib/stores/store.spec.js.map +0 -1
  597. package/lib/test.d.ts +0 -162
  598. package/lib/test.js +0 -399
  599. package/lib/test.js.map +0 -1
  600. package/lib/unpackedapplication.d.ts +0 -76
  601. package/lib/unpackedapplication.js +0 -299
  602. package/lib/unpackedapplication.js.map +0 -1
  603. package/lib/utils/abstractdeployer.spec.d.ts +0 -1
  604. package/lib/utils/abstractdeployer.spec.js +0 -21
  605. package/lib/utils/abstractdeployer.spec.js.map +0 -1
  606. package/lib/utils/case.d.ts +0 -7
  607. package/lib/utils/case.js +0 -43
  608. package/lib/utils/case.js.map +0 -1
  609. package/lib/utils/case.spec.d.ts +0 -1
  610. package/lib/utils/case.spec.js +0 -50
  611. package/lib/utils/case.spec.js.map +0 -1
  612. package/lib/utils/context.d.ts +0 -462
  613. package/lib/utils/context.js +0 -732
  614. package/lib/utils/context.js.map +0 -1
  615. package/lib/utils/context.spec.d.ts +0 -9
  616. package/lib/utils/context.spec.js +0 -372
  617. package/lib/utils/context.spec.js.map +0 -1
  618. package/lib/utils/cookie.js.map +0 -1
  619. package/lib/utils/cookie.spec.d.ts +0 -1
  620. package/lib/utils/cookie.spec.js +0 -78
  621. package/lib/utils/cookie.spec.js.map +0 -1
  622. package/lib/utils/esm.d.ts +0 -13
  623. package/lib/utils/esm.js +0 -19
  624. package/lib/utils/esm.js.map +0 -1
  625. package/lib/utils/httpcontext.js.map +0 -1
  626. package/lib/utils/httpcontext.spec.d.ts +0 -4
  627. package/lib/utils/httpcontext.spec.js +0 -77
  628. package/lib/utils/httpcontext.spec.js.map +0 -1
  629. package/lib/utils/logger.d.ts +0 -91
  630. package/lib/utils/logger.js +0 -121
  631. package/lib/utils/logger.js.map +0 -1
  632. package/lib/utils/logger.spec.d.ts +0 -1
  633. package/lib/utils/logger.spec.js +0 -48
  634. package/lib/utils/logger.spec.js.map +0 -1
  635. package/lib/utils/serializers.d.ts +0 -161
  636. package/lib/utils/serializers.js +0 -420
  637. package/lib/utils/serializers.js.map +0 -1
  638. package/lib/utils/serializers.spec.d.ts +0 -1
  639. package/lib/utils/serializers.spec.js +0 -313
  640. package/lib/utils/serializers.spec.js.map +0 -1
  641. package/lib/utils/session.d.ts +0 -126
  642. package/lib/utils/session.js +0 -166
  643. package/lib/utils/session.js.map +0 -1
  644. package/lib/utils/session.spec.d.ts +0 -1
  645. package/lib/utils/session.spec.js +0 -71
  646. package/lib/utils/session.spec.js.map +0 -1
  647. package/lib/utils/throttler.d.ts +0 -102
  648. package/lib/utils/throttler.js +0 -168
  649. package/lib/utils/throttler.js.map +0 -1
  650. package/lib/utils/throttler.spec.d.ts +0 -1
  651. package/lib/utils/throttler.spec.js +0 -55
  652. package/lib/utils/throttler.spec.js.map +0 -1
  653. package/lib/utils/waiter.d.ts +0 -93
  654. package/lib/utils/waiter.js +0 -148
  655. package/lib/utils/waiter.js.map +0 -1
  656. package/lib/utils/waiter.spec.d.ts +0 -1
  657. package/lib/utils/waiter.spec.js +0 -98
  658. package/lib/utils/waiter.spec.js.map +0 -1
  659. package/test/config-file-missing-file-no-default.json +0 -44
  660. package/test/config-file-missing-file.json +0 -55
  661. package/test/config-file-no-reload.json +0 -69
  662. package/test/config-file-reload.json +0 -68
  663. package/test/config-invitation.json +0 -63
  664. package/test/config-kube-reload.json +0 -68
  665. package/test/config-reload.json +0 -66
  666. package/test/config.old.json +0 -152
  667. package/test/jsonutils/mdocs.yaml +0 -56
  668. package/test/jsonutils/test.json +0 -3
  669. package/test/jsonutils/test.yml +0 -5
  670. package/test/moddas/annotatedservice.js +0 -23
  671. package/test/moddas/debugmailer.js +0 -13
  672. package/test/moddas/fakeservice.js +0 -4
  673. package/test/moddas/voidstore.js +0 -66
  674. package/test/models/ident.js +0 -36
  675. package/test/models/task.js +0 -42
@@ -1,70 +1,129 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- import { Counter, Histogram } from "../core.js";
8
- import { MemoryStore, ModelMapLoaderImplementation, Throttler, WebdaError } from "../index.js";
9
- import { CoreModel } from "../models/coremodel.js";
10
- import { Route, Service, ServiceParameters } from "../services/service.js";
11
- import * as WebdaQL from "@webda/ql";
1
+ import { Counter, Histogram } from "../metrics/metrics.js";
2
+ import * as WebdaError from "../errors/errors.js";
3
+ import { registerRepository } from "@webda/models";
4
+ import { ServiceParameters } from "../services/serviceparameters.js";
5
+ import { Service } from "../services/service.js";
6
+ import { useApplication, useModel, useModelId } from "../application/hooks.js";
7
+ import { useLog } from "../loggers/hooks.js";
8
+ import { useCore, useModelMetadata } from "../core/hooks.js";
9
+ /** Error thrown when an item is not found in a store */
12
10
  export class StoreNotFoundError extends WebdaError.CodeError {
11
+ /** Create a new StoreNotFoundError
12
+ * @param uuid - the item primary key
13
+ * @param storeName - the store name
14
+ */
13
15
  constructor(uuid, storeName) {
14
16
  super("STORE_NOTFOUND", `Item not found ${uuid} Store(${storeName})`);
15
17
  }
16
18
  }
19
+ /** Error thrown when a conditional update fails due to a version/condition mismatch */
17
20
  export class UpdateConditionFailError extends WebdaError.CodeError {
21
+ /** Create a new UpdateConditionFailError
22
+ * @param uuid - the item primary key
23
+ * @param conditionField - the condition field name
24
+ * @param condition - the expected condition value
25
+ */
18
26
  constructor(uuid, conditionField, condition) {
19
27
  super("STORE_UPDATE_CONDITION_FAILED", `UpdateCondition not met on ${uuid}.${conditionField} === ${condition instanceof Date ? condition.toISOString() : condition}`);
20
28
  }
21
29
  }
22
30
  /**
23
31
  * Store parameter
32
+ *
33
+ * @internal — Store configuration schema. Authored in `webda.config`/deployment
34
+ * files; not consumed by app code directly.
24
35
  */
25
36
  export class StoreParameters extends ServiceParameters {
26
- constructor(params, service) {
27
- var _a;
28
- super(params);
29
- this.model ?? (this.model = "Webda/CoreModel");
30
- let expose = params.expose;
31
- if (typeof expose == "boolean") {
32
- expose = {};
33
- expose.url = "/" + service.getName().toLowerCase();
34
- }
35
- else if (typeof expose == "string") {
36
- expose = {
37
- url: expose
38
- };
39
- }
40
- else if (typeof expose == "object" && expose.url == undefined) {
41
- expose.url = "/" + service.getName().toLowerCase();
37
+ /**
38
+ * Models managed by this Store.
39
+ *
40
+ * @default ["Webda/RegistryEntry"]
41
+ */
42
+ models;
43
+ /**
44
+ * Allow to load object that does not have the type data
45
+ *
46
+ * If set to true, then the Store will only managed the defined _model and no
47
+ * model extending this one
48
+ *
49
+ * @default false
50
+ */
51
+ strict;
52
+ /**
53
+ * When __type model not found, use the model
54
+ * If strict is setup this parameter is not used
55
+ *
56
+ * @default true
57
+ */
58
+ defaultModel;
59
+ /**
60
+ * If set, Store will ignore the __type
61
+ *
62
+ * @default false
63
+ */
64
+ forceModel;
65
+ /**
66
+ * Slow query threshold
67
+ *
68
+ * @default 30000
69
+ */
70
+ slowQueryThreshold;
71
+ /**
72
+ * Model Aliases to allow easier rename of Model
73
+ */
74
+ modelAliases;
75
+ /**
76
+ * Disable default memory cache
77
+ */
78
+ noCache;
79
+ /**
80
+ * Load store parameters with defaults for model type, strict mode, and aliases
81
+ * @param params - the service parameters
82
+ * @returns the result
83
+ */
84
+ load(params) {
85
+ // REFACTOR >= 5
86
+ if (params.expose) {
87
+ throw new Error("Expose is not supported anymore, use DomainService instead");
42
88
  }
43
- if (expose) {
44
- expose.restrict = expose.restrict || {};
45
- this.expose = expose;
46
- (_a = this.expose).queryMethod ?? (_a.queryMethod = "GET");
47
- this.url = expose.url;
89
+ // END_REFACTOR
90
+ super.load(params);
91
+ // Deprecation mapping: model + additionalModels → models[]
92
+ const hasModels = Array.isArray(params.models);
93
+ const hasModel = typeof params.model === "string";
94
+ // Presence check (not length) used for the conflict guard so that
95
+ // `{ models: [...], additionalModels: [] }` is still detected as ambiguous.
96
+ const hasAdditionalKey = Array.isArray(params.additionalModels);
97
+ // Length check used for the deprecation branch: an empty additionalModels
98
+ // alongside a bare `model` is unambiguous and should not warn on its own.
99
+ const hasAdditional = hasAdditionalKey && params.additionalModels.length > 0;
100
+ if (hasModels && (hasModel || hasAdditionalKey)) {
101
+ throw new Error("StoreParameters: `models` and `model`/`additionalModels` are mutually exclusive — ambiguous configuration");
48
102
  }
49
- if (params.map) {
50
- throw new Error("Deprecated map usage, use a MapperService");
103
+ if (hasModels) {
104
+ this.models = [...params.models];
51
105
  }
52
- if (params.index) {
53
- throw new Error("Deprecated index usage, use an AggregatorService");
106
+ else if (hasModel || hasAdditional) {
107
+ useLog("WARN", `StoreParameters: \`model\` and \`additionalModels\` are deprecated. Use \`models: [...]\` instead.`);
108
+ this.models = [params.model ?? "Webda/RegistryEntry", ...(params.additionalModels ?? [])];
54
109
  }
55
- this.strict ?? (this.strict = false);
56
- this.defaultModel ?? (this.defaultModel = true);
57
- this.forceModel ?? (this.forceModel = false);
58
- this.slowQueryThreshold ?? (this.slowQueryThreshold = 30000);
59
- this.modelAliases ?? (this.modelAliases = {});
60
- this.additionalModels ?? (this.additionalModels = []);
110
+ else {
111
+ this.models = ["Webda/RegistryEntry"];
112
+ }
113
+ // When the caller passed `models[]` (or nothing at all), backfill the deprecated
114
+ // fields from the canonical `models[]` so any code still reading `parameters.model`
115
+ // or `parameters.additionalModels` keeps working. In the legacy-input branch
116
+ // `super.load(params)` already set both via Object.assign, so the `??=` is a no-op.
117
+ this.strict ??= false;
118
+ this.defaultModel ??= true;
119
+ this.forceModel ??= false;
120
+ this.slowQueryThreshold ??= 30000;
121
+ this.modelAliases ??= {};
122
+ return this;
61
123
  }
62
124
  }
63
125
  /**
64
126
  * This class handle NoSQL storage and mapping (duplication) between NoSQL object
65
- * TODO Create the mapping documentation
66
- *
67
- * It use basic CRUD, and can expose those 4 to through HTTP
68
127
  *
69
128
  * It emits events :
70
129
  * Store.Save: Before saving the object
@@ -77,106 +136,162 @@ export class StoreParameters extends ServiceParameters {
77
136
  * Store.Action: When an action will be done on an object
78
137
  * Store.Actioned: When an action has been done on an object
79
138
  *
80
- * Mapping:
81
- *
82
- *
83
- * Parameters
84
- *
85
- * map: { ... }
86
- * expose: { // Enable the HTTP exposure
87
- * url: '', // The url to expose to by default it is service name in lowercase ( users for example )
88
- * restrict: {
89
- * create: true, // Don't expose the POST /users
90
- * update: true, // Don't expose the PUT /users/{uuid}
91
- * delete: true, // Don't expose the DELETE /users/{uuid}
92
- * get: true // Don't expose the GET /users/{uuid}
93
- * }
94
- * }
139
+ * @internal — Subclassed by store packages only. App code never references a
140
+ * Store directly: use `useRepository(Model)` or static model methods
141
+ * (`Model.create()`, `Model.query()`, `Model.ref()`).
95
142
  * @category CoreServices
96
143
  */
97
144
  class Store extends Service {
98
- constructor() {
99
- super(...arguments);
100
- /**
101
- * Contain the reverse map
102
- */
103
- this._reverseMap = [];
104
- /**
105
- * Store teh manager hierarchy with their depth
106
- */
107
- this._modelsHierarchy = {};
108
- /**
109
- * Contain the model uuid field
110
- */
111
- this._uuidField = "uuid";
145
+ /** All model classes managed by this store. Index 0 is the legacy "primary" model. */
146
+ _models = [];
147
+ /** Metadata for each model in `_models`, keyed by Identifier. */
148
+ _modelMetadatas = new Map();
149
+ /** Store the manager hierarchy with their depth */
150
+ _modelsHierarchy = {};
151
+ /**
152
+ * Override the resolved model class for this store at runtime. Used by
153
+ * the abstract `StoreTest` harness so test fixtures can substitute a
154
+ * subclass with extra fields in place of the configured model. In
155
+ * production this is a no-op the framework never calls.
156
+ * @param model - the substitute model class
157
+ */
158
+ setModelDefinitionHelper(model) {
159
+ this._models[0] = model;
160
+ }
161
+ /**
162
+ * Compute and register repositories for all known models based on available stores.
163
+ *
164
+ * Called from `Store.init()` so each store's init triggers a recompute.
165
+ * Cannot be cached: the FIRST store to init (typically `Registry`) would
166
+ * claim every model with its fallback repository, and subsequent
167
+ * stores wouldn't get a chance to claim their configured models.
168
+ * Re-running is idempotent — `registerRepository` overwrites map entries
169
+ * in place, and the resolution loop is deterministic per current
170
+ * service/model state.
171
+ */
172
+ static computeStores() {
173
+ // Gather all stores and register Repository
174
+ const stores = Object.values(useCore().getServices()).filter(s => s instanceof Store);
175
+ const models = Object.values(useApplication().getModels());
176
+ const registry = useCore().getService("Registry");
177
+ // Check each available models
178
+ for (const model of models) {
179
+ // Model can be null?
180
+ if (!model)
181
+ continue;
182
+ if (!model.Metadata || !Array.isArray(model.Metadata.PrimaryKey)) {
183
+ useLog("WARN", `${useModelId(model)} does not have Metadata or PrimaryKey defined`);
184
+ continue;
185
+ }
186
+ let currentValue = -1;
187
+ let currentStore = undefined;
188
+ for (const store of stores) {
189
+ const value = store.handleModel(model);
190
+ if (value < 0 || (value > currentValue && currentValue !== -1)) {
191
+ continue;
192
+ }
193
+ currentValue = value;
194
+ currentStore = store;
195
+ }
196
+ if (!currentStore) {
197
+ useLog("TRACE", `${useModelId(model)} fallback to Registry store`);
198
+ currentStore = registry;
199
+ }
200
+ // Register the repository
201
+ registerRepository(model, currentStore.getRepository(model));
202
+ useLog("DEBUG", `${useModelId(model)} using store ${currentStore.getName()}`);
203
+ }
112
204
  }
113
205
  /**
114
- * Retrieve the Model
206
+ * Retrieve the Models and build the models hierarchy map.
115
207
  *
116
- * @throws Error if model is not found
208
+ * Walks `parameters.models[]` (the canonical flat list introduced in Task 1).
209
+ * If the list is empty or contains only the default "Webda/RegistryEntry"
210
+ * fallback, the hierarchy stays empty and the store will not claim any model
211
+ * — preserving the pre-migration fallback behaviour for test-only or
212
+ * misconfigured stores.
117
213
  */
118
214
  computeParameters() {
119
215
  super.computeParameters();
120
- const app = this.getWebda().getApplication();
121
- const p = this.parameters;
122
- this._model = app.getModel(p.model);
123
- this._modelType = this._model.getIdentifier();
124
- this._uuidField = this._model.getUuidField();
125
- if (!this.parameters.noCache) {
126
- this._cacheStore = new MemoryStore(this._webda, `_${this.getName()}_cache`, {
127
- model: this.parameters.model
128
- });
129
- this._cacheStore.computeParameters();
130
- this._cacheStore.initMetrics();
131
- this.cacheStorePatchException();
216
+ const ids = this.parameters.models ?? [];
217
+ // Empty / default RegistryEntry → leave hierarchy empty (preserves test-only / fallback behaviour).
218
+ const isOnlyDefault = ids.length === 1 && ids[0] === "Webda/RegistryEntry";
219
+ if (ids.length === 0 || isOnlyDefault) {
220
+ return;
132
221
  }
133
- const recursive = (tree, depth) => {
134
- var _a;
135
- for (let i in tree) {
136
- (_a = this._modelsHierarchy)[i] ?? (_a[i] = depth);
137
- this._modelsHierarchy[i] = Math.min(depth, this._modelsHierarchy[i]);
138
- this._modelsHierarchy[app.completeNamespace(i)] = this._modelsHierarchy[i];
139
- recursive(app.getModelHierarchy(i).children, depth + 1);
222
+ this._models = [];
223
+ this._modelMetadatas = new Map();
224
+ this._modelsHierarchy = {};
225
+ // Subclasses in ModelMetadata are resolved to ModelClass objects at runtime
226
+ // (see Application.setModelMetadata). Accept both string IDs and ModelClass
227
+ // references so the hierarchy is keyed by string identifier throughout.
228
+ const recursive = (subclasses, depth) => {
229
+ for (const entry of subclasses) {
230
+ let subModel;
231
+ let subId;
232
+ if (typeof entry === "string") {
233
+ subId = entry;
234
+ try {
235
+ subModel = useModel(entry);
236
+ }
237
+ catch {
238
+ continue;
239
+ }
240
+ }
241
+ else {
242
+ subModel = entry;
243
+ subId = useModelId(subModel);
244
+ }
245
+ if (!subId || !subModel)
246
+ continue;
247
+ this._modelsHierarchy[subId] = Math.min(depth, this._modelsHierarchy[subId] ?? depth);
248
+ const subMeta = useModelMetadata(subModel);
249
+ if (!subMeta)
250
+ continue;
251
+ recursive(subMeta.Subclasses ?? [], depth + 1);
140
252
  }
141
253
  };
142
- // Compute the hierarchy
143
- this._modelsHierarchy[this._model.getIdentifier(false)] = 0;
144
- this._modelsHierarchy[this._model.getIdentifier()] = 0;
145
- // Strict Store only store their model
146
- if (!this.parameters.strict) {
147
- recursive(this._model.getHierarchy().children, 1);
148
- }
149
- // Add additional models
150
- if (this.parameters.additionalModels.length) {
151
- // Strict mode is to only allow one model per store
152
- if (this.parameters.strict) {
153
- this.log("ERROR", "Cannot add additional models in strict mode");
254
+ for (const id of ids) {
255
+ let model;
256
+ try {
257
+ model = useModel(id);
154
258
  }
155
- else {
156
- for (let modelType of this.parameters.additionalModels) {
157
- const model = app.getModel(modelType);
158
- this._modelsHierarchy[model.getIdentifier(false)] = 0;
159
- this._modelsHierarchy[model.getIdentifier()] = 0;
160
- recursive(model.getHierarchy().children, 1);
161
- }
259
+ catch {
260
+ model = undefined;
261
+ }
262
+ if (!model) {
263
+ useLog("TRACE", `Store ${this.getName?.() ?? "unknown"}: model not found: ${id}`);
264
+ continue;
265
+ }
266
+ const meta = useModelMetadata(model);
267
+ if (!meta) {
268
+ useLog("WARN", `Store ${this.getName?.() ?? "unknown"}: model metadata not found for ${id}`);
269
+ continue;
270
+ }
271
+ this._models.push(model);
272
+ this._modelMetadatas.set(meta.Identifier, meta);
273
+ this._modelsHierarchy[meta.Identifier] = 0;
274
+ if (!this.parameters.strict) {
275
+ recursive(meta.Subclasses ?? [], 1);
162
276
  }
163
- }
164
- if (this.getParameters().expose) {
165
- this.log("WARN", "Exposing a store is not recommended, use a DomainService instead to expose all your CoreModel");
166
277
  }
167
278
  }
279
+ /**
280
+ * Log a slow query (placeholder for future implementation)
281
+ * @param _query - the query to execute
282
+ * @param _reason - the reason
283
+ * @param _time - the time
284
+ */
168
285
  logSlowQuery(_query, _reason, _time) {
169
286
  // TODO Need to implement: https://github.com/loopingz/webda.io/issues/202
170
287
  }
171
288
  /**
172
- * Invalidate a cache entry
173
- * @param uid
289
+ * Initialize the store
290
+ * @returns this for chaining
174
291
  */
175
- async invalidateCache(uid) {
176
- if (this._cacheStore) {
177
- this.metrics.cache_invalidations.inc();
178
- await this._cacheStore.delete(uid, undefined, undefined, true);
179
- }
292
+ async init() {
293
+ Store.computeStores();
294
+ return super.init();
180
295
  }
181
296
  /**
182
297
  * @override
@@ -192,1619 +307,44 @@ class Store extends Service {
192
307
  name: "slow_queries",
193
308
  help: "Number of slow queries encountered"
194
309
  });
195
- this.metrics.cache_invalidations = this.getMetric(Counter, {
196
- name: "cache_invalidations",
197
- help: "Number of cache invalidation encountered"
198
- });
199
- this.metrics.cache_hits = this.getMetric(Counter, {
200
- name: "cache_hits",
201
- help: "Number of cache hits"
202
- });
310
+ // this.metrics.cache_invalidations = this.getMetric(Counter, {
311
+ // name: "cache_invalidations",
312
+ // help: "Number of cache invalidation encountered"
313
+ // });
314
+ // this.metrics.cache_hits = this.getMetric(Counter, {
315
+ // name: "cache_hits",
316
+ // help: "Number of cache hits"
317
+ // });
203
318
  this.metrics.queries = this.getMetric(Histogram, {
204
319
  name: "queries",
205
320
  help: "Query duration"
206
321
  });
207
322
  }
208
323
  /**
209
- * Return Store current model
210
- * @returns
324
+ * All models managed by this store.
325
+ * @returns the array of model classes managed by this store
211
326
  */
212
- getModel() {
213
- return this._model;
327
+ getModels() {
328
+ return this._models;
214
329
  }
215
330
  /**
216
331
  * Return if a model is handled by the store
217
- * @param model
332
+ * @param model - the model to use
218
333
  * @return distance from the managed class -1 means not managed, 0 manage exactly this model, >0 manage an ancestor model
219
334
  *
335
+ * @returns the result number
220
336
  */
221
337
  handleModel(model) {
222
- const name = this.getWebda().getApplication().getModelName(model);
338
+ const name = useModelId(model);
223
339
  return this._modelsHierarchy[name] ?? -1;
224
340
  }
225
341
  /**
226
- * Get From Cache or main
227
- * @param uuid
228
- * @param raiseIfNotFound
229
- * @returns
230
- */
231
- async _getFromCache(uuid, raiseIfNotFound = false) {
232
- let res = await this._cacheStore?._get(uuid);
233
- if (!res) {
234
- res = await this._get(uuid, raiseIfNotFound);
235
- if (res) {
236
- await this._cacheStore?._save(res);
237
- }
238
- }
239
- else {
240
- this.metrics.cache_hits.inc();
241
- res.__store = this;
242
- }
243
- return res;
244
- }
245
- /**
246
- * Get object from store
247
- * @param uid
248
- * @returns
249
- */
250
- async getObject(uid) {
251
- this.metrics.operations_total.inc({ operation: "get" });
252
- return this._getFromCache(uid);
253
- }
254
- /**
255
- * @override
256
- */
257
- getUrl(url, methods) {
258
- // If url is absolute
259
- if (url.startsWith("/")) {
260
- return url;
261
- }
262
- // Parent url to find here
263
- const expose = this.parameters.expose;
264
- if (!expose.url ||
265
- (url === "." && methods.includes("POST") && expose.restrict.create) ||
266
- (url === "./{uuid}" && methods.includes("DELETE") && expose.restrict.delete) ||
267
- (url === "./{uuid}" && methods.includes("PATCH") && expose.restrict.update) ||
268
- (url === "./{uuid}" && methods.includes("PUT") && expose.restrict.update) ||
269
- (url === "./{uuid}" && methods.includes("GET") && expose.restrict.get) ||
270
- (url === ".{?q}" && methods.includes("GET") && expose.restrict.query) ||
271
- (url === "." && methods.includes("PUT") && expose.restrict.query)) {
272
- return undefined;
273
- }
274
- return super.getUrl(url, methods);
275
- }
276
- static getOpenAPI() { }
277
- /**
278
- * @inheritdoc
279
- */
280
- initRoutes() {
281
- if (!this.parameters.expose) {
282
- return;
283
- }
284
- super.initRoutes();
285
- // We enforce ExposeParameters within the constructor
286
- const expose = this.parameters.expose;
287
- this.getWebda().getRouter().registerModelUrl(this.parameters.model, expose.url);
288
- // Query endpoint
289
- if (!expose.restrict.query) {
290
- let requestBody;
291
- if (expose.queryMethod === "PUT") {
292
- requestBody = {
293
- content: {
294
- "application/json": {
295
- schema: {
296
- properties: {
297
- q: {
298
- type: "string"
299
- }
300
- }
301
- }
302
- }
303
- }
304
- };
305
- }
306
- this.addRoute(expose.queryMethod === "GET" ? `.{?q}` : ".", [expose.queryMethod], this.httpQuery, {
307
- model: this.parameters.model,
308
- [expose.queryMethod.toLowerCase()]: {
309
- description: `Query on ${this.parameters.model} model with WebdaQL`,
310
- summary: "Query " + this.parameters.model,
311
- operationId: `query${this._model.name}`,
312
- requestBody,
313
- responses: {
314
- "200": {
315
- description: `Retrieve models ${this._model.name}`,
316
- content: {
317
- "application/json": {
318
- schema: {
319
- properties: {
320
- continuationToken: {
321
- type: "string"
322
- },
323
- results: {
324
- type: "array",
325
- items: {
326
- $ref: `#/components/schemas/${this._model.name}`
327
- }
328
- }
329
- }
330
- }
331
- }
332
- }
333
- },
334
- "400": {
335
- description: "Query is invalid"
336
- },
337
- "403": {
338
- description: "You don't have permissions"
339
- }
340
- }
341
- }
342
- });
343
- }
344
- // Model actions
345
- if (this._model && this._model.getActions) {
346
- let actions = this._model.getActions();
347
- Object.keys(actions).forEach(name => {
348
- let action = actions[name];
349
- action.method ?? (action.method = name);
350
- if (!action.methods) {
351
- action.methods = ["PUT"];
352
- }
353
- let executer;
354
- if (action.global) {
355
- // By default will grab the object and then call the action
356
- if (!this._model[action.method]) {
357
- throw Error("Action static method " + action.method + " does not exist");
358
- }
359
- executer = this.httpGlobalAction;
360
- this.addRoute(`./${name}`, action.methods, executer, action.openapi);
361
- }
362
- else {
363
- // By default will grab the object and then call the action
364
- if (!this._model.prototype[action.method]) {
365
- throw Error("Action method " + action.method + " does not exist");
366
- }
367
- executer = ctx => this.httpAction(ctx, action.method);
368
- this.addRoute(`./{uuid}/${name}`, action.methods, executer, action.openapi);
369
- }
370
- });
371
- }
372
- }
373
- /**
374
- * OVerwrite the model
375
- * Used mainly in test
376
- */
377
- setModel(model) {
378
- this._model = model;
379
- this._cacheStore?.setModel(model);
380
- this.parameters.strict = false;
381
- }
382
- /**
383
- * We should ignore exception from the store
384
- */
385
- cacheStorePatchException() {
386
- const replacer = original => {
387
- return (...args) => {
388
- return original
389
- .bind(this._cacheStore, ...args)()
390
- .catch(err => {
391
- this.log("TRACE", `Ignoring cache exception ${this._name}: ${err.message}`);
392
- });
393
- };
394
- };
395
- for (let i of [
396
- "_get",
397
- "_patch",
398
- "_update",
399
- "_delete",
400
- "_incrementAttributes",
401
- "_upsertItemToCollection",
402
- "_deleteItemFromCollection",
403
- "_removeAttribute"
404
- ]) {
405
- this._cacheStore[i] = replacer(this._cacheStore[i]);
406
- }
407
- }
408
- /**
409
- * Init a model from the current stored data
410
- *
411
- * Initial the reverse map as well
412
- *
413
- * @param object
414
- * @returns
415
- */
416
- initModel(object = {}) {
417
- var _a;
418
- object.__type ?? (object.__type = this.getWebda().getApplication().getModelFromInstance(object) || this._modelType);
419
- // Make sure to send a model object
420
- if (!(object instanceof this._model)) {
421
- // Dynamic load type
422
- if (object.__type && !this.getParameters().forceModel) {
423
- try {
424
- const modelType = this.getWebda()
425
- .getApplication()
426
- .getModel(this.parameters.modelAliases[object.__type] || object.__type);
427
- object = new modelType().load(object, true);
428
- }
429
- catch (err) {
430
- if (!this.parameters.defaultModel) {
431
- throw new Error(`Unknown model ${object.__type} found for Store(${this.getName()})`);
432
- }
433
- object = this._model.factory(object);
434
- }
435
- }
436
- else {
437
- object = this._model.factory(object);
438
- }
439
- }
440
- if (!object.getUuid()) {
441
- object.setUuid(object.generateUid(object));
442
- }
443
- object.__store = this;
444
- for (let i in this._reverseMap) {
445
- object[_a = this._reverseMap[i].property] ?? (object[_a] = []);
446
- for (let j in object[this._reverseMap[i].property]) {
447
- if (object[this._reverseMap[i].property][j] instanceof ModelMapLoaderImplementation) {
448
- continue;
449
- }
450
- // Use Partial
451
- object[this._reverseMap[i].property][j] = this._reverseMap[i].mapper.newModel(object[this._reverseMap[i].property][j]);
452
- object[this._reverseMap[i].property][j].setContext(object.getContext());
453
- }
454
- }
455
- return object;
456
- }
457
- /**
458
- * Get a new model with this data preloaded
459
- * @param object
460
- * @returns
461
- */
462
- newModel(object = {}) {
463
- let result = this.initModel(object);
464
- Object.keys(object).forEach(k => result.__dirty.add(k));
465
- return result;
466
- }
467
- /**
468
- * Add reverse map information
469
- *
470
- * @param prop
471
- * @param cascade
472
- * @param store
473
- */
474
- addReverseMap(prop, store) {
475
- this._reverseMap.push({
476
- property: prop,
477
- mapper: store
478
- });
479
- }
480
- /**
481
- * Increment attributes of an object
482
- *
483
- * @param uid
484
- * @param info
485
- * @returns
486
- */
487
- async incrementAttributes(uid, info) {
488
- let params = info.filter(i => i.value !== 0);
489
- // If value === 0 no need to update anything
490
- if (params.length === 0) {
491
- return;
492
- }
493
- let updateDate = new Date();
494
- this.metrics.operations_total.inc({ operation: "increment" });
495
- await this._incrementAttributes(uid, params, updateDate);
496
- const evt = {
497
- object_id: uid,
498
- store: this,
499
- updateDate,
500
- partial_update: {
501
- increments: params
502
- }
503
- };
504
- await this.emitStoreEvent("Store.PartialUpdated", evt);
505
- return updateDate;
506
- }
507
- /**
508
- * Helper function that call incrementAttributes
509
- * @param uid
510
- * @param prop
511
- * @param value
512
- * @returns
513
- */
514
- async incrementAttribute(uid, prop, value) {
515
- return this.incrementAttributes(uid, [{ property: prop, value }]);
516
- }
517
- /**
518
- * Add or update an item to an array in the model
519
- *
520
- * @param uid of the model
521
- * @param prop of the model to add in
522
- * @param item to add in the array
523
- * @param index if specified update item in this index
524
- * @param itemWriteCondition value of the condition to test (in case of update)
525
- * @param itemWriteConditionField field to read the condition from (in case of update)
526
- */
527
- async upsertItemToCollection(uid, prop, item, index = undefined, itemWriteCondition = undefined, itemWriteConditionField = this._uuidField) {
528
- let updateDate = new Date();
529
- this.metrics.operations_total.inc({ operation: "collectionUpsert" });
530
- await this._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
531
- await this.emitStoreEvent("Store.PartialUpdated", {
532
- object_id: uid,
533
- store: this,
534
- updateDate,
535
- partial_update: {
536
- addItem: {
537
- value: item,
538
- property: prop,
539
- index: index
540
- }
541
- }
542
- });
543
- return updateDate;
544
- }
545
- /**
546
- * Remove an item from an array in the model
547
- *
548
- * @param uid of the model
549
- * @param prop of the model to remove from
550
- * @param index of the item to remove in the array
551
- * @param itemWriteCondition value of the condition
552
- * @param itemWriteConditionField field to read the condition from
553
- */
554
- async deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField = this._uuidField) {
555
- let updateDate = new Date();
556
- this.metrics.operations_total.inc({ operation: "collectionDelete" });
557
- await this._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
558
- await this.emitStoreEvent("Store.PartialUpdated", {
559
- object_id: uid,
560
- store: this,
561
- updateDate,
562
- partial_update: {
563
- deleteItem: {
564
- property: prop,
565
- index: index
566
- }
567
- }
568
- });
569
- return updateDate;
570
- }
571
- /**
572
- * Iterate through the results
573
- *
574
- * This can be resource consuming
575
- *
576
- * @param query
577
- * @param context
578
- */
579
- async *iterate(query = "", context) {
580
- if (query.includes("OFFSET")) {
581
- throw new Error("Cannot contain an OFFSET for iterate method");
582
- }
583
- let continuationToken;
584
- do {
585
- let q = query + (continuationToken !== undefined ? ` OFFSET "${continuationToken}"` : "");
586
- let page = await this.query(q, context);
587
- for (let item of page.results) {
588
- yield item;
589
- }
590
- continuationToken = page.continuationToken;
591
- } while (continuationToken);
592
- }
593
- // REFACTOR . >= 4
594
- /**
595
- * Query all the results
596
- *
597
- *
598
- * @param query
599
- * @param context
600
- * @returns
601
- * @deprecated use iterate instead
602
- */
603
- async queryAll(query, context) {
604
- let res = [];
605
- for await (let item of this.iterate(query, context)) {
606
- res.push(item);
607
- }
608
- return res;
609
- }
610
- // END_REFACTOR
611
- /**
612
- * Check that __type Comparison is only used with = and CONTAINS
613
- * If CONTAINS is used, move __type to __types
614
- * If __type = store._model, remove it
615
- */
616
- queryTypeUpdater(query) {
617
- return query;
618
- }
619
- /**
620
- * Query store with WebdaQL
621
- * @param query
622
- * @param context to apply permission
623
- */
624
- async query(query, context) {
625
- let permissionQuery = this._model.getPermissionQuery(context);
626
- let partialPermission = true;
627
- let fullQuery = query;
628
- if (permissionQuery) {
629
- partialPermission = permissionQuery.partial;
630
- fullQuery = WebdaQL.PrependCondition(query, permissionQuery.query);
631
- }
632
- let queryValidator = new WebdaQL.QueryValidator(fullQuery);
633
- let offset = queryValidator.getOffset();
634
- const limit = queryValidator.getLimit();
635
- const parsedQuery = this.queryTypeUpdater(queryValidator.getQuery());
636
- parsedQuery.limit = limit;
637
- // __type is a special field to filter on the type of the object
638
- // Emit the default event
639
- await this.emitSync("Store.Query", {
640
- query,
641
- parsedQuery,
642
- store: this,
643
- context
644
- });
645
- const result = {
646
- results: [],
647
- continuationToken: undefined
648
- };
649
- /*
650
- Offset are split in two with _
651
-
652
- MainOffset is the database offset, retrieving a page from the database
653
- SubOffset is the offset within the page
654
-
655
- As we filter through the page, for additional filters or permissions, the page cut
656
- by database does not endup being our final page cut, so we need a page offset to
657
- abstract this completely
658
- */
659
- let [mainOffset, subOffset] = offset.split("_");
660
- let secondOffset = parseInt(subOffset || "0");
661
- let duration = Date.now();
662
- this.metrics.operations_total.inc({ operation: "query" });
663
- while (result.results.length < limit) {
664
- let tmpResults = await this.find({
665
- ...parsedQuery,
666
- continuationToken: mainOffset
667
- });
668
- // If no filter is returned assume it is by mistake and apply filtering
669
- if (tmpResults.filter === undefined) {
670
- tmpResults.filter = queryValidator.getExpression();
671
- this.log("WARN", `Store '${this.getName()}' postquery full filtering`);
672
- }
673
- let subOffsetCount = 0;
674
- for (let item of tmpResults.results) {
675
- item.setContext(context);
676
- // Because of dynamic filter and permission we need to suboffset the pagination
677
- subOffsetCount++;
678
- if (subOffsetCount <= secondOffset) {
679
- continue;
680
- }
681
- if (tmpResults.filter !== true && !tmpResults.filter.eval(item)) {
682
- continue;
683
- }
684
- if (context && partialPermission && (await item.canAct(context, "get")) !== true) {
685
- continue;
686
- }
687
- result.results.push(item);
688
- if (result.results.length >= limit) {
689
- if (subOffsetCount === tmpResults.results.length) {
690
- result.continuationToken = tmpResults.continuationToken;
691
- }
692
- else {
693
- result.continuationToken = `${mainOffset}_${subOffsetCount}`;
694
- }
695
- break;
696
- }
697
- }
698
- // Update both offset
699
- mainOffset = tmpResults.continuationToken;
700
- // Fresh new query so we do not need to skip
701
- secondOffset = 0;
702
- if (mainOffset === undefined || result.results.length >= limit) {
703
- break;
704
- }
705
- }
706
- duration = Date.now() - duration;
707
- this.metrics.queries.observe(duration / 1000);
708
- if (duration > this.parameters.slowQueryThreshold) {
709
- this.logSlowQuery(query, "", duration);
710
- this.metrics.slow_queries_total.inc();
711
- }
712
- await this.emitSync("Store.Queried", {
713
- query,
714
- parsedQuery: parsedQuery,
715
- store: this,
716
- continuationToken: result.continuationToken,
717
- results: result.results,
718
- context
719
- });
720
- return result;
721
- }
722
- /**
723
- * Expose query to http
724
- */
725
- async httpQuery(ctx) {
726
- let query;
727
- if (ctx.getHttpContext().getMethod() === "GET") {
728
- query = ctx.getParameters().q;
729
- }
730
- else {
731
- query = WebdaQL.unsanitize((await ctx.getRequestBody()).q);
732
- }
733
- try {
734
- ctx.write(await this.query(query, ctx));
735
- }
736
- catch (err) {
737
- if (err instanceof SyntaxError) {
738
- this.log("INFO", "Query syntax error");
739
- throw new WebdaError.BadRequest("Query syntax error");
740
- }
741
- throw err;
742
- }
743
- }
744
- /**
745
- * Handle StoreEvent and update cache based on it
746
- * Then emit the event, it allows the cache to be updated
747
- * before listeners are called
748
- *
749
- * @param event
750
- * @param data
751
- */
752
- async emitStoreEvent(event, data) {
753
- if (event === "Store.Deleted") {
754
- await this._cacheStore?._delete(data.object_id);
755
- }
756
- else if (event === "Store.PartialUpdated") {
757
- const partialEvent = data;
758
- if (partialEvent.partial_update.increments) {
759
- await this._cacheStore?._incrementAttributes(partialEvent.object_id, partialEvent.partial_update.increments, partialEvent.updateDate);
760
- }
761
- else if (partialEvent.partial_update.deleteAttribute) {
762
- await this._cacheStore?._removeAttribute(partialEvent.object_id, partialEvent.partial_update.deleteAttribute, partialEvent.updateDate);
763
- }
764
- else if (partialEvent.partial_update.addItem) {
765
- await this._cacheStore?._upsertItemToCollection(partialEvent.object_id, partialEvent.partial_update.addItem.property, partialEvent.partial_update.addItem.value, partialEvent.partial_update.addItem.index, undefined, undefined, partialEvent.updateDate);
766
- }
767
- else if (partialEvent.partial_update.deleteItem) {
768
- await this._cacheStore?._deleteItemFromCollection(partialEvent.object_id, partialEvent.partial_update.deleteItem.property, partialEvent.partial_update.deleteItem.index, undefined, undefined, partialEvent.updateDate);
769
- }
770
- else if (partialEvent.partial_update.patch) {
771
- await this._cacheStore?._patch(partialEvent.partial_update.patch, partialEvent.object_id);
772
- }
773
- else {
774
- await this.invalidateCache(partialEvent.object_id);
775
- }
776
- }
777
- else if (event === "Store.Updated") {
778
- await this._cacheStore?._update(data.update, data.object_id);
779
- }
780
- else if (event === "Store.PatchUpdated") {
781
- await this._cacheStore?._patch(data.object, data.object_id);
782
- }
783
- await this.emitSync(event, data);
784
- }
785
- /**
786
- * Save an object
787
- *
788
- * @param {Object} Object to save
789
- * @param {String} Uuid to use, if not specified take the object.uuid or generate one if not found
790
- * @return {Promise} with saved object
791
- *
792
- * Might want to rename to create
793
- */
794
- async save(object, ctx = undefined) {
795
- if (object instanceof this._model && object._creationDate !== undefined && object._lastUpdate !== undefined) {
796
- if (ctx) {
797
- object.setContext(ctx);
798
- }
799
- return await object.save();
800
- }
801
- return this.create(object, ctx);
802
- }
803
- /**
804
- *
805
- * @param object
806
- * @param ctx
807
- * @returns
808
- */
809
- async create(object, ctx = undefined) {
810
- object = this.initModel(object);
811
- // Dates should be store by the Store
812
- if (!object._creationDate) {
813
- object._creationDate = object._lastUpdate = new Date();
814
- }
815
- else {
816
- object._lastUpdate = new Date();
817
- }
818
- const ancestors = this.getWebda().getApplication().getModelHierarchy(object.__type).ancestors;
819
- object.__types = [object.__type, ...ancestors].filter(i => i !== "Webda/CoreModel" && i !== "CoreModel");
820
- if (ctx) {
821
- object.setContext(ctx);
822
- }
823
- // Handle object auto listener
824
- const evt = {
825
- object: object,
826
- object_id: object.getUuid(),
827
- store: this,
828
- context: ctx
829
- };
830
- await Promise.all([
831
- this.emitSync("Store.Save", evt),
832
- object?.__class.emitSync("Store.Save", evt),
833
- object._onSave()
834
- ]);
835
- this.metrics.operations_total.inc({ operation: "save" });
836
- let res = await this._save(object);
837
- await this._cacheStore?._save(object);
838
- object = this.initModel(res);
839
- const evtSaved = {
840
- object: object,
841
- object_id: object.getUuid(),
842
- store: this,
843
- context: ctx
844
- };
845
- await Promise.all([
846
- this.emitSync("Store.Saved", evtSaved),
847
- object?.__class.emitSync("Store.Saved", evtSaved),
848
- object._onSaved()
849
- ]);
850
- return object;
851
- }
852
- /**
853
- * Patch an object
854
- *
855
- * @param object
856
- * @param reverseMap
857
- * @returns
858
- */
859
- async patch(object, reverseMap = true, conditionField, conditionValue) {
860
- return this.update(object, reverseMap, true, conditionField, conditionValue);
861
- }
862
- /**
863
- * Check if an UpdateCondition is met
864
- * @param model
865
- * @param conditionField
866
- * @param condition
867
- * @param uid
342
+ * Check that keys are valid
343
+ * All keys of model stored in a Store must have the same type of primary key
868
344
  */
869
- checkUpdateCondition(model, conditionField, condition, uid) {
870
- if (conditionField) {
871
- // Add toString to manage Date object
872
- if (model[conditionField].toString() !== condition.toString()) {
873
- throw new UpdateConditionFailError(uid ? uid : model.getUuid(), conditionField, condition);
874
- }
875
- }
876
- }
877
- /**
878
- * Check if an UpdateCondition is met
879
- * @param model
880
- * @param conditionField
881
- * @param condition
882
- * @param uid
883
- */
884
- checkCollectionUpdateCondition(model, collection, conditionField, condition, index) {
885
- // No index so addition to collection
886
- if (index === null) {
887
- // The condition must be length of the collection
888
- if (!model[collection] || model[collection].length !== condition) {
889
- throw new UpdateConditionFailError(model.getUuid(), collection, condition);
890
- }
891
- }
892
- else if (condition && model[collection][index][conditionField] !== condition) {
893
- throw new UpdateConditionFailError(model.getUuid(), `${collection}[${index}].${conditionField}`, condition);
894
- }
895
- }
896
- /**
897
- * Update conditionally
898
- * @param uuid
899
- * @param updates
900
- * @param conditionField
901
- * @param condition
902
- */
903
- async conditionalPatch(uuid, updates, conditionField, condition) {
904
- try {
905
- await this._patch(updates, uuid, condition, conditionField);
906
- // CoreModel should also emit this one but cannot do within this context
907
- await this.emitStoreEvent("Store.PartialUpdated", {
908
- object_id: uuid,
909
- partial_update: {
910
- patch: updates
911
- },
912
- store: this
913
- });
914
- return true;
915
- }
916
- catch (err) {
917
- if (err instanceof UpdateConditionFailError) {
918
- return false;
919
- }
920
- throw err;
921
- }
922
- }
923
- /**
924
- *
925
- * @param model
926
- * @param prop
927
- * @param item
928
- * @param index
929
- * @param itemWriteCondition
930
- * @param itemWriteConditionField
931
- * @param updateDate
932
- */
933
- async simulateUpsertItemToCollection(model, prop, item, updateDate, index, itemWriteCondition, itemWriteConditionField) {
934
- if (prop === "__proto__") {
935
- throw new Error("Cannot update __proto__: js/prototype-polluting-assignment");
936
- }
937
- this.checkCollectionUpdateCondition(model, prop, itemWriteConditionField, itemWriteCondition, index);
938
- if (index === undefined) {
939
- if (model[prop] === undefined) {
940
- model[prop] = [item];
941
- }
942
- else {
943
- model[prop].push(item);
944
- }
945
- }
946
- else {
947
- model[prop][index] = item;
948
- }
949
- model._lastUpdate = updateDate;
950
- await this._save(model);
951
- }
952
- /**
953
- * Update an object
954
- *
955
- * If no attribute can be updated then return undefined
956
- *
957
- * @param {Object} Object to save
958
- * @param {Boolean} reverseMap internal use only, for disable map resolution
959
- * @return {Promise} with saved object
960
- */
961
- async update(object, reverseMap = true, partial = false, conditionField, conditionValue) {
962
- /** @ignore */
963
- let saved;
964
- let loaded;
965
- // Dont allow to update collections from map
966
- if (this._reverseMap != undefined && reverseMap) {
967
- for (let i in this._reverseMap) {
968
- if (object[this._reverseMap[i].property] != undefined) {
969
- delete object[this._reverseMap[i].property];
970
- }
971
- }
972
- }
973
- if (Object.keys(object).length < 2) {
974
- return undefined;
975
- }
976
- object._lastUpdate = new Date();
977
- this.metrics.operations_total.inc({ operation: "get" });
978
- const uuid = object.getUuid ? object.getUuid() : object[this._uuidField];
979
- let load = await this._getFromCache(uuid, true);
980
- if (load.__type !== this._modelType && this.parameters.strict) {
981
- this.log("WARN", `Object '${uuid}' was not created by this store ${load.__type}:${this._modelType}`);
982
- throw new StoreNotFoundError(uuid, this.getName());
983
- }
984
- loaded = this.initModel(load);
985
- if (object instanceof CoreModel) {
986
- loaded.setContext(object.getContext());
987
- }
988
- const update = object;
989
- const evt = {
990
- object: loaded,
991
- object_id: loaded.getUuid(),
992
- store: this,
993
- update
994
- };
995
- await Promise.all([
996
- this.emitSync(partial ? `Store.PatchUpdate` : `Store.Update`, evt),
997
- object?.__class?.emitSync(partial ? `Store.PatchUpdate` : `Store.Update`, evt),
998
- loaded._onUpdate(object)
999
- ]);
1000
- let res;
1001
- if (conditionField !== null) {
1002
- conditionField ?? (conditionField = "_lastUpdate");
1003
- conditionValue ?? (conditionValue = load[conditionField]);
1004
- }
1005
- if (partial) {
1006
- this.metrics.operations_total.inc({ operation: "partialUpdate" });
1007
- await this._patch(object, uuid, conditionValue, conditionField);
1008
- res = object;
1009
- }
1010
- else {
1011
- // Copy back the mappers
1012
- for (let i in this._reverseMap) {
1013
- object[this._reverseMap[i].property] = loaded[this._reverseMap[i].property];
1014
- }
1015
- object = this.initModel(object);
1016
- this.metrics.operations_total.inc({ operation: "update" });
1017
- res = await this._update(object, uuid, conditionValue, conditionField);
1018
- }
1019
- // Reinit save
1020
- saved = this.initModel({
1021
- ...loaded,
1022
- ...res
1023
- });
1024
- const evtUpdated = {
1025
- object: saved,
1026
- object_id: saved.getUuid(),
1027
- store: this,
1028
- update,
1029
- previous: loaded
1030
- };
1031
- await Promise.all([
1032
- this.emitStoreEvent(partial ? `Store.PatchUpdated` : `Store.Updated`, evtUpdated),
1033
- saved?.__class.emitSync(partial ? `Store.PatchUpdated` : `Store.Updated`, evtUpdated),
1034
- saved._onUpdated()
1035
- ]);
1036
- return saved;
1037
- }
1038
- /**
1039
- * Manage the store migration for __type case sensitivity
1040
- */
1041
- async v3Migration() {
1042
- // Compute case for all object
1043
- await this.recomputeTypeCase();
1044
- // Compute all __types
1045
- await this.recomputeTypes();
1046
- // We do not move to short id as it is not compatible with v2
1047
- }
1048
- /**
1049
- *
1050
- */
1051
- async recomputeTypeShortId() {
1052
- this.log("INFO", "Ensuring __type is using its short id form");
1053
- const app = this.getWebda().getApplication();
1054
- // We need to be laxist for migration
1055
- this.parameters.strict = false;
1056
- await this.migration("typesShortId", async (item) => {
1057
- if (item.__type !== undefined && item.__type.includes("/")) {
1058
- const model = app.getWebdaObject("models", item.__type);
1059
- const name = app.getShortId(app.getModelName(model));
1060
- if (name !== item.__type) {
1061
- this.log("INFO", "Migrating type " + item.__type + " to " + name);
1062
- return {
1063
- __type: name
1064
- };
1065
- }
1066
- }
1067
- });
1068
- }
1069
- /**
1070
- * Ensure model aliases are not used in this store
1071
- *
1072
- * So alias can be cleaned
1073
- */
1074
- async cleanModelAliases() {
1075
- this.log("INFO", "Ensuring __type is not using any aliases");
1076
- // We need to be laxist for migration
1077
- this.parameters.strict = false;
1078
- await this.migration("cleanAliases", async (item) => {
1079
- if (this.parameters.modelAliases[item.__type]) {
1080
- this.log("INFO", "Migrating type " + item.__type + " to " + this.parameters.modelAliases[item.__type]);
1081
- return {
1082
- __type: this.parameters.modelAliases[item.__type]
1083
- };
1084
- }
1085
- });
1086
- }
1087
- /**
1088
- * Recompute type case
1089
- */
1090
- async recomputeTypeCase() {
1091
- this.log("INFO", "Ensuring __type is case sensitive from migration from v2.x");
1092
- const app = this.getWebda().getApplication();
1093
- // We need to be laxist for migration
1094
- this.parameters.strict = false;
1095
- await this.migration("typesCase", async (item) => {
1096
- if (item.__type !== undefined) {
1097
- if (!app.hasWebdaObject("models", item.__type, true) && app.hasWebdaObject("models", item.__type, false)) {
1098
- const model = app.getWebdaObject("models", item.__type, false);
1099
- const name = app.getModelName(model);
1100
- if (model) {
1101
- this.log("INFO", "Migrating type " + item.__type + " to " + name);
1102
- return {
1103
- __type: name
1104
- };
1105
- }
1106
- }
1107
- }
1108
- });
1109
- }
1110
- /**
1111
- * Recompute the __types for all objects (storeMigration.Registry.typesCompute)
1112
- */
1113
- async recomputeTypes() {
1114
- this.log("INFO", "Ensuring __types is correct from migration from v2.x");
1115
- // Update __types for each __type will be more efficient
1116
- await this.migration("typesCompute", async (item) => {
1117
- let __types = this.getWebda().getApplication().getModelTypes(item);
1118
- if (!item.__types ||
1119
- item.__types.length !== __types.length ||
1120
- !__types.every((element, index) => element === item.__types[index])) {
1121
- this.log("INFO", "Migrating types " + JSON.stringify(item.__types) + " to " + JSON.stringify(__types), "for", item.__type, item.getUuid());
1122
- return {
1123
- __types
1124
- };
1125
- }
1126
- });
1127
- }
1128
- /**
1129
- * Delete a migration
1130
- * @param name
1131
- */
1132
- async cancelMigration(name) {
1133
- await this.getWebda().getRegistry().delete(`storeMigration.${this.getName()}.${name}`);
1134
- }
1135
- /**
1136
- * Get a migration
1137
- * @param name
1138
- */
1139
- async getMigration(name) {
1140
- return await this.getWebda().getRegistry().get(`storeMigration.${this.getName()}.${name}`);
1141
- }
1142
- /**
1143
- * Add a migration mechanism to store
1144
- * @param name
1145
- * @param patcher
1146
- */
1147
- async migration(name, patcher, batchSize = 500) {
1148
- let status = await this.getWebda().getRegistry().get(`storeMigration.${this.getName()}.${name}`, undefined, {});
1149
- status.count ?? (status.count = 0);
1150
- status.updated ?? (status.updated = 0);
1151
- const worker = new Throttler(20);
1152
- do {
1153
- const res = await this.query(status.continuationToken ? `LIMIT ${batchSize} OFFSET "${status.continuationToken}"` : `LIMIT ${batchSize}`);
1154
- status.count += res.results.length;
1155
- for (let item of res.results) {
1156
- let updated = await patcher(item);
1157
- if (updated !== undefined) {
1158
- status.updated++;
1159
- if (typeof updated === "function") {
1160
- worker.queue(updated);
1161
- }
1162
- else {
1163
- worker.queue(async () => {
1164
- await item.patch(updated, null);
1165
- });
1166
- }
1167
- }
1168
- }
1169
- this.log("INFO", `storeMigration.${this.getName()}.${name}: Migrated ${status.count} items: ${status.updated} updated`);
1170
- status.continuationToken = res.continuationToken;
1171
- await worker.wait();
1172
- await status.save();
1173
- } while (status.continuationToken);
1174
- }
1175
- /**
1176
- * Remove an attribute from an object
1177
- *
1178
- * @param uuid
1179
- * @param attribute
1180
- * @returns
1181
- */
1182
- async removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
1183
- this.metrics.operations_total.inc({ operation: "attributeDelete" });
1184
- await this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
1185
- await this.emitStoreEvent("Store.PartialUpdated", {
1186
- object_id: uuid,
1187
- partial_update: {
1188
- deleteAttribute: attribute
1189
- },
1190
- store: this
1191
- });
1192
- }
1193
- /**
1194
- * Cascade delete a related object
1195
- *
1196
- * @param obj
1197
- * @param uuid
1198
- * @returns
1199
- */
1200
- async cascadeDelete(obj, _uuid) {
1201
- // We dont need uuid but Binary store will need it
1202
- return this.delete(obj.getUuid());
1203
- }
1204
- /**
1205
- * Delete an object from the store without condition nor async
1206
- * @param uid to delete
1207
- * @returns
1208
- */
1209
- async forceDelete(uid) {
1210
- return this.delete(uid, undefined, undefined, true);
1211
- }
1212
- /**
1213
- * Delete an object
1214
- *
1215
- * @param {String} uuid to delete
1216
- * @param {Boolean} delete sync even if asyncDelete is active
1217
- * @return {Promise} the deletion promise
1218
- */
1219
- async delete(uid, writeCondition, writeConditionField, sync = false) {
1220
- /** @ignore */
1221
- let to_delete;
1222
- // Allow full object or just its uuid
1223
- if (typeof uid === "object") {
1224
- to_delete = uid;
1225
- }
1226
- else {
1227
- this.metrics.operations_total.inc({ operation: "get" });
1228
- to_delete = await this._getFromCache(uid);
1229
- if (to_delete === undefined) {
1230
- return;
1231
- }
1232
- if (to_delete.__type !== this._modelType && this.parameters.strict) {
1233
- this.log("WARN", `Object '${uid}' was not created by this store ${to_delete.__type}:${this._modelType}`);
1234
- return;
1235
- }
1236
- to_delete = this.initModel(to_delete);
1237
- }
1238
- // Check condition as we have the object
1239
- if (writeCondition) {
1240
- if (to_delete[writeConditionField] !== writeCondition) {
1241
- throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
1242
- }
1243
- }
1244
- const evt = {
1245
- object: to_delete,
1246
- object_id: to_delete.getUuid(),
1247
- store: this
1248
- };
1249
- // Send preevent
1250
- await Promise.all([
1251
- this.emitSync("Store.Delete", evt),
1252
- to_delete?.__class.emitSync("Store.Delete", evt),
1253
- to_delete._onDelete()
1254
- ]);
1255
- // If async we just tag the object as deleted
1256
- if (this.parameters.asyncDelete && !sync) {
1257
- this.metrics.operations_total.inc({ operation: "partialUpdate" });
1258
- await this._patch({
1259
- __deleted: true
1260
- }, to_delete.getUuid());
1261
- await this._cacheStore?._patch({
1262
- __deleted: true
1263
- }, to_delete.getUuid());
1264
- }
1265
- else {
1266
- this.metrics.operations_total.inc({ operation: "delete" });
1267
- // Delete from the DB for real
1268
- await this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
1269
- await this._cacheStore?._delete(to_delete.getUuid(), writeCondition, writeConditionField);
1270
- }
1271
- // Send post event
1272
- const evtDeleted = {
1273
- object: to_delete,
1274
- object_id: to_delete.getUuid(),
1275
- store: this
1276
- };
1277
- await Promise.all([
1278
- this.emitStoreEvent("Store.Deleted", evtDeleted),
1279
- to_delete.__class.emitSync("Store.Deleted", evtDeleted),
1280
- to_delete._onDeleted()
1281
- ]);
1282
- }
1283
- /**
1284
- * By default we cannot know if the store will trigger or not
1285
- *
1286
- * @param id
1287
- * @param callback
1288
- */
1289
- canTriggerConfiguration(_id, _callback) {
1290
- return false;
1291
- }
1292
- /**
1293
- * Provide a way to store configuration in store
1294
- * @param {string} id
1295
- * @returns {Promise<Map<string, any>>}
1296
- */
1297
- async getConfiguration(id) {
1298
- this.metrics.operations_total.inc({ operation: "get" });
1299
- let object = await this._getFromCache(id);
1300
- if (!object) {
1301
- return undefined;
1302
- }
1303
- let result = {};
1304
- for (let i in object) {
1305
- if (i === this._uuidField || i === "_lastUpdate" || i.startsWith("_")) {
1306
- continue;
1307
- }
1308
- result[i] = object[i];
1309
- }
1310
- return result;
1311
- }
1312
- /**
1313
- * Upsert the uuid object
1314
- * @param uuid
1315
- * @param data
1316
- */
1317
- async put(uuid, data) {
1318
- if (await this.exists(uuid)) {
1319
- return this.update({ ...data, uuid });
1320
- }
1321
- return this.save(data instanceof CoreModel ? data.setUuid(uuid) : { ...data, uuid });
1322
- }
1323
- /**
1324
- * Get an object
1325
- *
1326
- * @param {String} uuid to get
1327
- * @return {Promise} the object retrieved ( can be undefined if not found )
1328
- */
1329
- async get(uid, ctx = undefined, defaultValue = undefined) {
1330
- /** @ignore */
1331
- if (!uid) {
1332
- return undefined;
1333
- }
1334
- this.metrics.operations_total.inc({ operation: "get" });
1335
- let object = await this._getFromCache(uid);
1336
- if (!object) {
1337
- return defaultValue ? this.initModel(defaultValue).setUuid(uid) : undefined;
1338
- }
1339
- if (object.__type !== this._modelType && this.parameters.strict) {
1340
- this.log("WARN", `Object '${uid}' was not created by this store ${object.__type}:${this._modelType}`);
1341
- return undefined;
1342
- }
1343
- object = this.initModel(object);
1344
- object.setContext(ctx);
1345
- const evt = {
1346
- object: object,
1347
- object_id: object.getUuid(),
1348
- store: this,
1349
- context: ctx
1350
- };
1351
- await Promise.all([this.emitSync("Store.Get", evt), object.__class.emitSync("Store.Get", evt), object._onGet()]);
1352
- return object;
1353
- }
1354
- /**
1355
- * Set one attribute in an object
1356
- *
1357
- * this is an helper function that calls patch
1358
- *
1359
- * @param uid of the object
1360
- * @param property to update1
1361
- * @param value new value
1362
- * @returns
1363
- */
1364
- async setAttribute(uid, property, value) {
1365
- let patch = {};
1366
- patch[property] = value;
1367
- patch[this.getUuidField()] = uid;
1368
- await this.patch(patch);
1369
- }
1370
- /**
1371
- * @override
1372
- */
1373
- async simulateFind(query, uuids) {
1374
- let result = {
1375
- results: [],
1376
- continuationToken: undefined,
1377
- filter: true
1378
- };
1379
- let count = 0;
1380
- let limit = query.limit;
1381
- let offset = parseInt(query.continuationToken || "0");
1382
- let originalOffset = offset;
1383
- if (query.orderBy && query.orderBy.length) {
1384
- offset = 0;
1385
- // We need to retrieve everything to orderBy after
1386
- limit = Number.MAX_SAFE_INTEGER;
1387
- }
1388
- // Need to transfert to Array
1389
- for (let uuid of uuids) {
1390
- count++;
1391
- // Offset start
1392
- if (offset >= count) {
1393
- continue;
1394
- }
1395
- let obj = await this._getFromCache(uuid);
1396
- if (obj && query.filter.eval(obj)) {
1397
- result.results.push(obj);
1398
- if (result.results.length >= limit) {
1399
- result.continuationToken = count.toString();
1400
- return result;
1401
- }
1402
- }
1403
- }
1404
- // Order by
1405
- if (query.orderBy && query.orderBy.length) {
1406
- // Sorting the results
1407
- result.results.sort((a, b) => {
1408
- let valA, valB;
1409
- for (let orderBy of query.orderBy) {
1410
- let invert = orderBy.direction === "ASC" ? 1 : -1;
1411
- valA = WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1412
- valB = WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1413
- if (valA === valB) {
1414
- continue;
1415
- }
1416
- if (typeof valA === "string") {
1417
- return valA.localeCompare(valB) * invert;
1418
- }
1419
- return (valA < valB ? -1 : 1) * invert;
1420
- }
1421
- return -1;
1422
- });
1423
- result.results = result.results.slice(originalOffset, query.limit + originalOffset);
1424
- if (result.results.length >= query.limit) {
1425
- result.continuationToken = (query.limit + originalOffset).toString();
1426
- }
1427
- }
1428
- return result;
1429
- }
1430
- getOpenApiReplacements() {
1431
- return {
1432
- modelName: this._model.name
1433
- };
1434
- }
1435
- /**
1436
- * Handle POST
1437
- * @param ctx
1438
- */
1439
- async httpCreate(ctx) {
1440
- return this.operationCreate(ctx, this.parameters.model);
1441
- }
1442
- /**
1443
- * Create a new object based on the context
1444
- * @param ctx
1445
- * @param model
1446
- */
1447
- async operationCreate(ctx, model) {
1448
- let body = await ctx.getInput();
1449
- const modelPrototype = this.getWebda().getApplication().getModel(model);
1450
- let object = modelPrototype.factory(body, ctx);
1451
- object._creationDate = new Date();
1452
- await object.checkAct(ctx, "create");
1453
- try {
1454
- await object.validate(ctx, body);
1455
- }
1456
- catch (err) {
1457
- this.log("INFO", "Object is not valid", err);
1458
- throw new WebdaError.BadRequest("Object is not valid");
1459
- }
1460
- if (object[this._uuidField] && (await this.exists(object[this._uuidField]))) {
1461
- throw new WebdaError.Conflict("Object already exists");
1462
- }
1463
- await this.save(object, ctx);
1464
- ctx.write(object);
1465
- const evt = {
1466
- context: ctx,
1467
- values: body,
1468
- object: object,
1469
- object_id: object.getUuid(),
1470
- store: this
1471
- };
1472
- await Promise.all([object.__class.emitSync("Store.WebCreate", evt), this.emitSync("Store.WebCreate", evt)]);
1473
- }
1474
- /**
1475
- * Handle obect action
1476
- * @param ctx
1477
- */
1478
- async httpAction(ctx, actionMethod) {
1479
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1480
- actionMethod ?? (actionMethod = action);
1481
- let object = await this.get(ctx.parameter("uuid"), ctx);
1482
- if (object === undefined || object.__deleted) {
1483
- throw new WebdaError.NotFound("Object not found or is deleted");
1484
- }
1485
- const inputSchema = `${object.__class.getIdentifier(false)}.${action}.input`;
1486
- if (this.getWebda().getApplication().hasSchema(inputSchema)) {
1487
- const input = await ctx.getInput();
1488
- try {
1489
- this.getWebda().validateSchema(inputSchema, input);
1490
- }
1491
- catch (err) {
1492
- this.log("INFO", "Object invalid", err);
1493
- this.log("INFO", "Object invalid", inputSchema, input, this.getWebda().getApplication().getSchema(inputSchema));
1494
- throw new WebdaError.BadRequest("Body is invalid");
1495
- }
1496
- }
1497
- await object.checkAct(ctx, action);
1498
- const evt = {
1499
- action: action,
1500
- object: object,
1501
- store: this,
1502
- context: ctx
1503
- };
1504
- await Promise.all([this.emitSync("Store.Action", evt), object.__class.emitSync("Store.Action", evt)]);
1505
- const res = await object[actionMethod](ctx);
1506
- if (res) {
1507
- ctx.write(res);
1508
- }
1509
- const evtActioned = {
1510
- action: action,
1511
- object: object,
1512
- store: this,
1513
- context: ctx,
1514
- result: res
1515
- };
1516
- await Promise.all([
1517
- this.emitSync("Store.Actioned", evtActioned),
1518
- object?.__class.emitSync("Store.Actioned", evtActioned)
1519
- ]);
1520
- }
1521
- /**
1522
- * Handle collection action
1523
- * @param ctx
1524
- */
1525
- async httpGlobalAction(ctx, model = this._model) {
1526
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1527
- const evt = {
1528
- action: action,
1529
- store: this,
1530
- context: ctx,
1531
- model
1532
- };
1533
- await Promise.all([this.emitSync("Store.Action", evt), model.emitSync("Store.Action", evt)]);
1534
- const res = await model[action](ctx);
1535
- if (res) {
1536
- ctx.write(res);
1537
- }
1538
- const evtActioned = {
1539
- action: action,
1540
- store: this,
1541
- context: ctx,
1542
- result: res,
1543
- model
1544
- };
1545
- await Promise.all([this.emitSync("Store.Actioned", evtActioned), model?.emitSync("Store.Actioned", evtActioned)]);
1546
- }
1547
- /**
1548
- * Handle HTTP Update for an object
1549
- *
1550
- * @param ctx context of the request
1551
- */
1552
- async httpUpdate(ctx) {
1553
- const { uuid } = ctx.getParameters();
1554
- const body = await ctx.getInput();
1555
- body[this._uuidField] = uuid;
1556
- let object = await this.get(uuid, ctx);
1557
- if (!object || object.__deleted)
1558
- throw new WebdaError.NotFound("Object not found or is deleted");
1559
- await object.checkAct(ctx, "update");
1560
- if (ctx.getHttpContext().getMethod() === "PATCH") {
1561
- try {
1562
- await object.validate(ctx, body, true);
1563
- }
1564
- catch (err) {
1565
- this.log("INFO", "Object invalid", err, object);
1566
- throw new WebdaError.BadRequest("Object is not valid");
1567
- }
1568
- let updateObject = new this._model();
1569
- // Clean any default attributes from the model
1570
- Object.keys(updateObject)
1571
- .filter(i => i !== "__class")
1572
- .forEach(i => {
1573
- delete updateObject[i];
1574
- });
1575
- updateObject.setContext(ctx);
1576
- updateObject.setUuid(uuid);
1577
- updateObject.load(body, false, false);
1578
- await this.patch(updateObject);
1579
- object = undefined;
1580
- }
1581
- else {
1582
- let updateObject = new this._model();
1583
- updateObject.setContext(ctx);
1584
- updateObject.load(body);
1585
- // Copy back the _ attributes
1586
- Object.keys(object)
1587
- .filter(i => i.startsWith("_"))
1588
- .forEach(i => {
1589
- updateObject[i] = object[i];
1590
- });
1591
- try {
1592
- await updateObject.validate(ctx, body);
1593
- }
1594
- catch (err) {
1595
- this.log("INFO", "Object invalid", err);
1596
- throw new WebdaError.BadRequest("Object is not valid");
1597
- }
1598
- // Add mappers back to
1599
- object = await this.update(updateObject);
1600
- }
1601
- ctx.write(object);
1602
- const evt = {
1603
- context: ctx,
1604
- updates: body,
1605
- object: object,
1606
- store: this,
1607
- method: ctx.getHttpContext().getMethod()
1608
- };
1609
- await Promise.all([object?.__class.emitSync("Store.WebUpdate", evt), this.emitSync("Store.WebUpdate", evt)]);
1610
- }
1611
- /**
1612
- * Handle GET on object
1613
- *
1614
- * @param ctx context of the request
1615
- */
1616
- async httpGet(ctx) {
1617
- let uuid = ctx.parameter("uuid");
1618
- let object = await this.get(uuid, ctx);
1619
- await this.emitSync("Store.WebGetNotFound", {
1620
- context: ctx,
1621
- uuid,
1622
- store: this
1623
- });
1624
- if (object === undefined || object.__deleted) {
1625
- throw new WebdaError.NotFound("Object not found or is deleted");
1626
- }
1627
- await object.checkAct(ctx, "get");
1628
- ctx.write(object);
1629
- const evt = {
1630
- context: ctx,
1631
- object: object,
1632
- store: this
1633
- };
1634
- await Promise.all([this.emitSync("Store.WebGet", evt), object.__class.emitSync("Store.WebGet", evt)]);
1635
- ctx.write(object);
1636
- }
1637
- /**
1638
- * Handle HTTP request
1639
- *
1640
- * @param ctx context of the request
1641
- * @returns
1642
- */
1643
- async httpDelete(ctx) {
1644
- let uuid = ctx.parameter("uuid");
1645
- let object = await this.get(uuid, ctx);
1646
- if (!object || object.__deleted)
1647
- throw new WebdaError.NotFound("Object not found or is deleted");
1648
- await object.checkAct(ctx, "delete");
1649
- // http://stackoverflow.com/questions/28684209/huge-delay-on-delete-requests-with-204-response-and-no-content-in-objectve-c#
1650
- // IOS don't handle 204 with Content-Length != 0 it seems
1651
- // Might still run into: Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1652
- ctx.writeHead(204, { "Content-Length": "0" });
1653
- await this.delete(uuid);
1654
- const evt = {
1655
- context: ctx,
1656
- object_id: uuid,
1657
- store: this
1658
- };
1659
- await Promise.all([this.emitSync("Store.WebDelete", evt), object.__class.emitSync("Store.WebDelete", evt)]);
1660
- }
1661
- /**
1662
- * Return the model uuid field
1663
- */
1664
- getUuidField() {
1665
- return this._uuidField;
1666
- }
1667
- /**
1668
- * Check if an object exists
1669
- * @abstract
1670
- * @params {String} uuid of the object or the object
1671
- */
1672
- async exists(uid) {
1673
- if (typeof uid !== "string") {
1674
- uid = uid.getUuid();
1675
- }
1676
- return this._exists(uid);
345
+ checkKeys() {
346
+ // TODO Implement
1677
347
  }
1678
348
  }
1679
- __decorate([
1680
- Route(".", ["POST"], {
1681
- post: {
1682
- description: "The way to create a new ${modelName} model",
1683
- summary: "Create a new ${modelName}",
1684
- operationId: "create${modelName}",
1685
- requestBody: {
1686
- content: {
1687
- "application/json": {
1688
- schema: {
1689
- $ref: "#/components/schemas/${modelName}"
1690
- }
1691
- }
1692
- }
1693
- },
1694
- responses: {
1695
- "200": {
1696
- description: "Retrieve model",
1697
- content: {
1698
- "application/json": {
1699
- schema: {
1700
- $ref: "#/components/schemas/${modelName}"
1701
- }
1702
- }
1703
- }
1704
- },
1705
- "400": {
1706
- description: "Object is invalid"
1707
- },
1708
- "403": {
1709
- description: "You don't have permissions"
1710
- },
1711
- "409": {
1712
- description: "Object already exists"
1713
- }
1714
- }
1715
- }
1716
- })
1717
- ], Store.prototype, "httpCreate", null);
1718
- __decorate([
1719
- Route("./{uuid}", ["PUT", "PATCH"], {
1720
- put: {
1721
- description: "Update a ${modelName} if the permissions allow",
1722
- summary: "Update a ${modelName}",
1723
- operationId: "update${modelName}",
1724
- schemas: {
1725
- input: "${modelName}",
1726
- output: "${modelName}"
1727
- },
1728
- responses: {
1729
- "200": {},
1730
- "400": {
1731
- description: "Object is invalid"
1732
- },
1733
- "403": {
1734
- description: "You don't have permissions"
1735
- },
1736
- "404": {
1737
- description: "Unknown object"
1738
- }
1739
- }
1740
- },
1741
- patch: {
1742
- description: "Patch a ${modelName} if the permissions allow",
1743
- summary: "Patch a ${modelName}",
1744
- operationId: "partialUpdatet${modelName}",
1745
- schemas: {
1746
- input: "${modelName}"
1747
- },
1748
- responses: {
1749
- "204": {
1750
- description: ""
1751
- },
1752
- "400": {
1753
- description: "Object is invalid"
1754
- },
1755
- "403": {
1756
- description: "You don't have permissions"
1757
- },
1758
- "404": {
1759
- description: "Unknown object"
1760
- }
1761
- }
1762
- }
1763
- })
1764
- ], Store.prototype, "httpUpdate", null);
1765
- __decorate([
1766
- Route("./{uuid}", ["GET"], {
1767
- get: {
1768
- description: "Retrieve ${modelName} model if permissions allow",
1769
- summary: "Retrieve a ${modelName}",
1770
- operationId: "get${modelName}",
1771
- schemas: {
1772
- output: "${modelName}"
1773
- },
1774
- responses: {
1775
- "200": {},
1776
- "400": {
1777
- description: "Object is invalid"
1778
- },
1779
- "403": {
1780
- description: "You don't have permissions"
1781
- },
1782
- "404": {
1783
- description: "Unknown object"
1784
- }
1785
- }
1786
- }
1787
- })
1788
- ], Store.prototype, "httpGet", null);
1789
- __decorate([
1790
- Route("./{uuid}", ["DELETE"], {
1791
- delete: {
1792
- operationId: "delete${modelName}",
1793
- description: "Delete ${modelName} if the permissions allow",
1794
- summary: "Delete a ${modelName}",
1795
- responses: {
1796
- "204": {
1797
- description: ""
1798
- },
1799
- "403": {
1800
- description: "You don't have permissions"
1801
- },
1802
- "404": {
1803
- description: "Unknown object"
1804
- }
1805
- }
1806
- }
1807
- })
1808
- ], Store.prototype, "httpDelete", null);
1809
349
  export { Store };
1810
350
  //# sourceMappingURL=store.js.map