zibri 2.4.1 → 2.5.0

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 (496) hide show
  1. package/dist/cjs/application-options.model.d.ts +2 -2
  2. package/dist/cjs/application-options.model.d.ts.map +1 -1
  3. package/dist/cjs/application.d.ts.map +1 -1
  4. package/dist/cjs/application.js +0 -1
  5. package/dist/cjs/application.js.map +1 -1
  6. package/dist/cjs/assets/asset.service.d.ts.map +1 -1
  7. package/dist/cjs/assets/asset.service.js +3 -1
  8. package/dist/cjs/assets/asset.service.js.map +1 -1
  9. package/dist/cjs/auth/2fa/methods/otp/otp-credentials.model.d.ts +1 -1
  10. package/dist/cjs/auth/2fa/methods/otp/otp-credentials.model.d.ts.map +1 -1
  11. package/dist/cjs/auth/2fa/methods/otp/otp-credentials.model.js.map +1 -1
  12. package/dist/cjs/auth/2fa/methods/otp/otp.two-factor-method.js +1 -1
  13. package/dist/cjs/auth/2fa/methods/otp/otp.two-factor-method.js.map +1 -1
  14. package/dist/cjs/auth/strategies/cookie/cookie-auth.controller.js +1 -1
  15. package/dist/cjs/auth/strategies/cookie/cookie-auth.controller.js.map +1 -1
  16. package/dist/cjs/auth/strategies/jwt/jwt-auth.controller.js +1 -1
  17. package/dist/cjs/auth/strategies/jwt/jwt-auth.controller.js.map +1 -1
  18. package/dist/cjs/auth/strategies/jwt/jwt.auth-strategy.js +1 -1
  19. package/dist/cjs/auth/strategies/jwt/jwt.auth-strategy.js.map +1 -1
  20. package/dist/cjs/backup/backup-resource-entity.model.d.ts +1 -1
  21. package/dist/cjs/backup/backup-resource-entity.model.d.ts.map +1 -1
  22. package/dist/cjs/backup/backup-resource-entity.model.js.map +1 -1
  23. package/dist/cjs/change-sets/models/change-set.model.d.ts +1 -1
  24. package/dist/cjs/change-sets/models/change-set.model.d.ts.map +1 -1
  25. package/dist/cjs/change-sets/models/change-set.model.js +1 -1
  26. package/dist/cjs/change-sets/models/change-set.model.js.map +1 -1
  27. package/dist/cjs/change-sets/models/change.model.d.ts +2 -2
  28. package/dist/cjs/change-sets/models/change.model.d.ts.map +1 -1
  29. package/dist/cjs/change-sets/models/change.model.js.map +1 -1
  30. package/dist/cjs/context/cache/cache.context.d.ts +2 -2
  31. package/dist/cjs/context/cache/cache.context.d.ts.map +1 -1
  32. package/dist/cjs/context/cache/cache.context.js +2 -2
  33. package/dist/cjs/context/cache/cache.context.js.map +1 -1
  34. package/dist/cjs/context/request/request-context-token.model.js +1 -1
  35. package/dist/cjs/context/request/request-context-token.model.js.map +1 -1
  36. package/dist/cjs/cron/cron-job-entity.model.d.ts +2 -2
  37. package/dist/cjs/cron/cron-job-entity.model.d.ts.map +1 -1
  38. package/dist/cjs/cron/cron-job-entity.model.js.map +1 -1
  39. package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.d.ts +1 -0
  40. package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.d.ts.map +1 -1
  41. package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.js +9 -0
  42. package/dist/cjs/data-source/data-sources/postgres-typeorm-data-source.model.js.map +1 -1
  43. package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.d.ts.map +1 -1
  44. package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.js +3 -3
  45. package/dist/cjs/data-source/data-sources/typeorm-base-data-source.model.js.map +1 -1
  46. package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.d.ts +2 -1
  47. package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.d.ts.map +1 -1
  48. package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js +20 -0
  49. package/dist/cjs/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js.map +1 -1
  50. package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.d.ts +4 -0
  51. package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.d.ts.map +1 -1
  52. package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.js +3 -1
  53. package/dist/cjs/data-source/data-sources/where-converter/typeorm-where-filter.converter.js.map +1 -1
  54. package/dist/cjs/data-source/migration/migration-entity.model.d.ts +2 -2
  55. package/dist/cjs/data-source/migration/migration-entity.model.d.ts.map +1 -1
  56. package/dist/cjs/data-source/migration/migration-entity.model.js.map +1 -1
  57. package/dist/cjs/data-source/migration/migration.model.d.ts +2 -2
  58. package/dist/cjs/data-source/migration/migration.model.d.ts.map +1 -1
  59. package/dist/cjs/data-source/models/where/date-where-filter.model.d.ts +10 -2
  60. package/dist/cjs/data-source/models/where/date-where-filter.model.d.ts.map +1 -1
  61. package/dist/cjs/data-source/models/where/string-where-filter.model.d.ts +17 -0
  62. package/dist/cjs/data-source/models/where/string-where-filter.model.d.ts.map +1 -1
  63. package/dist/cjs/data-source/models/where/where-filter-keys.model.d.ts.map +1 -1
  64. package/dist/cjs/data-source/models/where/where-filter-keys.model.js +3 -0
  65. package/dist/cjs/data-source/models/where/where-filter-keys.model.js.map +1 -1
  66. package/dist/cjs/di/default/zibri-di-providers.default.d.ts.map +1 -1
  67. package/dist/cjs/di/default/zibri-di-providers.default.js +4 -0
  68. package/dist/cjs/di/default/zibri-di-providers.default.js.map +1 -1
  69. package/dist/cjs/di/default/zibri-di-tokens.default.d.ts +3 -0
  70. package/dist/cjs/di/default/zibri-di-tokens.default.d.ts.map +1 -1
  71. package/dist/cjs/di/default/zibri-di-tokens.default.js +2 -0
  72. package/dist/cjs/di/default/zibri-di-tokens.default.js.map +1 -1
  73. package/dist/cjs/email/email.service.d.ts +1 -1
  74. package/dist/cjs/email/email.service.d.ts.map +1 -1
  75. package/dist/cjs/email/email.service.js +4 -4
  76. package/dist/cjs/email/email.service.js.map +1 -1
  77. package/dist/cjs/email/models/email.model.d.ts +4 -4
  78. package/dist/cjs/email/models/email.model.d.ts.map +1 -1
  79. package/dist/cjs/email/models/email.model.js +4 -4
  80. package/dist/cjs/email/models/email.model.js.map +1 -1
  81. package/dist/cjs/entity/generation/generate-entity-file.function.js +1 -1
  82. package/dist/cjs/entity/generation/generate-entity-file.function.js.map +1 -1
  83. package/dist/cjs/event/event-subscriber-run.model.d.ts +1 -1
  84. package/dist/cjs/event/event-subscriber-run.model.d.ts.map +1 -1
  85. package/dist/cjs/event/event-subscriber-run.model.js +1 -1
  86. package/dist/cjs/event/event-subscriber-run.model.js.map +1 -1
  87. package/dist/cjs/global/global-registry.d.ts +2 -2
  88. package/dist/cjs/global/global-registry.d.ts.map +1 -1
  89. package/dist/cjs/http/http-request.model.d.ts +2 -2
  90. package/dist/cjs/http/http-request.model.d.ts.map +1 -1
  91. package/dist/cjs/http/known-header.enum.d.ts +1 -0
  92. package/dist/cjs/http/known-header.enum.d.ts.map +1 -1
  93. package/dist/cjs/http/known-header.enum.js +1 -0
  94. package/dist/cjs/http/known-header.enum.js.map +1 -1
  95. package/dist/cjs/http-client/http-client.d.ts.map +1 -1
  96. package/dist/cjs/http-client/http-client.js.map +1 -1
  97. package/dist/cjs/index.d.ts +7 -3
  98. package/dist/cjs/index.d.ts.map +1 -1
  99. package/dist/cjs/index.js +8 -3
  100. package/dist/cjs/index.js.map +1 -1
  101. package/dist/cjs/localization/formatting/format-price.function.d.ts.map +1 -1
  102. package/dist/cjs/localization/formatting/format-price.function.js.map +1 -1
  103. package/dist/cjs/logging/log-context.model.d.ts +6 -6
  104. package/dist/cjs/logging/log-context.model.d.ts.map +1 -1
  105. package/dist/cjs/logging/log-context.model.js +6 -6
  106. package/dist/cjs/logging/log-context.model.js.map +1 -1
  107. package/dist/cjs/logging/logger.js +1 -1
  108. package/dist/cjs/logging/logger.js.map +1 -1
  109. package/dist/cjs/multithreading/models/thread-job-entity.model.d.ts +5 -5
  110. package/dist/cjs/multithreading/models/thread-job-entity.model.d.ts.map +1 -1
  111. package/dist/cjs/multithreading/models/thread-job-entity.model.js +4 -4
  112. package/dist/cjs/multithreading/models/thread-job-entity.model.js.map +1 -1
  113. package/dist/cjs/multithreading/services/thread-job.d.ts +4 -4
  114. package/dist/cjs/multithreading/services/thread-job.d.ts.map +1 -1
  115. package/dist/cjs/multithreading/services/thread-job.js.map +1 -1
  116. package/dist/cjs/open-api/open-api-service.interface.d.ts +2 -1
  117. package/dist/cjs/open-api/open-api-service.interface.d.ts.map +1 -1
  118. package/dist/cjs/open-api/open-api.service.d.ts +5 -2
  119. package/dist/cjs/open-api/open-api.service.d.ts.map +1 -1
  120. package/dist/cjs/open-api/open-api.service.js +256 -139
  121. package/dist/cjs/open-api/open-api.service.js.map +1 -1
  122. package/dist/cjs/parsing/html/csp-options.model.d.ts +1 -1
  123. package/dist/cjs/parsing/html/csp-options.model.d.ts.map +1 -1
  124. package/dist/cjs/parsing/html/csp-options.model.js.map +1 -1
  125. package/dist/cjs/parsing/parser.js +3 -3
  126. package/dist/cjs/parsing/parser.js.map +1 -1
  127. package/dist/cjs/plugin/invoicing/models/invoice-address.model.d.ts +2 -2
  128. package/dist/cjs/plugin/invoicing/models/invoice-address.model.d.ts.map +1 -1
  129. package/dist/cjs/plugin/invoicing/models/invoice-address.model.js +2 -2
  130. package/dist/cjs/plugin/invoicing/models/invoice-address.model.js.map +1 -1
  131. package/dist/cjs/plugin/invoicing/models/vat.model.d.ts +1 -1
  132. package/dist/cjs/plugin/invoicing/models/vat.model.d.ts.map +1 -1
  133. package/dist/cjs/plugin/invoicing/models/vat.model.js +1 -1
  134. package/dist/cjs/plugin/invoicing/models/vat.model.js.map +1 -1
  135. package/dist/cjs/plugin/mailing-list/mailing-list.controller.js +1 -1
  136. package/dist/cjs/plugin/mailing-list/mailing-list.controller.js.map +1 -1
  137. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscriber.model.d.ts +1 -1
  138. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscriber.model.d.ts.map +1 -1
  139. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscriber.model.js +1 -1
  140. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscriber.model.js.map +1 -1
  141. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.d.ts +1 -1
  142. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.d.ts.map +1 -1
  143. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.js +1 -1
  144. package/dist/cjs/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.js.map +1 -1
  145. package/dist/cjs/plugin/payment/models/payment.model.d.ts +2 -2
  146. package/dist/cjs/plugin/payment/models/payment.model.d.ts.map +1 -1
  147. package/dist/cjs/plugin/payment/models/payment.model.js +1 -1
  148. package/dist/cjs/plugin/payment/models/payment.model.js.map +1 -1
  149. package/dist/cjs/plugin/payment/providers/pay-pal/pay-pal-client.d.ts +17 -17
  150. package/dist/cjs/plugin/payment/providers/pay-pal/pay-pal-client.d.ts.map +1 -1
  151. package/dist/cjs/plugin/payment/providers/pay-pal/pay-pal-client.js +17 -17
  152. package/dist/cjs/plugin/payment/providers/pay-pal/pay-pal-client.js.map +1 -1
  153. package/dist/cjs/plugin/payment/providers/pay-pal/pay-pal.payment-provider.js +1 -1
  154. package/dist/cjs/plugin/payment/providers/pay-pal/pay-pal.payment-provider.js.map +1 -1
  155. package/dist/cjs/preact/preact.utilities.js +1 -1
  156. package/dist/cjs/preact/preact.utilities.js.map +1 -1
  157. package/dist/cjs/preact/validate-email-templates.function.js +1 -1
  158. package/dist/cjs/preact/validate-email-templates.function.js.map +1 -1
  159. package/dist/cjs/rate-limiting/rate-limiter.d.ts +10 -5
  160. package/dist/cjs/rate-limiting/rate-limiter.d.ts.map +1 -1
  161. package/dist/cjs/rate-limiting/rate-limiter.js +22 -12
  162. package/dist/cjs/rate-limiting/rate-limiter.js.map +1 -1
  163. package/dist/cjs/routing/controller-route-configuration.model.d.ts +5 -0
  164. package/dist/cjs/routing/controller-route-configuration.model.d.ts.map +1 -1
  165. package/dist/cjs/routing/decorators/controller.decorator.d.ts +5 -0
  166. package/dist/cjs/routing/decorators/controller.decorator.d.ts.map +1 -1
  167. package/dist/cjs/routing/decorators/controller.decorator.js +3 -2
  168. package/dist/cjs/routing/decorators/controller.decorator.js.map +1 -1
  169. package/dist/cjs/routing/decorators/create-http-decorator.function.d.ts +2 -1
  170. package/dist/cjs/routing/decorators/create-http-decorator.function.d.ts.map +1 -1
  171. package/dist/cjs/routing/decorators/create-http-decorator.function.js +2 -2
  172. package/dist/cjs/routing/decorators/create-http-decorator.function.js.map +1 -1
  173. package/dist/cjs/routing/decorators/delete.decorator.d.ts +3 -1
  174. package/dist/cjs/routing/decorators/delete.decorator.d.ts.map +1 -1
  175. package/dist/cjs/routing/decorators/delete.decorator.js +3 -2
  176. package/dist/cjs/routing/decorators/delete.decorator.js.map +1 -1
  177. package/dist/cjs/routing/decorators/get.decorator.d.ts +3 -1
  178. package/dist/cjs/routing/decorators/get.decorator.d.ts.map +1 -1
  179. package/dist/cjs/routing/decorators/get.decorator.js +3 -2
  180. package/dist/cjs/routing/decorators/get.decorator.js.map +1 -1
  181. package/dist/cjs/routing/decorators/http-decorator-option-input.model.d.ts +11 -0
  182. package/dist/cjs/routing/decorators/http-decorator-option-input.model.d.ts.map +1 -0
  183. package/dist/cjs/routing/decorators/http-decorator-option-input.model.js +3 -0
  184. package/dist/cjs/routing/decorators/http-decorator-option-input.model.js.map +1 -0
  185. package/dist/cjs/routing/decorators/patch.decorator.d.ts +3 -1
  186. package/dist/cjs/routing/decorators/patch.decorator.d.ts.map +1 -1
  187. package/dist/cjs/routing/decorators/patch.decorator.js +3 -2
  188. package/dist/cjs/routing/decorators/patch.decorator.js.map +1 -1
  189. package/dist/cjs/routing/decorators/post.decorator.d.ts +3 -1
  190. package/dist/cjs/routing/decorators/post.decorator.d.ts.map +1 -1
  191. package/dist/cjs/routing/decorators/post.decorator.js +3 -2
  192. package/dist/cjs/routing/decorators/post.decorator.js.map +1 -1
  193. package/dist/cjs/routing/resolve-route-params.function.js +1 -0
  194. package/dist/cjs/routing/resolve-route-params.function.js.map +1 -1
  195. package/dist/cjs/routing/route-configuration.model.d.ts +11 -1
  196. package/dist/cjs/routing/route-configuration.model.d.ts.map +1 -1
  197. package/dist/cjs/routing/router.d.ts +6 -2
  198. package/dist/cjs/routing/router.d.ts.map +1 -1
  199. package/dist/cjs/routing/router.js +173 -88
  200. package/dist/cjs/routing/router.js.map +1 -1
  201. package/dist/cjs/utilities/fs.utilities.d.ts +1 -1
  202. package/dist/cjs/utilities/fs.utilities.js +1 -1
  203. package/dist/cjs/utilities/sem-ver.utilities.d.ts +46 -0
  204. package/dist/cjs/utilities/sem-ver.utilities.d.ts.map +1 -0
  205. package/dist/cjs/utilities/sem-ver.utilities.js +204 -0
  206. package/dist/cjs/utilities/sem-ver.utilities.js.map +1 -0
  207. package/dist/cjs/utilities/uuid.utilities.js +2 -2
  208. package/dist/cjs/utilities/uuid.utilities.js.map +1 -1
  209. package/dist/cjs/versioning/route-with-version-data.model.d.ts +15 -0
  210. package/dist/cjs/versioning/route-with-version-data.model.d.ts.map +1 -0
  211. package/dist/cjs/versioning/route-with-version-data.model.js +3 -0
  212. package/dist/cjs/versioning/route-with-version-data.model.js.map +1 -0
  213. package/dist/cjs/versioning/supported-versions-options.model.d.ts +17 -0
  214. package/dist/cjs/versioning/supported-versions-options.model.d.ts.map +1 -0
  215. package/dist/cjs/versioning/supported-versions-options.model.js +3 -0
  216. package/dist/cjs/versioning/supported-versions-options.model.js.map +1 -0
  217. package/dist/cjs/versioning/version.model.d.ts +29 -0
  218. package/dist/cjs/versioning/version.model.d.ts.map +1 -0
  219. package/dist/{esm/types/version.type.js → cjs/versioning/version.model.js} +1 -1
  220. package/dist/cjs/versioning/version.model.js.map +1 -0
  221. package/dist/cjs/versioning/versioning-service.interface.d.ts +31 -0
  222. package/dist/cjs/versioning/versioning-service.interface.d.ts.map +1 -0
  223. package/dist/cjs/versioning/versioning-service.interface.js +3 -0
  224. package/dist/cjs/versioning/versioning-service.interface.js.map +1 -0
  225. package/dist/cjs/versioning/versioning.service.d.ts +41 -0
  226. package/dist/cjs/versioning/versioning.service.d.ts.map +1 -0
  227. package/dist/cjs/versioning/versioning.service.js +366 -0
  228. package/dist/cjs/versioning/versioning.service.js.map +1 -0
  229. package/dist/cjs/websocket/decorators/websocket-controller.decorator.d.ts +10 -0
  230. package/dist/cjs/websocket/decorators/websocket-controller.decorator.d.ts.map +1 -1
  231. package/dist/cjs/websocket/decorators/websocket-controller.decorator.js +2 -2
  232. package/dist/cjs/websocket/decorators/websocket-controller.decorator.js.map +1 -1
  233. package/dist/cjs/websocket/decorators/websocket-route.decorator.d.ts +13 -1
  234. package/dist/cjs/websocket/decorators/websocket-route.decorator.d.ts.map +1 -1
  235. package/dist/cjs/websocket/decorators/websocket-route.decorator.js +3 -2
  236. package/dist/cjs/websocket/decorators/websocket-route.decorator.js.map +1 -1
  237. package/dist/cjs/websocket/models/connection/base-websocket-connection.model.d.ts +5 -0
  238. package/dist/cjs/websocket/models/connection/base-websocket-connection.model.d.ts.map +1 -1
  239. package/dist/cjs/websocket/models/connection/socket-io-websocket-connection.model.d.ts +3 -1
  240. package/dist/cjs/websocket/models/connection/socket-io-websocket-connection.model.d.ts.map +1 -1
  241. package/dist/cjs/websocket/models/connection/socket-io-websocket-connection.model.js +3 -1
  242. package/dist/cjs/websocket/models/connection/socket-io-websocket-connection.model.js.map +1 -1
  243. package/dist/cjs/websocket/models/websocket-controller-route-configuration.model.d.ts +6 -0
  244. package/dist/cjs/websocket/models/websocket-controller-route-configuration.model.d.ts.map +1 -1
  245. package/dist/cjs/websocket/models/websocket-message.model.d.ts +2 -2
  246. package/dist/cjs/websocket/models/websocket-message.model.d.ts.map +1 -1
  247. package/dist/cjs/websocket/models/websocket-message.model.js.map +1 -1
  248. package/dist/cjs/websocket/models/websocket-request.model.d.ts +3 -3
  249. package/dist/cjs/websocket/models/websocket-request.model.d.ts.map +1 -1
  250. package/dist/cjs/websocket/models/websocket-request.model.js +1 -1
  251. package/dist/cjs/websocket/models/websocket-request.model.js.map +1 -1
  252. package/dist/cjs/websocket/services/websocket.service.d.ts +6 -4
  253. package/dist/cjs/websocket/services/websocket.service.d.ts.map +1 -1
  254. package/dist/cjs/websocket/services/websocket.service.js +121 -33
  255. package/dist/cjs/websocket/services/websocket.service.js.map +1 -1
  256. package/dist/esm/application.js +0 -1
  257. package/dist/esm/application.js.map +1 -1
  258. package/dist/esm/assets/asset.service.js +3 -1
  259. package/dist/esm/assets/asset.service.js.map +1 -1
  260. package/dist/esm/auth/2fa/methods/otp/otp-credentials.model.js.map +1 -1
  261. package/dist/esm/auth/2fa/methods/otp/otp.two-factor-method.js +1 -1
  262. package/dist/esm/auth/2fa/methods/otp/otp.two-factor-method.js.map +1 -1
  263. package/dist/esm/auth/strategies/cookie/cookie-auth.controller.js +1 -1
  264. package/dist/esm/auth/strategies/cookie/cookie-auth.controller.js.map +1 -1
  265. package/dist/esm/auth/strategies/jwt/jwt-auth.controller.js +1 -1
  266. package/dist/esm/auth/strategies/jwt/jwt-auth.controller.js.map +1 -1
  267. package/dist/esm/auth/strategies/jwt/jwt.auth-strategy.js +1 -1
  268. package/dist/esm/auth/strategies/jwt/jwt.auth-strategy.js.map +1 -1
  269. package/dist/esm/backup/backup-resource-entity.model.js.map +1 -1
  270. package/dist/esm/change-sets/models/change-set.model.js +1 -1
  271. package/dist/esm/change-sets/models/change-set.model.js.map +1 -1
  272. package/dist/esm/change-sets/models/change.model.js.map +1 -1
  273. package/dist/esm/context/cache/cache.context.js +2 -2
  274. package/dist/esm/context/cache/cache.context.js.map +1 -1
  275. package/dist/esm/context/request/request-context-token.model.js +1 -1
  276. package/dist/esm/context/request/request-context-token.model.js.map +1 -1
  277. package/dist/esm/cron/cron-job-entity.model.js.map +1 -1
  278. package/dist/esm/data-source/data-sources/postgres-typeorm-data-source.model.js +9 -0
  279. package/dist/esm/data-source/data-sources/postgres-typeorm-data-source.model.js.map +1 -1
  280. package/dist/esm/data-source/data-sources/typeorm-base-data-source.model.js +3 -3
  281. package/dist/esm/data-source/data-sources/typeorm-base-data-source.model.js.map +1 -1
  282. package/dist/esm/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js +20 -0
  283. package/dist/esm/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.js.map +1 -1
  284. package/dist/esm/data-source/data-sources/where-converter/typeorm-where-filter.converter.js +3 -1
  285. package/dist/esm/data-source/data-sources/where-converter/typeorm-where-filter.converter.js.map +1 -1
  286. package/dist/esm/data-source/migration/migration-entity.model.js.map +1 -1
  287. package/dist/esm/data-source/models/where/where-filter-keys.model.js +3 -0
  288. package/dist/esm/data-source/models/where/where-filter-keys.model.js.map +1 -1
  289. package/dist/esm/di/default/zibri-di-providers.default.js +4 -0
  290. package/dist/esm/di/default/zibri-di-providers.default.js.map +1 -1
  291. package/dist/esm/di/default/zibri-di-tokens.default.js +2 -0
  292. package/dist/esm/di/default/zibri-di-tokens.default.js.map +1 -1
  293. package/dist/esm/email/email.service.js +4 -4
  294. package/dist/esm/email/email.service.js.map +1 -1
  295. package/dist/esm/email/models/email.model.js +4 -4
  296. package/dist/esm/email/models/email.model.js.map +1 -1
  297. package/dist/esm/entity/generation/generate-entity-file.function.js +1 -1
  298. package/dist/esm/entity/generation/generate-entity-file.function.js.map +1 -1
  299. package/dist/esm/event/event-subscriber-run.model.js +1 -1
  300. package/dist/esm/event/event-subscriber-run.model.js.map +1 -1
  301. package/dist/esm/http/known-header.enum.js +1 -0
  302. package/dist/esm/http/known-header.enum.js.map +1 -1
  303. package/dist/esm/http-client/http-client.js.map +1 -1
  304. package/dist/esm/index.js +8 -3
  305. package/dist/esm/index.js.map +1 -1
  306. package/dist/esm/localization/formatting/format-price.function.js.map +1 -1
  307. package/dist/esm/logging/log-context.model.js +6 -6
  308. package/dist/esm/logging/log-context.model.js.map +1 -1
  309. package/dist/esm/logging/logger.js +1 -1
  310. package/dist/esm/logging/logger.js.map +1 -1
  311. package/dist/esm/multithreading/models/thread-job-entity.model.js +4 -4
  312. package/dist/esm/multithreading/models/thread-job-entity.model.js.map +1 -1
  313. package/dist/esm/multithreading/services/thread-job.js.map +1 -1
  314. package/dist/esm/open-api/open-api.service.js +256 -139
  315. package/dist/esm/open-api/open-api.service.js.map +1 -1
  316. package/dist/esm/parsing/html/csp-options.model.js.map +1 -1
  317. package/dist/esm/parsing/parser.js +3 -3
  318. package/dist/esm/parsing/parser.js.map +1 -1
  319. package/dist/esm/plugin/invoicing/models/invoice-address.model.js +2 -2
  320. package/dist/esm/plugin/invoicing/models/invoice-address.model.js.map +1 -1
  321. package/dist/esm/plugin/invoicing/models/vat.model.js +1 -1
  322. package/dist/esm/plugin/invoicing/models/vat.model.js.map +1 -1
  323. package/dist/esm/plugin/mailing-list/mailing-list.controller.js +1 -1
  324. package/dist/esm/plugin/mailing-list/mailing-list.controller.js.map +1 -1
  325. package/dist/esm/plugin/mailing-list/models/mailing-list-subscriber.model.js +1 -1
  326. package/dist/esm/plugin/mailing-list/models/mailing-list-subscriber.model.js.map +1 -1
  327. package/dist/esm/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.js +1 -1
  328. package/dist/esm/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.js.map +1 -1
  329. package/dist/esm/plugin/payment/models/payment.model.js +1 -1
  330. package/dist/esm/plugin/payment/models/payment.model.js.map +1 -1
  331. package/dist/esm/plugin/payment/providers/pay-pal/pay-pal-client.js +17 -17
  332. package/dist/esm/plugin/payment/providers/pay-pal/pay-pal-client.js.map +1 -1
  333. package/dist/esm/plugin/payment/providers/pay-pal/pay-pal.payment-provider.js +1 -1
  334. package/dist/esm/plugin/payment/providers/pay-pal/pay-pal.payment-provider.js.map +1 -1
  335. package/dist/esm/preact/preact.utilities.js +1 -1
  336. package/dist/esm/preact/preact.utilities.js.map +1 -1
  337. package/dist/esm/preact/validate-email-templates.function.js +1 -1
  338. package/dist/esm/preact/validate-email-templates.function.js.map +1 -1
  339. package/dist/esm/rate-limiting/rate-limiter.js +22 -12
  340. package/dist/esm/rate-limiting/rate-limiter.js.map +1 -1
  341. package/dist/esm/routing/decorators/controller.decorator.js +3 -2
  342. package/dist/esm/routing/decorators/controller.decorator.js.map +1 -1
  343. package/dist/esm/routing/decorators/create-http-decorator.function.js +2 -2
  344. package/dist/esm/routing/decorators/create-http-decorator.function.js.map +1 -1
  345. package/dist/esm/routing/decorators/delete.decorator.js +3 -2
  346. package/dist/esm/routing/decorators/delete.decorator.js.map +1 -1
  347. package/dist/esm/routing/decorators/get.decorator.js +3 -2
  348. package/dist/esm/routing/decorators/get.decorator.js.map +1 -1
  349. package/dist/esm/routing/decorators/http-decorator-option-input.model.js +3 -0
  350. package/dist/esm/routing/decorators/http-decorator-option-input.model.js.map +1 -0
  351. package/dist/esm/routing/decorators/patch.decorator.js +3 -2
  352. package/dist/esm/routing/decorators/patch.decorator.js.map +1 -1
  353. package/dist/esm/routing/decorators/post.decorator.js +3 -2
  354. package/dist/esm/routing/decorators/post.decorator.js.map +1 -1
  355. package/dist/esm/routing/resolve-route-params.function.js +1 -0
  356. package/dist/esm/routing/resolve-route-params.function.js.map +1 -1
  357. package/dist/esm/routing/router.js +173 -88
  358. package/dist/esm/routing/router.js.map +1 -1
  359. package/dist/esm/utilities/fs.utilities.js +1 -1
  360. package/dist/esm/utilities/sem-ver.utilities.js +204 -0
  361. package/dist/esm/utilities/sem-ver.utilities.js.map +1 -0
  362. package/dist/esm/utilities/uuid.utilities.js +2 -2
  363. package/dist/esm/utilities/uuid.utilities.js.map +1 -1
  364. package/dist/esm/versioning/route-with-version-data.model.js +3 -0
  365. package/dist/esm/versioning/route-with-version-data.model.js.map +1 -0
  366. package/dist/esm/versioning/supported-versions-options.model.js +3 -0
  367. package/dist/esm/versioning/supported-versions-options.model.js.map +1 -0
  368. package/dist/{cjs/types/version.type.js → esm/versioning/version.model.js} +1 -1
  369. package/dist/esm/versioning/version.model.js.map +1 -0
  370. package/dist/esm/versioning/versioning-service.interface.js +3 -0
  371. package/dist/esm/versioning/versioning-service.interface.js.map +1 -0
  372. package/dist/esm/versioning/versioning.service.js +366 -0
  373. package/dist/esm/versioning/versioning.service.js.map +1 -0
  374. package/dist/esm/websocket/decorators/websocket-controller.decorator.js +2 -2
  375. package/dist/esm/websocket/decorators/websocket-controller.decorator.js.map +1 -1
  376. package/dist/esm/websocket/decorators/websocket-route.decorator.js +3 -2
  377. package/dist/esm/websocket/decorators/websocket-route.decorator.js.map +1 -1
  378. package/dist/esm/websocket/models/connection/socket-io-websocket-connection.model.js +3 -1
  379. package/dist/esm/websocket/models/connection/socket-io-websocket-connection.model.js.map +1 -1
  380. package/dist/esm/websocket/models/websocket-message.model.js.map +1 -1
  381. package/dist/esm/websocket/models/websocket-request.model.js +1 -1
  382. package/dist/esm/websocket/models/websocket-request.model.js.map +1 -1
  383. package/dist/esm/websocket/services/websocket.service.js +121 -33
  384. package/dist/esm/websocket/services/websocket.service.js.map +1 -1
  385. package/package.json +17 -19
  386. package/src/__testing__/test-server/providers.ts +25 -1
  387. package/src/__testing__/test-server/start-test-server.function.ts +76 -8
  388. package/src/application-options.model.ts +2 -2
  389. package/src/application.ts +0 -1
  390. package/src/assets/asset.service.ts +3 -1
  391. package/src/auth/2fa/methods/otp/otp-credentials.model.ts +1 -1
  392. package/src/auth/2fa/methods/otp/otp.two-factor-method.ts +1 -1
  393. package/src/auth/strategies/cookie/cookie-auth.controller.ts +1 -1
  394. package/src/auth/strategies/jwt/jwt-auth.controller.ts +1 -1
  395. package/src/auth/strategies/jwt/jwt.auth-strategy.ts +1 -1
  396. package/src/backup/backup-resource-entity.model.ts +1 -1
  397. package/src/backup/backup-service.test.ts +2 -1
  398. package/src/change-sets/models/change-set.model.ts +1 -1
  399. package/src/change-sets/models/change.model.ts +2 -2
  400. package/src/context/cache/cache.context.ts +2 -2
  401. package/src/context/request/request-context-token.model.ts +1 -1
  402. package/src/cron/cron-job-entity.model.ts +2 -2
  403. package/src/data-source/data-sources/postgres-typeorm-data-source.model.ts +10 -0
  404. package/src/data-source/data-sources/typeorm-base-data-source.model.ts +4 -5
  405. package/src/data-source/data-sources/where-converter/postgres-typeorm-where-filter.converter.ts +35 -2
  406. package/src/data-source/data-sources/where-converter/typeorm-where-filter.converter.ts +14 -1
  407. package/src/data-source/hooks/hooks.test.ts +1 -1
  408. package/src/data-source/migration/migration-entity.model.ts +2 -2
  409. package/src/data-source/migration/migration.model.ts +2 -2
  410. package/src/data-source/migration/migration.test.ts +2 -2
  411. package/src/data-source/models/where/date-where-filter.model.ts +11 -3
  412. package/src/data-source/models/where/string-where-filter.model.ts +18 -1
  413. package/src/data-source/models/where/where-filter-keys.model.ts +3 -0
  414. package/src/data-source/nested-where-filter.test.ts +8 -3
  415. package/src/data-source/repository.test.ts +2 -2
  416. package/src/data-source/where-filter.test.ts +17 -7
  417. package/src/di/default/zibri-di-providers.default.ts +4 -0
  418. package/src/di/default/zibri-di-tokens.default.ts +3 -0
  419. package/src/email/email.service.ts +5 -5
  420. package/src/email/models/email.model.ts +4 -4
  421. package/src/entity/generation/generate-entity-file.function.ts +1 -1
  422. package/src/event/event-subscriber-run.model.ts +1 -1
  423. package/src/global/global-registry.ts +2 -2
  424. package/src/http/http-request.model.ts +2 -2
  425. package/src/http/known-header.enum.ts +1 -0
  426. package/src/http-client/http-client.ts +0 -1
  427. package/src/index.ts +9 -3
  428. package/src/localization/formatting/format-price.function.ts +2 -3
  429. package/src/logging/log-context.model.ts +6 -6
  430. package/src/logging/logger.ts +1 -1
  431. package/src/multithreading/models/thread-job-entity.model.ts +5 -5
  432. package/src/multithreading/services/thread-job.ts +4 -4
  433. package/src/open-api/open-api-service.interface.ts +2 -1
  434. package/src/open-api/open-api.service.ts +263 -141
  435. package/src/parsing/html/csp-options.model.ts +3 -0
  436. package/src/parsing/parser.ts +3 -3
  437. package/src/plugin/invoicing/models/invoice-address.model.ts +2 -2
  438. package/src/plugin/invoicing/models/vat.model.ts +1 -1
  439. package/src/plugin/mailing-list/mailing-list.controller.ts +1 -1
  440. package/src/plugin/mailing-list/models/mailing-list-subscriber.model.ts +1 -1
  441. package/src/plugin/mailing-list/models/mailing-list-subscription-confirmation-token.model.ts +1 -1
  442. package/src/plugin/payment/models/payment.model.ts +2 -2
  443. package/src/plugin/payment/providers/pay-pal/pay-pal-client.ts +17 -17
  444. package/src/plugin/payment/providers/pay-pal/pay-pal.payment-provider.test.ts +1 -1
  445. package/src/plugin/payment/providers/pay-pal/pay-pal.payment-provider.ts +1 -1
  446. package/src/preact/preact.utilities.ts +1 -1
  447. package/src/preact/validate-email-templates.function.ts +1 -1
  448. package/src/rate-limiting/rate-limiter.ts +23 -12
  449. package/src/routing/controller-route-configuration.model.ts +6 -1
  450. package/src/routing/decorators/controller.decorator.ts +8 -2
  451. package/src/routing/decorators/create-http-decorator.function.ts +3 -2
  452. package/src/routing/decorators/delete.decorator.ts +4 -2
  453. package/src/routing/decorators/get.decorator.ts +4 -2
  454. package/src/routing/decorators/http-decorator-option-input.model.ts +11 -0
  455. package/src/routing/decorators/patch.decorator.ts +4 -2
  456. package/src/routing/decorators/post.decorator.ts +4 -2
  457. package/src/routing/resolve-route-params.function.ts +1 -0
  458. package/src/routing/route-configuration.model.ts +13 -3
  459. package/src/routing/router.ts +265 -134
  460. package/src/utilities/fs.utilities.ts +1 -1
  461. package/src/utilities/sem-ver.utilities.ts +270 -0
  462. package/src/utilities/uuid.utilities.ts +2 -2
  463. package/src/versioning/route-with-version-data.model.ts +15 -0
  464. package/src/versioning/supported-versions-options.model.ts +25 -0
  465. package/src/versioning/version.model.ts +30 -0
  466. package/src/versioning/versioning-service.interface.ts +39 -0
  467. package/src/versioning/versioning-websocket.test.ts +351 -0
  468. package/src/versioning/versioning.service.test.ts +582 -0
  469. package/src/versioning/versioning.service.ts +496 -0
  470. package/src/websocket/decorators/websocket-controller.decorator.ts +13 -3
  471. package/src/websocket/decorators/websocket-route.decorator.ts +15 -2
  472. package/src/websocket/models/connection/base-websocket-connection.model.ts +6 -0
  473. package/src/websocket/models/connection/socket-io-websocket-connection.model.ts +8 -1
  474. package/src/websocket/models/websocket-controller-route-configuration.model.ts +8 -1
  475. package/src/websocket/models/websocket-message.model.ts +2 -2
  476. package/src/websocket/models/websocket-request.model.ts +4 -3
  477. package/src/websocket/services/websocket.service.ts +143 -38
  478. package/dist/cjs/types/version.type.d.ts +0 -5
  479. package/dist/cjs/types/version.type.d.ts.map +0 -1
  480. package/dist/cjs/types/version.type.js.map +0 -1
  481. package/dist/cjs/utilities/compare-versions.function.d.ts +0 -9
  482. package/dist/cjs/utilities/compare-versions.function.d.ts.map +0 -1
  483. package/dist/cjs/utilities/compare-versions.function.js +0 -33
  484. package/dist/cjs/utilities/compare-versions.function.js.map +0 -1
  485. package/dist/cjs/utilities/is-version.function.d.ts +0 -7
  486. package/dist/cjs/utilities/is-version.function.d.ts.map +0 -1
  487. package/dist/cjs/utilities/is-version.function.js +0 -18
  488. package/dist/cjs/utilities/is-version.function.js.map +0 -1
  489. package/dist/esm/types/version.type.js.map +0 -1
  490. package/dist/esm/utilities/compare-versions.function.js +0 -33
  491. package/dist/esm/utilities/compare-versions.function.js.map +0 -1
  492. package/dist/esm/utilities/is-version.function.js +0 -18
  493. package/dist/esm/utilities/is-version.function.js.map +0 -1
  494. package/src/types/version.type.ts +0 -4
  495. package/src/utilities/compare-versions.function.ts +0 -33
  496. package/src/utilities/is-version.function.ts +0 -16
@@ -0,0 +1,496 @@
1
+ import { Dirent } from 'node:fs';
2
+
3
+ import { Version, VersionFile } from './version.model';
4
+ import { VersioningServiceInterface } from './versioning-service.interface';
5
+ import { ZibriApplication } from '../application';
6
+ import { RouteWithVersionData } from './route-with-version-data.model';
7
+ import { SemVerMatcher, SupportedVersionsOptions, VersionMatcher } from './supported-versions-options.model';
8
+ import { HttpRequestContext } from '../context/request/http-request.context';
9
+ import { WebsocketRequestContext } from '../context/request/websocket-request.context';
10
+ import { Inject } from '../di/decorators/inject.decorator';
11
+ import { Injectable } from '../di/decorators/injectable.decorator';
12
+ import { ZIBRI_DI_TOKENS } from '../di/default/zibri-di-tokens.default';
13
+ import { BadRequestError } from '../error-handling/errors/bad-request.error';
14
+ import { AfterAppInit } from '../global/after-app-init.interface';
15
+ import { type Header } from '../http/header.type';
16
+ import { ControllerRouteConfiguration } from '../routing/controller-route-configuration.model';
17
+ import { ControllerData } from '../routing/decorators/controller.decorator';
18
+ import { type RouterInterface } from '../routing/router.interface';
19
+ import { OmitStrict } from '../types/omit-strict.type';
20
+ import { FsPath, FsUtilities } from '../utilities/fs.utilities';
21
+ import { isDate } from '../utilities/is-date.function';
22
+ import { JsonUtilities } from '../utilities/json.utilities';
23
+ import { MetadataUtilities } from '../utilities/metadata.utilities';
24
+ import { SemVerUtilities, SemVerVersion } from '../utilities/sem-ver.utilities';
25
+ import { WebsocketControllerData } from '../websocket/decorators/websocket-controller.decorator';
26
+ import { WebsocketControllerRouteConfiguration } from '../websocket/models/websocket-controller-route-configuration.model';
27
+
28
+ const ROUTE_VERSION_MISMATCH_ERROR_MESSAGE: string = 'Route version mismatch detected:';
29
+
30
+ /**
31
+ * Default implementation of the versioning service.
32
+ */
33
+ @Injectable({ register: 'onUse' })
34
+ export class VersioningService implements VersioningServiceInterface, AfterAppInit {
35
+
36
+ private readonly versionsPath: FsPath = FsUtilities.getPath(__dirname, '..', 'versions');
37
+ private versionFiles: VersionFile[] = [];
38
+
39
+ constructor(
40
+ @Inject(ZIBRI_DI_TOKENS.VERSION_HEADER)
41
+ private readonly versionHeader: Header,
42
+ @Inject(ZIBRI_DI_TOKENS.ROUTER)
43
+ private readonly router: RouterInterface
44
+ ) {}
45
+
46
+ // eslint-disable-next-line jsdoc/require-jsdoc
47
+ async afterAppInit(app: ZibriApplication): Promise<void> {
48
+ await FsUtilities.mkdir(this.versionsPath);
49
+ this.versionFiles = await this.loadAllVersionFiles();
50
+ const currentLatestVersions: VersionFile[] = this.versionFiles.filter(v => v.endsAt == undefined);
51
+
52
+ if (currentLatestVersions.length === 1 && currentLatestVersions.at(0)?.value === app.options.version) {
53
+ // is already at the latest version, doesn't need to do anything.
54
+ return;
55
+ }
56
+
57
+ if (!this.versionFiles.length) {
58
+ await this.createVersionFile({
59
+ startsAt: new Date(),
60
+ value: app.options.version,
61
+ routes: this.getAllRoutes(app)
62
+ });
63
+ this.versionFiles = await this.loadAllVersionFiles();
64
+ return;
65
+ }
66
+
67
+ const currentLatest: VersionFile | undefined = this.resolveCurrentLatest(currentLatestVersions, app);
68
+ const inCodeRoutes: RouteWithVersionData[] = this.getAllRoutes(app);
69
+ const storedRoutes: RouteWithVersionData[] = currentLatest ? currentLatest.routes : [];
70
+
71
+ this.validateNoDowngrade(app);
72
+ this.validateRouteVersionSnapshot(inCodeRoutes, storedRoutes, this.versionFiles, currentLatest?.value, app.options.version);
73
+ this.validateRouteVersionsExist(inCodeRoutes, this.versionFiles, app.options.version);
74
+ this.validateLatestRoutes(inCodeRoutes, app.options.version, this.versionFiles);
75
+
76
+ // Create new version file (deprecate the old one)
77
+ const transitionTime: Date = new Date();
78
+ const newVersion: VersionFile | undefined = this.versionFiles.find(v => v.value === app.options.version);
79
+
80
+ if (newVersion != undefined) {
81
+ // Sort old active versions (excluding the new one) by startsAt
82
+ const oldActives: VersionFile[] = currentLatestVersions
83
+ .filter(v => v.value !== app.options.version)
84
+ .sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime());
85
+
86
+ // Chain the end dates: each old version ends when the next one starts
87
+ for (let i: number = 0; i < oldActives.length; i++) {
88
+ const nextStart: Date = i < oldActives.length - 1
89
+ ? new Date(oldActives[i + 1].startsAt)
90
+ : new Date(newVersion.startsAt);
91
+ await this.updateVersionFile(oldActives[i], { endsAt: nextStart });
92
+ }
93
+
94
+ // Ensure the new file’s routes are up to date
95
+ await this.updateVersionFile(newVersion, { routes: inCodeRoutes });
96
+ this.versionFiles = await this.loadAllVersionFiles();
97
+ return;
98
+ }
99
+
100
+ await this.createVersionFile({
101
+ value: app.options.version,
102
+ startsAt: transitionTime,
103
+ routes: inCodeRoutes
104
+ });
105
+
106
+ for (const active of currentLatestVersions) {
107
+ await this.updateVersionFile(active, { endsAt: transitionTime });
108
+ }
109
+ this.versionFiles = await this.loadAllVersionFiles();
110
+ }
111
+
112
+ private validateNoDowngrade(app: ZibriApplication): void {
113
+ const latestVersion: VersionFile = this.versionFiles.reduce(
114
+ (max, v) => SemVerUtilities.compare(v.value, max.value) === 'bigger' ? v : max
115
+ );
116
+ if (SemVerUtilities.compare(latestVersion.value, app.options.version) === 'bigger') {
117
+ throw new Error(
118
+ [
119
+ `Version "${app.options.version}" was previously active but has been superseded by "${latestVersion.value}".`,
120
+ 'Downgrading is not supported automatically. To resolve this, either:',
121
+ '- Revert your code and version files together via git',
122
+ `- Manually delete and update version files so that "${app.options.version}" is treated as a fresh version`
123
+ ].join('\n')
124
+ );
125
+ }
126
+ }
127
+
128
+ private resolveCurrentLatest(currentLatestVersions: VersionFile[], app: ZibriApplication): VersionFile | undefined {
129
+ if (currentLatestVersions.length === 1) {
130
+ return currentLatestVersions.at(0);
131
+ }
132
+ if (currentLatestVersions.length < 1) {
133
+ return this.versionFiles.reduce((max, v) => SemVerUtilities.compare(v.value, max.value) === 'bigger' ? v : max);
134
+ }
135
+
136
+ const currentLatest: VersionFile | undefined = currentLatestVersions.find(v => v.value !== app.options.version);
137
+ if (!currentLatest) {
138
+ throw new Error(
139
+ 'Inconsistent version state: multiple active versions exist, but they all represent the global version.'
140
+ + ' Check for duplicate version files.'
141
+ );
142
+ }
143
+ return currentLatest;
144
+ }
145
+
146
+ private async loadAllVersionFiles(): Promise<VersionFile[]> {
147
+ const entries: Dirent[] = await FsUtilities.readdir(FsUtilities.getPath(this.versionsPath));
148
+ const res: (VersionFile | undefined)[] = await Promise.all(entries.map(async e => {
149
+ if (!e.isFile() || !e.name.endsWith('.json')) {
150
+ return undefined;
151
+ }
152
+ const raw: string = await FsUtilities.readFile(FsUtilities.getPath(e.parentPath, e.name));
153
+ return JsonUtilities.parse(raw);
154
+ }));
155
+ return res.filter(Boolean) as VersionFile[];
156
+ }
157
+
158
+ private async createVersionFile(data: VersionFile): Promise<void> {
159
+ await FsUtilities.createFile(
160
+ FsUtilities.getPath(this.versionsPath, `${data.value}.json`),
161
+ JsonUtilities.stringify(data)
162
+ );
163
+ }
164
+
165
+ private async updateVersionFile(versionFile: VersionFile, data: Partial<OmitStrict<VersionFile, 'value'>>): Promise<void> {
166
+ const updated: VersionFile = { ...versionFile, ...data };
167
+ await FsUtilities.updateFile(
168
+ FsUtilities.getPath(this.versionsPath, `${versionFile.value}.json`),
169
+ JsonUtilities.stringify(updated),
170
+ 'replace'
171
+ );
172
+ }
173
+
174
+ private validateRouteVersionSnapshot(
175
+ inCodeRoutes: RouteWithVersionData[],
176
+ storedRoutes: RouteWithVersionData[],
177
+ versionFiles: VersionFile[],
178
+ currentLatest: SemVerVersion | undefined,
179
+ newVersion: SemVerVersion
180
+ ): void {
181
+ if (!currentLatest) {
182
+ return;
183
+ }
184
+ const knownVersions: Set<SemVerVersion> = new Set(versionFiles.map(e => e.value));
185
+ const errors: string[] = [];
186
+
187
+ for (const storedRoute of storedRoutes) {
188
+ const routes: RouteWithVersionData[] = inCodeRoutes.filter(r => r.key === storedRoute.key);
189
+
190
+ if (!routes.length) {
191
+ errors.push(`Route "${storedRoute.key}" no longer exists in code.`);
192
+ continue;
193
+ }
194
+
195
+ const removedVersions: SemVerVersion[] = this.getRemovedVersions(
196
+ storedRoute.versions,
197
+ routes.some(r => r.versions === 'all')
198
+ ? 'all'
199
+ : routes.flatMap(r => r.versions === 'all' ? [] : r.versions),
200
+ [...knownVersions],
201
+ currentLatest,
202
+ newVersion
203
+
204
+ );
205
+ if (!removedVersions.length) {
206
+ continue;
207
+ }
208
+
209
+ const versionLabel: string = removedVersions.length > 1 ? 'versions' : 'version';
210
+ errors.push(
211
+ `Route "${storedRoute.key}" removed ${versionLabel}: ${removedVersions.join(', ')}`
212
+ );
213
+ }
214
+
215
+ if (errors.length) {
216
+ throw new Error([ROUTE_VERSION_MISMATCH_ERROR_MESSAGE, ...errors.map(error => `- ${error}`)].join('\n'));
217
+ }
218
+ }
219
+
220
+ private getRemovedVersions(
221
+ previous: SupportedVersionsOptions,
222
+ current: SupportedVersionsOptions,
223
+ knownVersions: SemVerVersion[],
224
+ currentLatest: SemVerVersion,
225
+ newVersion: SemVerVersion
226
+ ): SemVerVersion[] {
227
+ const previousResolved: SemVerVersion[] = this.resolveConcreteVersions(previous, knownVersions, currentLatest);
228
+ const currentResolved: SemVerVersion[] = this.resolveConcreteVersions(current, knownVersions, newVersion);
229
+
230
+ return previousResolved.filter(v => !currentResolved.includes(v));
231
+ }
232
+
233
+ private resolveConcreteVersions(
234
+ versions: SupportedVersionsOptions,
235
+ knownVersions: SemVerVersion[],
236
+ currentLatest: SemVerVersion
237
+ ): SemVerVersion[] {
238
+ if (versions === 'all') {
239
+ return [...knownVersions];
240
+ }
241
+
242
+ const resolvedMatchers: SemVerMatcher[] = versions.map(
243
+ v => this.versionMatcherToSemVerMatcher(v, currentLatest)
244
+ );
245
+
246
+ return knownVersions.filter(version => SemVerUtilities.matches(version, resolvedMatchers));
247
+ }
248
+
249
+ private validateRouteVersionsExist(
250
+ inCodeRoutes: RouteWithVersionData[],
251
+ versionFiles: VersionFile[],
252
+ newVersion: SemVerVersion
253
+ ): void {
254
+ const knownVersions: SemVerVersion[] = versionFiles.map(v => v.value);
255
+ const candidateVersions: SemVerVersion[] = [...knownVersions, newVersion];
256
+ const errors: string[] = [];
257
+
258
+ // eslint-disable-next-line typescript/typedef
259
+ const validateRoute = (route: RouteWithVersionData, latest: SemVerVersion, location: string): void => {
260
+ if (route.versions === 'all') {
261
+ return;
262
+ }
263
+
264
+ for (const matcher of route.versions) {
265
+ const resolvedMatcher: SemVerMatcher = this.versionMatcherToSemVerMatcher(matcher, latest);
266
+
267
+ const matchesAny: boolean = candidateVersions.some(version => SemVerUtilities.matches(version, [resolvedMatcher]));
268
+
269
+ if (!matchesAny) {
270
+ errors.push(`Unknown version "${matcher}" ${location}`);
271
+ }
272
+ }
273
+ };
274
+
275
+ for (const file of versionFiles) {
276
+ for (const route of file.routes) {
277
+ validateRoute(route, file.value, `in version file "${file.value}.json" on route "${route.key}"`);
278
+ }
279
+ }
280
+
281
+ if (errors.length) {
282
+ throw new Error([ROUTE_VERSION_MISMATCH_ERROR_MESSAGE, ...errors.map(error => `- ${error}`)].join('\n'));
283
+ }
284
+
285
+ for (const route of inCodeRoutes) {
286
+ validateRoute(route, newVersion, `on route "${route.key}"`);
287
+ }
288
+
289
+ if (errors.length) {
290
+ throw new Error([ROUTE_VERSION_MISMATCH_ERROR_MESSAGE, ...errors.map(error => `- ${error}`)].join('\n'));
291
+ }
292
+ }
293
+
294
+ private validateLatestRoutes(
295
+ inCodeRoutes: RouteWithVersionData[],
296
+ currentVersion: SemVerVersion,
297
+ allVersionFiles: VersionFile[]
298
+ ): void {
299
+ const previousCandidates: VersionFile[] = allVersionFiles.filter(
300
+ v => v.endsAt == undefined && v.value !== currentVersion
301
+ );
302
+ if (previousCandidates.length === 0) {
303
+ return;
304
+ }
305
+
306
+ const previousLatest: VersionFile = previousCandidates.reduce((max, v) => new Date(v.startsAt) > new Date(max.startsAt) ? v : max);
307
+ const previousRoutesByKey: Map<string, RouteWithVersionData> = new Map(
308
+ previousLatest.routes.map(route => [route.key, route])
309
+ );
310
+
311
+ const routesThatNeedUpdate: RouteWithVersionData[] = inCodeRoutes.filter(r => {
312
+ if (r.versions === 'all') {
313
+ return false;
314
+ }
315
+
316
+ const usesLatestAlias: boolean = r.versions.some(
317
+ v => v === 'latest' || v === '^latest' || v === '~latest'
318
+ );
319
+
320
+ if (!usesLatestAlias) {
321
+ return false;
322
+ }
323
+
324
+ const previousRoute: RouteWithVersionData | undefined = previousRoutesByKey.get(r.key);
325
+ if (!previousRoute || previousRoute.versions === 'all') {
326
+ return true;
327
+ }
328
+
329
+ return !this.routeSupportsVersion(previousRoute, previousLatest.value, previousLatest.value);
330
+ });
331
+
332
+ if (routesThatNeedUpdate.length) {
333
+ throw new Error(
334
+ [
335
+ `There are routes that have been used under the previous version "${previousLatest.value}"`,
336
+ 'To continue, you either need to:',
337
+ '- Define that the route supports the previous version as well as \'latest\'',
338
+ '- Define that it only supports the previous version and optionally create a separate endpoint for the new version',
339
+ 'This can be done on the @Get/@Post etc. decorators or on the @Controller/@WebsocketController decorators',
340
+ '',
341
+ 'Affected routes/websocket events:',
342
+ ...routesThatNeedUpdate.map(r => `- ${r.key}`)
343
+ ].join('\n')
344
+ );
345
+ }
346
+ }
347
+
348
+ // eslint-disable-next-line jsdoc/require-jsdoc
349
+ resolveVersion(context: HttpRequestContext | WebsocketRequestContext): Version {
350
+ const versionValue: string | undefined = context instanceof WebsocketRequestContext
351
+ ? context.connection?.resolvedVersion.value ?? context.request.headers?.[this.versionHeader]
352
+ : context.request.headers?.[this.versionHeader];
353
+
354
+ try {
355
+ if (versionValue == undefined) {
356
+ const latest: VersionFile | undefined = this.versionFiles.find(v => v.endsAt == undefined);
357
+ if (!latest) {
358
+ throw new BadRequestError('No active version found');
359
+ }
360
+ return latest;
361
+ }
362
+ if (isDate(versionValue)) {
363
+ return this.resolveVersionForDate(new Date(versionValue), this.versionFiles);
364
+ }
365
+ const res: VersionFile | undefined = this.versionFiles.find(v => v.value === versionValue);
366
+ if (!res) {
367
+ throw new BadRequestError(`Version "${versionValue}" not found`);
368
+ }
369
+ return res;
370
+ }
371
+ catch (error) {
372
+ if (error instanceof BadRequestError) {
373
+ throw error;
374
+ }
375
+ throw new BadRequestError('Could not resolve version');
376
+ }
377
+ }
378
+
379
+ // eslint-disable-next-line jsdoc/require-jsdoc
380
+ findOverlappingVersions(
381
+ a: SupportedVersionsOptions,
382
+ b: SupportedVersionsOptions,
383
+ currentLatest: SemVerVersion
384
+ ): SupportedVersionsOptions {
385
+ if (a === 'all' || b === 'all') {
386
+ return 'all';
387
+ }
388
+
389
+ const resolvedA: SemVerMatcher[] = a.map(v => this.versionMatcherToSemVerMatcher(v, currentLatest));
390
+ const resolvedB: SemVerMatcher[] = b.map(v => this.versionMatcherToSemVerMatcher(v, currentLatest));
391
+
392
+ return resolvedA.filter(v => SemVerUtilities.matches(v, resolvedB));
393
+ }
394
+
395
+ private versionMatcherToSemVerMatcher(version: VersionMatcher, currentLatest: SemVerVersion): SemVerMatcher {
396
+ if (version === 'latest') {
397
+ return currentLatest;
398
+ }
399
+ if (version === '^latest') {
400
+ return `^${currentLatest}`;
401
+ }
402
+ if (version === '~latest') {
403
+ return `~${currentLatest}`;
404
+ }
405
+
406
+ return version;
407
+ }
408
+
409
+ // eslint-disable-next-line jsdoc/require-jsdoc
410
+ hasOverlappingVersions(
411
+ a: SupportedVersionsOptions,
412
+ b: SupportedVersionsOptions,
413
+ currentLatest: SemVerVersion
414
+ ): boolean {
415
+ const result: SupportedVersionsOptions = this.findOverlappingVersions(a, b, currentLatest);
416
+ return result === 'all' || !!result.length;
417
+ }
418
+
419
+ // eslint-disable-next-line jsdoc/require-jsdoc
420
+ matchesVersion(versions: SupportedVersionsOptions, resolvedVersion: Version): boolean {
421
+ if (versions === 'all') {
422
+ return true;
423
+ }
424
+
425
+ const latest: VersionFile | undefined = this.versionFiles.find(v => v.endsAt == undefined);
426
+ if (!latest) {
427
+ throw new BadRequestError('No active version found');
428
+ }
429
+ const resolvedMatchers: SemVerMatcher[] = versions.map(
430
+ v => this.versionMatcherToSemVerMatcher(v, latest.value)
431
+ );
432
+
433
+ return SemVerUtilities.matches(resolvedVersion.value, resolvedMatchers);
434
+ }
435
+
436
+ // eslint-disable-next-line jsdoc/require-jsdoc
437
+ getVersions(): VersionFile[] {
438
+ return this.versionFiles;
439
+ }
440
+
441
+ private resolveVersionForDate(date: Date, allVersions: VersionFile[]): Version {
442
+ const res: VersionFile | undefined = allVersions.find(v => {
443
+ return (new Date(v.startsAt).getTime() <= date.getTime())
444
+ && (v.endsAt == undefined || new Date(v.endsAt).getTime() > date.getTime());
445
+ });
446
+ if (!res) {
447
+ throw new BadRequestError('No version active at that date');
448
+ }
449
+ return res;
450
+ }
451
+
452
+ private routeSupportsVersion(
453
+ route: RouteWithVersionData,
454
+ version: SemVerVersion,
455
+ latestContext: SemVerVersion
456
+ ): boolean {
457
+ if (route.versions === 'all') {
458
+ return true;
459
+ }
460
+
461
+ const resolved: SemVerMatcher[] = route.versions.map(v => this.versionMatcherToSemVerMatcher(v, latestContext));
462
+
463
+ return SemVerUtilities.matches(version, resolved);
464
+ }
465
+
466
+ private getAllRoutes(app: ZibriApplication): RouteWithVersionData[] {
467
+ const allRoutes: RouteWithVersionData[] = [
468
+ ...this.router.manuallyRegisteredRoutes.map(r => ({ key: `${r.httpMethod.toUpperCase()} ${r.route}`, versions: r.versions })),
469
+ ...app.options.controllers.flatMap(c => {
470
+ const controllerData: ControllerData | undefined = MetadataUtilities.getControllerData(c);
471
+ if (!controllerData) {
472
+ throw new Error('Could not resolve controller data');
473
+ }
474
+ const routes: ControllerRouteConfiguration[] = MetadataUtilities.getControllerRoutes(c);
475
+ return routes.map(r => ({
476
+ versions: r.versions ?? controllerData.versions,
477
+ key: controllerData.baseRoute === '/'
478
+ ? `${r.httpMethod.toUpperCase()} ${r.route}`
479
+ : `${r.httpMethod.toUpperCase()} ${controllerData.baseRoute}${r.route}`
480
+ }));
481
+ }),
482
+ ...app.options.websocketControllers.flatMap(c => {
483
+ const controllerData: WebsocketControllerData | undefined = MetadataUtilities.getWebsocketControllerData(c);
484
+ if (!controllerData) {
485
+ throw new Error('Could not resolve controller data');
486
+ }
487
+ const routes: WebsocketControllerRouteConfiguration[] = MetadataUtilities.getWebsocketControllerRoutes(c);
488
+ return routes.map(r => ({
489
+ versions: r.versions ?? controllerData.versions,
490
+ key: `${controllerData.eventPrefix}${r.event}`
491
+ }));
492
+ })
493
+ ];
494
+ return allRoutes;
495
+ }
496
+ }
@@ -1,15 +1,25 @@
1
1
  import { GlobalRegistry } from '../../global/global-registry';
2
2
  import { Newable } from '../../types/newable.type';
3
3
  import { MetadataUtilities } from '../../utilities/metadata.utilities';
4
+ import { SupportedVersionsOptions } from '../../versioning/supported-versions-options.model';
4
5
 
5
6
  /**
6
7
  * Data of a websocket controller.
7
8
  */
8
9
  export type WebsocketControllerData = {
10
+ /**
11
+ * A prefix that all events of the controller should have.
12
+ * @default ''
13
+ */
14
+ eventPrefix: string,
9
15
  /**
10
16
  * Whether or not this websocket controller is allowed to exist without being registered in the application.
11
17
  */
12
- allowOrphan: boolean
18
+ allowOrphan: boolean,
19
+ /**
20
+ * The versions that should be supported by this websocket controller's events. Can be overridden per event.
21
+ */
22
+ versions: SupportedVersionsOptions
13
23
  };
14
24
 
15
25
  /**
@@ -17,12 +27,12 @@ export type WebsocketControllerData = {
17
27
  * @param options - Options for the websocket controller.
18
28
  */
19
29
  export function WebsocketController(options: Partial<WebsocketControllerData> = {}): ClassDecorator {
20
- const { allowOrphan = false } = options;
30
+ const { allowOrphan = false, versions = ['^latest'], eventPrefix = '' } = options;
21
31
  return target => {
22
32
  // eslint-disable-next-line unicorn/error-message
23
33
  const stack: string = new Error().stack ?? '';
24
34
  MetadataUtilities.setFilePath(target, stack);
25
- MetadataUtilities.setWebsocketControllerData(target, { allowOrphan });
35
+ MetadataUtilities.setWebsocketControllerData(target, { allowOrphan, versions, eventPrefix });
26
36
  GlobalRegistry.injectables.push({
27
37
  token: target as unknown as Newable<unknown>,
28
38
  useClass: target as unknown as Newable<unknown>
@@ -1,18 +1,31 @@
1
1
  import { MetadataUtilities } from '../../utilities/metadata.utilities';
2
+ import { SupportedVersionsOptions } from '../../versioning/supported-versions-options.model';
2
3
  import { WebsocketControllerRouteConfiguration } from '../models/websocket-controller-route-configuration.model';
3
4
 
5
+ /**
6
+ * Options for a websocket route.
7
+ */
8
+ export type WebsocketRouteOptions = {
9
+ /**
10
+ * The supported versions of this route.
11
+ * Defaults to '^latest'.
12
+ */
13
+ versions?: SupportedVersionsOptions
14
+ };
15
+
4
16
  /**
5
17
  * Defines a route to receive websocket messages.
6
18
  * @param event - The event to listen on.
19
+ * @param options - The options of the route, like eg. The supported versions.
7
20
  */
8
- export function WebsocketRoute(event: string): MethodDecorator {
21
+ export function WebsocketRoute(event: string, options: WebsocketRouteOptions = {}): MethodDecorator {
9
22
  return (target, propertyKey) => {
10
23
  const ctor: Function = target.constructor;
11
24
  // eslint-disable-next-line unicorn/error-message
12
25
  const stack: string = new Error().stack ?? '';
13
26
  MetadataUtilities.setFilePath(ctor, stack);
14
27
  const routes: WebsocketControllerRouteConfiguration[] = MetadataUtilities.getWebsocketControllerRoutes(ctor);
15
- routes.push({ event, controllerMethod: propertyKey.toString() });
28
+ routes.push({ event, controllerMethod: propertyKey.toString(), versions: options.versions });
16
29
  MetadataUtilities.setWebsocketControllerRoutes(ctor, routes);
17
30
  };
18
31
  }
@@ -1,3 +1,5 @@
1
+ import { Version } from '../../../versioning/version.model';
2
+
1
3
  /**
2
4
  * Basic definition of a websocket connection.
3
5
  * Your implementation probably needs to extend this.
@@ -11,6 +13,10 @@ export type BaseWebsocketConnection = {
11
13
  * The id of the user that this connection belongs to.
12
14
  */
13
15
  readonly userId: string | undefined,
16
+ /**
17
+ * The resolved version of the connection.
18
+ */
19
+ readonly resolvedVersion: Version,
14
20
  /**
15
21
  * The current offset of the connection.
16
22
  * Is used to sync the state of the server with the client after a reconnect.
@@ -1,6 +1,7 @@
1
1
  import { Socket } from 'socket.io';
2
2
 
3
3
  import { BaseWebsocketConnection } from './base-websocket-connection.model';
4
+ import { Version } from '../../../versioning/version.model';
4
5
  import { LooseWebsocketEvent, WebsocketEvent } from '../websocket-event.enum';
5
6
  import { WebsocketMessage } from '../websocket-message.model';
6
7
 
@@ -15,6 +16,7 @@ export class SocketIOWebsocketConnection implements BaseWebsocketConnection {
15
16
  * In that case, any missed packets will be transmitted to the client, the data attribute and the rooms will be restored.
16
17
  */
17
18
  readonly recovered: boolean;
19
+
18
20
  // eslint-disable-next-line jsdoc/require-jsdoc
19
21
  get offset(): number {
20
22
  if (typeof this.socket.handshake.auth.offset !== 'number') {
@@ -26,7 +28,12 @@ export class SocketIOWebsocketConnection implements BaseWebsocketConnection {
26
28
  this.socket.handshake.auth.offset = value;
27
29
  }
28
30
 
29
- constructor(private readonly socket: Socket, public userId: string | undefined) {
31
+ constructor(
32
+ private readonly socket: Socket,
33
+ public userId: string | undefined,
34
+ readonly resolvedVersion: Version
35
+
36
+ ) {
30
37
  this.id = this.socket.id;
31
38
  this.recovered = this.socket.recovered;
32
39
  }
@@ -1,3 +1,5 @@
1
+ import { SupportedVersionsOptions } from '../../versioning/supported-versions-options.model';
2
+
1
3
  /**
2
4
  * The configuration for a websocket controller route.
3
5
  */
@@ -9,5 +11,10 @@ export type WebsocketControllerRouteConfiguration = {
9
11
  /**
10
12
  * The name of the method on the controller that is responsible for handling messages to the websocket event.
11
13
  */
12
- controllerMethod: string
14
+ controllerMethod: string,
15
+ /**
16
+ * The supported versions of this route.
17
+ * Defaults to '^latest'.
18
+ */
19
+ versions: SupportedVersionsOptions | undefined
13
20
  };
@@ -56,12 +56,12 @@ export class WebsocketMessage extends BaseEntity {
56
56
  * The id of the user that has sent the message.
57
57
  */
58
58
  @Property.string({ required: false, format: 'uuid' })
59
- senderUserId: string | undefined;
59
+ senderUserId: string | undefined | null;
60
60
  /**
61
61
  * The of the connection that has sent the message.
62
62
  */
63
63
  @Property.string({ required: false })
64
- senderConnectionId: string | undefined;
64
+ senderConnectionId: string | undefined | null;
65
65
  /**
66
66
  * The actual data of the message.
67
67
  */
@@ -1,5 +1,6 @@
1
1
  import { BaseWebsocketConnection } from './connection/base-websocket-connection.model';
2
2
  import { Property } from '../../entity/decorators/property.decorator';
3
+ import { Header } from '../../http/header.type';
3
4
  import { HttpRequest } from '../../http/http-request.model';
4
5
  import { KnownHeader } from '../../http/known-header.enum';
5
6
 
@@ -23,7 +24,7 @@ export class WebsocketRequest<
23
24
  T = unknown,
24
25
  PathParamsObject extends Record<string, unknown> = Record<string, string | undefined>,
25
26
  QueryParamsObject extends Record<string, unknown> = Record<string, string | undefined>,
26
- HeaderParamsObject extends Record<string, unknown> = Partial<Record<KnownHeader, string | undefined>>
27
+ HeaderParamsObject extends Record<string, unknown> = Partial<Record<Header, string | undefined>>
27
28
  > implements Partial<Pick<
28
29
  HttpRequest<T, PathParamsObject, QueryParamsObject, HeaderParamsObject>,
29
30
  'headers' | 'body' | 'query' | 'params'>
@@ -33,8 +34,8 @@ export class WebsocketRequest<
33
34
  query: QueryParamsObject | undefined;
34
35
 
35
36
  // eslint-disable-next-line jsdoc/require-jsdoc
36
- @Property.object({ cls: () => HeadersObject, allowAdditionalProperties: true })
37
- headers!: HeaderParamsObject;
37
+ @Property.object({ cls: () => HeadersObject, required: false, allowAdditionalProperties: true })
38
+ headers: HeaderParamsObject | undefined;
38
39
 
39
40
  // eslint-disable-next-line jsdoc/require-jsdoc
40
41
  @Property.object({ cls: () => ParamsObject, required: false, allowAdditionalProperties: true })