@tstdl/base 0.93.182 → 0.93.183

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 (353) hide show
  1. package/api/server/api-request-token.provider.js +1 -1
  2. package/api/server/gateway.js +6 -1
  3. package/authentication/authentication.api.d.ts +13 -40
  4. package/authentication/authentication.api.js +5 -14
  5. package/authentication/client/authentication.service.d.ts +6 -14
  6. package/authentication/client/authentication.service.js +22 -4
  7. package/authentication/client/module.d.ts +1 -1
  8. package/authentication/client/module.js +4 -4
  9. package/authentication/models/index.d.ts +1 -0
  10. package/authentication/models/index.js +1 -0
  11. package/authentication/models/totp-results.model.d.ts +11 -0
  12. package/authentication/models/totp-results.model.js +37 -0
  13. package/authentication/server/authentication.api-controller.d.ts +3 -3
  14. package/authentication/server/authentication.api-controller.js +31 -4
  15. package/authentication/server/authentication.service.d.ts +5 -14
  16. package/authentication/server/authentication.service.js +6 -4
  17. package/core.d.ts +0 -5
  18. package/core.js +0 -8
  19. package/document-management/api/document-management.api.d.ts +2 -2
  20. package/document-management/service-models/document.service-model.d.ts +1 -1
  21. package/examples/config.d.ts +25 -0
  22. package/examples/config.js +26 -0
  23. package/notification/server/module.d.ts +1 -1
  24. package/notification/server/module.js +1 -1
  25. package/package.json +5 -5
  26. package/signals/api.d.ts +5 -1
  27. package/signals/api.js +3 -1
  28. package/signals/implementation/api.d.ts +13 -5
  29. package/signals/implementation/api.js +7 -1
  30. package/signals/implementation/asserts.d.ts +2 -2
  31. package/signals/implementation/asserts.js +3 -3
  32. package/signals/implementation/computed.d.ts +7 -34
  33. package/signals/implementation/computed.js +14 -83
  34. package/signals/implementation/configure.js +6 -2
  35. package/signals/implementation/effect.d.ts +65 -46
  36. package/signals/implementation/effect.js +97 -62
  37. package/signals/implementation/index.d.ts +2 -4
  38. package/signals/implementation/index.js +2 -4
  39. package/signals/implementation/linked_signal.d.ts +36 -0
  40. package/signals/implementation/linked_signal.js +34 -0
  41. package/signals/implementation/primitive/computed.d.ts +55 -0
  42. package/signals/implementation/primitive/computed.js +107 -0
  43. package/signals/implementation/primitive/effect.d.ts +26 -0
  44. package/signals/implementation/primitive/effect.js +31 -0
  45. package/signals/implementation/{equality.d.ts → primitive/equality.d.ts} +1 -1
  46. package/signals/implementation/{equality.js → primitive/equality.js} +1 -1
  47. package/signals/implementation/primitive/errors.d.ts +10 -0
  48. package/signals/implementation/{errors.js → primitive/errors.js} +3 -4
  49. package/signals/implementation/primitive/formatter.d.ts +19 -0
  50. package/signals/implementation/primitive/formatter.js +136 -0
  51. package/signals/implementation/{graph.d.ts → primitive/graph.d.ts} +68 -36
  52. package/signals/implementation/primitive/graph.js +386 -0
  53. package/signals/implementation/primitive/linked_signal.d.ts +46 -0
  54. package/signals/implementation/primitive/linked_signal.js +110 -0
  55. package/signals/implementation/primitive/signal.d.ts +31 -0
  56. package/signals/implementation/primitive/signal.js +80 -0
  57. package/signals/implementation/primitive/untracked.d.ts +12 -0
  58. package/signals/implementation/primitive/untracked.js +23 -0
  59. package/signals/implementation/{watch.d.ts → primitive/watch.d.ts} +1 -2
  60. package/signals/implementation/{watch.js → primitive/watch.js} +22 -16
  61. package/signals/implementation/resource/api.d.ts +275 -0
  62. package/signals/implementation/resource/api.js +26 -0
  63. package/signals/implementation/resource/debounce.d.ts +13 -0
  64. package/signals/implementation/resource/debounce.js +113 -0
  65. package/signals/implementation/resource/from_snapshots.d.ts +16 -0
  66. package/signals/implementation/resource/from_snapshots.js +44 -0
  67. package/signals/implementation/resource/index.d.ts +11 -0
  68. package/signals/implementation/resource/index.js +11 -0
  69. package/signals/implementation/resource/resource.d.ts +110 -0
  70. package/signals/implementation/resource/resource.js +402 -0
  71. package/signals/implementation/root_effect_scheduler.d.ts +50 -0
  72. package/signals/implementation/root_effect_scheduler.js +66 -0
  73. package/signals/implementation/signal.d.ts +42 -18
  74. package/signals/implementation/signal.js +29 -49
  75. package/signals/implementation/to-observable.d.ts +12 -5
  76. package/signals/implementation/to-observable.js +12 -2
  77. package/signals/implementation/to-signal.d.ts +9 -18
  78. package/signals/implementation/to-signal.js +46 -13
  79. package/signals/implementation/untracked.d.ts +1 -1
  80. package/signals/implementation/untracked.js +3 -11
  81. package/signals/operators/debounce.d.ts +8 -0
  82. package/signals/operators/debounce.js +19 -0
  83. package/signals/operators/derive-async.js +43 -15
  84. package/signals/operators/index.d.ts +2 -0
  85. package/signals/operators/index.js +2 -0
  86. package/signals/operators/throttle.d.ts +8 -0
  87. package/signals/operators/throttle.js +31 -0
  88. package/ai/genkit/tests/multi-region.test.d.ts +0 -2
  89. package/ai/genkit/tests/multi-region.test.js +0 -179
  90. package/ai/genkit/tests/token-limit-fallback.test.d.ts +0 -2
  91. package/ai/genkit/tests/token-limit-fallback.test.js +0 -209
  92. package/ai/prompts/tests/prompt-builder.test.d.ts +0 -1
  93. package/ai/prompts/tests/prompt-builder.test.js +0 -22
  94. package/ai/tests/instructions-formatter.test.d.ts +0 -1
  95. package/ai/tests/instructions-formatter.test.js +0 -116
  96. package/ai/tests/steering.test.d.ts +0 -1
  97. package/ai/tests/steering.test.js +0 -37
  98. package/api/client/tests/api-client.test.d.ts +0 -1
  99. package/api/client/tests/api-client.test.js +0 -194
  100. package/api/server/tests/csrf.middleware.test.d.ts +0 -1
  101. package/api/server/tests/csrf.middleware.test.js +0 -91
  102. package/authentication/tests/authentication-password-requirements.validator.test.d.ts +0 -1
  103. package/authentication/tests/authentication-password-requirements.validator.test.js +0 -29
  104. package/authentication/tests/authentication.api-controller.test.d.ts +0 -1
  105. package/authentication/tests/authentication.api-controller.test.js +0 -156
  106. package/authentication/tests/authentication.api-request-token.provider.test.d.ts +0 -1
  107. package/authentication/tests/authentication.api-request-token.provider.test.js +0 -48
  108. package/authentication/tests/authentication.client-error-handling.test.d.ts +0 -1
  109. package/authentication/tests/authentication.client-error-handling.test.js +0 -123
  110. package/authentication/tests/authentication.client-middleware.test.d.ts +0 -1
  111. package/authentication/tests/authentication.client-middleware.test.js +0 -118
  112. package/authentication/tests/authentication.client-service-methods.test.d.ts +0 -1
  113. package/authentication/tests/authentication.client-service-methods.test.js +0 -177
  114. package/authentication/tests/authentication.client-service-refresh.test.d.ts +0 -1
  115. package/authentication/tests/authentication.client-service-refresh.test.js +0 -153
  116. package/authentication/tests/authentication.client-service.test.d.ts +0 -1
  117. package/authentication/tests/authentication.client-service.test.js +0 -76
  118. package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +0 -1
  119. package/authentication/tests/authentication.refresh-busy-loop.test.js +0 -84
  120. package/authentication/tests/authentication.service.test.d.ts +0 -1
  121. package/authentication/tests/authentication.service.test.js +0 -167
  122. package/authentication/tests/authentication.test-ancillary-service.d.ts +0 -9
  123. package/authentication/tests/authentication.test-ancillary-service.js +0 -27
  124. package/authentication/tests/brute-force-protection.test.d.ts +0 -1
  125. package/authentication/tests/brute-force-protection.test.js +0 -211
  126. package/authentication/tests/helper.test.d.ts +0 -1
  127. package/authentication/tests/helper.test.js +0 -122
  128. package/authentication/tests/password-requirements.error.test.d.ts +0 -1
  129. package/authentication/tests/password-requirements.error.test.js +0 -14
  130. package/authentication/tests/remember.api.test.d.ts +0 -1
  131. package/authentication/tests/remember.api.test.js +0 -117
  132. package/authentication/tests/remember.service.test.d.ts +0 -1
  133. package/authentication/tests/remember.service.test.js +0 -83
  134. package/authentication/tests/subject.service.test.d.ts +0 -1
  135. package/authentication/tests/subject.service.test.js +0 -140
  136. package/authentication/tests/suspended-subject.test.d.ts +0 -1
  137. package/authentication/tests/suspended-subject.test.js +0 -120
  138. package/authentication/tests/totp.enrollment.test.d.ts +0 -1
  139. package/authentication/tests/totp.enrollment.test.js +0 -123
  140. package/authentication/tests/totp.login.test.d.ts +0 -1
  141. package/authentication/tests/totp.login.test.js +0 -213
  142. package/authentication/tests/totp.recovery-codes.test.d.ts +0 -1
  143. package/authentication/tests/totp.recovery-codes.test.js +0 -97
  144. package/authentication/tests/totp.status.test.d.ts +0 -1
  145. package/authentication/tests/totp.status.test.js +0 -72
  146. package/cancellation/tests/coverage.test.d.ts +0 -1
  147. package/cancellation/tests/coverage.test.js +0 -49
  148. package/cancellation/tests/leak.test.d.ts +0 -1
  149. package/cancellation/tests/leak.test.js +0 -35
  150. package/cancellation/tests/token.test.d.ts +0 -1
  151. package/cancellation/tests/token.test.js +0 -136
  152. package/circuit-breaker/tests/circuit-breaker.test.d.ts +0 -1
  153. package/circuit-breaker/tests/circuit-breaker.test.js +0 -116
  154. package/cryptography/tests/cryptography.test.d.ts +0 -1
  155. package/cryptography/tests/cryptography.test.js +0 -175
  156. package/cryptography/tests/jwt.test.d.ts +0 -1
  157. package/cryptography/tests/jwt.test.js +0 -54
  158. package/cryptography/tests/modern.test.d.ts +0 -1
  159. package/cryptography/tests/modern.test.js +0 -105
  160. package/cryptography/tests/module.test.d.ts +0 -1
  161. package/cryptography/tests/module.test.js +0 -100
  162. package/cryptography/tests/totp.test.d.ts +0 -1
  163. package/cryptography/tests/totp.test.js +0 -108
  164. package/document-management/tests/ai-config-hierarchy.test.d.ts +0 -1
  165. package/document-management/tests/ai-config-hierarchy.test.js +0 -59
  166. package/document-management/tests/ai-config-integration.test.d.ts +0 -1
  167. package/document-management/tests/ai-config-integration.test.js +0 -125
  168. package/document-management/tests/ai-config-merge.test.d.ts +0 -1
  169. package/document-management/tests/ai-config-merge.test.js +0 -46
  170. package/document-management/tests/document-management-ai-overrides.test.d.ts +0 -1
  171. package/document-management/tests/document-management-ai-overrides.test.js +0 -63
  172. package/document-management/tests/document-management-core.test.d.ts +0 -1
  173. package/document-management/tests/document-management-core.test.js +0 -157
  174. package/document-management/tests/document-management.api.test.d.ts +0 -1
  175. package/document-management/tests/document-management.api.test.js +0 -101
  176. package/document-management/tests/document-statistics.service.test.d.ts +0 -1
  177. package/document-management/tests/document-statistics.service.test.js +0 -498
  178. package/document-management/tests/document-validation-ai-overrides.test.d.ts +0 -1
  179. package/document-management/tests/document-validation-ai-overrides.test.js +0 -87
  180. package/document-management/tests/document.service.test.d.ts +0 -1
  181. package/document-management/tests/document.service.test.js +0 -143
  182. package/document-management/tests/enum-helpers.test.d.ts +0 -1
  183. package/document-management/tests/enum-helpers.test.js +0 -452
  184. package/document-management/tests/helper.d.ts +0 -24
  185. package/document-management/tests/helper.js +0 -39
  186. package/errors/tests/format.test.d.ts +0 -1
  187. package/errors/tests/format.test.js +0 -84
  188. package/http/tests/server-timing.test.d.ts +0 -1
  189. package/http/tests/server-timing.test.js +0 -42
  190. package/injector/tests/advanced.test.d.ts +0 -1
  191. package/injector/tests/advanced.test.js +0 -116
  192. package/injector/tests/async-init.test.d.ts +0 -1
  193. package/injector/tests/async-init.test.js +0 -77
  194. package/injector/tests/basic.test.d.ts +0 -1
  195. package/injector/tests/basic.test.js +0 -114
  196. package/injector/tests/hierarchical.test.d.ts +0 -1
  197. package/injector/tests/hierarchical.test.js +0 -59
  198. package/injector/tests/leak.test.d.ts +0 -1
  199. package/injector/tests/leak.test.js +0 -45
  200. package/injector/tests/lifecycles.test.d.ts +0 -1
  201. package/injector/tests/lifecycles.test.js +0 -109
  202. package/logger/tests/pretty-print.test.d.ts +0 -1
  203. package/logger/tests/pretty-print.test.js +0 -60
  204. package/notification/tests/notification-api.test.d.ts +0 -1
  205. package/notification/tests/notification-api.test.js +0 -124
  206. package/notification/tests/notification-client.test.d.ts +0 -1
  207. package/notification/tests/notification-client.test.js +0 -101
  208. package/notification/tests/notification-flow.test.d.ts +0 -1
  209. package/notification/tests/notification-flow.test.js +0 -296
  210. package/notification/tests/notification-sse.service.test.d.ts +0 -1
  211. package/notification/tests/notification-sse.service.test.js +0 -43
  212. package/notification/tests/notification-type.service.test.d.ts +0 -1
  213. package/notification/tests/notification-type.service.test.js +0 -41
  214. package/object-storage/s3/tests/s3.object-storage.integration.test.d.ts +0 -1
  215. package/object-storage/s3/tests/s3.object-storage.integration.test.js +0 -303
  216. package/orm/tests/build-jsonb.test.d.ts +0 -1
  217. package/orm/tests/build-jsonb.test.js +0 -39
  218. package/orm/tests/data-types.test.d.ts +0 -1
  219. package/orm/tests/data-types.test.js +0 -39
  220. package/orm/tests/database-extension.test.d.ts +0 -1
  221. package/orm/tests/database-extension.test.js +0 -63
  222. package/orm/tests/database-migration.test.d.ts +0 -1
  223. package/orm/tests/database-migration.test.js +0 -83
  224. package/orm/tests/decorators.test.d.ts +0 -1
  225. package/orm/tests/decorators.test.js +0 -77
  226. package/orm/tests/encryption.test.d.ts +0 -1
  227. package/orm/tests/encryption.test.js +0 -31
  228. package/orm/tests/query-complex.test.d.ts +0 -1
  229. package/orm/tests/query-complex.test.js +0 -172
  230. package/orm/tests/query-converter-complex.test.d.ts +0 -1
  231. package/orm/tests/query-converter-complex.test.js +0 -131
  232. package/orm/tests/query-converter.test.d.ts +0 -1
  233. package/orm/tests/query-converter.test.js +0 -123
  234. package/orm/tests/repository-advanced.test.d.ts +0 -1
  235. package/orm/tests/repository-advanced.test.js +0 -189
  236. package/orm/tests/repository-attributes.test.d.ts +0 -1
  237. package/orm/tests/repository-attributes.test.js +0 -83
  238. package/orm/tests/repository-compound-primary-key.test.d.ts +0 -2
  239. package/orm/tests/repository-compound-primary-key.test.js +0 -226
  240. package/orm/tests/repository-comprehensive.test.d.ts +0 -1
  241. package/orm/tests/repository-comprehensive.test.js +0 -162
  242. package/orm/tests/repository-coverage.test.d.ts +0 -2
  243. package/orm/tests/repository-coverage.test.js +0 -242
  244. package/orm/tests/repository-cti-complex.test.d.ts +0 -1
  245. package/orm/tests/repository-cti-complex.test.js +0 -151
  246. package/orm/tests/repository-cti-embedded.test.d.ts +0 -1
  247. package/orm/tests/repository-cti-embedded.test.js +0 -178
  248. package/orm/tests/repository-cti-extensive.test.d.ts +0 -2
  249. package/orm/tests/repository-cti-extensive.test.js +0 -279
  250. package/orm/tests/repository-cti-mapping.test.d.ts +0 -2
  251. package/orm/tests/repository-cti-mapping.test.js +0 -108
  252. package/orm/tests/repository-cti-search.test.d.ts +0 -1
  253. package/orm/tests/repository-cti-search.test.js +0 -141
  254. package/orm/tests/repository-cti-soft-delete.test.d.ts +0 -2
  255. package/orm/tests/repository-cti-soft-delete.test.js +0 -103
  256. package/orm/tests/repository-cti-transactions.test.d.ts +0 -1
  257. package/orm/tests/repository-cti-transactions.test.js +0 -112
  258. package/orm/tests/repository-cti-upsert-many.test.d.ts +0 -2
  259. package/orm/tests/repository-cti-upsert-many.test.js +0 -115
  260. package/orm/tests/repository-cti.test.d.ts +0 -2
  261. package/orm/tests/repository-cti.test.js +0 -390
  262. package/orm/tests/repository-edge-cases.test.d.ts +0 -1
  263. package/orm/tests/repository-edge-cases.test.js +0 -178
  264. package/orm/tests/repository-expiration.test.d.ts +0 -2
  265. package/orm/tests/repository-expiration.test.js +0 -140
  266. package/orm/tests/repository-extra-coverage.test.d.ts +0 -2
  267. package/orm/tests/repository-extra-coverage.test.js +0 -402
  268. package/orm/tests/repository-mapping.test.d.ts +0 -2
  269. package/orm/tests/repository-mapping.test.js +0 -65
  270. package/orm/tests/repository-regression.test.d.ts +0 -1
  271. package/orm/tests/repository-regression.test.js +0 -288
  272. package/orm/tests/repository-search-coverage.test.d.ts +0 -1
  273. package/orm/tests/repository-search-coverage.test.js +0 -107
  274. package/orm/tests/repository-search.test.d.ts +0 -1
  275. package/orm/tests/repository-search.test.js +0 -105
  276. package/orm/tests/repository-soft-delete.test.d.ts +0 -1
  277. package/orm/tests/repository-soft-delete.test.js +0 -118
  278. package/orm/tests/repository-transactions-nested.test.d.ts +0 -1
  279. package/orm/tests/repository-transactions-nested.test.js +0 -178
  280. package/orm/tests/repository-types.test.d.ts +0 -1
  281. package/orm/tests/repository-types.test.js +0 -184
  282. package/orm/tests/repository-undelete.test.d.ts +0 -2
  283. package/orm/tests/repository-undelete.test.js +0 -201
  284. package/orm/tests/schema-converter.test.d.ts +0 -1
  285. package/orm/tests/schema-converter.test.js +0 -82
  286. package/orm/tests/schema-generation.test.d.ts +0 -2
  287. package/orm/tests/schema-generation.test.js +0 -174
  288. package/orm/tests/sql-helpers.test.d.ts +0 -1
  289. package/orm/tests/sql-helpers.test.js +0 -67
  290. package/orm/tests/transaction-safety.test.d.ts +0 -1
  291. package/orm/tests/transaction-safety.test.js +0 -81
  292. package/orm/tests/transactional.test.d.ts +0 -1
  293. package/orm/tests/transactional.test.js +0 -215
  294. package/orm/tests/utils.test.d.ts +0 -1
  295. package/orm/tests/utils.test.js +0 -70
  296. package/pdf/tests/utils.test.d.ts +0 -1
  297. package/pdf/tests/utils.test.js +0 -187
  298. package/process/tests/spawn.test.d.ts +0 -1
  299. package/process/tests/spawn.test.js +0 -182
  300. package/rate-limit/tests/postgres-rate-limiter.test.d.ts +0 -1
  301. package/rate-limit/tests/postgres-rate-limiter.test.js +0 -84
  302. package/renderer/tests/renderer.test.d.ts +0 -1
  303. package/renderer/tests/renderer.test.js +0 -88
  304. package/rpc/tests/rpc.integration.test.d.ts +0 -1
  305. package/rpc/tests/rpc.integration.test.js +0 -615
  306. package/signals/implementation/errors.d.ts +0 -2
  307. package/signals/implementation/graph.js +0 -312
  308. package/signals/implementation/writable-signal.d.ts +0 -48
  309. package/signals/implementation/writable-signal.js +0 -32
  310. package/task-queue/tests/coverage-branch.test.d.ts +0 -1
  311. package/task-queue/tests/coverage-branch.test.js +0 -395
  312. package/task-queue/tests/coverage-enhancement.test.d.ts +0 -1
  313. package/task-queue/tests/coverage-enhancement.test.js +0 -150
  314. package/task-queue/tests/dag.test.d.ts +0 -1
  315. package/task-queue/tests/dag.test.js +0 -188
  316. package/task-queue/tests/dependencies.test.d.ts +0 -1
  317. package/task-queue/tests/dependencies.test.js +0 -296
  318. package/task-queue/tests/enqueue-batch.test.d.ts +0 -1
  319. package/task-queue/tests/enqueue-batch.test.js +0 -125
  320. package/task-queue/tests/enqueue-item.test.d.ts +0 -1
  321. package/task-queue/tests/enqueue-item.test.js +0 -12
  322. package/task-queue/tests/fan-out-spawning.test.d.ts +0 -1
  323. package/task-queue/tests/fan-out-spawning.test.js +0 -94
  324. package/task-queue/tests/idempotent-replacement.test.d.ts +0 -1
  325. package/task-queue/tests/idempotent-replacement.test.js +0 -114
  326. package/task-queue/tests/missing-idempotent-tasks.test.d.ts +0 -1
  327. package/task-queue/tests/missing-idempotent-tasks.test.js +0 -39
  328. package/task-queue/tests/optimization-edge-cases.test.d.ts +0 -1
  329. package/task-queue/tests/optimization-edge-cases.test.js +0 -124
  330. package/task-queue/tests/queue-generic.test.d.ts +0 -1
  331. package/task-queue/tests/queue-generic.test.js +0 -8
  332. package/task-queue/tests/queue.test.d.ts +0 -1
  333. package/task-queue/tests/queue.test.js +0 -756
  334. package/task-queue/tests/shutdown.test.d.ts +0 -1
  335. package/task-queue/tests/shutdown.test.js +0 -41
  336. package/task-queue/tests/task-context.test.d.ts +0 -1
  337. package/task-queue/tests/task-context.test.js +0 -7
  338. package/task-queue/tests/task-union.test.d.ts +0 -1
  339. package/task-queue/tests/task-union.test.js +0 -18
  340. package/task-queue/tests/transactions.test.d.ts +0 -1
  341. package/task-queue/tests/transactions.test.js +0 -47
  342. package/task-queue/tests/typing.test.d.ts +0 -1
  343. package/task-queue/tests/typing.test.js +0 -9
  344. package/task-queue/tests/worker.test.d.ts +0 -1
  345. package/task-queue/tests/worker.test.js +0 -258
  346. package/task-queue/tests/zombie-parent.test.d.ts +0 -1
  347. package/task-queue/tests/zombie-parent.test.js +0 -45
  348. package/task-queue/tests/zombie-recovery.test.d.ts +0 -1
  349. package/task-queue/tests/zombie-recovery.test.js +0 -51
  350. package/utils/tests/backoff.test.d.ts +0 -1
  351. package/utils/tests/backoff.test.js +0 -41
  352. package/utils/tests/retry-with-backoff.test.d.ts +0 -1
  353. package/utils/tests/retry-with-backoff.test.js +0 -49
@@ -1,91 +0,0 @@
1
- import { ForbiddenError } from '../../../errors/index.js';
2
- import { HttpHeaders } from '../../../http/http-headers.js';
3
- import { HttpServerResponse } from '../../../http/server/index.js';
4
- import { toArray } from '../../../utils/array/array.js';
5
- import { describe, expect, it, vi } from 'vitest';
6
- import { csrfMiddleware } from '../middlewares/csrf.middleware.js';
7
- describe('csrfMiddleware', () => {
8
- const middleware = csrfMiddleware();
9
- it('should allow safe methods (GET, HEAD, OPTIONS, TRACE)', async () => {
10
- const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE'];
11
- for (const method of safeMethods) {
12
- const context = {
13
- request: { method, headers: new HttpHeaders() },
14
- response: new HttpServerResponse(),
15
- };
16
- const next = vi.fn();
17
- await middleware(context, next);
18
- expect(next).toHaveBeenCalled();
19
- }
20
- });
21
- it('should allow mutating methods (POST, PUT, DELETE, PATCH) without headers (non-browser client)', async () => {
22
- const mutatingMethods = ['POST', 'PUT', 'DELETE', 'PATCH'];
23
- for (const method of mutatingMethods) {
24
- const context = {
25
- request: { method, headers: new HttpHeaders() },
26
- response: new HttpServerResponse(),
27
- };
28
- const next = vi.fn();
29
- await middleware(context, next);
30
- expect(next).toHaveBeenCalled();
31
- }
32
- });
33
- it('should allow same-origin requests via Sec-Fetch-Site', async () => {
34
- const headers = new HttpHeaders();
35
- headers.set('Sec-Fetch-Site', 'same-origin');
36
- const context = {
37
- request: { method: 'POST', headers },
38
- response: new HttpServerResponse(),
39
- };
40
- const next = vi.fn();
41
- await middleware(context, next);
42
- expect(next).toHaveBeenCalled();
43
- });
44
- it('should allow user-initiated requests via Sec-Fetch-Site (none) when enabled', async () => {
45
- const middlewareWithNone = csrfMiddleware({ allowFetchSiteNone: true });
46
- const headers = new HttpHeaders();
47
- headers.set('Sec-Fetch-Site', 'none');
48
- const context = {
49
- request: { method: 'POST', headers },
50
- response: new HttpServerResponse(),
51
- };
52
- const next = vi.fn();
53
- await middlewareWithNone(context, next);
54
- expect(next).toHaveBeenCalled();
55
- });
56
- it('should reject cross-site requests via Sec-Fetch-Site', async () => {
57
- const headers = new HttpHeaders();
58
- headers.set('Sec-Fetch-Site', 'cross-site');
59
- const context = {
60
- request: { method: 'POST', headers },
61
- response: new HttpServerResponse(),
62
- };
63
- const next = vi.fn();
64
- await expect(middleware(context, next)).rejects.toThrow(ForbiddenError);
65
- expect(next).not.toHaveBeenCalled();
66
- });
67
- it('should allow same-origin requests via Origin fallback', async () => {
68
- const headers = new HttpHeaders();
69
- headers.set('Origin', 'http://localhost:8080');
70
- headers.set('Host', 'localhost:8080');
71
- const context = {
72
- request: { method: 'POST', headers },
73
- response: new HttpServerResponse(),
74
- };
75
- const next = vi.fn();
76
- await middleware(context, next);
77
- expect(next).toHaveBeenCalled();
78
- });
79
- it('should include Vary: Sec-Fetch-Site, Origin for mutating methods', async () => {
80
- const context = {
81
- request: { method: 'POST', headers: new HttpHeaders() },
82
- response: new HttpServerResponse(),
83
- };
84
- const next = vi.fn();
85
- await middleware(context, next);
86
- const vary = context.response.headers.tryGet('Vary');
87
- const varyArray = toArray(vary).flatMap((v) => v.split(',').map((s) => s.trim()));
88
- expect(varyArray).toContain('Sec-Fetch-Site');
89
- expect(varyArray).toContain('Origin');
90
- });
91
- });
@@ -1,29 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { PasswordRequirementsError } from '../errors/password-requirements.error.js';
3
- import { DefaultAuthenticationPasswordRequirementsValidator } from '../server/authentication-password-requirements.validator.js';
4
- describe('DefaultAuthenticationPasswordRequirementsValidator', () => {
5
- const validator = new DefaultAuthenticationPasswordRequirementsValidator();
6
- it('should return success when password is strong and not pwned', async () => {
7
- // A very long random string is unlikely to be pwned and will be strong
8
- const result = await validator.testPasswordRequirements('Very-Strong-And-Long-Password-2026!@#$%^&*()');
9
- expect(result.success).toBe(true);
10
- });
11
- it('should return failure when password is pwned', async () => {
12
- // "password" is definitely pwned
13
- const result = await validator.testPasswordRequirements('password');
14
- expect(result.success).toBe(false);
15
- expect(result.reason).toContain('exposed in data breach');
16
- });
17
- it('should return failure when password is too weak', async () => {
18
- // "abc" is too weak (and likely pwned)
19
- const result = await validator.testPasswordRequirements('abc');
20
- expect(result.success).toBe(false);
21
- expect(result.reason).toBeDefined();
22
- });
23
- it('should throw PasswordRequirementsError on validation failure', async () => {
24
- await expect(validator.validatePasswordRequirements('abc')).rejects.toThrow(PasswordRequirementsError);
25
- });
26
- it('should not throw on validation success', async () => {
27
- await expect(validator.validatePasswordRequirements('Very-Strong-And-Long-Password-2026!@#$%^&*()')).resolves.not.toThrow();
28
- });
29
- });
@@ -1,156 +0,0 @@
1
- import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
2
- import { Auditor } from '../../audit/index.js';
3
- import { AuthenticationClientService } from '../../authentication/client/index.js';
4
- import { AuthenticationAncillaryService, AuthenticationService as AuthenticationServerService } from '../../authentication/server/index.js';
5
- import { HttpClientOptions } from '../../http/client/index.js';
6
- import { HttpServer } from '../../http/server/index.js';
7
- import { runInInjectionContext } from '../../injector/index.js';
8
- import { clearTenantData, setupIntegrationTest } from '../../testing/index.js';
9
- import { currentTimestampSeconds } from '../../utils/date-time.js';
10
- import { SubjectService } from '../server/subject.service.js';
11
- import { DefaultAuthenticationAncillaryService } from './authentication.test-ancillary-service.js';
12
- describe('AuthenticationApiController Integration', () => {
13
- let injector;
14
- let database;
15
- let service;
16
- let serverService;
17
- let subjectService;
18
- let server;
19
- const schema = 'authentication';
20
- const tenantId = crypto.randomUUID();
21
- beforeAll(async () => {
22
- const storage = new Map();
23
- globalThis.localStorage = {
24
- getItem: vi.fn((key) => storage.get(key) ?? null),
25
- setItem: vi.fn((key, value) => storage.set(key, value)),
26
- removeItem: vi.fn((key) => storage.delete(key)),
27
- clear: vi.fn(() => storage.clear()),
28
- };
29
- ({ injector, database } = await setupIntegrationTest({
30
- modules: { authentication: true, audit: true, keyValueStore: true, signals: true, api: true, webServer: true },
31
- authentication: {
32
- ancillaryService: DefaultAuthenticationAncillaryService,
33
- },
34
- }));
35
- await runInInjectionContext(injector, async () => {
36
- server = injector.resolve(HttpServer);
37
- const httpClientOptions = injector.resolve(HttpClientOptions);
38
- httpClientOptions.baseUrl = `http://localhost:${server.port}`;
39
- serverService = await injector.resolveAsync(AuthenticationServerService);
40
- subjectService = await injector.resolveAsync(SubjectService);
41
- service = await injector.resolveAsync(AuthenticationClientService);
42
- service.initialize();
43
- });
44
- });
45
- afterAll(async () => {
46
- await server?.close(1000);
47
- await injector?.dispose();
48
- });
49
- beforeEach(async () => {
50
- globalThis.localStorage?.clear();
51
- await clearTenantData(database, schema, ['used_totp_tokens', 'totp_recovery_code', 'totp', 'password', 'session', 'user', 'service_account', 'system_account', 'subject'], tenantId);
52
- });
53
- test('login should work via API client', async () => {
54
- await runInInjectionContext(injector, async () => {
55
- const user = await subjectService.createUser({ tenantId, email: 'api-login@example.com', firstName: 'A', lastName: 'L' });
56
- await serverService.setPassword(user, 'Strong-Password-2026!');
57
- await service.login({ tenantId, subject: user.id }, 'Strong-Password-2026!');
58
- expect(service.isLoggedIn()).toBe(true);
59
- expect(service.subjectId()).toBe(user.id);
60
- });
61
- });
62
- test('login should work even if an expired token is present in the Authorization header', async () => {
63
- await runInInjectionContext(injector, async () => {
64
- const user = await subjectService.createUser({ tenantId, email: 'expired-token-login@example.com', firstName: 'E', lastName: 'L' });
65
- await serverService.setPassword(user, 'Strong-Password-2026!');
66
- // Create an expired token
67
- const now = currentTimestampSeconds();
68
- const expiredTokenResult = await serverService.createToken({
69
- subject: user,
70
- sessionId: crypto.randomUUID(),
71
- impersonator: undefined,
72
- additionalTokenPayload: {},
73
- refreshTokenExpiration: now - 3600,
74
- expiration: now - 3600, // Expired 1 hour ago
75
- issuedAt: now - 7200,
76
- timestamp: (now - 7200) * 1000,
77
- });
78
- // Inject the expired token into the client service
79
- service.updateRawTokens(`Bearer ${expiredTokenResult.token}`);
80
- // Now try to login
81
- await service.login({ tenantId, subject: user.id }, 'Strong-Password-2026!');
82
- expect(service.isLoggedIn()).toBe(true);
83
- expect(service.subjectId()).toBe(user.id);
84
- });
85
- });
86
- test('checkPassword should work via API client', async () => {
87
- const result = await service.checkPassword('abc');
88
- expect(result.strength).toBeLessThan(2);
89
- });
90
- test('refresh should work via API client', async () => {
91
- await runInInjectionContext(injector, async () => {
92
- const user = await subjectService.createUser({ tenantId, email: 'api-refresh@example.com', firstName: 'A', lastName: 'L' });
93
- await serverService.setPassword(user, 'Strong-Password-2026!');
94
- await service.login({ tenantId, subject: user.id }, 'Strong-Password-2026!');
95
- const initialToken = service.token()?.jti;
96
- await service.refresh();
97
- expect(service.token()?.jti).not.toBe(initialToken);
98
- });
99
- });
100
- test('impersonation should work via API client', async () => {
101
- await runInInjectionContext(injector, async () => {
102
- const admin = await subjectService.createUser({ tenantId, email: 'api-admin@example.com', firstName: 'A', lastName: 'D' });
103
- const user = await subjectService.createUser({ tenantId, email: 'api-user@example.com', firstName: 'U', lastName: 'S' });
104
- await serverService.setPassword(admin, 'Admin-Pass-123!');
105
- expect(await subjectService.exists(tenantId, admin.id)).toBe(true);
106
- expect(await subjectService.exists(tenantId, user.id)).toBe(true);
107
- await service.login({ tenantId, subject: admin.id }, 'Admin-Pass-123!');
108
- await service.impersonate(user.id);
109
- expect(service.subjectId()).toBe(user.id);
110
- expect(service.token()?.impersonator).toBe(admin.id);
111
- await service.unimpersonate();
112
- expect(service.subjectId()).toBe(admin.id);
113
- });
114
- });
115
- test('password reset should work via API client', async () => {
116
- await runInInjectionContext(injector, async () => {
117
- const user = await subjectService.createUser({ tenantId, email: 'api-reset@example.com', firstName: 'A', lastName: 'L' });
118
- const ancillaryService = await injector.resolveAsync(AuthenticationAncillaryService);
119
- await service.initPasswordReset({ tenantId, subject: user.id }, undefined);
120
- await vi.waitFor(() => expect(ancillaryService.lastResetData).toBeDefined(), { timeout: 5000, interval: 50 });
121
- await service.resetPassword(ancillaryService.lastResetData.token, 'New-API-Pass-123!');
122
- await service.login({ tenantId, subject: user.id }, 'New-API-Pass-123!');
123
- expect(service.isLoggedIn()).toBe(true);
124
- });
125
- });
126
- test('listSessions and invalidateAllOtherSessions should work via API client', async () => {
127
- await runInInjectionContext(injector, async () => {
128
- const user = await subjectService.createUser({ tenantId, email: 'api-sessions@example.com', firstName: 'S', lastName: 'E' });
129
- await serverService.setPassword(user, 'Strong-Password-2026!');
130
- // Create two sessions
131
- const auditor = injector.resolve(Auditor);
132
- await serverService.login({ tenantId, subject: user.id }, 'Strong-Password-2026!', undefined, auditor);
133
- await service.login({ tenantId, subject: user.id }, 'Strong-Password-2026!');
134
- const sessions = await service.listSessions();
135
- expect(sessions.length).toBe(2);
136
- expect(sessions[0]).toHaveProperty('id');
137
- expect(sessions[0]).toHaveProperty('begin');
138
- expect(sessions[0]).toHaveProperty('end');
139
- await service.invalidateAllOtherSessions();
140
- const updatedSessions = await service.listSessions();
141
- // Only the current session should remain
142
- expect(updatedSessions.length).toBe(1);
143
- expect(updatedSessions[0].id).toBe(service.sessionId());
144
- });
145
- });
146
- test('changePassword should work via API client', async () => {
147
- await runInInjectionContext(injector, async () => {
148
- const user = await subjectService.createUser({ tenantId, email: 'api-change-secret@example.com', firstName: 'C', lastName: 'S' });
149
- await serverService.setPassword(user, 'Old-Strong-Password-2026!');
150
- await service.login({ tenantId, subject: user.id }, 'Old-Strong-Password-2026!');
151
- await service.changePassword('Old-Strong-Password-2026!', 'New-Strong-Password-2026!');
152
- const authResult = await serverService.authenticateWithPassword({ tenantId, subject: user.id }, 'New-Strong-Password-2026!');
153
- expect(authResult.success).toBe(true);
154
- });
155
- });
156
- });
@@ -1,48 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, test } from 'vitest';
2
- import { AuthenticationApiRequestTokenProvider } from '../../authentication/server/authentication-api-request-token.provider.js';
3
- import { AuthenticationService } from '../../authentication/server/index.js';
4
- import { runInInjectionContext } from '../../injector/index.js';
5
- import { setupIntegrationTest } from '../../testing/index.js';
6
- import { SubjectService } from '../server/subject.service.js';
7
- describe('AuthenticationApiRequestTokenProvider', () => {
8
- let injector;
9
- let authenticationService;
10
- let subjectService;
11
- let tokenProvider;
12
- const tenantId = crypto.randomUUID();
13
- beforeAll(async () => {
14
- ({ injector } = await setupIntegrationTest({ modules: { authentication: true, signals: true } }));
15
- authenticationService = await injector.resolveAsync(AuthenticationService);
16
- subjectService = await injector.resolveAsync(SubjectService);
17
- tokenProvider = injector.resolve(AuthenticationApiRequestTokenProvider);
18
- });
19
- afterAll(async () => {
20
- await injector?.dispose();
21
- });
22
- test('should extract and validate token', async () => {
23
- await runInInjectionContext(injector, async () => {
24
- const user = await subjectService.createUser({ tenantId, email: 'provider-test@example.com', firstName: 'P', lastName: 'T' });
25
- const tokenResult = await authenticationService.getToken(user, undefined);
26
- const request = {
27
- headers: {
28
- tryGet: (name) => name == 'Authorization' ? `Bearer ${tokenResult.token}` : undefined,
29
- },
30
- cookies: {
31
- tryGet: () => undefined,
32
- },
33
- };
34
- const data = { request };
35
- const token = await tokenProvider.tryGetToken(data);
36
- expect(token.payload.subject).toBe(user.id);
37
- });
38
- });
39
- test('should return null if no token', async () => {
40
- const request = {
41
- headers: { tryGet: () => undefined },
42
- cookies: { tryGet: () => undefined },
43
- };
44
- const data = { request };
45
- const token = await tokenProvider.tryGetToken(data);
46
- expect(token).toBeNull();
47
- });
48
- });
@@ -1,123 +0,0 @@
1
- import { Subject } from 'rxjs';
2
- import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
3
- import { AuthenticationClientService } from '../../authentication/client/authentication.service.js';
4
- import { AUTHENTICATION_API_CLIENT } from '../../authentication/client/tokens.js';
5
- import { CancellationSignal, CancellationToken } from '../../cancellation/token.js';
6
- import { BadRequestError } from '../../errors/bad-request.error.js';
7
- import { ForbiddenError } from '../../errors/forbidden.error.js';
8
- import { InvalidTokenError } from '../../errors/invalid-token.error.js';
9
- import { NotFoundError } from '../../errors/not-found.error.js';
10
- import { NotSupportedError } from '../../errors/not-supported.error.js';
11
- import { UnauthorizedError } from '../../errors/unauthorized.error.js';
12
- import { Injector } from '../../injector/index.js';
13
- import { Lock } from '../../lock/index.js';
14
- import { Logger } from '../../logger/index.js';
15
- import { MessageBus } from '../../message-bus/index.js';
16
- import { configureDefaultSignalsImplementation } from '../../signals/implementation/configure.js';
17
- import { currentTimestampSeconds } from '../../utils/date-time.js';
18
- import { timeout } from '../../utils/timing.js';
19
- describe('AuthenticationClientService Error Handling & Stuck States', () => {
20
- let injector;
21
- let service;
22
- let mockApiClient;
23
- let mockLock;
24
- let mockMessageBus;
25
- let mockLogger;
26
- let disposeToken;
27
- beforeEach(() => {
28
- const storage = new Map();
29
- globalThis.localStorage = {
30
- getItem: vi.fn((key) => storage.get(key) ?? null),
31
- setItem: vi.fn((key, value) => storage.set(key, value)),
32
- removeItem: vi.fn((key) => storage.delete(key)),
33
- clear: vi.fn(() => storage.clear()),
34
- };
35
- configureDefaultSignalsImplementation();
36
- injector = new Injector('Test');
37
- mockApiClient = {
38
- login: vi.fn(),
39
- refresh: vi.fn(),
40
- timestamp: vi.fn().mockResolvedValue(currentTimestampSeconds()),
41
- endSession: vi.fn().mockResolvedValue(undefined),
42
- };
43
- mockLock = {
44
- tryUse: vi.fn(async (_timeout, callback) => {
45
- const result = await callback({ lost: false });
46
- return { success: true, result };
47
- }),
48
- use: vi.fn(async (_timeout, callback) => {
49
- return await callback({ lost: false });
50
- }),
51
- };
52
- mockMessageBus = {
53
- publishAndForget: vi.fn(),
54
- messages$: new Subject(),
55
- dispose: vi.fn(),
56
- allMessages$: new Subject(),
57
- };
58
- mockLogger = {
59
- error: vi.fn(),
60
- warn: vi.fn(),
61
- info: vi.fn(),
62
- debug: vi.fn(),
63
- };
64
- injector.register(AUTHENTICATION_API_CLIENT, { useValue: mockApiClient });
65
- injector.register(Lock, { useValue: mockLock });
66
- injector.register(MessageBus, { useValue: mockMessageBus });
67
- injector.register(Logger, { useValue: mockLogger });
68
- disposeToken = new CancellationToken();
69
- injector.register(CancellationSignal, { useValue: disposeToken.signal });
70
- });
71
- afterEach(async () => {
72
- disposeToken.set();
73
- await injector.dispose();
74
- });
75
- function setupServiceWithToken(iatOffset = -10, expOffset = 5) {
76
- const now = currentTimestampSeconds();
77
- const initialToken = { iat: now + iatOffset, exp: now + expOffset, jti: 'initial' };
78
- globalThis.localStorage.setItem('AuthenticationService:token', JSON.stringify(initialToken));
79
- service = injector.resolve(AuthenticationClientService);
80
- }
81
- test('Corrupt Storage: should handle invalid JSON in storage gracefully', async () => {
82
- // initialize with corrupt token
83
- globalThis.localStorage.setItem('AuthenticationService:token', '{ invalid-json');
84
- service = injector.resolve(AuthenticationClientService);
85
- expect(service.token()).toBeUndefined();
86
- expect(mockLogger.warn).toHaveBeenCalled(); // Should warn about parse error
87
- });
88
- test.each([
89
- ['InvalidTokenError', new InvalidTokenError()],
90
- ['NotFoundError', new NotFoundError('Session not found')],
91
- ['ForbiddenError', new ForbiddenError()],
92
- ['UnauthorizedError', new UnauthorizedError()],
93
- ['NotSupportedError', new NotSupportedError()],
94
- ['BadRequestError', new BadRequestError()],
95
- ])('Unrecoverable Errors: should logout on %s during refresh', async (_, error) => {
96
- setupServiceWithToken();
97
- mockApiClient.refresh.mockRejectedValue(error);
98
- // Wait for loop to pick up refresh
99
- await timeout(20);
100
- expect(mockApiClient.endSession).toHaveBeenCalled();
101
- expect(service.token()).toBeUndefined();
102
- });
103
- test('Recoverable Errors: should NOT logout on generic Error during refresh', async () => {
104
- setupServiceWithToken();
105
- mockApiClient.refresh.mockRejectedValue(new Error('Network failure'));
106
- await timeout(20);
107
- // Should NOT have called endSession (logout)
108
- expect(mockApiClient.endSession).not.toHaveBeenCalled();
109
- // Token should still be present (retry logic handles it)
110
- expect(service.token()).toBeDefined();
111
- // Trigger immediate retry to finish test quickly
112
- service.requestRefresh();
113
- await timeout(20);
114
- });
115
- test('Logout Failure: should clear local token even if server logout fails', async () => {
116
- setupServiceWithToken(-1000, 1000);
117
- mockApiClient.endSession.mockRejectedValue(new Error('Network error during logout'));
118
- await service.logout();
119
- expect(mockApiClient.endSession).toHaveBeenCalled();
120
- expect(service.token()).toBeUndefined();
121
- expect(mockMessageBus.publishAndForget).toHaveBeenCalled(); // loggedOutBus
122
- });
123
- });
@@ -1,118 +0,0 @@
1
- import { of } from 'rxjs';
2
- import { describe, expect, test, vi } from 'vitest';
3
- import { HttpClientRequest, HttpClientResponse, HttpError, HttpErrorReason } from '../../http/index.js';
4
- import { dontWaitForValidToken } from '../authentication.api.js';
5
- import { logoutOnUnauthorizedMiddleware, waitForAuthenticationMiddleware } from '../client/http-client.middleware.js';
6
- describe('waitForAuthenticationMiddleware', () => {
7
- test('should wait for token and call next', async () => {
8
- const authenticationServiceMock = {
9
- token: vi.fn().mockReturnValue({ jti: 'test-token' }),
10
- validToken$: of({ jti: 'test-token' }),
11
- hasValidToken: true,
12
- };
13
- const middleware = waitForAuthenticationMiddleware(authenticationServiceMock);
14
- const request = new HttpClientRequest('http://localhost');
15
- request.context = {
16
- endpoint: {
17
- credentials: true,
18
- },
19
- };
20
- const next = vi.fn().mockResolvedValue(undefined);
21
- await middleware({ request }, next);
22
- expect(next).toHaveBeenCalled();
23
- });
24
- test('should NOT wait if endpoint has dontWaitForValidToken', async () => {
25
- const authenticationServiceMock = {
26
- isLoggedIn: vi.fn().mockReturnValue(true),
27
- hasValidToken: false,
28
- };
29
- const middleware = waitForAuthenticationMiddleware(authenticationServiceMock);
30
- const request = new HttpClientRequest('http://localhost');
31
- request.context = {
32
- endpoint: {
33
- credentials: true,
34
- data: {
35
- [dontWaitForValidToken]: true,
36
- },
37
- },
38
- };
39
- const next = vi.fn().mockResolvedValue(undefined);
40
- await middleware({ request }, next);
41
- expect(next).toHaveBeenCalled();
42
- });
43
- test('should NOT wait if credentials is NOT true', async () => {
44
- const authenticationServiceMock = {
45
- isLoggedIn: vi.fn().mockReturnValue(true),
46
- hasValidToken: false,
47
- };
48
- const middleware = waitForAuthenticationMiddleware(authenticationServiceMock);
49
- const request = new HttpClientRequest('http://localhost');
50
- request.context = {
51
- endpoint: {
52
- credentials: false,
53
- },
54
- };
55
- const next = vi.fn().mockResolvedValue(undefined);
56
- await middleware({ request }, next);
57
- expect(next).toHaveBeenCalled();
58
- });
59
- });
60
- describe('logoutOnUnauthorizedMiddleware', () => {
61
- test('should call logout on 401 error', async () => {
62
- const authenticationServiceMock = {
63
- logout: vi.fn().mockResolvedValue(undefined),
64
- };
65
- const middleware = logoutOnUnauthorizedMiddleware(authenticationServiceMock);
66
- const request = new HttpClientRequest('http://localhost');
67
- const response = new HttpClientResponse({
68
- request,
69
- statusCode: 401,
70
- statusMessage: 'Unauthorized',
71
- headers: {},
72
- body: undefined,
73
- closeHandler: () => { }
74
- });
75
- const error = new HttpError(HttpErrorReason.StatusCode, request, { response });
76
- const next = vi.fn().mockRejectedValue(error);
77
- await expect(middleware({ request }, next)).rejects.toThrow(HttpError);
78
- expect(authenticationServiceMock.logout).toHaveBeenCalled();
79
- });
80
- test('should NOT call logout on 401 error if endpoint has dontWaitForValidToken', async () => {
81
- const authenticationServiceMock = {
82
- logout: vi.fn().mockResolvedValue(undefined),
83
- };
84
- const middleware = logoutOnUnauthorizedMiddleware(authenticationServiceMock);
85
- const request = new HttpClientRequest('http://localhost');
86
- request.context = {
87
- endpoint: {
88
- resource: 'end-session',
89
- data: {
90
- [dontWaitForValidToken]: true,
91
- },
92
- },
93
- };
94
- const response = new HttpClientResponse({
95
- request,
96
- statusCode: 401,
97
- statusMessage: 'Unauthorized',
98
- headers: {},
99
- body: undefined,
100
- closeHandler: () => { }
101
- });
102
- const error = new HttpError(HttpErrorReason.StatusCode, request, { response });
103
- const next = vi.fn().mockRejectedValue(error);
104
- await expect(middleware({ request }, next)).rejects.toThrow(HttpError);
105
- expect(authenticationServiceMock.logout).not.toHaveBeenCalled();
106
- });
107
- test('should not call logout on other errors', async () => {
108
- const authenticationServiceMock = {
109
- logout: vi.fn().mockResolvedValue(undefined),
110
- };
111
- const middleware = logoutOnUnauthorizedMiddleware(authenticationServiceMock);
112
- const request = new HttpClientRequest('http://localhost');
113
- const error = new Error('Some other error');
114
- const next = vi.fn().mockRejectedValue(error);
115
- await expect(middleware({ request }, next)).rejects.toThrow('Some other error');
116
- expect(authenticationServiceMock.logout).not.toHaveBeenCalled();
117
- });
118
- });